当前位置:首页区块链让人痴迷的技术:实现比特币减半的十五行代码

让人痴迷的技术:实现比特币减半的十五行代码

北京时间5月12日3时23分左右,BTC在区块高度630000处完成问世至今第3次减半,比特币区块奖赏由12.5枚BTC降至6.25枚BTC,剩下待开采比特币数量只剩下约262万...

作者|MattiasGeniar

译者|杨志昂

策划|Tina

北京时间5月12日3时23分左右,BTC在区块高度630000处完成问世至今第3次减半,比特币区块奖赏由12.5枚BTC降至6.25枚BTC,剩下待挖矿比特币数量只剩下约262万。

那麼,什么叫比特币减半,该事件背后的代码设计原理是什么呢?

让我们一起深入了解在这当中有意思的小细节吧。

区块补贴和奖赏减半

先来简洁回顾一下下1个基础知识要点,常说的“矿工”,就是指此刻分布于世界各国,正在运作硬件和软件来计算下个比特币区块hash值的人。

假如矿工们及时解决了比特币区块链网络中的数学难题,她们就可以得到区块奖赏。

以上所述简述里出現了许多 流行的流行词,是不是?这就来我们一起对这些进行逐一解读。

什么叫hash值?

BTC全部挖矿的设计构思得非常合理。事实上,挖矿并非1个苦思冥想答题的过程,它更多的的是某种试着猜到1个神奇数字的蛮干试着。

BTC网络基本上在全部地方都选用了SHA256hash算法。世界各国的矿工都是会试着运作的挖矿功能模块,可以用下方这一个简易版的函数公式来表述:

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

在这当中$magicNumber也称作随机数(nonce),在密码算法中就是指1个只被使用一次的数字。经过在新区块的哈希来计算中涉及之前区块的hash值,事实上就产生了1个链条式结构,将每一个之前的区块逐一连接,始终连接到新的区块为止。因而,区块链技术实质上也就是个高端版的链表。

矿工们所做的也就是始终一次又一次推测magicNumber的值。她们一遍又一遍地运作同样的来计算,用递增(或随机)的穷举法来试magicNumber的有效值。经过这类的来计算方法,矿工每一次都是会改变以上所述函数公式的hash值最终结果。

那她们什么时候算“赢”呢?

一旦发现她们发现1个开头0的数量足够多的hash值。

就是如此:开头有足够多的0。

这一个答案也就是如此简洁而粗暴,看起来并不洋气。而挖矿来计算的难度就就在于hash值的开头需要多少个0。当第一个区块被挖矿出来时,它的hash值开头只有8个0:

00000000839a8e6886ab5951d76f411475428afc90947ee

而在编写这篇时,该区块链得来的第629828个区块的hash值,它开头有19个0:

0000000000000000000133e7bffe43530e508183ec48a89bad23a370692b16e8而开头需要的0数量越多,就越难答出这样的随机数。

这里多讲一句,BTC这样的计算方法的精妙之处就在于,它区间2016个区块会系统自动再次估算其难度系数目标(即开头需要多少个0),但这篇就不再在此赘述了。

矿工奖励

如果你猜对了这样的随机数,你便会获得奖赏。这样的奖赏以新锻造出來的BTC的方式派发。

本质上,这种BTC是凭空形成的。只不过是它既不价格便宜也不是唾手可得。BTC网路中挖矿是需花很多算力和用电量的。投入这种辛勤工作后,你获得了BTC。为了能维系推进这样的BTC网路,你作为一名挖矿会获得理所当然的奖赏。

这种新挖矿的BTC是在所说的*生成交易(CoinbaseTransaction)*中建立的。它是一种与众不同的交易,它包含在每一个区块中,其功能是支付必要数量的BTC奖赏给猜出了准确hash值的挖矿的人。

是的,热门的“Coinbase加密货币交换所”的名字就来自这样的词汇,它本来就是指每一个区块中对挖矿提供奖赏的特殊交易(生成交易)的引用。

每一个被准确得来的区块,会系统自动估算出挖矿奖赏,并随着BTC网路的发展而对奖赏金额进行系统自动调整。它的设计原理也设计得非常精妙,请让我来和你一起认识一下其背后的源代码。

GetBlockSubsidy()函数

挖矿奖赏减半的魔法发生在函数GetBlockSubsidy()中,该函数包含在源码的src/alidt.cpp文件中。

CAmount GetBlockSubsidy(int nHeight, const Consensus::ParamsAMPL consensusParams){ int halings = nHeight / consensusParams.nSubsidyHalingInteral; // Force block reward to zero when right shift is unDeFined.
if (halings gt;= 64)plain return 0;
CAmount nSubsidy = 50 * COIN;
// Subsidy is cut in half eery 210,000 blocks which will occur approximately eery 4 years.nSubsidy= halings;return nSubsidy;}

现在,这一涵数涉及到什么基本功能?我们一起来分析一下下源代码。尽管我已经有段时间没碰C语言了,但幸运的是,这些源代码非常容易搞懂。

己经出現过几次比特币减半了?

我们一起从顶部逐渐开始看:

inthalings=nHeight/consensusParams.nSubsidyHalingInteral;

上面最后共识参数

consensusParams.nSubsidyHalingInteral,在src/chainparms.cpp文件中被定义为共识标准的一部分。这些是BTC网络上每一个人都必需遵守的一套公共标准。

在这里需要表明的是,对这些共识标准的任何变更都将建立一个“硬分叉(Hardfork)”,即1组不会再遵从原始区块链标准的新标准。

consensus.nSubsidyHalingInteral=210000;

这一常量表明,每产生210,000个区块,就会出現一次比特币减半。在其中自变量nHeight指的是现阶段的区块高度(Height)。或是换句话,己经采掘出來的区块的总数。

而5月12日BTC采掘总数就到达630,000个区块了。所以这时,这一等式就变成:inthalings=630000/210000;

这将使减半的次数值变成3这也是BTC网络第三次将其区块奖赏减半。

可是如果結果是一个浮点值,显然这一結果并不符合该自变量所声明的int类,那会出現什么事情呢?比如:inthalings=620000/210000;

这将得到2.952380952的计算结果。可是,因为自变量被定义为正整数类别,所以会根据真接抹除小数位后边的值,而取整数为该結果范围内最小的整数值。所以,这时的减半的次数是2。

区块奖励结束

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

//ForceblockrewardtozerowhenrightshiftisunDeFined.if (halings gt;= 64)    return 0;

因为 nSubsidy 是个 64 位的有符号整数,在执行右移操作时可能出现未定义行为,这意味着 x 65 操作会变成 x 1,就会导致数值环回,所以这里需要保留对减半次数大于等于 64 的检查。这对于上面所贴的后续代码很重要。

最初的比特币核心代码并没有包含这个 bug 的修复,直到 2014 年才合并了这个 pull request 。

这部分经常被误解为“将会有 64 次比特币减半”这并不正确。其实只会有 33 次比特币减半,后面我们会看到关于这一点的解释。

矿工得到多少奖励?

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

CAmountnSubsidy=50*COIN;nSubsidy= halings;returnnSubsidy;

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

然后,在 210,000 个区块被挖矿之后,这个奖励金额被减半为 25 个比特币。又采出 210,000 个区块之后,变成了 12.5 个比特币。这就是截止到这次减半之前的情况。

而这次减半之后,比特币挖矿奖励又会被减为一半,也即是说矿工只能得到 6.25 个比特币的奖励。之后再采出 210,000 个区块,奖励就会变成 3.125。以此类推。

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

nSubsidygt;gt;=halings;

我打赌你并不是每天都能在自己的代码中看到这样的= 运算符。

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

CAmountnSubsidy=50*100000000;nSubsidy= 3;returnnSubsidy;

区块奖励有一个固定的初始值 50。而按照 src/amount.h 文件中的定义,每枚比特币又可分为 1 亿个更小的基本单位(Satoshi,即“聪”)。如果想要说得更准确的话,矿工不会得到 1 整个“比特币”作为奖励,而是将 1 个比特币均分为 1 亿份,然后得到“1 亿”份这样的基本单位作为奖励。

而这样 1 亿份基本单位加在一起等于 1 个比特币。

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

100101010000001011111001000000000

表示将位右移 3 位。这就得到了:

100101010000001011111001000000

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

在下一次减半发生时,会随着右移一位让上面的二进制数值末尾的 0 又减少一个,从而有效地再次将奖励金额减半。

因为初始值 50 亿总共只有 33 比特位,我们将在第 33 比特减半后让区块奖励变为 0,这大约会发生在 2140 年。

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

结论

BTC的货币供应量通过硬编码进行了限定,每一个人都能够见到和核查这一段源代码。

矿工数量巨大,即便并非上百万量级,最少也是成百上千,能让这么多矿工能以和睦的形式一同运作的创意确实让人觉得难以置信。假如你当初试着设定过任何一种包括五个连接点的群集,你也就会懂得要在众多连接点间达成一致或大部分仲载是那么艰难的一件事情,这是因为须要像BTC网络同样充分考虑:

如何让全部连接点达成一致?

如何防止結果发生偏离?

如何防止网络连接中断导致的干扰?

如何防止数据损失导致的干扰?

如果一种连接点在执行写操作的过程中崩溃了该怎么办?

而在BTC网络上这一切都正常的运作,并且是在硬件、网速、连接点版本和软件均为不明的前提下运作的——这都是由于设计方案时所包括的数学原理和社会共识,让每一个人在该网络上面都遵从同样的规则。

这真是让人痴迷的技术啊。

温馨提示:

文章标题:让人痴迷的技术:实现比特币减半的十五行代码

文章链接:https://www.btchangqing.cn/22602.html

更新时间:2020年06月02日

本站大部分内容均收集于网络,若内容若侵犯到您的权益,请联系我们,我们将第一时间处理。

让人痴迷的技术:实现比特币减半的十五行代码
区块链

从“新基础设施”的角度理解区块链

2020-5-19 10:57:46

区块链

减半后,已有45个比特币矿工无利可图

2020-5-19 12:02:01

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索