How To Calculate and Verify a Hash Of a Block
A blockchain is a chain of individual blocks where every block consists of header and body. The body is the list of all transaction done by the creator of the block while the header consists of the identification details used to prove the validity of the block and transaction. The header of each block comprises the following six parameters used to create the hash of the block:
- Version: use to create the block, gives a new version once the software is updated. It has 4 x bytes.
- HashPrevBlock: hash of the previous block. It has 32 x bytes = 32 x 8 = 256 bits
- MerkleRoot: hash based on all the transaction in the block having 256-bits.
- Time: Block creation time / current block timestamp and has 32- bits.
- Bits: difficulty of block hash with 32-bits.
- Nonce: 32-bit number starts with 0 to try hash.
With the above parameters a user can verify, if a block is valid.
The input values need to be in little endian hexadecimal format. So, when taking the values from a block explorer we might have to convert them form decimal to hexadecimal (usually big endian) and subsequently into little endian.
In order to calculate the block hash we take three steps:
- Receive and transform input values
- Concatenate the values
- Double SHA256 and transform to little endian
Step 1: Receive Input values and transform them into little endian hexadecimal
In our example we consider the block 200000 and construct the hash from the information given below. We got the details from the block explorer btc.com.
- Define block header fields:
PrevHash: 00000000000003a20def7a05a77361b9657ff954b2f2080e135ea6f5970da215
MerkleRoot: a08f8101f50fd9c9b3e5252aff4c1c1bd668f878fffaf3d0dbddeb029c307e88
Timestamp: UTC 2012-09-22 12:45:59 = 1348310759
Use https://www.epochconverter.com/#tools for time conversion from local to epoch format.
Bits: 1a05db8b
Nonce: f7d8d840
Note: Some block explorers cut off the seconds in their timestamp. But they are necessary. If leaving them out, we get a wrong result.
- Convert parameters into hexadecimal:
PrevHash: 0x000000000 00003a20def7a05a77361b9657ff954b2f2080e135ea6f5970da215
MerkleRoot: 0xa08f8101f50fd9c9b3e5252aff4c1c1bd668f878fffaf3d0dbddeb029c307e88
Timestamp: 0x505d96e7
Bits: 0x1a05db8b
Nonce: 0xf7d8d840
- Convert into little-endian hex:
Little endian hex means that the least significant byte is on the left side. The following figure makes it clear. In hex a byte consists of two digits.
Version: 0x02000000
PrevHash: 0x15a20d97f5a65e130e08f2b254f97f65b96173a7057aef0da203000000000000
MerkleRoot: 0x887e309c02ebdddbd0f3faff78f868d61b1c4cff2a25e5b3c9d90ff501818fa0
Timestamp: 0xe7965d50
Bits: 0x8bdb051a Nonce: 0x40d8d8f7
Step 2: Concatenate inputs
Now, we concatenate (||) all components into single hex string.
The order is: version || PrevHash || MerkleRoot || Timestamp || Bits || Nonce
“02000000” + “15a20d97f5a65e130e08f2b254f97f65b96173a7057aef0da203000000000000” + “887e309c02ebdddbd0f3faff78f868d61b1c4cff2a25e5b3c9d90ff501818fa0” + “e7965d50” + “8bdb051a” + “40d8d8f7” then we have:
0200000015a20d97f5a65e130e08f2b254f97f65b96173a7057aef0da203000000000000887e309c02ebdddbd0f3faff78f868d61b1c4cff2a25e5b3c9d90ff501818fa0e7965d508bdb051a40d8d8f7
Step 3: Apply Double SHA-256
Here, we take the hex value of step two and apply the SHA-256 twice.
- Applying SHA-256 on the first hex to find the first hash yields:
d20176bc6e0b0a904efdfe257b8a50143cd6e3d4f2a154460d7d3a770b9847c4
- Applying SHA-256 on first hash to find the second hash yields:
bf0e2e13fce62f3a5f15903a177ad6a258a01f164aefed7d4a03000000000000
Note: When hashing the concatenated inputs, remember to use hex as input format. Some hash calculators only consider the input as string instead. This will result in a wrong output.
We use this calculator. Here you can state whether the input is in hex or string.
Hashcalculator
There are also other calculators available:
https://emn178.github.io/online-tools/sha256.html
To verify the bloc hash, you can use this tool:
Bitcoin Hash Validation
Step 0: Enter Parameters
Alternatively enter a Block number in the filed above and click the Calculate Button to automatically get the necessary values.
Step 1: Convert to Hexadecimal values
Step 2: Convert into Little-Endian
Step 3: Concatenate Values
Order = version || PrevHash || MerkleRoot || Timestamp || Bits || Nonce
Step 4: Double SHA-256 Application
Step 5: Convert SHA-256 Result in Little Endian
[1] https://cse.buffalo.edu/blockchain/blockhash.html
[2] https://www.rapidtables.com/convert/num
- Convert hash into little-endian hex:
import hashlib
import codecs #library to encode and decode from hex to string and string to hex
def littleEndian(string):
splited = [str(string)[i:i + 2] for i in range(0, len(str(string)), 2)]
splited.reverse()
return "".join(splited)
header_hex = ("02000000" +
"15a20d97f5a65e130e08f2b254f97f65b96173a7057aef0da203000000000000" +
"887e309c02ebdddbd0f3faff78f868d61b1c4cff2a25e5b3c9d90ff501818fa0" +
"e7965d50" +
"8bdb051a" +
"40d8d8f7")
header_bin = codecs.decode(header_hex, 'hex') #First decode string data to real hex value
hash = hashlib.sha256(header_bin).digest() #Calculate the first hash
print ("First Hash => ", codecs.encode(hash, 'hex_codec').decode('ascii'))
First Hash => d20176bc6e0b0a904efdfe257b8a50143cd6e3d4f2a154460d7d3a770b9847c4
hash = hashlib.sha256(hash).digest() #Calculate second hash on the first hash
print ("Second Hash => ", codecs.encode(hash, 'hex_codec').decode('ascii'))
Second Hash => bf0e2e13fce62f3a5f15903a177ad6a258a01f164aefed7d4a03000000000000
hash = codecs.encode(hash, 'hex_codec').decode('ascii') #Convert data back to the string value
littleEndian(hash)
Output: '000000000000034a7dedef4a161fa058a2d67a173a90155f3a2fe6fc132e0ebf'