一种Fabric与Tendermint的多通道集成方案

       将Fabric与Tendermint进行集成,使其支持PBFT共识算法,以应用于一些对拜占庭容错有要求的生产环境。为了达到这个目的,首先我们要解决的就是Tendermint如何支持多链的问题。

       这里有2种方案:

       1.针对Fabric的每一个通道,我们都启动一个对应的Tendermint共识节点集群。

       2.改造Tendermint,使其支持多链模式。

       方案1的开发成本较低,但因为每一个通道都需要有一个独立的Tendermint集群,将造成维护成本上升和系统资源占用的增加。

       方案2开发成本较高,但不会造成方案一上述问题。我下面主要讲解方案2的设计思路和实现原理。

思路:

     借鉴kafka的topic概念,每一条交易在经过orderer送往kafka时都会附带上topic信息,即该交易本身所属的通道信息。因此我们同样可以将发Tendermint共识节点的交易附加上通道信息,使其在同一条链上记录不同通道的交易数据。

     同时,在Tendermint的abci接口中,每当我们从Tendermint共识节点收到一条交易,我们即将该交易在Tendermint链上的位置附加在该交易数据中,并且在orderer打包出块时将这个区块里最后一条交易在Tendermint链中的位置信息附加到块信息中。这样我们在每个Fabric通道中的区块都与Tendermint中的区块有了对应关系,因此便可以在Fabric与Tendermint之间进行区块同步。

问题:

     设想这样一种场景:如果我们的Fabric系统中创建了3个channel,分别为C1,C2,C3。其中C1的最后一个块的最后一条交易在Tendermint中的位置为blocknum=1000000, txoffset=1。C2的最后一个块的最后一条交易在Tendermint中的位置为blocknum=1000000, txoffset=200。C3的最后一个块的最后一条交易在Tendermint中的位置为blocknum=1, txoffset=0。此时Fabric中的orderer在重启后与Tendermint进行同步,若从3个通道中最高的C2通道进行同步,则可能造成C1和C3的数据丢失。若从最低高度的C3通道开始同步,则我们将会传输巨量的无效数据,这可能将消耗大量的时间和资源,致使同步节点长时间无法工作。

    为了解决上述问题,我们在Tendermint节点中为每一个通道在内存中建立一个映射表。通道同步时会查询自己的映射表,并根据映射表中的信息,逐一将该通道未同步的交易数据返回给abci接口,并交由orderer进行同步。为了解决映射表可能过大的问题,我们将映射表信息存储在本地数据库中,每次启动Tendermint节点时读取数据中近期的一些映射信息到内存,以便快速查询。

示例:

一种Fabric与Tendermint的多通道集成方案