以太坊的矿工出块的流程,不同版本有过变更,下面基于1.7.3版本和1.8.4版本来分享
1. 以太坊的通信机制:
channel: 用于1发1收
发送:sampleChan<-
接收: <-sampleChan
Feed:用于1发多收,参考chainHeadCh
接收者注册:Subscribe(sampleChan)
发送:send, 发送的地方不太好找,需要通过send和event/channel类型查找,例如miner中主要涉及到的就是PostChainEvents
接收:<-sampleChan
2. 1.7.3 以太坊 miner流程
数据结构:
可以理解为操作间(eth)中有了矿(tx),那么矿主(miner)安排工人(worker)挖矿(seal)。结构体定义如下:
Type Minerstruct{ ---理解为矿主
mux *event.TypeMux
worker *worker ----理解为干活的工人
coinbase common.Address
eth Backend ----理解为操作间
engine consensus.Engine ----理解为挖矿的工具
exitCh chan struct{}
canStart int32 //canstart indicates whether we can start the mining operation
shouldStart int32 //shouldstart indicates whether we should start after sync
}
流程图如下:
1. 节点启动: backend.new->miner.new->worker.new: 调用commitNewWork,里面使用push把work传递给cpuAgent, 之后在geth命令行敲miner.start()后->miner.start->worker.start->cpuAgent.start,调用Seal,计算nonce值,再发送recv消息,通知worker.wait,在收到之后将块打包插入到区块链,之后调用PostChainEvents,发送消息chainHeadCh,Worker.update在收到消息后,重新调用commitNewWork,形成一个循环。
2. 创世块:调用geth的init命令触发调用initGenesis->SetupGenesisBlock, 里面具体强调一下time是使用的genesisBlock.json中的值,一般都是0.
3. 正常情况:worker.wait,在收到之后将块打包插入到区块链,之后调用PostChainEvents,发送消息chainHeadCh,Worker.update在收到消息后,重新调用commitNewWork,形成一个循环。
Miner.new: 在backend new的时候调用,即在节点启动的时候调用。
Miner.update:在节点启动的时候调用,用于监控是否有块同步,如果有则停止挖矿,如果没有启动挖矿,这个在POW这种竞争性出块的环境中需要。
Worker.new: 在miner.new的时候调用,记载节点启动的时候调用
Worker.update: 节点启动的时候调用,如果是非全节点的话用于监控接受交易transaction,关键函数commitTransactions,还用于调度在收到chainHeadCh的消息后,触发commitNewWork
其中commitNewWork: 用于将pending的tx输入到系统,计算trie等等操作,生成block,并将work push到cpuAgent处理,注意没有盖章
Worker.wait(对应于1.8.4的resultLoop):节点启动的时候调用,循环监听recv消息,将携带的block插入区块链中、发送广播消息(NewMinedBlockEvent)、发送消息PostChainEvents(发送ChainHeadEvent,即chainHeadCh),其中的关键函数是WriteBlockAndState。
cpuAgent.update(): 在cpuAgent.start()->worker.start->miner.start->geth的命令行调用之后启动循环,用于接收commitNewWork分配下来的work,关键函数mine,里面调用Seal,主要是完成POW寻找nonce值的操作,发送recv消息通知worker,也可以叫做盖章。
3. 1.8.4以太坊miner流程:
类图如下:
具体结构不再赘述
流程:
Miner.update:用于监控是否有块同步,如果有则停止挖矿,这个在POW这种竞争性出块的环境中需要
mainLoop:收到newWorkCh消息后处理,调用commitNewWork中的commit发送taskCh消息
newWorkLoop:收到startCh消息和chainHeadCh消息后发送newWorkCh消息
resultLoop:循环监听resultCh(seal发送)消息,将携带的block插入区块链中,并发送广播消息,关键函数WriteBlockAndState,并发送chainHeadCh消息
taskLoop:以前agent做的事情,收到taskCh消息后,调用seal,里面发送resultCh消息