Code snippet: How to manually validate a Bitcoin block?


2 min read

The other day, I was trying to understand how Bitcoin works. There are a lot of references that tell you some general description of the cryptocurrency, but a few of them get to the real details about the internals.

The blog post on [1] was really helpful, although it did not act as I wanted. After a little searching here and there, finally, I managed to prepare a Python code snippet you can use to manually make sure a Bitcoin block is valid.

This code represents the underlying design of a Bitcoin mining algorithm. Miners try with different arguments (most importantly, nonce) to come up with a hash result which starts with enough zeros.

Here is how you can use this code:

You need to provide six inputs to the code:

  1. version: The version number (Normally 2 but can differ in some cases)
  2. prev_block: The hash of the previous block
  3. merkle_root: A hash of the Merkle root
  4. date_time: Time in which the block is mined
  5. bits: A parameter related to difficulty level
  6. nonce**: **A random number generated as a part of mining the block

You can find these numbers easily in website for each block. If you replace their values inside below code, the result which is printed out should be equal to “Hash” parameter there.

This code snippet shows a block’s header is hashed to produce a hash value which if has a specific structure, will indicate the block is valid.

#Current values here are related to block number 474650
import hashlib, struct
import time

def reverse(a):
    return "".join(reversed([a[i:i+2] for i in range(0, len(a), 2)]))

version = "00000020"
prev_block = "0000000000000000012d11c46a420474875d0e3cfcdba19aac18df597fbb6d21"
merkle_root = "2f4f3f91ce5ffa9edcf728f9574f1e5ee1f97fe6142ee612da1db14f35f0d2db"
date_time = '07.07.2017 15:22:06' 
bits = 402754864
nonce = 999740600

pattern = '%d.%m.%Y %H:%M:%S'
epoch = int(time.mktime(time.strptime(date_time, pattern)))

header_hex = (version +
reverse(prev_block) +
reverse(hex(epoch).split('x')[-1]) +
reverse(hex(bits).split('x')[-1]) +

header_bin = header_hex.decode('hex')
hash = hashlib.sha256(hashlib.sha256(header_bin).digest()).digest()

print hash[::-1].encode('hex_codec')