原文题目:《Tendermint: Byzantine Fault Tolerance in the Age of Blockchains》react
原文做者:Ethan Buchman算法
翻译:杜满想缓存
校对:饶云坤安全
本文为节选网络
Tendermint子协议性能
上一章中对Tendermint共识的介绍省略了有关用于广播区块(blocks),投票(votes),交易(transactions)和其余节点信息的gossip协议的一些细节。之因此这样作是为了聚焦在共识协议自己,而不让工程实践的细节分散注意力。本章讲述一种特定的用来填充这些细节的方法,经过把这些组件实现为相对独立的反应器(reactors),在这些反应器中每一个对等链接(peer connection)是复用的。区块链
P2P网络优化
在启动时,每一个Tendermint节点都会收到一份须要拨号的对等节点的初始列表(initial list)。对于每一个对等节点,节点会保持一个持久的TCP链接(persistent TCP connection),在该链接上以速率受限的方式复用了多个子协议(subprotocols)。消息被序列化为紧凑的二进制表示,而且经过认证的加密协议对链接进行加密。加密
本章的其他部分的每一小节分别描述了一个独立的反应器,该反应器在每个对等连接进行了复用。有一个额外的对等节点交换反应器(peer exchange reactor),该反应器容许节点彼此请求其余对等节点地址,并跟踪它们先前链接到的对等节点,以便保持链接其余对等点的最小数量。.net
共识Gossip
共识反应器(consensus reactor)封装了共识状态机(consensus state machine),用来确保当每一个节点的状态发生变化时都向其全部对等节点广播其当前状态。以这种方式,每一个节点跟踪全部对等节点的共识状态,只发送对等节点此刻须要的信息,或者对等节点没有的信息,以此来优化消息的gossip过程。对于每一个对等节点,本地节点维护来两个例程(routine)来不断检查发送给对其等节点的新信息,即提议(proposals)和投票(votes)。信息应该以“第一稀有”(ratest first)的原则来最大限度地提升gossip的效率,并尽可能减小某些信息变得不可用的几率。
区块数据
在上一章节中,假设提议信息是包含区块的。然而因为区块是从一个验证节点发出的,而且能够至关大,对于块提议节点来讲把数据上传到全部其余节点的方式压力过大;若是把区块分红若干块后再广播出去会快不少。
一个经常使用来保证数据被安全广播的方法,就是利用Merkle树,此方法也被各类P2P协议所采用,具体方法就是容许每一段数据伴随一个简短的证实(原数据的对数级大小),用来证实该片断是总体的一部分。为了使用这种方法,根据区块大小和验证者的数量,区块被序列化并分割成适当大小的块(chunks),块(chunks)被散列成Merkle树。被签名的提议(proposals)再也不包含整个区块,而是只包含Merkle的根哈希(root hash),容许网络经过协做来广播被分割后的块(chunks)。节点每次收到块(chunks)时都会通知它的对等节点,来避免把同一个块对一个节点传输屡次,以此来节省带宽。
一旦接收到全部块,就对块进行反序列化和验证,以确保它正确地指向前一个块,而且其各类校验和(用Merkle树实现)是正确的。虽然先前假定验证者在接收到提案(包括块)以前不预先投票,可是经过容许验证者在收到提案以后,在接收到完整的块数据以前进行投票,能够提高性能。这意味着预先投票到最后证实是无效的块也是能够的。无论怎么样,对一个无效区块进行预提交(pre-commit)被认为是拜占庭行为。
节点经过接受块(chunks)的方式同步到最新的高度,以一次一个区块的方式进行同步(progress one block at a time)。
投票
在共识状态机中,一个块被提议之后,节点就会开始等待投票(或者本地计时器过时)以往前推动。若是一个节点恰好进入了下一个区块高度的状态下收到一个对上一个块的pre-commits投票,而这个节点若是同时是这轮区块的提议者,它也许会把pre-commits投票看成下一个块的中的LastCommit值存入区块。若是一个对等节点(peer)已经预投票,但还没有预先提交,或者已经预先提交,但还没有进入下一轮,则其被分别发送预投票(pre-votes)或预提交(pre-commits)。若是一个节点是在同步区块的状况下,它将会收到在它当前的高度下预提交(pre-commits)。
内存池
交易独立地在内存缓存中被管理,这个缓存沿用比特币的叫法就是内存池。交易被业务逻辑验证合法后加入内存池,并用有序组播算法发送给相邻节点。一个节点会为每一个相邻节点维持一个例程(routine),用来确保发送交易的顺序是和本身处理的顺序是一致的。
块提议者会把内存池的有序交易列表中的交易打包进新的区块。一旦一个区块被确认提交,区块中的全部交易都会被从内存池中删除,而留下来的交易会被业务逻辑从新验证,由于帐户中的其余交易被确认提交,致使它们的有效性也许会改变。
区块同步
共识反应器(consensus reactor)提供一种相对较慢的区块同步方法,这是为了实时共识而设计的,也就是说节点在处理下一个块以前,会等待接受到全部的信息来确认当下的一个块。为了适应一个节点远落后与当前高度的状况,有一个区块链反应器(blockchain reactor),这个反应器容许节点同时并行地下载多个区块,使节点能够百倍于共识反应器的速度来同步区块数据。
当一个节点连接一个新的对等节点时,这个对等节点须要把它当前区块高度发送给对方。节点并行的从全部比本身高度高的对等节点中循序的请求区块,并下载区块加入到本身的区块池(block pool)。另外一个例程不断尝试从池中删除块并经过验证和执行将它们添加到区块链中,一次两个块,相对于区块链的最新状态。必须每次同时处理两个区块,由于一个区块的提交确认被包含在下一个区块的LastCommit字段中。
节点持续的查询它全部对等节点的当前高度,同时不断的并行请求区块,直到同步到其全部对等节点的最高高度,一旦同步到最高高度就会中止请求区块,并开启共识反应器。
总结
实现Tendermint区块链涉及不少子协议。这些子协议包括包括gossip区块数据和交易的共识数据(投票和提议),和新节点快速同步区块链状态的方法。
相关阅读: