前几个月,公司接了ava这个项目,我也参与了其中的审计,这里对其共识进行个简单的介绍。
Ava的亮点就是其共识了,称为avalanche共识。顾名思义,雪崩协议,其共识过程是积少成多,从一个点开始蔓延开来,最后达成共识。观察源码,其实可以看到共识部分包含DAG和blockchain这两块。两者都是用的雪崩协议,只是底层数据结构不同,这里不介绍有向无环图和区块的区别,仅介绍雪崩协议。后面结合源码部分也是通过block结构的snowman部分来介绍。
https://files.avalabs.org/papers/consensus.pdf
白皮书
结合白皮书上的一张流程图来讲解。
共识的开始,节点会自己有一个pref的区块。这个节点会从validator中随机抽出一些节点参与共识,这个抽取的工程虽然是随机的,但是和抵押的比例成正比,抵押的多,这个随机过程中被抽到的比例就越高。这个过程就是图中的
1 | K = SAMPLE(N/u,k) |
当节点抽出K个节点后,会分别向这几个节点发出请求。它会告诉这些节点自己pref的区块,然后这些节点也会返回他们pref的区块。这个过程就是图中的
1 | P := [QUERY(v,col)] |
拿到来自K个节点的P个返回后,就是要进行统计了。
这里对于不同的区块用col(颜色)表示。对于这P个返回,计算各个区块获得投票的次数。这之后的关键有α,β,cnf这三个参数以及一个计数的数组d。需要记得的是,这个α必须大于K/2下取整。
如果这些区块中,没有一个获得的投票数大于α,那么这个cnt会被置为0。
对于那个获得大于α票数的区块,其对应的数组d中的计数加1。而当前的节点的pref的区块是这个d数组中计数最大的那个。
这里β参数的意思是,每个区块连续达到α个投票的次数大于β就达成共识,一旦这次达到α次数的那个区块不是前一个,那么这个cnt置为1。而一旦这个cnt大于了β,那么就意味着这个区块被接受了。也就是
ACCEPT(col)那里。
可以看下代码中对应的部分。
https://github.com/ava-labs/gecko/blob/master/snow/consensus/snowball/tree.go#L402
1 | if votes.Len() >= u.tree.params.Alpha { |
来自α的限制。
https://github.com/ava-labs/gecko/blob/master/snow/consensus/snowball/binary_snowflake.go#L48
1 | sf.finalized = sf.confidence >= sf.beta |
β参数的限制。