How To Calculate and Verify a Hash Of a Block

Published by Mario Oettler on

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:

  1. Version: use to create the block, gives a new version once the software is updated. It has 4 x bytes.
  2. HashPrevBlock: hash of the previous block. It has 32 x bytes = 32 x 8 = 256 bits
  3. MerkleRoot: hash based on all the transaction in the block having 256-bits.
  4. Time: Block creation time / current block timestamp and has 32- bits.
  5. Bits: difficulty of block hash with 32-bits.
  6. 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:

  1. Receive and transform input values
  2. Concatenate the values
  3. 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:

       Version: 2

        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:

       Version: 0x00000002

        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
In the initial step it is necessary to get the required Parameters for the verification of the block hash. Visit a block explorer like: blockchain.com or btc.com
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
The Values from Step 0 need to be converted into hexadecimal form. The "Calculate Values" button below can make that automatically.
Step 2: Convert into Little-Endian
The Values from Step 1 need to be converted into Little-Endian format. The "Calculate Values" button below can make that automatically.
Step 3: Concatenate Values
The Values from Step 2 need to be concatenated together. The "Calculate Value" button below can make that automatically.
Order = version || PrevHash || MerkleRoot || Timestamp || Bits || Nonce
Step 4: Double SHA-256 Application
Next apply twice the Sha256 Hash to the Value from Step 3. The "Calculate Value" button below can make that automatically.
Step 5: Convert SHA-256 Result in Little Endian
In the last step change to encoding of the value from Step 4 to Little-Endian the Result should equal the Block hash. The "Get Result" button below can make that automatically.

[1] https://cse.buffalo.edu/blockchain/blockhash.html

[2] https://www.rapidtables.com/convert/num

ber/decimal-to-hex.html

  • 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'
Categories:

if()