源碼包路徑: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)
- 當前塊記錄爲未確認的塊