Looking for insights on proof of work from a miner's viewpoint

6 replies 38 views
im_altSenior Member
Posts: 130 · Reputation: 817
#1Jul 15, 2025, 03:07 AM
I've recently started to take a closer look at mining, something I pretty much overlooked until now. Got a bunch of thoughts after digging into it, and I'm hoping to get some clarity on a few things: - I’m struggling to understand how the SHA-256 hashing function fits into Bitcoin’s proof of work. Why is it so easy to check but tough to find a valid nonce? - I'm also curious about the merkle root's role in the block header. How does it help verify if transactions are included in a block? - Can miners change their block header while mining? Is that a thing? - Finally, I'd love a simple run-through of how Bitcoin's difficulty adjustment works. How's the new difficulty set after every 2016 blocks, and what block time does it aim to achieve?
2 Reply Quote Share
byte2019Senior Member
Posts: 270 · Reputation: 1836
#2Jul 16, 2025, 06:11 AM
The easiest way to figure it out, is to write any implementation of SHA-256 in any programming language. It would take at most few hundreds lines of code, probably less. And then, you will observe exactly, how a given message is turned into its hash. Some example implementation, where some empty message is hashed: https://github.com/stwenhao/small_curves/blob/master/sha256.cpp If you don't have any C++ compiler, you can run it online, for example here: https://www.onlinegdb.com/online_c++_compiler Example online calculator with SHA-256: https://emn178.github.io/online-tools/sha256.html Step-by-step calculator: https://sha256algorithm.com/ This is how the block header looks like: https://mempool.space/api/block/000000000000000000001de7b0cafc932a6e092f2160aeb3ba9a9602b0e3c394/header When you have merkle root, then it is just some 256-bit field. It is calculated once, and then, miners can change version, timestamp, and nonce, while leaving everything else as it is. And then, it doesn't matter, if your block takes 1 kB, or 1 MB: you still hash exactly the same 80-byte block header, every time. However, if there would be no merkle root, and if you would need to hash the whole block, then, suddenly, mining 1 MB block would be slower, than mining 1 kB block. And then, miners would have an incentive, to make blocks as empty, as they could be. But fortunately, it is not the case. Miners have to do that. You need to change something, to make a different hash. This is why nonce is needed in the first place. Early miners changed only their nonces, and when they checked all 2^32 possible values, and didn't find a valid block, then they changed the extra nonce in the coinbase transaction. Later, it turned out, that changing the block version, or the timestamp, is faster than that. Which is why miners started doing it. Because changing the merkle root is expensive: you need to calculate SHA-256 once again, for a different data. While flipping a bit in the block header directly, is much faster. It is simply measured, how much time it took, to produce the last 2016 blocks. It should take two weeks. If it took longer, then the difficulty goes down, if it was done faster, then it goes up. https://github.com/bitcoin/bitcoin/blob/master/src/pow.cpp#L14 There is a function "GetNextWorkRequired", which just counts, how long it took to mine the last 2016 blocks, and adjusts it.
3 Reply Quote Share
leo.wolfHero Member
Posts: 540 · Reputation: 2813
#3Jul 16, 2025, 09:31 AM
This is because nodes are taking the block data from the node that was able to compute the Nonce Let’s say you have all your transactions in a block, this transaction IDs (TXIDs) are hashed together in pairs  called merkle tree it until actually have a unique fingerprint for this transactions in the that block, this is now the Merkle root that is in the block header with other unique block contents. So the verification works in such a way that if all the transactions are actually hashed together then if one of the transactions is later removed or  another one is added  that  means a different hash result (merkle root) will be gotten  from the first transactions and this clears differs from what is in the Block header. And this clear shows that there is something wrong. Yes miners modify block headers during mining process to get a different hash example is modifying the nonce in  coinbase transaction (transaction which has the block reward), removing or adding transactions which modifies the merkle tree and subsequently the merkle root in the block header, the block time can still be modified for accuracy and all this changes the block header, but once the transaction is confirmed it cannot be modified. Just like the word difficulty itself, it’s how difficult it is for miners to actually find a new block, the average time is 10 minutes but it is not stagnant because of it is as new miners join it will take lesser time to mine blocks with more miners join. So the difficulty adjust after the 2016 block. It works like this, when 2016 block is mined the average time is for all this blocks let’s say 8 minutes is used to calculate the next difficulty First multiple the difficulty by 10 minutes ( the average time) =20160 Multiple the actually average time with the total blocks= 2016 x 8 = 16128 Dived the average difficulty by the actually difficulty in this period = 20160/16128= 1.25 It’s this 1.25 that’s now multiple by the difficulty to get the new difficulty for the next 2016 blocks before this process is actually done again
5 Reply Quote Share
paul.ninjaFull Member
Posts: 152 · Reputation: 539
#4Jul 17, 2025, 05:48 AM
Yes. They change the nonce first, but the nonce is only 32 bits, so modern miners exhaust that very quickly. After that they usually change the coinbase transaction through an extraNonce, which changes the Merkle root and gives them a fresh header search space. They can also adjust timestamp within consensus rules, choose a different transaction set, ordering, version bits, and so on. So the miner is not just staring at one frozen block forever like a confused goat. Every 2016 blocks, Bitcoin compares how long those blocks actually took versus the expected two weeks. If they came too fast, the target is lowered, making valid hashes harder to find. If they came too slow, the target is raised, making valid hashes easier to find.
0 Reply Quote Share
LuckyCoinLegendary
Posts: 832 · Reputation: 4795
#5Jul 19, 2025, 10:03 AM
To add to the other answers, the block header is 80 bytes, so there are a couple of combinations of fields which can be adjusted to get a different hash, not only the nonce. The only constants here is previous block hash, nbits, and possibly version (maybe miners can play around with different valid block versions, but I don't think any actually do this at the moment). It is actually an interesting science on how ASICs choose what values to hash in what order, and you can read about it on Bitcointalk here and here.
0 Reply Quote Share
byte2019Senior Member
Posts: 270 · Reputation: 1836
#6Jul 19, 2025, 02:07 PM
Of course they do. You can easily see that, if you compare some latest block headers: And there is even a proposal to allow them to use more bits, because they can use only some of them, as others are used to signal the support for some BIPs: https://groups.google.com/g/bitcoindev/c/fCfbi8hy-AE/m/WsFBoHXfAQAJ By the way: it shouldn't be surprising, if you see, how many zero bits are used. Nonce allows only 2^32 values. Current blocks have around 80 leading zero bits. So miners need to change something else, to mine their blocks fast. And changing fields in 80-byte block header is much faster, than for example updating merkle root, and hashing something with SHA-256 yet again.
5 Reply Quote Share
paul.stakeHero Member
Posts: 651 · Reputation: 3798
#7Jul 19, 2025, 03:42 PM
If I have a random message and I hash it, considering the hash function is a pseudo-random number generator like SHA256, the probability that the hash starts with five zeroes ("0x00000...") is 1 in 16^5. You can easily check that the message's hash starts with five zeroes, by just performing SHA256 once, but in order to find a message whose hash starts with five zeroes, you need to search around 16^5 hashes. Therefore finding a message whose hash is a valid Proof-of-Work is hard, but once you find it, it is easy for anyone to verify that you found it after searching. There is just no known way to find that message unless you perform that brutal search, and that's how it proves to any recipient that you worked for it.
0 Reply Quote Share

Related topics