區塊頭雜湊驗證
作為我正在處理的驗證服務的一部分,我需要能夠驗證是否正確創建了 blockHeader 雜湊。根據我的理解,以下是重新生成標頭雜湊的步驟,以及我在本練習中使用的相應腳本。
- 使用 web3 提供者作為 Infura 主網 api 密鑰
- 以塊號為輸入,從 中獲取值
eth.getBlock
,得到以下響應:{困難:‘6022643743806’,而額外:‘0xd583010202844765746885676f312e35856c696e7578’,gasLimit:3141592,gasUsed:0,散列:
‘0x5d15649e25d8f3e2c0374946078539d200710afc977cdfc6a977bd23f20fa8e8’,logsBloom:‘0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000’,礦工:‘0x2a65Aca4D5fC5B5C859090a6c34d164135398226’,混合雜湊:
‘0x3fbea7af642a4e20cd93a945a1f5e23bd72fc5261153e09102cf718980aeff38’,隨機數:“0x6af23caae95692ef’,編號:400000,parentHash:
‘0x1e77d8f1267348b516ebc4f4da1e2aa59f85f0cbd853949500ffac8bfc38ba14’,receiptsRoot:
‘0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421’,sha3Uncles:
‘0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347’,尺寸:539,stateRoot:
‘0x0b5e4386680f43c224c5c037efc0b645c8e1c3f6b30da0eec07272b4e6f8cd89’,時間戳:1445130204,totalDifficulty:‘2014130882275463845 ‘,交易:
$$ $$,transactionsRoot:
‘0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421’,叔叔:$$ $$}
- 這個想法是
hash
在這個響應中創建值,因為這是塊的標頭雜湊(我在這個假設中是對的嗎?)。根據文件 (https://github.com/ethereum/go-ethereum/blob/master/core/types/block.go
),我需要首先創建上述響應的 rlp。我的方法是:將響應輸入到一個嵌套列表中,並使用這個庫()生成一個 rlp 緩衝區,這https://github.com/ethereumjs/rlp
是結果
<Buffer f9 02 b7 d2 8a 64 69 66 66 69 63 75 6c 74 79 86 05 7a 41 8a 7c 3e e1 89 65 78 74 72 61 44 61 74 61 96 d5 83 01 02 02 84 47 65 74 68 85 67 6f 31 2e 35 ... 648 more bytes>
- 此時,我將上述步驟的輸出,計算出一個 keccak256 雜湊 (
https://github.com/ethereumjs/ethereumjs-util/tree/master/docs#keccak256
),這是結果
0xc5bad52524f562d2783ec20331af3780b8233c2d13b04de79acb4347804f7578
- 檢查上面第 4 步的輸出,並與
hash
第 2 步中的值進行比較。我測試的雜湊值不匹配有人能夠驗證上述步驟並提供有關如何重新創建 blockHeader 雜湊的指導嗎?建議?
下面是計算blockHash的步驟,給定一個blockNumber:
第1步。eth.getBlock(400000)
輸出:{難度:‘6022643743806’,而額外:‘0xd583010202844765746885676f312e35856c696e7578’,gasLimit:3141592,gasUsed:0,散列:‘0x5d15649e25d8f3e2c0374946078539d200710afc977cdfc6a977bd23f20fa8e8’,logsBloom:‘0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000’,礦工:‘0x2a65Aca4D5fC5B5C859090a6c34d164135398226’,mixHash:‘0x3fbea7af642a4e20cd93a945a1f5e23bd72fc5261153e09102cf718980aeff38’,隨機數:“0x6af23caae95692ef’,編號:400000,parentHash:‘0x1e77d8f1267348b516ebc4f4da1e2aa59f85f0cbd853949500ffac8bfc38ba14’,receiptsRoot:‘0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421’,sha3Uncles:‘0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347’,尺寸:539,stateRoot:‘0x0b5e4386680f43c224c5c037efc0b645c8e1c3f6b30da0eec07272b4e6f8cd89’,時間戳:1445130204,totalDifficulty:‘2014130882275463845” ,交易:0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421’,sha3Uncles:“0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347”,規格:539,stateRoot:“0x0b5e4386680f43c224c5c037efc0b645c8e1c3f6b30da0eec07272b4e6f8cd89’,時間戳:1445130204,totalDifficulty:”2014130882275463845“,交易方式:0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421’,sha3Uncles:“0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347”,規格:539,stateRoot:“0x0b5e4386680f43c224c5c037efc0b645c8e1c3f6b30da0eec07272b4e6f8cd89’,時間戳:1445130204,totalDifficulty:”2014130882275463845“,交易方式:
$$ $$,transactionsRoot:‘0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421’,叔叔:$$ $$}
上述對像中的雜湊是指我們要驗證的塊雜湊。這是稍後將用於比較測試結果的實際輸出。
第2步。從上面的對像中刪除一些元素,只保留那些作為 blockHeader 的輸入的元素,並將其重新排序如下:
$$ [‘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’ $$]
第三步。將帶有數字的值轉換為十六進制
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));
第4步。對於值為 0 的元素,使用 0x 而不是 0x0
範例:對於區塊 400000,gasUsed 的值為 0。因此,gasUsed 的值應為 0x 而不是 0x0
第五步。將數字更改為 Hex 並將值處理為 0 後,我們可以繼續刪除步驟 2 中列出的所有鍵並重組數組,如下所示:
$$ ‘0x1e77d8f1267348b516ebc4f4da1e2aa59f85f0cbd853949500ffac8bfc38ba14’, ‘0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347’, ‘0x2a65aca4d5fc5b5c859090a6c34d164135398226’, ‘0x0b5e4386680f43c224c5c037efc0b645c8e1c3f6b30da0eec07272b4e6f8cd89’, ‘0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421’, ‘0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421’, ‘0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000’, ‘0x57a418a7c3e’, ‘0x61a80’, ‘0x2fefd8’, ‘0x’, ‘0x5622efdc’, ‘0xd583010202844765746885676f312e35856c696e7578’, ‘0x3fbea7af642a4e20cd93a945a1f5e23bd72fc5261153e09102cf718980aeff38’, ‘0x6af23caae95692ef’ $$
第六步。上面的值數組現在可以輸入 rlp.encode 函式
輸出:0xf90213a01e77d8f1267348b516ebc4f4da1e2aa59f85f0cbd853949500ffac8bfc38ba14a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347942a65aca4d5fc5b5c859090a6c34d164135398226a00b5e4386680f43c224c5c037efc0b645c8e1c3f6b30da0eec07272b4e6f8cd89a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000086057a418a7c3e83061a80832fefd880845622efdc96d583010202844765746885676f312e35856c696e7578a03fbea7af642a4e20cd93a945a1f5e23bd72fc5261153e09102cf718980aeff38886af23caae95692ef
第七步。通過 keccak256 函式傳遞上述 RLP。下面是輸出:
測試輸出:0x5d15649e25d8f3e2c0374946078539d200710afc977cdfc6a977bd23f20fa8e8
實際輸出:0x5d15649e25d8f3e2c0374946078539d200710afc977cdfc6a977bd23f20fa8e8
結論:使用 eth.getBlock()。將它返回的對像作為輸出。刪除不需要的元素並僅保留那些作為 blockHeader 輸入的元素。將數字轉換為十六進制並處理帶有 0 的值。重組對像以形成字元串數組。將此數組傳遞給 rlp.encode 函式。獲取 rlp 輸出並對其應用 keccak256 雜湊。
連結:https ://github.com/ethereum/go-ethereum/blob/master/core/types/block.go#L69
這幾乎是正確的,但只需幾個細節即可使其發揮作用:
- 在倫敦分叉之後,必須考慮到 header 中的一個新欄位:
baseFeePerGas
. 這應該是欄位標題列表中的最後一個欄位。- 必須將十六進制數據轉換為十六進製字節狀數據。這僅意味著它必須具有奇數大小才能使 RLP 編碼起作用。例如
0xa
應該轉換為0x0a
,否則 RLP 編碼會失敗,因為它需要類似字節的輸入。就我而言,考慮到這一點後,我能夠在 ETH 主網中正確地重新計算塊頭雜湊。
對 Rinkeby 上的測試程式碼的一個建議是:目前這個測試網中存在一個錯誤,它保存了錯誤的標頭編號。更多資訊在這里和這裡。由於此錯誤,此過程將無法在此網路中執行。