Below are the steps to calculate blockHash, given a blockNumber:
Step1. eth.getBlock(400000)
Output:{ difficulty: '6022643743806', extraData: '0xd583010202844765746885676f312e35856c696e7578', gasLimit: 3141592, gasUsed: 0, hash:
'0x5d15649e25d8f3e2c0374946078539d200710afc977cdfc6a977bd23f20fa8e8', logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', miner: '0x2a65Aca4D5fC5B5C859090a6c34d164135398226', mixHash:
'0x3fbea7af642a4e20cd93a945a1f5e23bd72fc5261153e09102cf718980aeff38', nonce: '0x6af23caae95692ef', number: 400000, parentHash:
'0x1e77d8f1267348b516ebc4f4da1e2aa59f85f0cbd853949500ffac8bfc38ba14', receiptsRoot:
'0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421', sha3Uncles:
'0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347', size: 539, stateRoot:
'0x0b5e4386680f43c224c5c037efc0b645c8e1c3f6b30da0eec07272b4e6f8cd89', timestamp: 1445130204, totalDifficulty: '2014130882275463845', transactions: [], transactionsRoot:
'0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421', uncles: [] }
Hash in the above object refers to the blockHash which we are trying to validate. This is the actual output which will be used later to compare the test results with.
Step2. Remove some of the elements from the above object, keep only those that are inputs into a blockHeader, and reorder it as below:
[['ParentHash','0x1e77d8f1267348b516ebc4f4da1e2aa59f85f0cbd853949500ffac8bfc38ba14'],
['UncleHash','0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347'],
['Coinbase','0x2a65Aca4D5fC5B5C859090a6c34d164135398226'],
['Root','0x0b5e4386680f43c224c5c037efc0b645c8e1c3f6b30da0eec07272b4e6f8cd89'],
['TxHash','0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421'],
['ReceiptHash','0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421'],
['Bloom','0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'],
['Difficulty',6022643743806],
['Number','0x400000'],
['GasLimit',3141592],
['GasUsed',0],
['Time',1445130204],
['Extra','0xd583010202844765746885676f312e35856c696e7578'],
['MixDigest','0x3fbea7af642a4e20cd93a945a1f5e23bd72fc5261153e09102cf718980aeff38'],
['Nonce','0x6af23caae95692ef']]
Step3. Convert values with numbers to Hex
console.log(web3.utils.toHex(gasLimit));
console.log(web3.utils.toHex(gasUsed));
console.log(web3.utils.toHex(time));
console.log(web3.utils.toHex(difficulty));
console.log(web3.utils.toHex(number));
Step4. For elements with value as 0, use 0x and not 0x0
Example: for block 400000, the value for gasUsed is 0. So the value used for gasUsed should be 0x and not 0x0
Step5. After changing the numbers to Hex and handing values with 0, we can go ahead and remove all the keys listed in Step2 and restructure the array as below:
[ '0x1e77d8f1267348b516ebc4f4da1e2aa59f85f0cbd853949500ffac8bfc38ba14',
'0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347',
'0x2a65aca4d5fc5b5c859090a6c34d164135398226',
'0x0b5e4386680f43c224c5c037efc0b645c8e1c3f6b30da0eec07272b4e6f8cd89',
'0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
'0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
'0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
'0x57a418a7c3e',
'0x61a80',
'0x2fefd8',
'0x',
'0x5622efdc',
'0xd583010202844765746885676f312e35856c696e7578',
'0x3fbea7af642a4e20cd93a945a1f5e23bd72fc5261153e09102cf718980aeff38',
'0x6af23caae95692ef' ]
Step6. The above array of values can now be fed into a rlp.encode function
Output: 0xf90213a01e77d8f1267348b516ebc4f4da1e2aa59f85f0cbd853949500ffac8bfc38ba14a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347942a65aca4d5fc5b5c859090a6c34d164135398226a00b5e4386680f43c224c5c037efc0b645c8e1c3f6b30da0eec07272b4e6f8cd89a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000086057a418a7c3e83061a80832fefd880845622efdc96d583010202844765746885676f312e35856c696e7578a03fbea7af642a4e20cd93a945a1f5e23bd72fc5261153e09102cf718980aeff38886af23caae95692ef
Step7. Pass the above RLP through a keccak256 function. Below is the output:
TestOutput:
0x5d15649e25d8f3e2c0374946078539d200710afc977cdfc6a977bd23f20fa8e8
ActualOutput:
0x5d15649e25d8f3e2c0374946078539d200710afc977cdfc6a977bd23f20fa8e8
Conclusion: Use eth.getBlock().
Take the object it returns as output.
Remove unwanted elements and keep only those that are inputs to a blockHeader. Convert numbers to Hex and handle values with 0s.
Restructure the object to form an array of strings.
Pass this array into a rlp.encode function.
Take the rlp output and apply a keccak256 hash on it.
Links: https://github.com/ethereum/go-ethereum/blob/master/core/types/block.go#L69