How do I actually validate a bitcoin block's hash

EDIT: Without a node and only in windows

My assumption is that I can download a block, it's time stamp and the entire list of TXs and use comand line to hash it using sha256 algorithm and get the same 0000... hash thats on any explorer.

I checked blockchain com, mempool.space and a few other online blockchain viewers but I'm strugling to actualy find clean csv or smth to download that I could use for hashing.

Googling gives me some basic 101 on tx verification but not specifically what I need. Any one can guide me to the right direction?

I just want to ceck one hash out of curiosity.

Posted Apr 24, 2023, 7:25 PM UTC · edited

215
cookmanager•

I can point you to an excel spreadsheet that does it but not command line, especially if you want to re-hash all the transactions in the merkle tree.

2
basic_user321OP•

Okay. Then at least how do I get the spreadsheet that I could use for hashing?

1
cookmanager•
2
igadjeed•

I'm strugling to actualy find clean csv or smth to download that I could use for hashing

You could run your own node

As for the question, you've made a bad assumption. Hashing is not applied to the entire block, only the 80-byte header
https://developer.bitcoin.org/reference/block_chain.html#block-headers

Example

bitcoin-cli getblockheader 00000000000000000000afea9db33b1b1129d88d675f1d31105e43902edae986 false

.

00e0002020b3163bcb8ddb615ca91d44b7880a2bd39fa0317ce101000000000000000000a213fde43097b1878f2da89a380a4595a8727e5e286afc0bff2797ede0ff37ba7b42476439c70517c7f1d516

.

echo 00e0002020b3163bcb8ddb615ca91d44b7880a2bd39fa0317ce101000000000000000000a213fde43097b1878f2da89a380a4595a8727e5e286afc0bff2797ede0ff37ba7b42476439c70517c7f1d516|\
xxd -r -p|                                        # convert hexadecimal to binary \
openssl sha256 -binary|openssl sha256 -binary|    # double sha256 \
perl -e 'my $header_hash = do { local $/; <> };printf "%*v02x\n", "", scalar reverse $header_hash'
                                                  # reverse byte order and convert to hexadecimal for viewing

.

00000000000000000000afea9db33b1b1129d88d675f1d31105e43902edae986
1
[deleted]•

[deleted]

1
basic_user321OP•

Thanks for this info but a bit of context would be nice for some of the code here.

Should this be entered in bitcoin core's command line to extract the block data or somewhere else?

You could run your own node

Does running a node give clean block data that could be manualy hashed in command line?

you've made a bad assumption. Hashing is not applied to the entire block, only the 80-byte header

Something is incorrect here. Doesn't this leave room for man in the middle attack that could be used to overtake a broadcasted hash and stealing the block reward? I was under the impression that the whole block is hashed, which includes the miners' address and spoofing the block, changing the address would make the a new hash which would be invalid.

1
igadjeed•

Should this be entered in bitcoin core's command line

Linux command line

You could use the Core console, but you would have to pythonize the commands first

Does running a node give clean block data that could be manualy hashed in command line?

Each Core RPC endpoint can return data in JSON format, sometimes with a hexadecimal option

The bitcoin-cli command is a means of sending RPC requests to the node

Doesn't this leave room for man in the middle attack that could be used to overtake a broadcasted hash and stealing the block reward?

No, and that's not relevant to the question you asked
Did you actually follow the link to the developer page?

a broadcasted hash

The hash is not broadcasted. The entire block is

I was under the impression that the whole block is hashed

Now you know you're wrong

Don't make assumptions. Do some research
https://github.com/bitcoinbook/bitcoinbook/blob/develop/ch10.asciidoc

changing the address would make the a new hash which would be invalid

Indirectly

One of the six fields in the block header is the Merkle root hash. Read the Antonopoulos book to understand the relationship between the transactions and the Merkle tree

You asked about calculating the block hash, which is a double-sha256 hash of the 80-byte block header
Did you really mean to ask a different question?

1
basic_user321OP•

No, and that's not relevant to the question you asked Did you actually follow the link to the developer page?

Something you said seemed to relate to a previous post I made, it had some people say that all info in the block is actually hashed which made sense to me. here

You asked about calculating the block hash, which is a double-sha256 hash of the 80-byte block header Did you really mean to ask a different question?

One of the things that seemed obvious to me was to get a blocks hex data(honestly:whatever that is) I used this link that I found: blockchain.info/rawblock/1?format=hex This points to block 1(arbitrary example block since its small and hashes quickly on my pc)

Used that data to convert it to binary with an online converter.

And then used both comand line script and also power shells get-filehash to get the hash.

Neither returned correct hashes that are on a blockchain viewer for block 1

Anyway, I folowed your link. So the merkles are included instead of actual TXs. But this does not quite help me to get correct data and format of the block the use certufil -hashfile or get-filehash and get the correct sha256hash.

I guess I'll just use your commands for linux if I ever manage to get some separate hardware to setup a node to get the block data for hashing in cmd.

I was hoping this would be easier and possible in windows. I have even had windows return different sha256 hashes for the same data compared to linux sha256 hashes when I was testing something else a while back. So maybe windows is also the problem.

1
igadjeed•

https://www.reddit.com/r/Bitcoin/comments/12trudz/is_a_mqn_in_the_middle_attack_possible_for_a/jhdmfp2/

It is not possible to change the reward address without changing the hash. When the hash changes, the block becomes invalid

In more detail ...

Change the reward address. This changes the txID hash of the coinbase transaction. In turn, this changes all the hashes in the left-most branch of the Merkle tree, and changes the Merkle root hash. The Merkle root hash is one of the six fields in the 80-byte block header

The miner has spent 10 minutes hashing this 80 bytes at a rate of more than 100 trillion hashes per second, making a small change each time, competing with more than 2 million other miners

The hash of the winning miner's block is smaller than the current target hash (one of the six block header fields). If the Merkle root hash changes now, then the block header now has a different hash. The new block header hash is bigger than the target. The block is no longer a winner

maybe windows is also the problem

No, the only problem is you. You're told to hash the 80-byte header twice, and you choose to hash the entire block once. If you ignore what you're told, you're always going to get the wrong answer. There's even a proverb for what you're doing, Insanity is repeating the same mistakes and expecting different results

this does not quite help me to get correct data and format of the block

Just a beginner, huh?

Things to learn ...

  • how to extract the first 80 bytes of a Bitcoin block

  • how to convert hexadecimal to binary before hashing

  • how to get a 256-bit binary hash from the hashing utility (I don't use certutil, not sure if there's an option), or convert hexadecimal to binary before the second hash calculation

  • how to reverse the byte order of the second hash (this is a Bitcoin quirk). You don't really need to do this, if you can eye check the calculated hash in reverse byte order compared to the expected hash. Remember there are two hexadecimal digits in a byte

Stop using trashy block explorers. The API feature at blockstream.info will give you the hexadecimal strings you want

You like block #1?

https://blockstream.info/block-height/1
auto-redirects to
https://blockstream.info/block/00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048

API instructions: https://github.com/Blockstream/esplora/blob/master/API.md

GET /block/:hash

like so
https://blockstream.info/api/block/00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048

GET /block/:hash/header

https://blockstream.info/api/block/00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048/header

Well, look there. It's the 80-byte header, served on a hexadecimal platter, waiting to be converted to binary and hashed

A bit slower than last time ...

xxd -p -r <<<'010000006fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000982051fd1e4ba744bbbe680e1fee14677ba1a3c3540bf7b1cdb606e857233e0e61bc6649ffff001d01e36299'|
openssl sha256

.

(stdin)= a76dd73790def7b57776f22fa211d19cf43121a709a37eaeda17230eaac258f5

That's the first hash, in hexadecimal. Convert it to binary and hash again

xxd -p -r <<<'a76dd73790def7b57776f22fa211d19cf43121a709a37eaeda17230eaac258f5'|
openssl sha256

.

(stdin)= 4860eb18bf1b1620e37e9490fc8a427514416fd75159ab86688e9a8300000000

Do you think this is the reverse byte order of the expected hash?

00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048
4860eb18bf1b1620e37e9490fc8a427514416fd75159ab86688e9a8300000000

Reverse it anyway

fold -w2 <<<'4860eb18bf1b1620e37e9490fc8a427514416fd75159ab86688e9a8300000000'|
tac|tr -d '\n'

.

00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048

Compare

00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048
00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048

#OK?

2
basic_user321OP•

I wonder why is this down voted. Manually verifying a block should be a highly encouraged action and not only left to a client software that isn't quite clear what is happening under the hood. For non programers but still tech savy people like me, this method seems reliable but still very difficult to accomplish.

1