礦工在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。 最後兩張圖片來源網絡,侵刪。