概述
在阅读本文档之前,请确保拥有了Actor和Starcoin Service的知识,相关知识请参考starcoin 异步模型分析
本文结合代码阅读体验更佳
阅读完本文档可以大概了解一个block是如何被提交到区块链上的。本文档主要从几个场景描述了交易的执行过程,不管是哪个场景,最终都会到Block执行那一步。
通过远程节点同步区块到本地之后的交易过程
本地发起交易之后的执行过程。
创世交易
这里与之相关的流程为 同步服务、本地提交。
整体代码结构
TODO
远程同步
SystemStarted
当系统启动时会广播一次SystemStarted
系统通知(关于系统通知可参考TODO),SyncService
通过实现EventHandle<SystemStarted>
来处理该消息,它会往context中广播一次CheckSyncEvent
事件。同样的还 是它自己再捕获了这个事件,这里使用了广播事件通知了一次,看起来多此一举,实际是方便外面其它服务得知这个状态。在CheckSyncEvent
通知之后捕获了这个事件之后调用了 check_and_start_sync
函数。
check_and_start_sync
从本地(SyncService成员)中获取同步参数
生成一个实际的
Future
并将其放入到ctx执行器中,该Future实现了同步的完整流程构造RpcClient:根据选择策略选择策略
WeightdRandom
(关于选择策略部分,可以参考 Starcoin区块同步) 拿到了一个远程节点的列表且构建它们的荣誉值(Reputation Value),根据荣誉值构建一个PeerSelector,将其传入到RpcClient,用来获取最好的远程节点。调用
full_sync_task
full_sync_task
根据远程节点的区块高度,构建
FindAncestorTask
通过第一步的任务找到上一个区块的区块号,并根据其找到区块信息,准备好所有信息后,调用了生成
InnerSyncTask
,并调用InnerSyncTask::do_sync
函数。根据传入的BlockInfo去peer同步区块(这里调用了BlockSyncTask),当BlockSyncTask将区块信息取回之后,将结果放进了结果集BlockCollector,这里的BlockCollector作为BlockSyncTask的结果收集器,拿到了对应信息之后调用了
BlockCollector::apply_block
,它直接调用了BlockChain::apply
注意:这里直接调用了blockchain的apply方法,是否违背了模块隔离原则?
本地提交
TODO
创世
TODO
Block执行
包括验证(Verifier)、执行(Execute)、连接(Connect)三步
Verifier
apply_with_verifier
根据传入的Verifier类型来确定如何验证,通常为Basic,Consensus,Full,None四类,默认用的FullVerifier
Basic,验证区块高度,前一个区块高度,时间戳,epoch,gas上限、区块根hash;
Consensus,根据使用的共识算法对header进行验证,目前用的是
CryptoNight
Full,对区块进行Basic和Consensus验证;
None,不做任何验证。
验证完成Header会验证Body和Uncle block
Execute
execute_block_and_save
在区块被验证通过后调用,它执行了以下动作
将区块内所有的交易全部取出,调用
starcoin_executor::block_executor
执行所有的交易将执行过的txn的所有hash包含到当前
txn_accumulator
中,并计算其roothash,之后将与传过来的block.header中的roothash比较,若不一致则报错。将新的block_id包含到当前
block_accumulator
中根据新的block_id, txn_accumulator_info与block_accumulator_info生成新的block_info。
保存所有的交易信息到数据库
将新生成的
block_info
和传入的block
作为结果返回给调用方
Connect
这里是将执行之后的txn accumulator info和block accumulator info 合并到现有的accumulator tree中
相关链接
关于Service与事件处理机制可以参考这里starcoin 异步模型分析,