Dissecting the code responsible for the Bitcoin halving

栏目: IT技术 · 发布时间: 4年前

内容简介:In a few hours, the Bitcoin network will experience its third “halving”. So what is it and how does it work under the hood?Let’s deep-dive into the nitty-gritty details. The fun stuff.A quick recap:

In a few hours, the Bitcoin network will experience its third “halving”. So what is it and how does it work under the hood?

Let’s deep-dive into the nitty-gritty details. The fun stuff.

Block subsidy and reward halving

A quick recap: miners all around the world are, at this very moment, running hardware and software to calculate the hash of the next Bitcoin block.

If they manage to solve the mathematical puzzle in time, they can claim the block reward .

That’s a lot of buzzwords right there, isn’t it? Let’s break it down.

What’s a hash?

The whole concept of mining is extremely clever. There isn’t actually a puzzle to solve, it’s more of a brute force attempt at trying to guess a magic number.

The Bitcoin network uses SHA256 hashes pretty much everywhere. In a simplified version, miners all around the world are trying to run this function:

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

The $magicNumber is also called a nonce , a Number Used Once . By including the previous blocks’ hash in the new hash calculation, an actual chain is formed linking each block to the new one. A blockchain is essentially a linked list on steroids.

Miners are in the process of guessing the value of $magicNumber . They run the very same calculations over and over again, incrementing (or randomizing) the $magicNumber value. By doing so, they change the outcome of the function every time.

When do they “win”?

Once they find a hash with a sufficient number of zeroes at the beginning.

That’s right: sufficient zeroes .

It’s so simple it’s almost stupid. The difficulty of the calculations are determined by how many zeroes need to be at the front. When the very first block was mined , it only had 8 zeroes at the front:

00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048

When, at the time of writing, the last hash was calculated, it had 19 zeroes at the front.

0000000000000000000133e7bffe43530e508183ec48a89bad23a370692b16e8

The more zeroes are needed at the front, the more difficult it becomes to guess that magic number .

Sidenote: the brilliance of this algorithm is actually in the way it automatically re-calculates its difficulty target (aka: how many zeroes are needed) every 2016 blocks, but that’s for another write-up.

The reward

If you guess the number correctly, you get a reward. That reward comes in the form of newly minted Bitcoins.

These are Bitcoins that are essentially created out of thin air . Except it’s neither thin nor air. Effort was put into the network in the form of computational power and energy. As a result, you get Bitcoin. As a miner, your reward is the result for securing the network.

These newly created Bitcoin are created in what is called a Coinbase Transaction . This is a unique transaction, included in every block, that pays a certain amount of Bitcoin to the miner that guessed the correct hash.

(Yes, that’s probably where the popular cryptocurrency Exchange “Coinbase” got its name from, a reference to the miner reward transaction.)

The reward for each correct block is calculated automatically and auto-adjusts as the bitcoin network marches on. The way this works is quite beautiful, and I’d love to take you on a trip through the code.

The GetBlockSubsidy() function

The magic of the reward halving lies in function GetBlockSubsidy() , located in src/validation.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)
        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;
}

So, what’s in there? Let’s break it down. It’s been a while since I wrote C, but lucky for us it’s fairly readable.

How many halvings have there already been?

Let’s start at the top:

int halvings = nHeight / consensusParams.nSubsidyHalvingInterval;

The last parameter, consensusParams.nSubsidyHalvingInterval , is defined in src/chainparams.cpp as part of the consensus rules . These are a set of rules everyone on the bitcoin network needs to honour.

Sidenote: any change on these consensus rules would create a “hard fork”, a new set of rules that no longer follow the original chain.

consensus.nSubsidyHalvingInterval = 210000;

Every 210,000 blocks, a halving occurs.

The nHeight refers to the current block “height”. Or, put differently, the number of blocks that have already happened.

Soon, we’ll reach block 630,000. At that point, the equation becomes:

int halvings = 630000 / 210000;

Which will give halvings a value of 3. This will be the third time the network has halved its block reward.

But what happens if there’s a floating point result value, clearly that doesn’t fit in an int variable?

int halvings = 620000 / 210000;

This would result in 2.952380952. However, since the variable is defined as an integer, it is rounded to the lowest integer value by dropping the fractional. Then, halving becomes 2.

The end of block rewards

Let’s take a look at this bit:

// Force block reward to zero when right shift is undefined.
if (halvings >= 64)
    return 0;
This is safety code for a condition I don’t quite understand: if, for some reason, consensusParams.nSubsidyHalvingInterval is too low or nHeight is very high, it would result in the variable halvings with a high value too. I don’t think this check matters, because of the code we’ll see lower down? Would love to know what race condition this is supposed to prevent.

Update: thanks to @niobos , I now know that the shift-by operand is masked. This is important for the code lower in this post, but it means that x >> 65 becomes x >> 1 , so the check for >= 64 needs to stay.

This part is often misinterpreted as “there will be 64 Bitcoin halvings”. That is incorrect. There will be 33 Bitcoin halvings, as we’ll see lower.

How many Bitcoin do you get as a reward?

The word “halving” refers to the process of limiting the amount of Bitcoin you can get as a miner. At every 210,000 blocks, that amount is cut in half .

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

At the very start, more than 10 years ago, 50 Bitcoin were rewarded for every block found on the network.

Then, after 210,000 blocks, that got cut in half to 25. Another 210,000 blocks later, that became 12.5. That’s where we are today.

In a few hours, it’ll be cut in half again, and only 6.25 Bitcoins are rewarded to the miner. Fast-forward another 210,000 blocks and that becomes 3.125. And so on.

There’s a clever bitwise operation going on in that code that I want to highlight:

nSubsidy >>= halvings;

It’s not every day you see a >>= operator in your code.

Let’s rewrite that code with the filled in values for each variable:

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

The block rewards have a fixed start value at 50. Each coin can be divided into 100,000,000 units, defined in src/amount.h . If we want to be correct, a miner doesn’t get “a Bitcoin” as a reward, it gets “100,000,000” pieces of a Bitcoin as a reward.

A hundred million tiny pieces that form a single bitcoin.

This gives us an initial value of nSubsidy at 5,000,000,000 . If you write that in binary, you get

The nSubsidy >>= 3 means: shift the bits 3 places to the right. This leaves us with:

When you convert that binary value to its decimal representation, you get 625,000,000 . In other words: “625,000,000 mBTC” or “6.25 BTC”.

At the next halving, another zero gets cut at the end of the decimal representation, effectively halving the reward value once again.

Because there are only 33 bits in total, we will run out of block rewards to halve after the 33rd halving, roughly in 2140.

(It’s assumed that at that point, the transaction fees being paid should be sufficient to compensate the miner power consumption and hardware.)

In conclusion

Bitcoin’s monetary supply is hard-coded, for everyone to see and review.

The whole idea that a network of thousands, if not millions, of miners can work in harmony is mindblowing. If you’ve ever tried to set up a 5-node cluster of anything , you’ll know reaching consensus or quorum can be hard.

  • How do you get all your nodes to agree?
  • How do you prevent drift?
  • Or split brains?
  • Or dataloss?
  • What if one node crashes in the middle of a write operation?

This all just works on the Bitcoin network, operating on unknown hardware, on unknown internet speeds with unknown node versions and software - all because of math and the social consensus that everyone follows the same rules on the network.

Fascinating.


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

极简算法史:从数学到机器的故事

极简算法史:从数学到机器的故事

[法] 吕克•德•布拉班迪尔 / 任轶 / 人民邮电出版社 / 2019-1 / 39.00元

数学、逻辑学、计算机科学三大领域实属一家,彼此成就,彼此影响。从古希腊哲学到“无所不能”的计算机,数字、计算、推理这些貌似简单的概念在三千年里融汇、碰撞。如何将逻辑赋予数学意义?如何从简单运算走向复杂智慧?这背后充满了人类智慧的闪光:从柏拉图、莱布尼茨、罗素、香农到图灵都试图从数学公式中证明推理的合理性,缔造完美的思维体系。他们是凭天赋制胜,还是鲁莽地大胆一搏?本书描绘了一场人类探索数学、算法与逻......一起来看看 《极简算法史:从数学到机器的故事》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

URL 编码/解码
URL 编码/解码

URL 编码/解码

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试