Code snippet: How to manually validate a Bitcoin block?
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  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:
- version: The version number (Normally 2 but can differ in some cases)
- prev_block: The hash of the previous block
- merkle_root: A hash of the Merkle root
- date_time: Time in which the block is mined
- bits: A parameter related to difficulty level
- nonce**: **A random number generated as a part of mining the block
You can find these numbers easily in Blockchain.info 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(merkle_root)+ reverse(hex(epoch).split('x')[-1]) + reverse(hex(bits).split('x')[-1]) + reverse(hex(nonce).split('x')[-1])) header_bin = header_hex.decode('hex') hash = hashlib.sha256(hashlib.sha256(header_bin).digest()).digest() print hash[::-1].encode('hex_codec')