pythonblockchainbitcoin

Bitcoin Mining : How to regenerate the hash of already mined bitcoin block


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!


Solution

  • 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