以太坊的挖礦實現講解

一直想找個機會把這部分寫一下的,今天剛好有空,希望用最簡單方式把這部分邏輯講清楚,老規矩還是看圖說話吧

                                                                  圖1 挖礦功能核心對象之間的關係

挖礦的核心功能涉及到了Miner、worker、CpuAgent、RemoteAgent、Work、Clipue、Engine多個對象的協作,它們之間的關係如下 :

  • Miner:總包工頭(管大局,發號命令的)
  • worker:總包工頭助理(代替總包統管所有事務)
  • CpuAgent/RemoteAgent: 工人(真正幹活的人)
  • Work:  代表了要乾的事情
  • ethash/Clique: 幹活的工具

                                                              圖2 挖礦功能核心對象的定義

從上面的類圖也可以看出來,一個Miner只有一個助理worker,  Miner只負責一些最高級的工作如啓停挖礦。一個助理worker,可以僱傭多個工人(一般是多種類型的工人),新建任務Work,下發任務Work給工人(CpuAgent),並接收工人(CpuAgent)的成果,接收成果後的處理代碼在worker.wait()中實現:

func (self *worker) wait() {
    for {
        mustCommitNewWork := true
        for result := range self.recv {                     //self.recv保存了工人成果(其實就是成功爆破出滿足規則的區塊hash)
            atomic.AddInt32(&self.atWork, -1)

            if result == nil {
                continue
            }
            block := result.Block
            work := result.Work

            // Update the block hash in all logs since it is now available and not when the
            // receipt/log of individual transactions were created.
            for _, r := range work.receipts {
                for _, l := range r.Logs {
                    l.BlockHash = block.Hash()
                }
            }
            for _, log := range work.state.Logs() {
                log.BlockHash = block.Hash()
            }

            //把這個新區塊寫入本地leveldb
            stat, err := self.chain.WriteBlockWithState(block, work.receipts, work.state)
            if err != nil {
                log.Error("Failed writing block to chain", "err", err)
                continue
            }
            // check if canon block and write transactions
            if stat == core.CanonStatTy {
                // implicit by posting ChainHeadEvent
                mustCommitNewWork = false
            }
            // Broadcast the block and announce chain insertion event

            //通過設置事件把自己挖的新區塊廣播出來,已經達到宣告的目的(兄弟們,我挖到了,快來看,幫見證一下)
            self.mux.Post(core.NewMinedBlockEvent{Block: block})
            var (
                events []interface{}
                logs   = work.state.Logs()
            )
            events = append(events, core.ChainEvent{Block: block, Hash: block.Hash(), Logs: logs})
            if stat == core.CanonStatTy {

                //如果上面寫入了規範鏈,這裏添加一個事件,通過這個事件來開啓下一次的挖礦任務(commitNewWork
                events = append(events, core.ChainHeadEvent{Block: block})

            }
            self.chain.PostChainEvents(events, logs)

            // Insert the block into the set of pending ones to wait for confirmations
            self.unconfirmed.Insert(block.NumberU64(), block.Hash())

            if mustCommitNewWork {
                self.commitNewWork()
            }
        }
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章