Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

blockhash() broken between nightly-2044faec and nightly-b1e93654 #9198

Closed
2 tasks done
adraffy opened this issue Oct 26, 2024 · 39 comments
Closed
2 tasks done

blockhash() broken between nightly-2044faec and nightly-b1e93654 #9198

adraffy opened this issue Oct 26, 2024 · 39 comments
Labels
T-bug Type: bug T-needs-triage Type: this issue needs to be labelled

Comments

@adraffy
Copy link

adraffy commented Oct 26, 2024

Component

Anvil

Have you ensured that all of these are up to date?

  • Foundry
  • Foundryup

What version of Foundry are you on?

No response

What command(s) is the bug in?

anvil

Operating System

None

Describe the bug

  1. foundryup -v nightly-2044faec64f99a21f0e5f0094458a973612d0712
    blockhash(x) == keccak256(rlpEncodeBlock(x))

  2. foundryup -v nightly-b1e93654348a0f31effa34790adae18865b14aa8
    ⚠️ blockhash(x) != keccak256(rlpEncodeBlock(x))

@adraffy adraffy added T-bug Type: bug T-needs-triage Type: this issue needs to be labelled labels Oct 26, 2024
@github-project-automation github-project-automation bot moved this to Todo in Foundry Oct 26, 2024
@adraffy
Copy link
Author

adraffy commented Oct 26, 2024

@adraffy
Copy link
Author

adraffy commented Oct 26, 2024

on 2044

const parts = [
  "0xa2f9a8897a7dd5f1a0ae653ce793b42548bf9e4401b3ec5070ac94c383caac1f",
  "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
  "0x0000000000000000000000000000000000000000",
  "0x5186dcad803ce44d801473eb727d4fecc20f759869d4a4daf3e71606c0d580bd",
  "0xa4f2579787fc3ffad5e146925c46fdeda1215edb484443c8bf9bc82f3e5ebc4f",
  "0xa53dd7e7f6147d1f1f6081694647a3e4057eb6553638829138c7204ef86c29a1",
  "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  "0x",
  "0x04",
  "0x01c9c380",
  "0x0d921e",
  "0x671c6817",
  "0x",
  "0x0000000000000000000000000000000000000000000000000000000000000000",
  "0x0000000000000000",
  "0x29b2d57d",
  null,
  "0x",
  "0x",
  null
];
const rlp = `0xf90200a0a2f9a8897a7dd5f1a0ae653ce793b42548bf9e4401b3ec5070ac94c383caac1fa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a05186dcad803ce44d801473eb727d4fecc20f759869d4a4daf3e71606c0d580bda0a4f2579787fc3ffad5e146925c46fdeda1215edb484443c8bf9bc82f3e5ebc4fa0a53dd7e7f6147d1f1f6081694647a3e4057eb6553638829138c7204ef86c29a1b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080048401c9c380830d921e84671c681780a000000000000000000000000000000000000000000000000000000000000000008800000000000000008429b2d57d808080`;
const hash = `0x6ba7a2ecef76fd6cefb179b9d7e469e9acb6ada08ae54809aef5b14c3d665d0a`

on b1e9

const parts = [
  "0x0f915aef13700d93f833d79fae367fc290265667680128c4444fcf4da71049c2",
  "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
  "0x0000000000000000000000000000000000000000",
  "0x19115cf7490ca6c5d6ab3e14ec8822899ef75706e164f580ba081939fdd465c6",
  "0xa4f2579787fc3ffad5e146925c46fdeda1215edb484443c8bf9bc82f3e5ebc4f",
  "0xa53dd7e7f6147d1f1f6081694647a3e4057eb6553638829138c7204ef86c29a1",
  "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  "0x",
  "0x04",
  "0x01c9c380",
  "0x0d921e",
  "0x671c687e",
  "0x",
  "0x0000000000000000000000000000000000000000000000000000000000000000",
  "0x0000000000000000",
  "0x29b2d57d",
  null,
  "0x",
  "0x",
  null
];
const rlp = `0xf90200a00f915aef13700d93f833d79fae367fc290265667680128c4444fcf4da71049c2a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a019115cf7490ca6c5d6ab3e14ec8822899ef75706e164f580ba081939fdd465c6a0a4f2579787fc3ffad5e146925c46fdeda1215edb484443c8bf9bc82f3e5ebc4fa0a53dd7e7f6147d1f1f6081694647a3e4057eb6553638829138c7204ef86c29a1b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080048401c9c380830d921e84671c687e80a000000000000000000000000000000000000000000000000000000000000000008800000000000000008429b2d57d808080`;
// keccak256(rlp)
const hash1 = `0x846f24652b2f79182e55f2f6d74ab36c1b5cab6893113658f69a0bf326509cb1`;
// eth_getBlock(x).hash or blockhash(x)
const hash2 = `0xa53dd7e7f6147d1f1f6081694647a3e4057eb6553638829138c7204ef86c29a1`

@klkvr
Copy link
Member

klkvr commented Oct 26, 2024

hey @adraffy do you mind sharing steps to produce such block?

@klkvr
Copy link
Member

klkvr commented Oct 26, 2024

assuming that rlp you've provided corresponds to block header rlp it seems that parent hash (first element) changed between commits so would be nice to get data for the first block of the chain which ended up with different hash

@adraffy
Copy link
Author

adraffy commented Oct 26, 2024

I couldn't exactly trace out the issue, but since nightly-b1e93654, if you derive a blockhash from eth_getBlock it doesn't match the blockhash() op or the hash in eth_getBlock.

I noticed it was wrong after running foundryup because I'm working on crosschain proving and some tests started failing. I installed progressively older nightlies until it worked again.


I'm not sure how to give a repo: take any non-fork anvil block, compute the blockhash, compare.

Oh, let me fix the genesis timestamp and retry.

@klkvr
Copy link
Member

klkvr commented Oct 26, 2024

which software are you using for calculating block hashes?

@adraffy
Copy link
Author

adraffy commented Oct 26, 2024

Custom code but it just follows Ethereum Spec

@klkvr
Copy link
Member

klkvr commented Oct 26, 2024

could you please share complete rpc respone for block you are getting mismatch for?

@adraffy
Copy link
Author

adraffy commented Oct 26, 2024

foundryup -v nightly-2044faec64f99a21f0e5f0094458a973612d0712

{
  "block": {
    "hash": "0x0f5f17c2e499f9ce082e5e6ad62259a2521642055499b6b989b5f87748b027ce",
    "parentHash": "0x61549544fe8860f5639424662e6d76481dfe116e74d00c47a5bfb9a67022e8f2",
    "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
    "miner": "0x0000000000000000000000000000000000000000",
    "stateRoot": "0x7abe738f5dfba083438b59b6b3c52f20636ab3de1b25c2b4341f1cac5e6287a7",
    "transactionsRoot": "0x4a3029a969a44c52bbf6ccc8b206dd6ad17aae74ee9013acbca7e088822b3c54",
    "receiptsRoot": "0x80fd06f06aac644e62bfb7a663dfe6e3f71b4f49bbeb932b5b3f935a508db9a2",
    "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "difficulty": "0x0",
    "number": "0x1",
    "gasLimit": "0x1c9c380",
    "gasUsed": "0x15053",
    "timestamp": "0x3e9",
    "totalDifficulty": "0x0",
    "extraData": "0x",
    "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "nonce": "0x0000000000000000",
    "baseFeePerGas": "0x3b9aca00",
    "blobGasUsed": "0x0",
    "excessBlobGas": "0x0",
    "uncles": [],
    "transactions": [
      "0x2b7c2ac25f2b6f03273827e3bf38615f5e1bd6b7783bcb3b3273c0b7e3d886ac"
    ],
    "size": "0x31a"
  },
  "parts": [
    "0x61549544fe8860f5639424662e6d76481dfe116e74d00c47a5bfb9a67022e8f2",
    "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
    "0x0000000000000000000000000000000000000000",
    "0x7abe738f5dfba083438b59b6b3c52f20636ab3de1b25c2b4341f1cac5e6287a7",
    "0x4a3029a969a44c52bbf6ccc8b206dd6ad17aae74ee9013acbca7e088822b3c54",
    "0x80fd06f06aac644e62bfb7a663dfe6e3f71b4f49bbeb932b5b3f935a508db9a2",
    "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "0x",
    "0x01",
    "0x01c9c380",
    "0x015053",
    "0x03e9",
    "0x",
    "0x0000000000000000000000000000000000000000000000000000000000000000",
    "0x0000000000000000",
    "0x3b9aca00",
    null,
    "0x",
    "0x",
    null
  ],
  "rlp": "0xf901fea061549544fe8860f5639424662e6d76481dfe116e74d00c47a5bfb9a67022e8f2a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a07abe738f5dfba083438b59b6b3c52f20636ab3de1b25c2b4341f1cac5e6287a7a04a3029a969a44c52bbf6ccc8b206dd6ad17aae74ee9013acbca7e088822b3c54a080fd06f06aac644e62bfb7a663dfe6e3f71b4f49bbeb932b5b3f935a508db9a2b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080018401c9c380830150538203e980a00000000000000000000000000000000000000000000000000000000000000000880000000000000000843b9aca00808080",
  "hashFromRPC": "0x0f5f17c2e499f9ce082e5e6ad62259a2521642055499b6b989b5f87748b027ce",
  "hashFromSol": "0x0f5f17c2e499f9ce082e5e6ad62259a2521642055499b6b989b5f87748b027ce",
  "hashFromRLP": "0x0f5f17c2e499f9ce082e5e6ad62259a2521642055499b6b989b5f87748b027ce"
}

foundryup -v nightly-b1e93654348a0f31effa34790adae18865b14aa8

{
  "block": {
    "hash": "0x5a76af1bafbb5aaa7e1b20d0d31d2553a7916257a3c2f20399bf8c99f3395179",
    "parentHash": "0xf7a835f834b91de00f38edf5a7acdd1ebfc290f712c6f93effb8833ec28de646",
    "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
    "miner": "0x0000000000000000000000000000000000000000",
    "stateRoot": "0x7abe738f5dfba083438b59b6b3c52f20636ab3de1b25c2b4341f1cac5e6287a7",
    "transactionsRoot": "0x4a3029a969a44c52bbf6ccc8b206dd6ad17aae74ee9013acbca7e088822b3c54",
    "receiptsRoot": "0x80fd06f06aac644e62bfb7a663dfe6e3f71b4f49bbeb932b5b3f935a508db9a2",
    "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "difficulty": "0x0",
    "number": "0x1",
    "gasLimit": "0x1c9c380",
    "gasUsed": "0x15053",
    "timestamp": "0x3e8",
    "totalDifficulty": "0x0",
    "extraData": "0x",
    "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "nonce": "0x0000000000000000",
    "baseFeePerGas": "0x3b9aca00",
    "blobGasUsed": "0x0",
    "excessBlobGas": "0x0",
    "uncles": [],
    "transactions": [
      "0x2b7c2ac25f2b6f03273827e3bf38615f5e1bd6b7783bcb3b3273c0b7e3d886ac"
    ],
    "size": "0x319"
  },
  "parts": [
    "0xf7a835f834b91de00f38edf5a7acdd1ebfc290f712c6f93effb8833ec28de646",
    "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
    "0x0000000000000000000000000000000000000000",
    "0x7abe738f5dfba083438b59b6b3c52f20636ab3de1b25c2b4341f1cac5e6287a7",
    "0x4a3029a969a44c52bbf6ccc8b206dd6ad17aae74ee9013acbca7e088822b3c54",
    "0x80fd06f06aac644e62bfb7a663dfe6e3f71b4f49bbeb932b5b3f935a508db9a2",
    "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "0x",
    "0x01",
    "0x01c9c380",
    "0x015053",
    "0x03e8",
    "0x",
    "0x0000000000000000000000000000000000000000000000000000000000000000",
    "0x0000000000000000",
    "0x3b9aca00",
    null,
    "0x",
    "0x",
    null
  ],
  "rlp": "0xf901fea0f7a835f834b91de00f38edf5a7acdd1ebfc290f712c6f93effb8833ec28de646a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a07abe738f5dfba083438b59b6b3c52f20636ab3de1b25c2b4341f1cac5e6287a7a04a3029a969a44c52bbf6ccc8b206dd6ad17aae74ee9013acbca7e088822b3c54a080fd06f06aac644e62bfb7a663dfe6e3f71b4f49bbeb932b5b3f935a508db9a2b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080018401c9c380830150538203e880a00000000000000000000000000000000000000000000000000000000000000000880000000000000000843b9aca00808080",
  "hashFromRPC": "0x5a76af1bafbb5aaa7e1b20d0d31d2553a7916257a3c2f20399bf8c99f3395179",
  "hashFromSol": "0x5a76af1bafbb5aaa7e1b20d0d31d2553a7916257a3c2f20399bf8c99f3395179",
  "hashFromRLP": "0x1296f251b9bf477b924a212d877a1a5e8781fc998c97fa02945516589a7db039"
}

@adraffy
Copy link
Author

adraffy commented Oct 26, 2024

hum, I fixed the genesis timestamp, what else introduces randomness into the state?

@klkvr
Copy link
Member

klkvr commented Oct 26, 2024

two blocks you've linked have number 1 and different parent hashes so I guess they are still produced by chains with different genesis, you could compare the responses for block 0

@adraffy
Copy link
Author

adraffy commented Oct 26, 2024

I had deployed a contract to query blockhash() op. Here is block 0 at timestamp 1000:

2044

{
  "block": {
    "hash": "0x61549544fe8860f5639424662e6d76481dfe116e74d00c47a5bfb9a67022e8f2",
    "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
    "miner": "0x0000000000000000000000000000000000000000",
    "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
    "receiptsRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "difficulty": "0x0",
    "number": "0x0",
    "gasLimit": "0x1c9c380",
    "gasUsed": "0x0",
    "timestamp": "0x3e8",
    "totalDifficulty": "0x0",
    "extraData": "0x",
    "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "nonce": "0x0000000000000000",
    "baseFeePerGas": "0x3b9aca00",
    "blobGasUsed": "0x0",
    "excessBlobGas": "0x0",
    "uncles": [],
    "transactions": [],
    "size": "0x203"
  },
  "parts": [
    "0x0000000000000000000000000000000000000000000000000000000000000000",
    "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
    "0x0000000000000000000000000000000000000000",
    "0x0000000000000000000000000000000000000000000000000000000000000000",
    "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
    "0x0000000000000000000000000000000000000000000000000000000000000000",
    "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "0x",
    "0x",
    "0x01c9c380",
    "0x",
    "0x03e8",
    "0x",
    "0x0000000000000000000000000000000000000000000000000000000000000000",
    "0x0000000000000000",
    "0x3b9aca00",
    null,
    "0x",
    "0x",
    null
  ],
  "rlp": "0xf901fba00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a00000000000000000000000000000000000000000000000000000000000000000b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080808401c9c380808203e880a00000000000000000000000000000000000000000000000000000000000000000880000000000000000843b9aca00808080",
  "hashFromRPC": "0x61549544fe8860f5639424662e6d76481dfe116e74d00c47a5bfb9a67022e8f2",
  "hashFromRLP": "0x61549544fe8860f5639424662e6d76481dfe116e74d00c47a5bfb9a67022e8f2"
}

b1e9

{
  "block": {
    "hash": "0xf7a835f834b91de00f38edf5a7acdd1ebfc290f712c6f93effb8833ec28de646",
    "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
    "miner": "0x0000000000000000000000000000000000000000",
    "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
    "receiptsRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "difficulty": "0x0",
    "number": "0x0",
    "gasLimit": "0x1c9c380",
    "gasUsed": "0x0",
    "timestamp": "0x3e8",
    "totalDifficulty": "0x0",
    "extraData": "0x",
    "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "nonce": "0x0000000000000000",
    "baseFeePerGas": "0x3b9aca00",
    "blobGasUsed": "0x0",
    "excessBlobGas": "0x0",
    "uncles": [],
    "transactions": [],
    "size": "0x202"
  },
  "parts": [
    "0x0000000000000000000000000000000000000000000000000000000000000000",
    "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
    "0x0000000000000000000000000000000000000000",
    "0x0000000000000000000000000000000000000000000000000000000000000000",
    "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
    "0x0000000000000000000000000000000000000000000000000000000000000000",
    "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "0x",
    "0x",
    "0x01c9c380",
    "0x",
    "0x03e8",
    "0x",
    "0x0000000000000000000000000000000000000000000000000000000000000000",
    "0x0000000000000000",
    "0x3b9aca00",
    null,
    "0x",
    "0x",
    null
  ],
  "rlp": "0xf901fba00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a00000000000000000000000000000000000000000000000000000000000000000b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080808401c9c380808203e880a00000000000000000000000000000000000000000000000000000000000000000880000000000000000843b9aca00808080",
  "hashFromRPC": "0xf7a835f834b91de00f38edf5a7acdd1ebfc290f712c6f93effb8833ec28de646",
  "hashFromRLP": "0x61549544fe8860f5639424662e6d76481dfe116e74d00c47a5bfb9a67022e8f2"
}

@klkvr
Copy link
Member

klkvr commented Oct 26, 2024

I think this is likely related to alloy-rs/alloy#1524 cc @mattsse @Rjected

@klkvr
Copy link
Member

klkvr commented Oct 26, 2024

however, I think alloy-rs/alloy#1524 is actually correct

the only difference between header rlp between 2044 and b1e9 is that the older encoding has a 0x80 at the end representing parent_beacon_block_root which is None in this case. so the latest encoding is correct and you should account for that in your rlp implementation — i.e if parentBeaconBlockRoot is null nothing should be encoded

and another pov here is that this is actually incorrect for anvil to return blocks without parent beacon block root because every block should have one after cancun, this would need to be addressed

@adraffy
Copy link
Author

adraffy commented Oct 26, 2024

I believe the RLP encoding for trailing nulls is special, which is why my code doesn't use ethers RLP encoding directly. Let me see if I can find the docs on that.

@adraffy
Copy link
Author

adraffy commented Oct 26, 2024

https://github.com/ethereum/go-ethereum/blob/80bdab757dfb0f6d73fb869d834979536fe474e5/core/types/block.go#L75-L109

It's the optional stuff—trailing null optionals aren't included.

From what I remember, this prevents blockhashes from breaking when new fields are added.

@klkvr
Copy link
Member

klkvr commented Oct 26, 2024

yep, that's how it is now. it was incorrect before on our side

@klkvr
Copy link
Member

klkvr commented Oct 26, 2024

#9202 would fix the fields not being correctly set

for now closing this as I believe rlp encoding is correct on our side

@klkvr klkvr closed this as completed Oct 26, 2024
@github-project-automation github-project-automation bot moved this from Todo to Done in Foundry Oct 26, 2024
@adraffy
Copy link
Author

adraffy commented Oct 26, 2024

I'm not sure I follow, which fields are you saying are optional?

I can only replicate the hash in anvil latest if I say baseFeePerGas and blobGasUsed aren't optional.

@adraffy
Copy link
Author

adraffy commented Oct 26, 2024

I think my code is also wrong as I was saying an optional RLP encoded integer 0x0 wasn't null, but geth says the check isZero() not isNull(). I think my only test case for this was anvil so that makes sense.

@klkvr
Copy link
Member

klkvr commented Oct 26, 2024

I'm not sure I follow, which fields are you saying are optional?

parentBeaconRoot and withdrawalsRoot are optional and we were placing 0x80 for withdrawalsRoot which is incorrect. actually the entire block structure is off-spec here because there can't be a block without withdrawalsRoot and with blob-related fields

I'd recommend to just wait for the next nightly, it should fix the encoding

@adraffy
Copy link
Author

adraffy commented Oct 26, 2024

geth says:

// BaseFee was added by EIP-1559 and is ignored in legacy headers.
BaseFee *big.Int `json:"baseFeePerGas" rlp:"optional"`

// WithdrawalsHash was added by EIP-4895 and is ignored in legacy headers.
WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"`

// BlobGasUsed was added by EIP-4844 and is ignored in legacy headers.
BlobGasUsed *uint64 `json:"blobGasUsed" rlp:"optional"`

// ExcessBlobGas was added by EIP-4844 and is ignored in legacy headers.
ExcessBlobGas *uint64 `json:"excessBlobGas" rlp:"optional"`

// ParentBeaconRoot was added by EIP-4788 and is ignored in legacy headers.
ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`

// RequestsHash was added by EIP-7685 and is ignored in legacy headers.
RequestsHash *common.Hash `json:"requestsRoot" rlp:"optional"`

{
  "block": {
    "hash": "0xf3fb8013ae5e20cfed8ae36e77367d3cbdc51ccf9fa95d6763fd5f895bd8122d",
    "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
    "miner": "0x0000000000000000000000000000000000000000",
    "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
    "receiptsRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "difficulty": "0x0",
    "number": "0x0",
    "gasLimit": "0x1c9c380",
    "gasUsed": "0x0",
    "timestamp": "0x671d4f54",
    "totalDifficulty": "0x0",
    "extraData": "0x",
    "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "nonce": "0x0000000000000000",
    "baseFeePerGas": "0x3b9aca00",
    "blobGasUsed": "0x0",
    "excessBlobGas": "0x0",
    "uncles": [],
    "transactions": [],
    "size": "0x204"
  },
  "parts": [
    "0x0000000000000000000000000000000000000000000000000000000000000000",
    "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
    "0x0000000000000000000000000000000000000000",
    "0x0000000000000000000000000000000000000000000000000000000000000000",
    "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
    "0x0000000000000000000000000000000000000000000000000000000000000000",
    "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "0x",
    "0x",
    "0x01c9c380",
    "0x",
    "0x671d4f54",
    "0x",
    "0x0000000000000000000000000000000000000000000000000000000000000000",
    "0x0000000000000000",
    "0x3b9aca00", // baseFeePerGas
    null, // withdrawalsRoot
    "0x", // blobGasUsed
    null, // excessBlobGas
    null, // parentBeaconBlockRoot
    null // requestsRoot
  ],
  "hashFromRPC": "0xf3fb8013ae5e20cfed8ae36e77367d3cbdc51ccf9fa95d6763fd5f895bd8122d",
  "hashFromRLP": "0xf3fb8013ae5e20cfed8ae36e77367d3cbdc51ccf9fa95d6763fd5f895bd8122d"
}

I can only match this blockhash if I say { blobGasUsed: "0x0" } isn't optional, but it is.

@adraffy
Copy link
Author

adraffy commented Oct 26, 2024

@adraffy
Copy link
Author

adraffy commented Oct 26, 2024

in 2044 it's encoding up to excessBlobGas as non-optional
and my code matches that since I was saying 0x0 numbers were not null
eg. rlp encoding has 808080 (3 nulls at end)

in b1e9 it's encoding up to blobGasUsed as non-optional
eg. rlp encoding has 8080 (2 nulls at end)

but in both cases, those last 6 fields are optional, and only baseFeePerGas is non-zero, so the rlp encoding should have no trailing 80's.


The alloy code looks wrong, as must encode up to the last valued optional, and Some(0) isn't handled.

@klkvr
Copy link
Member

klkvr commented Oct 26, 2024

Does that correctly handle Some(0) ?

it does, Some(0) is encoded and decoded as 0x80. None is also 0x80 however it is never encoded as 0x80 because missing trailing fields are just not being encoded

2044 encoded 3 zeroes at the end — withdrawalsRoot, blobGasUsed and excessBlobGas which decodes as zeroes for all three. Basically, it was incorrectly encoding withdrawalsRoot as zero while it was actually missing making all blocks anvil produced technically un-encodable.

b1e9 skipped encoding withdrawalsRoot and only encoded 2 zeroes blobGasUsed and excessBlobGas which is still invalid encoding.

with #9202 it would get fixed because withdrawalsRoot would get correctly encoded as empty withdrawals root

@adraffy
Copy link
Author

adraffy commented Oct 26, 2024

if a, b, c, d are optional and c is defined, you must encode null + null + c

I don't see how the alloy code does that with separate if statements?

@klkvr
Copy link
Member

klkvr commented Oct 26, 2024

if a, b, c, d are optional and c is defined, you must encode null + null + c

where is this requirement from? for Ethereum blocks it is not possible to have c defined while a or b are None

@klkvr
Copy link
Member

klkvr commented Oct 26, 2024

https://github.com/ethereum/go-ethereum/blob/80bdab757dfb0f6d73fb869d834979536fe474e5/rlp/encode.go#L368-L386

this code will indeed encode null pointers as 0x80. however, rlp does not define encoding for None/null and geth's rlp implementation will decode 0x80 as zero which basically means that this encoding format is not correct

it is not possible to have a block which will get encoded like this because all trailing fields appear in order of corresponding hardforks being activated

@adraffy
Copy link
Author

adraffy commented Oct 26, 2024

I guess my point is that:

2044 and prior blockhash is wrong because it encoded 3 optional nulls
b1e9 and newer blockhash is wrong because it encoded 2 optional nulls

The last 6 values of block header encoding are optional.

if a, b, c are optional (ignoring the list header)

  • [0, 0, 1]"808001"
  • [0, 1, 0]"8001"
  • [1, 0, 0]"01"
  • [0, 0, 0]""
  • [0, 0]""
  • [0]""
  • []""

@klkvr
Copy link
Member

klkvr commented Oct 26, 2024

[0, 0, 0] must be encoded as 0x808080 and it is encoded like so in geth. all of the trailing fields in the block type are pointers, and pointer is only isZero() when it is .isNil(): https://github.com/golang/go/blob/889abb17e125bb0f5d8de61bb80ef15fbe2a130d/src/reflect/value.go#L1609

the only way to get "" is [nil, nil, nil], [0, 0, 0] would be 0x808080

@klkvr
Copy link
Member

klkvr commented Oct 26, 2024

the issue is that anvil produces incorrect blocks with latest fields being [nil, 0, 0] which is just not valid and thus we don't have special handling for this in alloy while geth encodes this as [0, 0, 0] which is probably fine because it doesn't really matter how you handle a case which is not possible from spec pov

@adraffy
Copy link
Author

adraffy commented Oct 26, 2024

I'm still not sure I follow: if the struct is [req, req, opt, opt]

[0, 0, 0, 0] is actually [0, 0]
[0, 0, 1, 0] is actually [0, 0, 1]
[0, 0, 0, 1] is actually [0, 0, 0, 1]

The length of list is up to the last non-zero optional. Trailing optionals are dropped. Possibly I am misreading the go code?

@klkvr
Copy link
Member

klkvr commented Oct 26, 2024

The length of list is up to the last non-zero optional

yep, in this case it means that the length is up to the last non-nil pointer. if pointer points to 0 it will not be dropped

@adraffy
Copy link
Author

adraffy commented Oct 26, 2024

So if the last 6 values are optional:
[baseFeePerGas, withdrawalsRoot, blobGasUsed, excessBlobGas, parentBeaconBlockRoot, requestsRoot]

in 2044, [0x999, null, 0x0, 0x0, null, null] encodes as 0x999 + 808080

in b1e9, [0x999, null, 0x0, 0x0, null, null] encodes as 0x999 + 8080 because the new alloy code incorrectly skips withdrawalsRoot ?

I find the geth rlp code nearly unreadable, so I'm not sure if an optional integer of 0 is considered null, however, it seems like both of these could be encoded as just 0x999 since the remaining 5 fields are null or 0.

@klkvr
Copy link
Member

klkvr commented Oct 26, 2024

there is only 1 way to correctly encode a well-formed block header in rlp and per specification and it is to encode 0's as 0x80 and skip trailing nil's

header with nil followed by non-nil fields is not well-formed

@adraffy
Copy link
Author

adraffy commented Oct 26, 2024

I'm confused then, doesn't my original issue describe the problem?

The blockhash in 2044 is correct (with 808080 since excessBlobGas is supplied as 0x0 and the last non-null, so withdrawalsRoot+blobGasUsed+excessBlobGas must be encoded)

And b1e9 is wrong, because the alloy encoding code makes the assumption that prior block values must exist, and withdrawalsRoot was None, so it was skipped and only wrote 8080.

@klkvr
Copy link
Member

klkvr commented Oct 26, 2024

2044 assumed withdrawalsRoot to be 0 if it was missing which resulted in invalid rlp-encodings for pre-shanghai blocks oops that's not true, it only assumed missing values to be 0 but pre-shanghai blocks were fine

b1e9 always produces valid encodings for well-formed blocks

the root issue is that anvil produced invalid blocks with withdrawalsRoot being None and subsequent fields being Some which is now fixed by #9202

@adraffy
Copy link
Author

adraffy commented Oct 26, 2024

Thanks for the help.

I guess the confusion here is that I'm using eth_getBlock, deriving the blockhash, and comparing it to anvil. So I literally don't care what the encoding is, except that it's right or wrong.

And you're saying the blockhash calculation was wrong in 2044 but it gave the correct answer, and was fixed in b1e9 but since it makes an assumption about block header optionals (what you're calling well-formed blocks), and withdrawalsRoot was supplied wrong, resulting in the wrong blockhash.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T-bug Type: bug T-needs-triage Type: this issue needs to be labelled
Projects
Archived in project
Development

No branches or pull requests

3 participants
@adraffy @klkvr and others