主页 > 下载imtoken钱包20app > 重磅!美图技术团队发布开源以太坊DPoS实现
重磅!美图技术团队发布开源以太坊DPoS实现
导读:目前以太坊采用PoW算法,并计划逐步替换为PoS。 是否可以在以太坊上引入 DPoS 算法? 美图区块链实验室对区块链做了大量研究,共识算法是重点研究方向之一。 近日,美图技术团队在以太坊上成功实现了DPoS算法,并通过本文对算法思路和源码进行了详细的描述。 文末评论有惊喜。
本文介绍美图区块链实验室在学习和研究过程中的一些近期成果。 以太坊是一个相对成熟和智能化的案例,对美图未来区块链技术的发展具有相当的借鉴意义,因此选择它作为研究对象。
我们基于以太坊(版本 1.7.3)实现 DPoS 共识算法有两个主要目的。 一是我们主要是通过看代码来研究区块链的一些技术,修改代码可以进一步加深共识。 并巩固对代码设计的理解。 还有一点就是通过将修改后的代码开源,来吸引更多人关注这个项目,这也是对社区的一种回馈。
Github地址:
共识算法
在开始分析DPoS的实现之前以太坊的共识算法,我们先简单介绍一下目前主流的数字货币共识算法。 下面列举的只是部分共识算法,还有很多算法没有提到。 所列顺序和时序不代表算法优劣。
PoW(工作量证明)
该算法可以简要描述如下:
PoW 的穷举法需要大量的计算资源来寻找满足条件的整数,而计算能力纯粹是为了寻找一个无意义的随机数,这也成为了大家诟病 PoW 的重要原因之一。 现在一些团队正在尝试将这些计算能力与一些现实场景相结合,比如AI模型计算。 PoW 的另一个问题是性能低下。 比特币目前的性能是7qps左右,以太坊是比特币的两倍左右。闪电网络,现在比较知名的offchain代表,主要是解决比特币的性能问题,还有V神在做的ethereum sharding,等等
PoS(股权证明)
PoS算法描述如下:
上式中唯一的变量是左边的t,变化范围在固定空间内(比如不超过1h,那么t的取值范围只有7200,如果找不到it, exit), 所以你不需要像 PoW 那样使用穷举的方式来寻找随机数,也不会有消耗大量算力的问题。 另外,我们可以看到在阈值的计算中加入了用户余额,这意味着如果用户拥有的资产越多,找到正确随机数的概率就会越大。
PoS 在解决算力的同时,也引入了潜在的攻击问题:
DPoS(委托权益证明)
DPoS 被认为是 PoS 的改进版本。 DPoS conducts elections every once in a while, and then these elected nodes are responsible for block generation and mutual supervision and verification, which can greatly reduce the time for block generation and block confirmation. 这种选举方式的问题在于出块节点会比 PoW 和 PoS 更加中心化。
DPoS 算法总结
以太坊目前的共识算法是PoW,未来会逐渐过渡到PoW+PoS。 目前,为了解决算力消耗过大和性能问题,我们的一个尝试是将共识算法从PoW修改为DPoS。
DPoS 共识算法最大的特点是区块生产者是选举产生的,而不是随机数产生的。 算法设计和中心化投票机制与Bitshares提出的DPoS算法没有本质区别。 唯一的区别是将投票过程变成了交易。 专家详细讲解了我们的整体流程和具体实施。
整体流程如下:
该算法主要由两个核心部分组成:
区块验证者选举
区块验证器调度
第一批区块验证者由创世区块指定,随后每个周期(周期由具体实现定义)在周期开始的第一个区块重新选举。 验证人选举流程如下:
踢出在上一个周期中没有产生足够区块的验证者
在选举区块(每个周期的第一个区块)产生时统计候选人的得票数,选出得票数最高的前N个作为验证人
随机打乱验证者出块的顺序,验证者按照随机结果的顺序出块
验证者根据选举结果调度出块,其他节点根据选举结果验证出块顺序是否与选举结果一致。 如果不一致,则认为该块不合法,直接丢弃。
DPoS 实施
以太坊目前的代码已经包含了几种共识算法的实现:
为了在代码中实现多种共识算法,以太坊抽象出一套共识算法接口,它只需要实现几个接口就可以实现不同的共识算法。 另外,为了避免每次选举都从创世块中重放历史数据,DPoS增加了几棵全局状态树来记录选举和投票的状态,并将树对应的根存储在区块头中,包括:
界面
核心实现
我们先看一下打包块的过程:
矿工会定期通过CheckValidator检查当前验证者是否为当前节点,如果是则通过CreateNewWork创建新的区块任务。 CreateNewWork主要包括三部分:
最后,Seal 会对新区块进行签名,然后将新区块广播给相邻节点。 其他节点将根据区块签名和选举结果检查新区块是否应由验证者产生。 DPoS共识算法与其他共识算法相比,主要区别在于选举,因此我们可以重点关注这个实现:
在打包每个区块之前,我们会调用tryElect,看看当前区块是否是新循环的第一个区块,如果是第一个区块,我们需要触发一次选举。 整体选举的实现比较简单,主要做了三件事:
根据上一周期出块情况,将部分被选中但未达到要求出块数量的候选者踢出
截至最后一个区块,选择得票数最高的前N个候选人作为验证人
打乱验证者的顺序
接下来看计票实现(忽略一些不重要的代码):
计票的逻辑也很简单:
先找出候选人对应的选民名单
所有选民的余额作为投票数累积到候选人的总票数中
之前我们看到,共识算法接口除了上面看到的几个接口外,还需要实现VerifyHeader()、VerifySeal()、VerifyUncles()等几个验证接口,主要是在其他人收到新区块的时候. 使用这些方法验证区块头、内容、叔块信息是否符合验证规则。 限于篇幅,这里不做详细介绍。
成为候选人/投票
如果一个节点想要成为验证者,它必须先成为一个候选人,然后其他人才能对这个候选人进行投票。 无论是投票还是成为候选人以太坊的共识算法,其实都是节点之间的交易。 之前的交易主要是转账或者合约调用,现在又增加了几种交易类型。
当一个新的区块被打包时,该区块中的所有交易都会被执行。 如果发现交易类型与之前的转账或合约调用类型不同,则会调用applyDposMessage进行处理。
可以看出,投票/成为候选人与我们传统的实现没有太大区别。 本质是对数据进行增删改查,但是区块链在数据更新方面会比普通的KV更加复杂和特殊。
测试
第一批创世验证器在 dpostestgenesis.json 中修改。 为了方便测试,可以减少验证器的数量(maxValidatorSize)
开发中遇到的问题
以太坊同步有三种同步机制:
full sync 同步所有区块,重放所有交易数据,构建全局状态树
fast sync (默认) 同步全量区块数据和第N个区块的全局状态树,只回放第N个区块之后的交易数据。 这种机制与Redis的RDB+AOF机制非常相似,避免了回放带来的性能问题(回放事务的主要性能瓶颈在于随机IO读写)。
light sync只同步区块头信息,不同步具体交易内容,主要用于钱包实现SPV功能
在fast sync模式下,广播的block会被直接丢弃,只有进入full sync后才会被接收。 如果我们同时以默认同步方式(fast sync)启动多个节点,由于节点间出块频率相同,所有节点无法进入全同步模式,节点间同步的块将被丢弃。 解决方案是以全同步模式启动创始节点。 为了方便测试,我们的开源代码也会默认使用全同步。
参考
[1] @dantheman/dpos-consensus-algorithm-this-missing-white-paper
[2]
[3]
[4]
[5]
[6]
前五名评论点赞送《高可用架构第一卷》一书(价值108元)和限量版美图抱枕一个