以太坊的挖矿实现讲解

一直想找个机会把这部分写一下的,今天刚好有空,希望用最简单方式把这部分逻辑讲清楚,老规矩还是看图说话吧

以太坊的挖矿实现讲解_第1张图片

                                                                  图1 挖矿功能核心对象之间的关系

挖矿的核心功能涉及到了Miner、worker、CpuAgent、RemoteAgent、Work、Clipue、Engine多个对象的协作,它们之间的关系如下 :

  • Miner:总包工头(管大局,发号命令的)
  • worker:总包工头助理(代替总包统管所有事务)
  • CpuAgent/RemoteAgent: 工人(真正干活的人)
  • Work:  代表了要干的事情
  • ethash/Clique: 干活的工具

以太坊的挖矿实现讲解_第2张图片

                                                              图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()
            }
        }
    }
}

你可能感兴趣的:(BlockChain)