-
Notifications
You must be signed in to change notification settings - Fork 542
Description
Description
I'm building an ethereum light-client, and one of the steps is verifying the block hash, however there's a mismatch between the block header returned by the RPC API and the actual header stored, as such I cannot recompute the block hash, preventing frontier from working with ethereum light-clients that relies on the RPC API.
After a investigation I realized this happens because of two issues:
- The block header stores the timestamp in milliseconds, while the API converts it to seconds: https://github.com/polkadot-evm/frontier/blob/pallet-evm-v5.0.0/client/rpc/src/eth.rs#L135
- The RPC API returns the
baseFeePerGasfield, but this field is not encoded in the header. EIP-1559 says this field MUST be part of the block header:
- https://github.com/paradigmxyz/reth/blob/v0.1.0-alpha.10/crates/primitives/src/header.rs#L88-L94
- https://eips.ethereum.org/EIPS/eip-1559
- The timestamp is important for TIMESTAMP opcode, a ethereum light-client relies on getting the contract state using
eth_createAccessListandeth_getProoffor executing the call locally, by returning the wrong timestamp the light-client and the real node will get different results.
Example, the eth_getBlockByNumber endpoint returns:
{
"author": "0xf02ddb48eda520c915c0dabadc70ba12d1b49ad2",
"baseFeePerGas": "0x1e4073dfbf",
"difficulty": "0x0",
"extraData": "0x",
"gasLimit": "0xe4e1c0",
"gasUsed": "0x4e6b11",
"hash": "0x84471574a6645fe3c4ea4fa7fb588f53f8cea681dd92d27d2de7c23f3040a7aa",
"logsBloom": "0x825080001000080802020000108400509000410406003440c08000402084300000021000910005c000300400022000004b000000210228020008001c31208000000008418c21101800082008c04880020408240008008c008200400ac22010448401040002820001000000080000080002030000020180030000001480988003240082802888080802200164000010208024040b0810a0004041208004200060224000400200040002b20b0409016048a1020080100210102001f12c40000ac0880144020048000603280802800014210400001001240001018022008400a100001908900000830420000018000260000800000640001040004600012c000060",
"miner": "0xf02ddb48eda520c915c0dabadc70ba12d1b49ad2",
"nonce": "0x0000000000000000",
"number": "0x4a1dbd",
"parentHash": "0x93434fec7bb917a3fdf071d43e6bda1061eab7c4d5663192ad88353925b49849",
"receiptsRoot": "0x088e158e77aa12898ed02e3ec20f030cd18054cd56890ad56a78a7ffadd4f5f3",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"size": "0x11f8",
"stateRoot": "0xa7b30b5144ee34730d42b8ea7b5f240d830190ad83b098ddce0e89978ea1055a",
"timestamp": "0x6551a2be",
"totalDifficulty": "0x0",
"transactions": [
"0xc42bbbe43ffbaa15c3f6fdd335eba12adf37520313d15b5496e77a67fbd35b1d",
"0x3df5b3ddaab690c68ed9e94cc086f210555d8ecc39c34aad292e8bd623b827d7",
"0xf708668e3002ec8a079e803e041091d8d5f2a7c3161a75c5c40592c18a9c67d2",
"0x5411f16773adac1f407d0161d3a0627fece66479e244d040d856e065794d4f04",
"0x0ba4819248cd220f1beb3f72482ef15f14121d7ab28d2deab0656452945db38b",
"0x9e01fd45eedbdf68665531dc9795f97c7a130b6bfbe633095b92f94a21c96adb",
"0xe227e458184c315517ea2c926d6505a6d53528d86acc1b29758f7c85e42a9821"
],
"transactionsRoot": "0xa34082f12ca71f5b7111e910ed9fb1350e5692a09456a37edc791f055e0603e5",
"uncles": []
}But for correctly represent the block header, it should omit the baseFeePerGas and return the correct timestamp:
{
"author": "0xf02ddb48eda520c915c0dabadc70ba12d1b49ad2",
"difficulty": "0x0",
"extraData": "0x",
"gasLimit": "0xe4e1c0",
"gasUsed": "0x4e6b11",
"hash": "0x84471574a6645fe3c4ea4fa7fb588f53f8cea681dd92d27d2de7c23f3040a7aa",
"logsBloom": "0x825080001000080802020000108400509000410406003440c08000402084300000021000910005c000300400022000004b000000210228020008001c31208000000008418c21101800082008c04880020408240008008c008200400ac22010448401040002820001000000080000080002030000020180030000001480988003240082802888080802200164000010208024040b0810a0004041208004200060224000400200040002b20b0409016048a1020080100210102001f12c40000ac0880144020048000603280802800014210400001001240001018022008400a100001908900000830420000018000260000800000640001040004600012c000060",
"miner": "0xf02ddb48eda520c915c0dabadc70ba12d1b49ad2",
"nonce": "0x0000000000000000",
"number": "0x4a1dbd",
"parentHash": "0x93434fec7bb917a3fdf071d43e6bda1061eab7c4d5663192ad88353925b49849",
"receiptsRoot": "0x088e158e77aa12898ed02e3ec20f030cd18054cd56890ad56a78a7ffadd4f5f3",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"size": "0x11f8",
"stateRoot": "0xa7b30b5144ee34730d42b8ea7b5f240d830190ad83b098ddce0e89978ea1055a",
"timestamp": "0x18bc6e3b748",
"totalDifficulty": "0x0",
"transactions": [
"0xc42bbbe43ffbaa15c3f6fdd335eba12adf37520313d15b5496e77a67fbd35b1d",
"0x3df5b3ddaab690c68ed9e94cc086f210555d8ecc39c34aad292e8bd623b827d7",
"0xf708668e3002ec8a079e803e041091d8d5f2a7c3161a75c5c40592c18a9c67d2",
"0x5411f16773adac1f407d0161d3a0627fece66479e244d040d856e065794d4f04",
"0x0ba4819248cd220f1beb3f72482ef15f14121d7ab28d2deab0656452945db38b",
"0x9e01fd45eedbdf68665531dc9795f97c7a130b6bfbe633095b92f94a21c96adb",
"0xe227e458184c315517ea2c926d6505a6d53528d86acc1b29758f7c85e42a9821"
],
"transactionsRoot": "0xa34082f12ca71f5b7111e910ed9fb1350e5692a09456a37edc791f055e0603e5",
"uncles": []
}Steps to Reproduce
To reproduce the issue above, simply build the Header using the block returned by the eth_getBlockBy* and notice the hash doesn't match:
use ethereum::Header;
use hex_literal::hex;
let header = Header {
parent_hash: hex!("93434fec7bb917a3fdf071d43e6bda1061eab7c4d5663192ad88353925b49849").into(),
ommers_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").into(),,
beneficiary: hex!("f02ddb48eda520c915c0dabadc70ba12d1b49ad2").into(),
state_root: hex!("a7b30b5144ee34730d42b8ea7b5f240d830190ad83b098ddce0e89978ea1055a").into(),
transactions_root: hex!("a34082f12ca71f5b7111e910ed9fb1350e5692a09456a37edc791f055e0603e5").into(),
receipts_root: hex!("088e158e77aa12898ed02e3ec20f030cd18054cd56890ad56a78a7ffadd4f5f3").into(),
logs_bloom: hex!("825080001000080802020000108400509000410406003440c08000402084300000021000910005c000300400022000004b000000210228020008001c31208000000008418c21101800082008c04880020408240008008c008200400ac22010448401040002820001000000080000080002030000020180030000001480988003240082802888080802200164000010208024040b0810a0004041208004200060224000400200040002b20b0409016048a1020080100210102001f12c40000ac0880144020048000603280802800014210400001001240001018022008400a100001908900000830420000018000260000800000640001040004600012c000060").into(),
difficulty: Default::default(),
number: 0x004a1dbd.into(),
gas_limit: 0x00e4e1c0.into(),
gas_used: 0x004e6b11.into(),
timestamp: 0x6551a2be,
extra_data: Default::default(),
mix_hash: Default::default(),
nonce: Default::default(),
};
let expected = hex!("84471574a6645fe3c4ea4fa7fb588f53f8cea681dd92d27d2de7c23f3040a7aa").into();
let actual = header.hash();
assert_eq(expected, actual);For testing the baseFeePerGas example, see the reth RLP encoder as reference:
https://github.com/paradigmxyz/reth/blob/v0.1.0-alpha.10/crates/primitives/src/header.rs#L324-L391