源码包路径:github.com/ethereum/go-ethereum/miner
A。 Miner.New 创建一个miner对象
- 需要启动挖矿cpuagent
- 监听事件(订阅sync新块的start,done,failed三个事件)(要注意防止别人dos攻击)一次性的啊
- start事件:先关闭miner,记住此时挖矿的标记
- done或者failed事件:根据标记启动miner;取消事件订阅(接下来的所有sync消息全部忽略)
- 创建worker对象
update :订阅TxPreEvent, blockchain head和side 等事件
chainHeadCh :commitNewWork 提交新的work
- chainSide : 记录可能的叔块
- TxPreEvent : 收到交易后,如果不在mining,就放到pending池子里面;否在啥都不做
wait() : 接受agent挖矿成功的块
commitNewWork :提交一个打包的任务
A.3.c : commitNewWork 提交一个打包的任务
- 计算新块时间戳,如果上一个块时间戳超过当前时间戳,需要等待;如果恶意延后呢?
- 调用共识引擎的prepare方法,计算新块难度 (参考.consensus – 共识)
- 获取txpool中的pending状态的交易,同一个addr下按照account nonce排序
- 再按照账户的gasprice将交易做排序(大堆排序法)
work.commitTransactions - 提交交易
- 获取一个当前gasprice最大的交易
- state.prepare修改statedb
- state快照,执行交易(会修改state), 如果失败则state回滚
- 依次循环,直到所有交易处理完(不符合条件的跳过)
- 处理叔块相关的打包
调用共识引擎的Finalize方法,将交易等等打包成块(除了nonce之外的所有信息)
push给挖矿agent,去做”解题“的事情
A.3.b wait() 接受agent解题成功的块,也就是自己成功的挖了一个块了
- 写块数据和state数据
- 广播当前挖矿成功的块 NewMinedBlockEvent
- 发送 ChainEvent ChainHeadEvent(会触发commitNewWork)
- 当前块记录为未确认的块