In order to prevent fraud, anyone wanting to add a block to the Bitcoin blockchain must prove that they’ve put in a certain amount of computational work. This post will focus on what problem must be solved in order produce proof of work.
You’ll see the proof of work function described as finding strings whose SHA256 hash value begins with a specified number of 0s. That’s sort of a zeroth-level approximation of the problem.
The string s you’re trying to find has the form data + nonce where the data comes from the block you’re wanting to add and the nonce is a value you concatenate on the end. You try different values until you get an acceptable hash value.
You’re not computing the SHA256(s) but rather the double hash:
SHA256²(s) = SHA256( (SHA256(s) )
The only way to find such a string s is by brute force [1], and applying the hash function twice doubles the amount of brute force work needed.
And you’re not exactly trying to produce leading zeros; you’re trying to produce a value less than a target T. This is roughly the same thing, but not quite.
To illustrate this, suppose you have a 2FA fob that generates six-digit random numbers. You’ve been asked to wait until your fob generates a number less than 2025. Waiting until you have three leading zeros would be sufficient, but that would be making the task harder than it needs to be. You’d be waiting for a number less than 1000 when you’re only asked to wait for a number less than 2025.
A SHA256 hash value is a 256-bit number. If your target T is a power of 2
T = 2256−n
then finding a value of s such that
SHA256²(s) < T
really is finding an s whose (double) hash begins with n zeros, though T is not required to be a power of 2.
Finding a value of s with
SHA256²(s) < 2256−n
will require, on average, testing 2n values of s.
The value of T is adjusted over time in order to keep the amount of necessary work roughly constant. As miners have become more efficient, the value of T has gone down and the amount of work has gone up. But the value of T can go up as well. It is currently fluctuating around 2176, i.e. hashes must have around 80 leading zero bits.
Now here’s where things get a little more complicated. I said at the beginning that the string s has the form
s = data + nonce
where the data comes from the block you’re trying to add and the nonce is a number you twiddle in order to get the desired hash value. But the nonce is a 32-bit integer. If you need to hash on the order of 280 strings in order to find one with 80 leading zeros, you can’t do that just by adjusting a 32-bit nonce.
In practice you’re going to have to twiddle the contents of what I’ve called data. The data contains a Merkle tree of transactions, and you can change the hash values by adjusting which transactions are included in addition to adjusting the nonce.
Related posts
- Computing hash functions
- Probability of secure hash collisions
- Base 58 encoding for addresses
- Elliptic curves in Bitcoin
[1] Unless someone finds a flaw in SHA256, which cryptographers have been trying to do for years and have not been able to do. And if a significant weakness is found in SHA256, it may not translate into a significant flaw in SHA256².
The post What is the Bitcoin proof-of-work problem? first appeared on John D. Cook.