接着上一章,我们看到了这章来看了go self.mine(work, self.quitCurrentOp)这部分代码,现在来看下具体挖矿算法的流程。
mine方法中调用engine.GenBlockWithSig方法,返回的result结果传递给returnCh通道,而returnCh通道的获取工作是在worker中进行处理的。上一节我们理了一下producer绑定CpuAgent的流程,在worker.New的时候,通过go worker.handlerSelfMinedBlock()这行代码启了一个协程去获取通道里的挖矿结果。
1 | func (self *CpuAgent) mine(work *Work, stop <-chan struct{}) { |
生成区块的过程:
- 数据合法性校验
- 获取签名者signer和签名方法signFn,这两个数据是在挖矿流程(二)中的StartMining方法中设置的,代码是promeengine.Authorize(eb, wallet.SignHash),即signer是当前节点的挖矿地址coinbase,signFn是对应钱包的签名方法,即keystoreWallet类的签名方法
- voting.GetHpbNodeSnap是获取高性能节点列表,其中有重新投票节点的过程,投票这个机制单独解读,这里就先不说了。
- 设置本地节点类型,是高性能节点还是候选节点
- 如果自己的当前节点不是包含在高性能节点中,则返回错误consensus.ErrUnauthorized
- 接着要判断一下自己当前节点是否轮到进行签名(挖矿),如果没轮到,需要通过高性能节点列表中自己的位置和正在挖矿的位置两个关键参数计算出自己需要等待的一个时间段,
- 时间到了的话就进行签名,签名方法为signFn,这个方法直接使用coinbase对应的私钥进行ECDSA签名
- 签名完了之后,把签名结果放置到header.Extra里,并返回最终block
1 | //生成区块 |
整个挖矿流程就到此结束了,当然其中会涉及一些其他的功能点,比如P2P,投票机制等,后续单独解读。
这段代码读了很久,被投票那块搞死了,说好的POW呢?怎么没看到呢
😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭