比特币源码解读十八(挖矿)
本篇我们就看挖矿成功后对区块的有效性进行检测的代码。也就是CheckWork所做的事情。检验之时,线程的优先级必须为THREAD_PRIORITY_NORMAL。现在我们就直接看下CheckWork()函数的代码逻辑。
CheckWork检测通过代码我们看到在进行ProcessBlock()正式检测之前要对难度值和父区块进行检测。如果这两项检测通过后,再正式调用ProcessBlock()进行新挖区块的检测。需要说明的是这个ProcessBlock()区块检测和从其他节点发送过来的区块信息("block")检测过程是一样的。都是调用这个ProcessBlock()进行检测。
我们现在就进入ProcessBlock()函数进行源码解读,由于这个函数很大,检测项目很多,我们也向往常一样分段来分析解读:
对块的基本信息和扩展信息检测上在的代码对是否是旧块(重复添加),基本信息(checkBlock()),和扩展信息进行了检测,块的基本信息检测包括:1。块的大小,2。(工作量证明)CheckProofOfWork 3。时间戳(区块时间戳早于验证时刻未来两个小时)4。块的第⼀一个交易信息必须是coinbase和有且有一个coinBase交易5。交易信息(CheckTransaction)6。检测多重支付(有2个或以上的同样的交易信息)7。签名的有效性8。MerkleRoot(默克树根)的有效性。
现在我们就看下checkBlock()的源码,就是按照这样一个检测列表进行检测的:
基本信息检测上面对基本信息和扩展信息进行了检测,我们接着往下看:
检测孤块和存储区块数据到磁盘中我们说一下孤块的概念和形成原因:
如果节点收到了一个有效的区块,而在现有的区块链中却未找到它的父区块,那么这个区块被认为是“孤块”。孤块会被保存在孤块池中,直到它们的父区块被节点收到。一旦收到了父区块并且将其连接到现有区块链上,节点就会将孤块从孤块池中取出,并且连接到它的父区块,让它作为区块链的一部分。当两个区块在很短的时间间隔内被挖出来,节点有可能会以相反的顺序接收到它们,这个时候孤块现象就会出现。
现在我们看AcceptBlock是如何将新区块存储到磁盘中的,在写入磁盘之前还要进行精确的POW校验。我们就直接通过源码来看下这个校验列表,这个函数很长,我分两部分截图来看:
一。区块普通检测
写入区块校验1二。区块版本检测
区块版本校验通过区块版本检测可以看到这里是用于区分比特币分叉之后的处理,这里用的方案就是平常说的大数投票方案(IsSuperMajority)简称ISM,这个方案的规是这样的,大家可以对着代码了解:
1.在对比特币协议进行升级时,是用区块的nVersion进行+1区分的。
2.升级开始后,如果在过去1000个区块(6~7天)内,有750个区块的nVersion为新版本号(也就是说75%的算力已升级),那么新功能会被激活。所有新版本软件产生的区块会按照新规则进行验证,未验证通过会被拒绝。而旧版本软件产生的区块依然按照旧规则进行验证,只要合格同样可被网络接受。
3.在版本号大于等于2的区块中,达到在过去1000个区块内有950个区块的nVersion为新版本号,那么所有由旧版本软件产生的旧版本号区块会被拒绝,这样软分叉激活就完成了。
我把IsSuperMajority函数截出来,大家可以更深刻的理解下。
IsSuperMajority函数对版本检测完成后,下面就开始真正的写入磁盘了。
存储和广播区块到这里基本上一个区块挖出来后就已经被记录下来了,但我们还有一个没有处理,那就是孤链池,就是如果有此区块的子区块,则可以被链记录了。所以ProcessBlock()最后的部分就是处理孤链池。
循环处理孤链池这个函数循环孤链池mapOrphanBlocksByPrev,通过区块hash值不断循环查找。然后调用AsseptBlock()处理所有依赖此区块的孤块。
到这里基本上一个挖矿的过程就完了,我们基本上了解挖矿的过程,和挖矿成功后是如何处理最新的交易和区块的。最后又是如何进行全网广播的,大家可以在源码中了解更详细的处理。
我们如果有理解不对的地方,欢迎大家指正。
作者:区块链研习社比特币源码研读班,black