> For the complete documentation index, see [llms.txt](https://agzs.gitbook.io/geth-pbft-book/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://agzs.gitbook.io/geth-pbft-book/chapter1-geth/mining-process.md).

# Section1.5 mining process

备注：文中所提到的函数都未带参数或参数不全，与源代码不同，并且挑选了关键函数，只用于说明。">>"代表调用，"=>"代表顺序执行，"==>"代表接口实现。

## 前期注册

### geth()>>makeFullNode()>>utils.RegisterEthService()

* 在utils.RegisterEthService()中会注册eth.New()函数（该函数在此只是注册，实际被调用在startNode()>>utils.StartNode()>>Node.Start()中的for循环下的constructor()，constructor是个函数类型），eth.New()函数会依次调用几个比较重要的函数：
  * core.NewBlockChain()
  * core.NewTxPool()
  * NewProtocolManager()
  * miner.New()，该函数实例化miner对象，与挖矿联系紧密
* miner.New()先实例化miner，其中成员变量worker由newWoker()实例化，newWorker()会先后启动两个goroutine，分别是worker.update()和worker.wait()：
  * worker.update() 通过不同的events执行不同的操作，这些events都是通过worker.mux.Subscribe(...Event...)订阅的
  * worker.wait() 从worker.recv中获取blockh和work，进行区块入链和广播区块等操作，最后会调用worker.commitNewWork
    * 分支一：worker.chain.InsertChain() => goroutine调用worker.mux.Post(core.NewMinedBlockEvent{Block:block})
    * 分支二：worker.state.commitTo() => worker.chain.writeBlock() => goroutine多次调用worker.mux.Post()，所传递的参数不同
* miner.New()调用miner.Register(NewCpuAgent(eth.BlockChain(),engine)):
  * eth.BlockChain()
  * NewCpuAgent()实例化一个CpuAgent
  * Register():
    * agent.Start()==>CpuAgent.Start()>>goroutine调用CpuAgent.update()>>goroutine调用CpuAgent.mine()>>CpuAgent.engine.Seal()>>ethash.mine()
    * miner.worker.register(agent)>>agent.setReturnCh(worker.recv)
* miner.New()启动goroutine调用miner.update():
  * 订阅events，通过miner.mux.Subscribe(startEvent,DoneEvent,FailedEvent)实现
  * for循环遍历events.Chan()，即读取readC，通过switch分支进行操作：
    * miner.stop()>>miner.worker.stop()
    * miner.start()依次调用miner.worker.start()和miner.worker.commitNewWork()

## 后期运行

### geth调用完makeFullNode()，接着会调用startNode()>>utils.StartNode()>>ethereum.StartMining()

* ethereum.StartMining()启动goroutine调用ethereum.miner.Start():
  * miner.worker.start()>>agent.Start()==>CpuAgent.Start()>>goroutine调用CpuAgent.update()>>goroutine调用CpuAgent.mine()>>CpuAgent.engine.Seal()==>ethash.mine()
  * miner.worker.commitNewWork():
    * worker.engine.Prepare()=>
    * work.commitTransactions()>>env.commitTransaction() => 启动goroutine，根据条件分别mux.Post()>>sub.deliver(event)
    * worker.engine.Finalize()>>types.NewBlock()
    * worker.push(work)，其中work含有刚刚构造好的block，候选block作为work被push到给worker，实际上发送到agent的workCh中
  * 前面已启动goroutine的CpuAgent.update()会读取workCh中的work，然后goroutine调用CpuAgent.mine()>>CpuAgent.engine.Seal()==>ethash.mine()
  * ethash.mine()会将添加nonce的block返回，保存在agent.resultch，即worker.wait()函数用到的worker.recv中
  * 前面已启动goroutine的Post()会发送NewMinedBlockEvent事件
