矿工在PoW中负责了产生区块的工做,把一大堆交易交给它,它生成一个证实本身作了不少工做的区块,而后将这个区块加入到本地区块链而且广播给其余节点。数据库
接下来咱们将从如下角度介绍矿工:缓存
介绍矿工由哪些部分组成,会和哪些其余模块进行交互,这些部分是如何协做产生区块的。网络
有3种角色:miner、worker、agent。咱们分别使用矿长、副矿长、矿工进行类比。ide
实际的挖矿过程基本不涉及miner,只涉及worker、agent和engine,engine是共识引擎模块,咱们利用下图介绍生成一个区块的主要流程。函数
挖矿过程当中只涉及engine的3个接口:1)Prepare()挖矿前的准备工做,2)Finalize()造成一个基本定型的区块,3)Seal()造成最终的区块。
block
,该block的header中缺乏Nonce
和MixDigest
,这两个值是挖矿获取的。work
,把work发送给全部的agent。Nonce
和MixDigest
填到区块头,生成一个new block
交给agent.mine.new block
封装成Result
,发送给worker。介绍miner、worker和agent的主要函数,他们是矿工的具体运做机制。区块链
主要关注2个函数:spa
New()
:负责建立miner。还建立1个worker和1个agent,但agent还能够经过API建立,而后启动update
函数。update()
:负责关注downloader的3个事件:StartEvent、DoneEvent、FailedEvent。StartEvent是开始同步区块,必须中止挖矿,DoneEvent和FailedEvent是同步成功或者失败,是同步的结束,已经能够挖矿了。代表:挖矿和同步区块不可同时进行,尽可能下降了区块冲突的可能。 主要是3个函数:code
commitNewWork()
:负责生成work,分配agent。这个阶段作了不少工做,调用Engine.Prepare进行准备工做,建立Header,执行交易,获取Uncle,使用Engine.Finalize造成“基本定型”的临时区块,建立Work,最后把work传递给agent。另外commitNewWork
存在多处调用,而且worker有wait
和update
另外2个协程,他们都会调用commitNewWork
,因此存在临界区须要谨慎加锁。update()
:负责处理外部事件。它是死循环,主要处理3种事件:1)ChainHeadEvent,有了新区块头,因此得切换到挖下一个高度的区块,2)ChainSideEvent,收到了uncle区块,缓存起来,3)TxPreEvent,预处理交易,若是在挖矿执行commitNewWork
,若是未挖矿,则交易设置为未决状态。wait()
:负责处理agent挖矿的结果。它是死循环,一直等待接收agent发回的result,而后把区块加入到本地数据库,若是没有问题,就发布NewMinedBlockEvent
事件,通告其余节点挖到了一个新块。主要2个函数:协程
update()
:负责接收worker发来的任务(work)。它是死循环,把work交给mine去挖矿。mine()
:负责挖矿。它拥有挖矿的能力,调用Engine.Seal挖矿,若是挖矿成功则生成result,发送给worker。 最后两张图片来源网络,侵删。