For testing purpose I am trying to verify a already mined block from the Bitcoin blockchain. I am using this block Block #814283
Below is my simple code in Python to check
import hashlib
version = 704782340
prevhash = "00000000000000000001686b4aa817800d902902537293d9a12d007d420bba23"
merkle_root = "0337fd9ace1c62516d36f60136ead2155d0163ac5de411905e21d77d375bf57a"
ntime = 1698524796
nbits = 386178217
nonce = 3003691568
expected_hash = "000000000000000000042ff1725b70b9d7a8ed199bdc852ee9cbfcaa01ad9039"
# Convert integers to little-endian hex strings
version_hex = format(version, '08x')
ntime_hex = format(ntime, '08x')
nbits_hex = format(nbits, '08x')
nonce_hex = format(nonce, '08x')
# Concatenate the fields and decode to bytes
block_header = bytes.fromhex(version_hex) + bytes.fromhex(prevhash) + bytes.fromhex(merkle_root) + bytes.fromhex(ntime_hex) + bytes.fromhex(nbits_hex) + bytes.fromhex(nonce_hex)
# Double SHA-256 hash the block header
first_hash = hashlib.sha256(block_header).digest()
second_hash = hashlib.sha256(first_hash).digest()
# Reverse the byte order for the hash
block_hash = second_hash[::-1].hex()
print( block_hash ) # prints f414c8e30b4a01ff0a29bed477e490dcf10bae439db4219f426c94d1479c4f0b which is wrong
I know I am doing a stupid wrong thing here, maybe the encoding are wrong. I am not sure what the version value is encoded in? Please do help me to understand. Happy Learning!
You need to convert prevhash
and merkle_root
to little-endian as well, i.e., reverse their byte order:
import hashlib
version = 704782340
prevhash = "00000000000000000001686b4aa817800d902902537293d9a12d007d420bba23"
merkle_root = "0337fd9ace1c62516d36f60136ead2155d0163ac5de411905e21d77d375bf57a"
ntime = 1698524796
nbits = 386178217
nonce = 3003691568
expected_hash = "000000000000000000042ff1725b70b9d7a8ed199bdc852ee9cbfcaa01ad9039"
# Convert to little-endian format where necessary
version_bytes = version.to_bytes(4, 'little')
prevhash_bytes = bytes.fromhex(prevhash)[::-1]
merkle_root_bytes = bytes.fromhex(merkle_root)[::-1]
ntime_bytes = ntime.to_bytes(4, 'little')
nbits_bytes = nbits.to_bytes(4, 'little')
nonce_bytes = nonce.to_bytes(4, 'little')
# Create the block header
block_header = version_bytes + prevhash_bytes + merkle_root_bytes + ntime_bytes + nbits_bytes + nonce_bytes
# Double SHA-256 hash the block header
first_hash = hashlib.sha256(block_header).digest()
second_hash = hashlib.sha256(first_hash).digest()
# Reverse the byte order for the hash
block_hash = second_hash[::-1].hex()
print(f'{block_hash = }')
print(f'{expected_hash == block_hash = }')
Output:
block_hash = '000000000000000000042ff1725b70b9d7a8ed199bdc852ee9cbfcaa01ad9039'
expected_hash == block_hash = True