详细讲解比特币挖矿原理。

区块链可以看作是记录所有交易的公共账本(清单),比特币网络的每一个参与者都将其视为所有权的权威记录。

比特币没有中心组织,几乎所有完整的节点都有一份公开的总账,可以视为认证记录。

到目前为止,还没有一次对骨干区块链的成功攻击,一次也没有。

通过创造新的区块,比特币以一定但缓慢的速度被铸造出来。大约每十分钟产生一个新块,每个新块都伴随着一定数量的新比特币从无到有。开采210000块需要4年左右,发币率降低50%。

在2016年的某个时间,在第420000块被“挖掘”后,降为12.5比特币/块。在13,23万块(2137发掘)之前,新币的发行速度会以指数形式“减半”64次。届时,每块发行的比特币数量将成为比特币的最小货币单位——1丛。最终,1.344亿块后,全部* * * 2099999997.69亿丛比特币将被完全释放。也就是说,到2140,将有近2100亿个比特币。之后新区块不再包含比特币奖励,矿工收入来自交易费。

每个节点收到事务后,会在全网广播前对这些事务进行检查,并在接收时按照相应的顺序为有效的新事务建立一个池(事务池)。

在验证每笔交易时,每个节点都需要对照一长串标准进行检查:

交易的语法和数据结构必须正确。

输入和输出列表不能为空。

事务的字节大小小于MAX_BLOCK_SIZE。

每个输出值,以及总金额,必须在指定的范围内(小于265,438+0百万币,大于0)。

没有hash等于0且n等于-1的输入(不应中继coinbase事务)。

NLockTime小于或等于INT_MAX。

事务的字节大小大于或等于100。

事务中的签名数应小于最大签名操作数。

解锁脚本(Sig)只能将数字压入堆栈,锁脚本(Pubkey)必须符合isStandard的格式(会拒绝非标准事务)。

池或主分支块中必须存在匹配的事务。

对于每个输入,如果引用的输出存在于池中的任何事务中,则该事务将被拒绝。

对于每个输入,在主分支和事务池中找到被引用的输出事务。如果输出事务缺少任何输入,它将成为一个孤立的事务。如果匹配的事务没有出现在池中,它将被添加到隔离事务池中。

对于每个输入,如果引用的输出事务是coinbase输出,则输入必须至少获得COINBASE_MATURITY (100)确认。

对于每个输入,引用的输出必须存在并且不被消耗。

使用报价的输出交易获取输入值,并检查每个输入值和总值是否在指定范围内(小于265,438+0百万个硬币,大于0)。

如果输入值的总和小于输出值的总和,事务将被中止。

如果交易成本太低,无法进入空区块,交易将被拒绝。

每个输入解锁脚本都必须根据相应的输出锁定脚本进行验证。

以下挖掘节点被命名为挖掘节点a。

挖掘节点总是在监听传播到比特币网络的新块。这些新添加的块对于挖掘节点具有特殊的意义。矿工之间的竞争随着新块的扩散而结束,就像宣布谁是最后的赢家。对于矿工来说,获得一个新的区块意味着参与者赢了,他们输了。但是,一轮比赛的结束也代表着下一轮比赛的开始。

验证交易后,比特币节点会将这些交易添加到自己的内存池中。内存池,也称为事务池,用于临时存储尚未添加到块中的事务记录。

节点A需要为内存池中的每个事务分配一个优先级,选择优先级较高的事务记录来构建候选块。

一个交易要成为“更高优先级”,必须满足以下条件:优先级值大于57,600,000,该值的生成依赖于三个参数:一个比特币(即654.38+0亿丛)、一天的账龄(654.38+0.44块)、交易大小250字节:

高优先级& gt100,000,000 satoshis * 144块/ 250字节= 57,600,000

用于存储块中事务的前50K字节保留给更高优先级的事务。节点在填充这50k字节时会优先考虑优先级最高的这些事务,不管是否包含矿工费。这种机制使得高优先级事务能够被首先处理,即使它们是零矿工费用。

然后,挖掘节点A会选择那些包含最小矿工费的事务,按照“每千字节矿工费”排序,优先选择矿工费高的事务来填充剩余的块。

如果块中还有剩余空间,挖掘节点A可以选择那些不包括矿工费用的事务。一些矿商会尽力将那些没有矿商费用的交易整合到区块中,而另一些矿商可能会选择忽略这些交易。

在一个块被填满之后,内存池中剩余的事务将成为下一个块的候选事务。因为这些事务仍然在内存池中,所以随着新的块被添加到链中,这些事务引用的UTXO的深度(即事务“块年龄”)也会增加。因为事务的优先级值取决于它输入的“块年龄”,所以这个事务的优先级值也增加了。最后,零矿工费交易的优先级值可能满足高优先级的阈值,并被免费打包到块中。

UTXO(未用交易输出):每笔交易都有几笔交易输入,即资金来源,也有几笔交易输出,即资金去向。一般来说,每一个事务都要花费一个输入,产生一个输出,它产生的输出就是“未使用的事务输出”,也就是UTXO。

区块年龄:UTXO的“区块年龄”是自区块链记录UTXO以来经历的区块数量,即该UTXO在区块链的深度。

块中的第一个事务是一个特殊的事务,称为硬币创建事务或硬币库事务。该事务由挖掘节点构成,用于奖励矿工的贡献。假设此时一个区块的奖励是25个比特币,A的挖矿节点会创建一个“向A的地址支付25.1个比特币(包括0.1个比特币用于矿工费用)”的交易,并将生成交易的奖励发送到其钱包。a挖出区块获得的奖励金额是coinbase奖励(25个全新比特币)和区块内所有交易矿工费用的总和。

一个节点构建了一个候选块,那么就轮到A的挖矿机来“挖掘”这个新块,并求解工作量证明算法,使这个块有效。比特币挖掘过程中使用SHA256哈希函数。

用最简单的话来说,挖掘节点一次又一次地尝试,直到找到一个使哈希值低于特定目标的随机调整。hash函数的结果是无法预先知道的,也没有模式可以得到一个具体的hash值。举个例子,你一个人在屋里打台球,白球从A点到达B点,但是一个人推门进来看到白球在B点,却无论如何也不知道怎么从A点到达B点。hash函数的这一特性意味着获取哈希值的唯一方法是不断尝试,每次都随机修改输入,直到出现合适的哈希值。

下列参数是必需的

?块的版本

?最后一块的哈希值:prev_hash。

?要写入的事务的哈希树的值:merkle_root。

?更新时间:ntime

?当前难度:nbits

挖矿的过程就是找x做

sha 256(sha 256(version+prev _ hash+merkle _ root+ntime+nbits+x))& lt;目标

上式中x的取值范围为0 ~ 2 ^ 32,根据当前难度可以获得target。

例如,想象一下,人们不断投掷一对骰子,以获得少于一定点数的游戏。第一局,目标是12。只要你不掷出两个六,你就赢了。那么下一个目标就是11。玩家只需掷出10以下的点数即可获胜,但也很简单。如果几局后目标减少到5。现在掷出的骰子有一半以上加起来会超过5分,所以无效。随着目标越来越小,如果你想赢,掷骰子的次数会成倍增加。最终,当目标是2(最小可能点数)时,平均投36次或2%次,只有一个人能赢。

如上所述,目标决定了难度,进而影响求解工作量证明算法所需的时间。那么问题来了:为什么这个难度值是可调的?谁来调节?怎么调整?

平均每10分钟产生一个比特币块。这是比特币的心跳,是货币发行率和交易速度的基础。它必须不仅在短期内保持不变,而且在几十年内保持不变。在此期间,计算机性能会迅速提高。此外,参与挖掘的人和计算机也会不断变化。为了使新区块的生产速度保持在10分钟,开采难度必须根据这些变化进行调整。其实难度是一个动态参数,会定期调整,以达到每10分钟一个新块的目标。简单来说,难度定在10分钟,不考虑挖矿能力。

那么,在一个完全分散的网络中,这种调整是如何进行的呢?难度的调整在每个完整的节点中独立自动地发生。每2016块(2周生成的块),所有节点都会调整难度。难度的调整公式是通过比较最新的2016个方块所用的时间和20160分钟(两个星期,即这些方块以10分钟的速率所用的预期时间)得出的。根据实际持续时间与预期持续时间的比率来调整难度(或变得困难或容易)。简单来说,如果网络发现块生成速率快于10分钟,会增加难度。如果发现比10分钟慢,难度会降低。

为了防止难度变化过快,每个循环的调整范围必须小于一个因子(值为4)。如果要调整的范围超过4倍,则调整4倍。因为接下来2,065,438+06区块的周期不平衡还会继续存在,下一周期会进行进一步的难度调整。因此,可能需要2016个块周期才能平衡哈希计算能力和难度的巨大差异。

比如目前节点A在挖277,365,438+06块。一旦挖掘节点A完成计算,它将立即把这个块发送给它的所有邻居节点。在接收和验证这个新块之后,这些节点将继续传播这个块。当这个新块在网络中传播时,每个节点将把它作为第277,316个块(父块是277,315)添加到它自己的区块链副本中。当挖掘节点接收并验证这个新的块时,它们将放弃先前构建这个具有相同高度的块的计算,并立即开始计算区块链中的下一个块。

比特币* * *知识机制的第三步是通过网络中的每个节点独立检查每个新块。当一个新的块在网络中传播时,每个节点将进行一系列测试来验证它,然后将其转发给它的节点。这确保了只有有效的数据块才会在网络中传播。

每个节点对每个新块的独立验证保证了矿工不能作弊。在前一章中,我们看到了矿工如何记录交易以获得新的比特币和在该区块中创建的交易费。矿工为什么不为自己录一笔交易来获得几千个比特币?这是因为每个节点根据相同的规则检查块。无效的coinbase交易会使整个块无效,从而导致该块被拒绝,因此该交易不会成为总帐的一部分。

比特币去中心化的* * *知识机制的最后一步,是用最大的工作量证明将块组装成链。一旦节点验证了新的块,它将尝试将新的块连接到现有的区块链并组装它们。

节点维护三种类型的块:

第一个连接到主链,

第二个是来自主链的分支(备用链),

第三是在已知链中没有找到已知的父块。

有时候,一个新区块延伸的区块链并不是主链,这一点我们会在下面的“区块链分叉”中看到。

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

在选择了最难的区块链后,整个网络中的所有节点最终达到* * *识。随着更多的工作量证明加入到链中,链中的暂时差异最终会得到解决。挖掘节点通过“投票”选择想要扩展的区块链。当他们挖掘一个新的区块,延伸出一个链条,这个新的区块本身就代表了他们的一票。

因为区块链是一种分散的数据结构,所以它在不同的副本之间并不总是一致的。数据块可能在不同的时间到达不同的节点,从而导致节点的不同区块链视角。解决方案是每个节点总是选择并试图扩展代表累积最大工作量证明的区块链,即最长或累积最多的难度链。

当两个候选块想要同时扩展最长的区块链时,就会发生分叉。在正常情况下,当两个矿工在短时间内制定出工作量证明解决方案时,就会出现分叉。两个矿工一在各自的候选块中找到解,就立刻把自己的“获胜”块传播到网络,先传播到邻居节点,再传播到整个网络。接收到有效块的每个节点将合并它并扩展区块链。如果该节点随后接收到另一个候选块,并且该块具有相同的父块,则该节点将该块连接到候选链。结果,一些节点接收到一个候选块,而其他节点接收到另一个候选块。这时,出现了两个不同版本的区块链。

分叉前

分叉起点

我们看到两个矿工几乎同时在两个不同的街区挖掘。为了便于跟踪这一分叉事件,我们假设有一个来自加拿大的标为红色的区块和一个来自澳大利亚的标为绿色的区块。

假设有这样一种情况,加拿大的一个矿工找到了“红色”区块的工作量证明解,并在“蓝色”母区块上扩展了区块链。几乎与此同时,一名澳大利亚矿工找到了“绿色”区块的解,并扩展了“蓝色”区块。所以现在我们有两个区块:一个是来自加拿大的“红色”区块;另一个是来自澳大利亚的“绿色”。两个块都是有效的,都包含有效的工作负载证明解决方案,并扩展了相同的父块。这两个块可能包含几乎相同的事务,但是在事务的顺序上有一些不同。

比特币网络中与加拿大相邻(拓扑邻近,而非地理邻近)的节点将首先接收“红色”块,并建立累积难度最大的块。“红色”块是链中的最后一块(蓝红色),而忽略后面到达的“绿色”块。相比之下,更靠近澳大利亚的节点将决定“绿色”块获胜,并将其作为延长区块链(蓝绿色)的最后一块,而忽略几秒钟后到达的“红色”块。首先接收到“红色”块的那些节点将立即将该块作为父块来生成新的候选块,并试图找到该候选块的工作负载证明解决方案。类似地,接受“绿色”块的节点将开始以该块作为链的顶点来生成新的块,并扩展链。

分歧问题几乎总是在一个块内解决。网络中的一些计算能力集中在“红色”块上作为父块,并在其上构建新的块;另一部分计算能力集中在“绿色”模块上。即使计算能力在两个阵营之间平均分配,一个阵营总会在另一个阵营之前找到工作负载证明解决方案并传播出去。这个例子,我们可以打个比方。如果在一个“绿色”区块工作的矿工发现了一个“粉色”区块,并延伸了区块链(蓝绿色粉色),他们会立即传播这个新区块,整个网络都会认为这个区块是有效的,如上图所示。

在上一轮中选择“绿色”块作为获胜者的所有节点将直接将该链延长一个块。然而,那些选择“红色”块作为获胜者的节点现在将看到两个链:“蓝绿色粉红色”和“蓝红色”。如上图所示,这些节点会根据结果将“蓝-绿-粉”链设置为主链,将“蓝-红”链设置为备用链。这些节点接受了新的、更长的链,被迫改变了原来对区块链的看法,这叫做对链的重新认识。因为作为父区块的“红色”区块已经不在最长的链上,他们的候选区块已经成为“孤儿区块”,所以现在任何原本想在“蓝红色”链上延长区块链的矿工都会止步。全网公认“蓝-绿-粉”链为主链,“粉”块是这个链的最后一块。所有矿工立即将他们生成的候选块的父块切换到“粉色”,以延长“蓝绿色粉色”链。

理论上,两个块的分叉是可能的。这种情况发生在矿工因为之前的分歧而对立,两个不同区块的解几乎同时找到的时候。但是,这种情况发生的概率很低。单块分叉每周都会发生,双块分叉非常少见。

比特币将区块间隔设计为10分钟,这是在更快的交易确认和更低的分叉概率之间的折中。较短的块生成间隔会使交易清算更快,同时也会导致更频繁的区块链分叉。相比之下,较长的间隔会减少分叉的数量,但会导致较长的清算时间。