上海时间5月12日3时23分左右,比特币在区块高度630000处完成诞生以来第三次减半,比特币区块奖励由12.5枚BTC减至6.25枚BTC,剩余待开采比特币数目仅存约262万。
这么,哪些是比特币减半,该风波背后的代码工作原理是哪些呢?
让我们一起深入了解其中有趣的细节吧。
区块补助和奖励减半
先来简单回顾一下一个基础知识点,所谓*“矿工”,是指此时此刻分布于世界各地,正在运行硬件和软件估算下一个比特币区块哈希值*的人。
假如矿工们及时解决了比特币区块链网路中的物理困局,她们就可以获得区块奖励。
以上描述里出现了不少时尚的流行语,是不是?这就来让我们对它们进行挨个解释。
哪些是哈希值?
比特币整个采矿的概念设计得非常巧妙。实际上,采矿并不是一个冥思苦想解题的过程,它更多的是一种尝试猜出一个神奇数字的蛮力尝试。
比特币网路几乎在所有地方都采用了SHA256哈希算法。世界各地的矿工都在尝试运行的采矿功能,可以用下边这个简化版本的函数来表示:
SHA256(
$previousBlockHash,
$newTransactionsToBeIncluded,
$magicNumber
);
其中$magicNumber也被称为随机数(nonce),在密码学中是指一个只被使用一次的数字。通过在新区块的哈希估算中包含先前区块的哈希值,实际上就产生了一个链式结构,将每位曾经的区块挨个链接,仍然链接到新的区块为止。为此,区块链本质上就是个高档版本的数组。
矿工们所做的就是始终不断地推测magicNumber的值。她们一遍又一遍地运行相同的估算,用递增(或随机)的穷举法来试magicNumber的值。她们一遍又一遍地运行相同的估算,用递增(或随机)的穷举法来试magicNumber的有效值。通过这样的估算方法,矿工每次就会改变上述函数的哈希值结果。
那她们哪些时侯算“赢”呢?
一旦她们找到一个开头0的数目足够多的哈希值。
就是这样:开头有足够多的0。
这个答案就是这么简单而粗鲁,看上去并不高大上。而采矿估算的难度就取决于哈希值的开头须要多少个0。当第一个区块被开采下来时,它的哈希值开头只有8个0:
00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048
而在编撰本文时,该区块链估算下来的第629828个区块的哈希值,它开头有19个0:
0000000000000000000133e7bffe43530e508183ec48a89bad23a370692b16e8
而开头须要的0数目越多,就越难猜出这个随机数。
这儿多说一句,比特币这个算法的精致之处在于,它每隔2016个区块会手动重新估算其难度目标(即开头须要多少个0),但本文就不再因此赘言了。
采矿奖励
假如你猜对了这个随机数,你都会得到奖励。这些奖励以新浇铸下来的比特币的方式领取。
本质上,这种比特币是陡然形成的。只不过它既不实惠也不是信手拈来。比特币网路中采矿是要耗费大量估算能力和电量的。付出这种辛劳劳动后,你得到了比特币。为了维护巩固这个比特币网路,你作为一名矿工会得到理所应该的奖励。
这种新浇铸的比特币是在所谓的*生成交易(CoinbaseTransaction)*中创建的。这是一种奇特的交易,它包括在每位区块之中,其作用是支付一定数目的比特币奖励给猜中了正确哈希值的矿工。
是的,热门的“Coinbase加密货币交换所”的名子就来始于这个词汇,它本来是指每位区块中对矿工提供奖励的特殊交易(生成交易)的引用。
每一个被正确估算下来的区块,会手动估算出矿工奖励,并随着比特币网路的发展而兑奖励金额进行手动调整。它的工作原理也设计得非常巧妙,请让我来带你了解一下背后的代码。
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语言了linux桌面,但辛运的是,这段代码相当容易看懂。
已然发生过多少次比特币减半了?
让我们从底部开始看:
int halvings = nHeight / consensusParams.nSubsidyHalvingInterval;
前面最后一个共识参数consensusParams.nSubsidyHalvingInterval,在src/chainparms.cpp文件中被定义为共识规则的一部份。那些是比特币网路上每位人都必须遵循的一套公共规则。
这儿须要说明的是,对这种共识规则的任何修改都将创建一个“硬分叉(Hardfork)”,即一组不再遵守原始区块链规则的新政则。
consensus.nSubsidyHalvingInterval = 210000;
这个常量表示,每形成210,000个区块,才会出现一次比特币减半。其中变量nHeight指的是当前的区块高度(Height)。或则换句话说,早已开采下来的区块的数目。
而5月12日比特币开采数目就达到630,000个区块了。所以此时,这个方程就变为:
int halvings = 630000 / 210000;
这将使减半次数值变为3。这也是比特币网路第三次将其区块奖励减半。
而且假如结果是一个浮点值,其实这个结果并不符合该变量所申明的int类型,那会发生哪些事情呢?诸如:
int halvings = 630000 / 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的检测。这对于前面所贴的后续代码很重要。
最初的比特币核心代码并没有包含这个bug的修补,直至2014年才合并了这个pullrequest。
这部份常常被误会为“将会有64次比特币减半”。这并不正确。虽然只会有33次比特币减半,前面我们会听到关于这一点的解释。
你能得到多少比特币作为奖励?
“减半”一词虽然指的是对矿工可以获得的比特币数目进行限制。每采出210,000个区块比特币挖矿程序 linux,这个奖励金额都会减为一半。
CAmount nSubsidy = 50 * COIN;
nSubsidy >>= halvings;
return nSubsidy;
一开始,在10多年前,在网路上每开采出一个区块,都会奖励矿工50个比特币。
之后,在210,000个区块被开采过后,这个奖励金额被减半为25个比特币。又采出210,000个区块以后,弄成了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亿份比特币挖矿程序 linux,之后得到“1亿”份这样的基本单位作为奖励。
而这样1亿份基本单位加在一起等于1个比特币。
这给出了nSubsidy的初始值为50亿基本单位。假如用二补码来表示,可以得到如下数字:
100101010000001011111001000000000
nSubsidy>>=3表示将位右移3位。这就得到了:
100101010000001011111001000000
当你将该二补码值转换为其十补码表示方式时,会得到625,000,000。换句话说,这就是625,000,000个基本单位或6.25个比特币。
在下一次减半发生时,会随着右移一位让里面的二补码数值末尾的0又降低一个,因而有效地再度将奖励金额减半。
由于初始值50亿总共只有33比特位,我们将在第33比特减半后让区块奖励变为0红旗 linux,这大概会发生在2140年。
且这个假定的前提是,到哪个时侯,交易所支付的采矿奖励应当还足以补偿矿工的电力消耗和硬件成本。
推论
比特币的货币供应量通过硬编码进行了限制,每位人都可以见到和审查这段代码。
矿工数目庞大,虽然不是百万数目级,起码也是数以千计,能让如此多矿工能以和谐的形式一起工作的看法真的令人倍感不可思议。假如你当初尝试设置过任意一个包含5个节点的集群,你都会明白要在多个节点间达成共识或多数仲裁是多么困难的一件事情,由于你须要像比特币网路一样考虑到:
而在比特币网路上这一切都正常运转,并且是在硬件、网速、节点版本和软件均为未知的条件下运行的——这都是由于设计时所包含的物理原理和社会共识,让每位人在该网路上都遵守相同的规则。
这真是令人着迷的技术啊。
作者介绍:
MattiasGeniar,独立开发人员,Linux系统管理员和通用问题解决者。
原文链接:
关注我并转发此篇文章,私信我“领取资料”,即可免费获得InfoQ价值4999元迷你书!