主页 > 华为为啥下载不了imtoken > 深度剖析实现比特币减半的十五行代码

深度剖析实现比特币减半的十五行代码

华为为啥下载不了imtoken 2023-09-11 05:10:02

比特币开源代码 java_莱特币是比特币?_比特币的代码是多少

作者|Mattias Geniar 译者| 杨之昂策划|Tina

北京时间5月12日凌晨3点23分左右,比特币在区块高度63万处完成诞生以来的第三次减半。 比特币区块奖励从 12.5 BTC 减少到 6.25 BTC。 剩余待开采的比特币数量 仅剩约 262 万枚。

那么,什么是比特币减半,事件背后的代码是如何运作的?

让我们一起深入了解有趣的细节。

区块补贴和奖励减半

先简单回顾一个基础知识点。 所谓“矿工”,是指此时此刻分布在世界各地,正在运行硬件和软件计算下一个比特币区块哈希值的人。

如果矿工及时解决了比特币区块链网络中的数学难题,他们将获得区块奖励。

上面的描述里有很多时髦的流行语,不是吗? 因此,让我们一一解释。

什么是哈希值?

比特币挖矿的整个概念设计得非常巧妙。 事实上,挖矿不是一个头脑风暴和解决问题的过程,它更像是一种暴力猜测一个神奇数字的尝试。

比特币网络几乎无处不在使用 SHA256 哈希算法。 世界各地的矿工都在尝试运行的挖矿函数可以用这个函数的简化版本来表示:

SHA256(    $previousBlockHash,    $newTransactionsToBeIncluded,    $magicNumber);

其中,$magicNumber也称为随机数(nonce),是指在密码学中只使用一次的数字。 通过将前一个区块的哈希值包含在新区块的哈希计算中,实际上形成了一个链式结构,将前一个区块一个一个地链接起来,一直到新区块。 因此,区块链本质上是链表的高端版本。

矿工所做的就是不断猜测 magicNumber 的值。 他们一遍又一遍地运行相同的计算,使用增量(或随机)蛮力来尝试 magicNumber 的有效值。 采用这种计算方式,矿工每次都会改变上述函数的哈希值结果。

他们什么时候算“赢”?

一旦他们找到具有足够前导零的哈希值。

就是这样:开头有足够的 0。

这个回答太简单粗暴了,看起来不高大上。 挖矿计算的难度取决于哈希值开头需要多少个0。 当第一个区块被开采时,它的哈希值在开头只有 8 个零:

00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048

在撰写本文时,区块链第 629828 个区块的计算哈希值,其中有 19 个前导零:

0000000000000000000133e7bffe43530e508183ec48a89bad23a370692b16e8

开始时需要的零越多,就越难猜到随机数。

这里还有一点,比特币算法的巧妙之处在于,它每2016个区块自动重新计算它的难度目标(即开始时需要多少个0),本文在此不再赘述。

挖矿奖励

如果您猜对了这个随机数,您将获得奖励。 该奖励以新铸造的比特币形式发放。

本质上,这些比特币是凭空创造的。 只是它既不便宜又不容易买到。 在比特币网络中挖矿会消耗大量的计算能力和电力。 经过所有这些艰苦的工作,你得到了比特币。 为了维护和加强比特币网络,作为矿工的你将得到应有的奖励。

这些新铸造的比特币是在所谓的*Coinbase 交易*中创建的。 这是每个区块中包含的独特交易,它向猜出正确哈希值的矿工支付一定数量的比特币。

是的,流行的“Coinbase cryptocurrency exchange”得名于该术语,它最初指的是对奖励每个区块中的矿工的特殊交易(生成交易)的引用。

对于每一个被正确计算出的区块,都会自动计算出矿工的奖励,奖励金额会随着比特币网络的发展自动调整。 它的工作原理也设计的非常巧妙,请大家看一下背后的代码。

GetBlockSubsidy() 函数

将矿工奖励减半的魔法发生在函数 GetBlockSubsidy() 中,该函数包含在源代码的 src/validt.cpp 文件中。

CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams){    int halvings = nHeight / consensusParams.nSubsidyHalvingInterval;    // Force block reward to zero when right shift is undefined.
if (halvings >= 64)plain return 0;
CAmount nSubsidy = 50 * COIN;
// Subsidy is cut in half every 210,000 blocks which will occur approximately every 4 years.nSubsidy >>= halvings;return nSubsidy;}

那么,这个函数包含什么呢? 让我们剖析代码。 我已经有一段时间没有接触 C 了,但幸运的是这段代码相当容易阅读。

比特币减半发生了多少次?

让我们从顶部开始:

int halvings = nHeight / consensusParams.nSubsidyHalvingInterval;

上面最后一个共识参数,consensusParams.nSubsidyHalvingInterval,在 src/chainparms.cpp 文件中被定义为共识规则的一部分。 这些是比特币网络上的每个人都必须遵守的一套公共规则。

这里需要注意的是,对这些共识规则的任何更改都将创建一个“硬分叉”,即一套不再遵循原始区块链规则的新规则。

consensus.nSubsidyHalvingInterval = 210000;

该常数表示每 210,000 个区块,比特币减半。 变量 nHeight 指的是当前区块高度(Height)。 或者换句话说,已经开采的区块数量。

5 月 12 日,比特币的开采数量达到 630,000 个区块。 所以在这一点上,等式变成了:

int halvings = 630000 / 210000;

这会将减半次数更改为 3。这也是比特币网络第三次将区块奖励减半。

但是,如果结果是一个浮点值,显然不符合变量声明的 int 类型,会发生什么情况? 例如:

int halvings = 620000 / 210000;

这将给出 2.952380952 的计算结果。 但是,由于变量被定义为整数类型,因此通过直接擦除小数点后的值,将其四舍五入为结果范围内的最小整数值。 因此比特币的代码是多少,此时减半次数为2次。

区块奖励结束

让我们看一下这个代码片段:

// Force block reward to zero when right shift is undefined.if (halvings >= 64)    return 0;

因为nSubsidy是一个64位有符号整数,所以在进行右移操作时可能会出现未定义的行为,即x >> 65操作会变成x >> 1,这会导致值回绕,所以我们需要保留对大于或等于 64 的减半计数的正确检查。这对于上面发布的后续代码很重要。

在 2014 年合并此拉取请求之前,原始比特币核心代码不包含针对此错误的修复程序。

这部分经常被误解为“将有 64 次比特币减半”。 这不是真的。 事实上,比特币减半只会有 33 次,我们稍后会看到对此的解释。

您可以获得多少比特币作为奖励?

“减半”一词实际上是指对矿工可以获得的比特币数量进行限制。 每开采 210,000 个区块,奖励金额就会减半。

CAmount nSubsidy = 50 * COIN;nSubsidy >>= halvings;return nSubsidy;

一开始,也就是 10 多年前,矿工在网络上每挖出一个区块,就会获得 50 个比特币的奖励。

然后,在开采了 210,000 个区块后,这个奖励金额减半为 25 个比特币。 再挖出21万个区块后,就变成了12.5个比特币。 这就是这次减半的情况。

本次减半后,比特币挖矿奖励将再次减半,也就是说矿工只能获得6.25个比特币奖励。 再挖出 210,000 个区块后,奖励变为 3.125。 等等。

这段代码中有一个巧妙的按位运算,我想在这里强调一下:

nSubsidy >>= halvings;

我敢打赌,您不是每天都能在代码中看到这样的 >>= 运算符。

让我们为每个变量填写实际值,重写代码如下:

CAmount nSubsidy = 50 * 100000000;nSubsidy >>= 3;return nSubsidy;

区块奖励初始值固定为50。根据src/amount.h文件中的定义,每个比特币可分为1亿个更小的基本单位(Satoshi,即“中本聪”)。 更准确的说,矿工不会得到1个完整的“比特币”作为奖励,而是将1个比特币分成1亿股,然后得到“亿”股这个基本单位作为奖励。

而这1亿个基本单位加起来就是1个比特币。

这为 nSubsidy 提供了 50 亿个基本单位的初始值。 如果用二进制表示,可以得到如下数字:

100101010000001011111001000000000

意思是将位右移3位。 这得到:

100101010000001011111001000000

当您将该二进制值转换为其十进制表示形式时,您将得到 625,000,000。 换句话说,这是 625,000,000 个基本单位或 6.25 个比特币。

当下一次减半发生时,上述二进制值末尾的 0 将随着该位右移而减少 1,从而有效地将奖励金额再次减半。

因为50亿的初始值一共只有33位,所以我们会在第33位减半后让区块奖励为0,这会发生在2140年左右。

而这个假设的前提是,到那时,交易所支付的挖矿奖励应该足以补偿矿工的电力消耗和硬件成本。

综上所述

比特币的货币供应量是硬编码的,每个人都可以看到和审查这个代码。

有成千上万甚至数百万的矿工,这么多矿工可以和谐地一起工作的想法真是令人难以置信。 如果你曾经尝试建立任何 5 个节点的集群,你就会知道在多个节点之间达成共识或多数法定人数是多么困难,因为你需要像比特币网络一样考虑:

在比特币网络上,这一切都有效,而且它在未知的硬件、网络速度、节点版本和软件的情况下也是如此——这一切都是因为设计中涉及的数学和社会共识,允许该网络上的每个人都按照相同的规则进行游戏。

这真是一项令人着迷的技术。

关于作者:

Mattias Geniar,独立开发人员、Linux 系统管理员和一般问题解决者。

参考阅读:

g代码比特币减半/

InfoQ读者交流群上线啦! 各位小伙伴,可以扫描下方二维码,添加InfoQ小助手比特币的代码是多少,回复关键词“入群”即可申请入群。 可以和InfoQ的读者畅所欲言,和编辑们亲密接触。 即可领取超值技术礼包,更有超值活动等你参与。 来加入我们!

比特币开源代码 java_莱特币是比特币?_比特币的代码是多少

莱特币是比特币?_比特币的代码是多少_比特币开源代码 java

单击以查看更少的错误