viewchange struct
1、当当前执行区块的seqNo
为checkpoint
周期(即pbftcore.K
)的整数倍的时候,就初始化checkpoint
的信息。
2、当接受到一个block
发送preprepare
消息的时候,都将会将给该block
分配的seqNo+1
。seqNo
默认是从0开始的。如果发生了viewchange
且当前的nv.Xset
里有给block
重新分配的序号,那么seqNo
就等于nv.Xset
里存的seqNo
的最大值;如果nv.Xset
里为空,那么seqNo
就等于当前结点的低水位。
数据清空
1、何时清空blockstore
?
当节点接受到的
checkpoint
对应block
的seqNo
大于本节点的高水位并且大于高水位的checkpoint
的个数大于f+1
的时候,那么该节点刚执行完的block.seqNo
对应的checkpoint
将永远也达不到stable
状态(stable
状态是指收到2f+1
条针对该block.seqNo
的checkpoint
信息),因为别的节点比本节点快太多,本节点错过了接受其他节点发送该block.seqNo
对应的checkpoint
的时机。在这种状况下,本节点将会清空blockStore
、outstandingBlocks
,从数据库里也删除block
,重新定义高低水位。当新的区块来到时,如果是非主节点就会调用recvPrePrepare()
,在其中针对block
的seqNo
在新的高低水位中进行判断;如果该节点是主节点,它就会调用sendPrePrepare
,此时分配的seqNo
就不在高低水位之间,就会触发viewchange
,在viewchange
的过程中会将pbftcore.seqNo
更新为当前的低水位或者是seqNo
就等于nv.Xset
里存的seqNo
的最大值。在调用函数
movewatermarks()
的时候,如果certstore
存储block
的seqNo
小于低水位就把block
从数据库里删除,从blockstore
里删除。viewchange
结束后blockstore
清空。blockStore
里存储的始终是当前view
下共识的区块,pset
、qset
里始终存储的是当前view
下的request
。所以如果再次发生viewchange
,blockStore
和pset
、qset
里的区块能正常进行对比,不会报错。
2、何时清空pset
、qset
、certstore
?
在调用函数movewatermarks()
的时候,如果pset
、qset
、certstore
存储的seqNo
小于低水位,就清空。
3、pset
、qset
能不能每当一个block
记录到区块链上,就清空一次pset
、qset
?能不能不用pset
、qset
了?
不能。如果一个block
处于committed
状态后,就把它从pset
、qset
里删除。假如再此时停止了挖矿,再重新启动节点的时候,pset
、qset
为空,那么在restoreState()
的时候就不能从pset
、qset
里面获得最新的关于view
和seqNo
的信息,结果导致seqNo
、view
又从0开始。在fabric
里面,除了第一次启动节点时会出现pset
、qset
为空的情况,在接下来的启动中不会出现pset
、qset
为空的情况,因为在进行movewatermarks(n)
的时候,低水位的值计算是小于n的,也就是说pset
、qset
里面只会删除一部分关于request
的信息,不会全删完。
4、在fabric
里面:假设一种情况,有一个RequestBatch1
进行共识,里面的请求都存储在了pset
、qset
里,一轮共识结束后,pset
、qset
里面并没有把RequestBatch1
里的请求进行删除。然后又来了一个RequestBatch2
,RequestBatch1
里的请求也都存储在了pset
、qset
里面,进行共识的过程中发生了viewchange
,此时会对pset
、qset
里面的请求重新进行共识,其中包括RequestBatch1
里面的请求,对RequestBatch1
里面的请求再重新进行共识有无必要?
有必要。RequestBatch1
里面的请求共识达到committed
状态,只能是说明在该节点上RequestBatch1
里的请求得到了其他节点的认可,但是其他节点上RequestBatch1
能否达到committed
状态还不一定。当节点在一个checkpoint
上收到2f+1
条来自其他节点的checkpoint
的信息的时候,说明2f+1
个其他节点都完成了该checkpoint
所在之前请求的共识,此时便可移动高低水位,把checkpoint
之前的请求从pset
、qset
等里删除。
在geth-pbtf
里面,当发生viewchange
的时候,我们就没必要对RequestBatch1
(这里相当于是Block1
)重新进行共识了,因为一轮共识结束之后,我们就把该区块放在了区块链上了。
Last updated
Was this helpful?