看源代码的过程中,我发现signedproposal(sp)和blockwithproof(bwf)都是bft模块发送给执行模块的包含有block的消息类型,同时两个消息也在executor/postman中执行相同的代码段。查看log中发现,共识同一个块时,执行模块先收到signedproposal,然后再收到blockwithproof;并且在收到sp消息时,模块执行相应的块内交易。我的理解是:sp把块内交易交给执行模块执行,生成closedblock,而bwf把sp生成的closedblock grow_up。不知理解是否正确?
Signedproposal和Blockwithproof消息类型差别
blockwithproof发给executor是正常操作,很容易理解。
之所以要把signedproposal发给executor,是个性能优化措施,让executor提前执行这个区块。因为正常情况下,大概率最后达成共识的块就是一开始发的proposal。
所以当bwf发过去给executor的时候,executor已经执行过一遍该交易中块内交易了,所以便可以不用再执行一次,仅仅把sp生成的closed_block处理即可?
如果是这样的话,会不会出现sp中交易还未执行完(未生成closed_block),而bwf就发送过来而导致错误的情况呢?
@rink1969 我还发现一种情况。查看自己输出的日志,如果一次共识的BlockTxs是空块的话,非proposer节点貌似不会发送VerifyBlockReq,也就不会接受到VerifyBlockResp,也就不会发送SignedProposal 。只会发送BlockWithProof,这部分是怎么解决的呢。还是说我看漏了。
这就是一种投机的优化策略,你说的这些异常情况都是需要处理的。
executor会提前执行signedproposal,BlockWithProof发过来之后会对比block hash,如果一致说明投机成功,这时对于executor来说执行signedproposal和执行BlockWithProof本来就是一回事。
如果不一致说明投机失败,会丢弃之前预执行的结果,或者打断正在执行的预执行操作,转而执行BlockWithProof,这时就跟没有优化一样。
空块的话,这种预执行优化就没什么意义了。
预执行主要是针对块里面包含的交易比较多,如果等共识完成之后executor再执行,可能两部分时间加起来整个耗时会超过出块间隔,拖慢后面的出块。
如果预执行投机成功,就相当于共识和executor在并行,让executor把共识的那段时间也利用起来了。