长安链TBFT支持随机函数类交易删除的实现

什么是随机函数类交易?

什么是随机函数类交易?简而言之就是交易每次执行的结果可能出现不一致,可能是不同的节点或者不同的时间,同一笔交易执行得到的结果具有随机性。例如现在有一个合约,合约的一个接口实现的是获取本地时间戳,然后存入到一个字段中。现在发起一笔交易,交易调用了这个合约接口,那么就可能出现这笔交易在不同的节点获取的时间戳不一样,导致交易在不同的节点执行结果不一致,站在区块链共识的角度来说,执行结果不一样就没法达成共识。

随机函数类交易在TFBT共识中

TBFT共识是基于拜占庭容错的算法,也就是支持3f+1的容错规则,由于主节点打包的特殊性,所以如果从节点验证提案发现不一致后,会生成并广播一个特殊的投票(NilBlockHash),如果NilBlockHash满足3f+1的规则,则认为该区块无效,进行换主操作,重新出块,也就是说落库的块一定是主节点提案的块,即使从节点内部达成一致,也不会将其落库。而这种随机函数类的交易存在于各个节点的交易池中,TBFT没有达成一致切换一个节点成为主节点,那么下一个节点也会重新将这种交易打包进提案,然后再次广播给其他从节点进行共识。最终导致每个节点成为主节点时,都可能将这种随机函数类的交易打包进提案广播给从节点进行共识,导致一直达不成共识落不了块。如下图:

图1

长安链TBFT共识的处理方案

TBFT共识流程

在了解TBFT对随机函数类交易的处理前,我们首先简单介绍一下TBFT共识的关键步骤,以下是TBFT的阶段图示:

图2

主节点在第一阶段,也就是上图的proposal这个阶段,从交易池中获取一批交易进行生成提案,生成提案的时候会执行这些交易,根据执行结果会生成读写集hash,在广播提案的时候,会携带每笔交易执行完成后的读写集hash。从节点收到主节点的提案之后,会执行提案中的所有交易,每笔交易的执行结果会根据提案附带的读写集Hash进行比较。如果不一致则不会对这个提案进行投票,继续在这个超时时间内从主节点获取这个提案,然后继续执行交易比对执行结果。如果在超时时间内,从节点的交易执行结果都和主节点的读写集hash不一致。那么从节点就会进入到prevote阶段,生成一个NilBlockHash的投票。然后在commit阶段,由于共识没有达成一个非空提案的共识,节点不会提交这个提案,而是进入到下一个轮次,重新换一个节点成为主节点,重新从交易池中打包交易生成提案,再广播给其他从节点继续共识。

共识对随机函数类交易投票

通过上面的描述我们知道,在第一阶段,也就是proposal阶段,主节点会打包交易生成提案,并且会附带这些交易的执行结果的读写集hash。从节点收到提案执行交易,然后根据交易执行结果和主节点附带的读写集hash进行比对。如果出现了不一致,则验证不通过,同时因为提案附带有主节点执行提案内交易的读写集hash,节点能够知道是哪些交易的执行结果不一致。因此在进入到第二阶段也就是prevote阶段的时候,生成的NilBlockHash投票中,TBFT共识将这些执行结果不一致的交易的TxId附加在这个针对空提案的prevote投票里面,表示这是一笔执行结果和主节点不一致的随机函数类交易,需要将其删除。这种带有txid的prevote投票结果如下图:

图3

举个例子,如果主节点广播的区块中有[tx0,tx1,tx2]三笔交易,从节点1在执行时发现tx0执行结果和主节点不一致,则它的prevote投票的信息为:{NilBlockHash,[tx0]},表示自己需要删除tx0这笔交易。如果从节点2执行时发现tx0和tx1执行结果和主节点不一致,则它的prevote投票的信息为:{NilBlockHash,[tx0,tx1]},表示自己需要删除tx0、tx1这笔交易,然后节点生成的prevote投票都会互相广播给其他节点。

共识汇聚投票

TBFT共识会在第二阶段收集到了2f+1张prevote投票进入到precommit阶段。在precommit阶段,共识会收集prevote投票中的需要删除的TxId。如果节点收到了超过f+1个针对某个TxId的prevote投票,那么表示本节点可以从交易池中删除这笔交易。为什么收到了f+1个针对这个txid的投票就可以删除呢,因为f+1可以保证的是至少有一个节点是诚实的,而诚实节点的数据是可信的,因此可以保证这笔交易确实是执行结果不一致的随机函数类交易。例如还是上文的例子,假如一共有4个共识节点,那么f+1的结果就是2。节点3执行的结果是需要删除[tx1,tx2]这两笔交易,然后自己收到了节点1的prevote投票删除的是[tx0,tx1],收到了节点2的prevote投票删除的是[tx3]。那么节点3现在的删除情况是:

tx0: 1票,来自节点1

tx1: 2票,来自节点1、节点3(来自自己)

tx2: 1票,来自节点3

tx3: 1票,来自节点2

那么节点3收到了2张针对tx1的投票,达到了f+1的票数,因此自己将tx1这笔交易从自己的交易池中删除,以便以后不会再打包这笔交易。而tx0、tx2、tx3的投票没有达到f+1张,因此这三笔交易不会被从交易池中删除。通过上面的方式,每个节点收到了f+1张对某个txid的删除投票,那么就将这笔交易从自己的交易池中删除,以便下次自己成为主节点的时候不会将这笔交易再次打包。

需要注意的是每个节点删除的随机函数类交易可能不一致,同时也不一定会全部删除,但是通过多轮次的打包和交易执行并且投票,这些随机函数类的交易会被全部删除,从而保证删除完毕后,节点打包的时候,从交易池获取的都是正常的交易。例如:

图4

在上图的例子中,一共有4个随机函数类交易,分别是tx0、tx1、tx2和tx3。在round0的时候,node0是主节点,它打包了tx0、tx1、tx2和tx3这四笔交易生成了提案,其他三个节点收到node0的提案,然后执行这四笔交易,每个节点根据自己的执行结果,投票里面附带的txid也不一样。同时每个节点根据收到的prevote投票不同,删除的交易也不同。在round0这个一个轮次中,每个节点都没有全部的删除随机函数类交易。在round1这个轮次的时候,又根据上面的流程,投票删除了一些交易。最终,可能需要经过多个轮次的删除,才会把全部的随机函数类交易全部删除掉。

TBFT共识的处理方案

通过我们上文的描述,面对随机函数类交易,TBFT的处理流程如下图:

图5

如图所示,TBFT的处理方式是:

1)  从节点收到提案,执行区块内的交易,和提案附带的读写集hash比较,找出所有的随机函数类交易的txid。

2)  在第二阶段也就是prevote阶段广播空prevote投票的同时,加上自己交易执行结果和主节点不一致的txid。

3)  接着节点在第三阶段也就是precommit阶段,通过汇聚收集到的prevote投票来判断是否剔除某些交易,如果某些交易有f+1张prevote投票对其投票,则将这些交易从交易池中删除。

通过这个处理流程,既保证了共识的安全性,又删除了随机函数类交易,防止其在下次被提案的时候被重复打包。

安全性和正确性

在TBFT共识流程中,如果提案中存在了随机函数类交易,那么从节点收到了提案,验证提案内交易的时候,根据提案附带的读写集hash进行比对,能够知道哪些交易是随机函数类交易。同时因为有随机函数类交易存在,导致提案验证不通过,第二阶段生成的是prevote空票,TBFT通过在第二阶段生成的prevote空票里面,附加上本节点验证出来的随机函数类交易的txid。因为没有修改TBFT的共识流程和内容,只是在空的prevote投票中附加了txid字段,因此保证了TBFT共识的安全性。

第三阶段汇聚投票时,有f+1张prevote投票的txid才删除,f+1保证了至少有一个节点是诚实节点,因此能够保证这个txid确实是随机函数类交易,从而保证了删除随机函数类交易的正确性。

因此通过TBFT共识删除随机函数类交易,在保证TBFT共识安全性的前提下,能够正确无误的删除随机函数类交易。

猜你喜欢

转载自blog.csdn.net/weixin_55760491/article/details/129830398