比特币源码解读十八(挖矿)

     本篇我们就看挖矿成功后对区块的有效性进行检测的代码。也就是CheckWork所做的事情。检验之时,线程的优先级必须为THREAD_PRIORITY_NORMAL。现在我们就直接看下CheckWork()函数的代码逻辑。

比特币源码解读十八(挖矿)_第1张图片
CheckWork检测

通过代码我们看到在进行ProcessBlock()正式检测之前要对难度值和父区块进行检测。如果这两项检测通过后,再正式调用ProcessBlock()进行新挖区块的检测。需要说明的是这个ProcessBlock()区块检测和从其他节点发送过来的区块信息("block")检测过程是一样的。都是调用这个ProcessBlock()进行检测。

    我们现在就进入ProcessBlock()函数进行源码解读,由于这个函数很大,检测项目很多,我们也向往常一样分段来分析解读:

比特币源码解读十八(挖矿)_第2张图片
对块的基本信息和扩展信息检测

上在的代码对是否是旧块(重复添加),基本信息(checkBlock()),和扩展信息进行了检测,块的基本信息检测包括:1。块的大小,2。(工作量证明)CheckProofOfWork 3。时间戳(区块时间戳早于验证时刻未来两个小时)4。块的第⼀一个交易信息必须是coinbase和有且有一个coinBase交易5。交易信息(CheckTransaction)6。检测多重支付(有2个或以上的同样的交易信息)7。签名的有效性8。MerkleRoot(默克树根)的有效性。

现在我们就看下checkBlock()的源码,就是按照这样一个检测列表进行检测的:

比特币源码解读十八(挖矿)_第3张图片
基本信息检测

上面对基本信息和扩展信息进行了检测,我们接着往下看:

比特币源码解读十八(挖矿)_第4张图片
检测孤块和存储区块数据到磁盘中

我们说一下孤块的概念和形成原因

如果节点收到了一个有效的区块,而在现有的区块链中却未找到它的父区块,那么这个区块被认为是“孤块”。孤块会被保存在孤块池中,直到它们的父区块被节点收到。一旦收到了父区块并且将其连接到现有区块链上,节点就会将孤块从孤块池中取出,并且连接到它的父区块,让它作为区块链的一部分。当两个区块在很短的时间间隔内被挖出来,节点有可能会以相反的顺序接收到它们,这个时候孤块现象就会出现。

现在我们看AcceptBlock是如何将新区块存储到磁盘中的,在写入磁盘之前还要进行精确的POW校验。我们就直接通过源码来看下这个校验列表,这个函数很长,我分两部分截图来看:

一。区块普通检测

比特币源码解读十八(挖矿)_第5张图片
写入区块校验1

二。区块版本检测

比特币源码解读十八(挖矿)_第6张图片
区块版本校验

通过区块版本检测可以看到这里是用于区分比特币分叉之后的处理,这里用的方案就是平常说的大数投票方案(IsSuperMajority)简称ISM,这个方案的规是这样的,大家可以对着代码了解:

1.在对比特币协议进行升级时,是用区块的nVersion进行+1区分的。

2.升级开始后,如果在过去1000个区块(6~7天)内,有750个区块的nVersion为新版本号(也就是说75%的算力已升级),那么新功能会被激活。所有新版本软件产生的区块会按照新规则进行验证,未验证通过会被拒绝。而旧版本软件产生的区块依然按照旧规则进行验证,只要合格同样可被网络接受。

3.在版本号大于等于2的区块中,达到在过去1000个区块内有950个区块的nVersion为新版本号,那么所有由旧版本软件产生的旧版本号区块会被拒绝,这样软分叉激活就完成了。

我把IsSuperMajority函数截出来,大家可以更深刻的理解下。

比特币源码解读十八(挖矿)_第7张图片
IsSuperMajority函数

对版本检测完成后,下面就开始真正的写入磁盘了。

比特币源码解读十八(挖矿)_第8张图片
存储和广播区块

到这里基本上一个区块挖出来后就已经被记录下来了,但我们还有一个没有处理,那就是孤链池,就是如果有此区块的子区块,则可以被链记录了。所以ProcessBlock()最后的部分就是处理孤链池。

比特币源码解读十八(挖矿)_第9张图片
循环处理孤链池

这个函数循环孤链池mapOrphanBlocksByPrev,通过区块hash值不断循环查找。然后调用AsseptBlock()处理所有依赖此区块的孤块。

到这里基本上一个挖矿的过程就完了,我们基本上了解挖矿的过程,和挖矿成功后是如何处理最新的交易和区块的。最后又是如何进行全网广播的,大家可以在源码中了解更详细的处理。

我们如果有理解不对的地方,欢迎大家指正。



作者:区块链研习社比特币源码研读班,black

你可能感兴趣的:(比特币源码解读十八(挖矿))