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

eth_getProof implementation returns invalid code hash #28355

Closed
Wollac opened this issue Oct 16, 2023 · 4 comments · Fixed by #28357
Closed

eth_getProof implementation returns invalid code hash #28355

Wollac opened this issue Oct 16, 2023 · 4 comments · Fixed by #28357
Labels

Comments

@Wollac
Copy link

Wollac commented Oct 16, 2023

Description

When eth_getProof is called for an account with an empty storage trie (storageTrie == nil), it always returns the empty code hash, even if the code is not empty.

Steps to reproduce the behaviour

An example of such an account would be contract 0xb55ac2656c53ccdc3b8218f86b5595ac88ad4752 that gets created in block 16044617. Thus, calling eth_getProof on this combination will result in the described problem:

$ curl localhost:8545 \ 
      -X POST \
      -H "Content-Type: application/json" \
      -d '{ "method": "eth_getProof", "params": ["0xb55ac2656c53ccdc3b8218f86b5595ac88ad4752", [], "0xf4d249"], "id": 1, "jsonrpc": "2.0" }'

Actual behaviour

The previous command returns

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "address": "0xb55ac2656c53ccdc3b8218f86b5595ac88ad4752",
    "accountProof": [
      "0xf90211a01a9ab5c1073bd6828b602f25c251ed37803bfff9aff714d1690ab82458aa324fa0cc93a6fccc48b7d3a772d0b527c76c0764d0ea8986fbbe43e76cc314eec89693a037dda77dc5bec99164ce7dc8611de411b610111b07a2df943f40c3ae4f7e4a44a0e958e7e343d1b08e376febbb1cbc8f0f6ebdbee4c82ef2d22d4e1df545b23db2a059f55f74f2f82a4c1823eed070979661fe6c19c4e9a437459e4b57e2ce5aeb09a01a6c4be05483582b484d7d6b369642c2caab54a98e91404fc95bf7e80ee2fef8a030885d431ca481b6be51b55d5d8c8cb505b239e70dd20132047af99162143512a063ecbeaec76ae6b130689d1462f47e0ffb19e15a709ea0a616dfa0061c05d5b7a049846c572f98c13f983fa5672d4eb17d5fa57fe76d33a86d2a1b3783caf8fcffa0851f7b8fff0aa1b2ca2e88322301238e0a48fe792109ec069a2c1fea6d61beaca01944e3c184491fedc0f97ff497e3b539ca9e8525170ecc8a9e5586dcdf3a18b1a0789b4da4445897356c33b565b363b87115a85141d4cc15b4d7c8f22eee548879a0fc4446bc3852feecbfccdb3fe9ade6d921e0b942b3a7a754b807963ce6519389a00ddae2b70af3a36146a7d399d222f36529eaa38f01d4f4e843da8a255a050ae1a046db27a92a23b9ab9e8828b73c34974f1c3183c2dd87095527e0e40936bc3415a0a3dd0a58ab4372a83899736d82649c2a8c75e5a1f54c465e417f07e349cf53c580",
      "0xf90211a0ea5029706c8e24fa524c26da1acdff66f0a7095ae37171a76a374450fb88f885a0337dee1437cffc89f3a4d595268751409316747118991114599e528e885c5a03a06e33465c287d7052c4b0b4db5987ffce50b8d65cb37efed16c36e4ec3147bc4da003adc08b0d3d64ed0ccbe7c1646bff2478fd3a35387cc99a6c57c2834a669836a05819223ada58125f8e9faa44a71e31ed7514d084de566adadb5cd082ff7c47bda07dfe44d75ea9745e03e9040fcb31493a5c51b8fea4b3186eaf7cdc30181ec63da013a2b7739210d33c8ac0e1f62a74da4c81a11a08b776e0f155cefa39271c55f4a0fb2694c51087847815936bfd3f45516c0179f24209300458e6b4831a92402081a030ea224f3d556234d044585c6e5ad0f321cd777d9bb28e260728ca4599f7b4dfa0ebb06b10f23b93364d253b7bb41808e58590cb403125bb01c60516593a802a87a04174fad7a4a30484270cdf239593e59d6b2376ca43ddba5abf1eaf82bca4798fa0038d3b8040a16f63f0ff52538e04c58499c697cdb962ad5616a99f78824a5b95a06e693508d9773f51eabe2c823d1f8b0de15b0a062ed276356d7714d871e414f5a0e5e7df452a0968cbef64ed216ed74044ffbadc821705d63c4a0d15a68f7b2eb0a087ae3d9232fb54b235fc468c897fe160df385ed62c5822a15f1c469bafec07cba0c281a98630268a6f8ee084465e560ecb0ee4910b09e9fa951ff29a4b1cb2601580",
      "0xf90211a0132966127985e045613c5578a974b1d2f731e31fb4c7edd95432357f3d460162a05728a05eac87efb228f6f6321cbb28f28b64d1d31979fb49cabfd102591ddfd7a008f862287058876ecee6888057f0c4705734884921f6eda00342dee8e3ac250fa0f44c1b55c9caa3643b154b56d2c18d8ab6f1ac28e47213af009f78b6275914d8a0094699bc91e21601a05bcfabd038f0bdfed5173a862a73dd664cad4ba08a604ca0b6812024b8e4ef6d0be3879b300f0db77ab55eb450f8e03b377f905296c40f1aa069a6dfd5c24640a449efbcb750a422dbf8859e1a93f7e5e6b533a11e64c377f3a0b401776a459ee9e61c21951629fcfde2e5dfbf346e5d260068196d5a727a9882a0f93c3a1fcbeb6d6356d3e5ca96fa5361080b5f8806738f2a4131dc87b9de93e0a0deb07a6bf00cd5b4e5435330f121923e4dc6fda540f7545bf97a9c10012ce82aa0627dbb767b495594650f26cd4b8033da363d3ba05bcaf751a4a2a4c7b021134ea0624cf51fd631735e6a62020f63bdb96e0b24b51de2d56aca72db8c68d9509bc6a01afcfcd17b980d6e83a3d1aff3c01d0ccd3d2708f6b3ac96433877786f835cd0a0993428c75bcdc0e6870adb52c1348133a38aa30f0e45cdd09a9620b8cb958370a063d258a07fa01fd191c3f2128f6fb62386bd190f4afd0b6d86a1a5c3120a6636a0f6216606747e5381486686e65d0c000d7040dca3e828fb80f40610844f2879ad80",
      "0xf90211a0bf3321f9bbe4e10d60641accf9b31dcc917d7c7bbbed6f4a1e3319602eb6b558a0140ceb3b4b02e0160d205c39b4d783440f6292e552c1d966047f61a144ce9613a0676dd900910d8272e6cb96fbe21e93b5f0d93ccde8fbf0737a15a137074fb234a0eb7ecd5866638abcfdc65bb11ed3399c953f333f2df73abce42c172be42d7027a0d6fa5e702f636263afd7b8c7f6d6565e403079d13bf79e737a556083402c7400a04f31a62de7bac32b9e0954d73c46e0c11af953e1f91d8e69e17be030abbeaf3aa04ea6477e8946196eff3d8dce673d0ca1f60b3e34c9fc018feeba75ac5c05ecf3a01f9ee69251586796b12b56ef9bd1eec0671660a954cbb7aa9456f1e3b6050da1a0fc7d0fdd056ba9d6a4e9ee8bb1f8059e5e47f334f00b04c69451511449e4195aa07a2751f13856b5a90c813950e19f22d1ccd7b93047eaa1f8a26234b04c9e1b1ca0bc6acb2de86fff47ecfabf9662e747305014575b040b12e31b7e02b8da0ed161a0eb0fbe7b01f8f0103bc63732415dd2d797045167b5ef94a2f29419b1812a7e8ca0a930ab238295a4c5f68318f0fd397b0fa6d65ec4be7aa6f0c3413b781cf4c50ea0d737bf58062c7995f2a588e5be5094831c15c184a0540e375c05b81716d7239ba0218450f80503610abd13856a40baebcba009ddab7a7f356b31079721cd091771a0fa4f82d0a882fa2c024b5eeb16518844b7249c5a32eee6c4a0be9ac5e029b11e80",
      "0xf90211a070ef23dd6707fcd735bf8cf47f0763c3cf11b57d6a0ca3a96b6d3cbd0c962fdaa0ac650b2c72e5129868805e57ad37bc39e58e1701f67aa230c87c230cca92d0e4a0244347c697c38dd50ffa1cceea0c550696119add6f580b0164f69be11168b012a029e361a972696b38abd33155ca636f57056945ee5611afb872af6e4a9a9235cda0932add0b4300087a70eb1add77ec198add50ba4cc5d162d398d03d21399061d8a00cdda7cae8f78df6a2b204e8ad91dd25fd544d8ef2b38b30acce6048e3d73463a01b736bf1691278d059c0d66988dc11205896f2e464a90d3f857d291b3043cd9ca0c10deaa8c6d37e1b92f97eb71697b2de26750ec3a012027acbef3b23b1f06083a0633a2459e827363a021b33bbf5d7793aa2a7f489cbf8b0200468de7c11266780a000e975ed58015bdbd88b2c49c4c4cab94cf58288fc37410edb114efc945129b0a0799b94ca6b34ca9f31db4d7e13be31958b163f88fdbe99216d58b575372e9438a0e0040198b1b75f8c5cd0c83ba7cc8ee429cef432f0be7f743a5e5ef25540c814a019704a00fe69681bad7f432c940dae857ed32759230decacb14a00a6ea10d128a0da9692bb29891e5a5cda58ac0b3cd3a7fc27080925d7e600ac9b2aad2fb11ef1a02f028ebc3ea92182a1ac571058f3ba2428c7ba1247f4af5b0dcef1f964af751ca05b783f14a6a93c920322bf12ec5b7c0593eb5cf079d7557f170caacc1be3024180",
      "0xf90211a0e257e6011bf010706fd16855c6a00c31979a70e6ae47a0b4250564c736d062aca0bee47df3349247c948056276697e6224c81f89f9c0649b6301955bea917d4d43a09ab9bf825699849fc85ef70684d1e4d5ad8366e03f79ecb4bfce193e070d66e5a03486c1798d0dbb05ab0f282f6c1c85f2777e40611066236d23b514253261cdb1a005387ab306510b2b629c14893dd331635725d09b1fc9b6f537ae099db8506224a04d60835ffbbb415e5defb5ece8746b9305ba08fa1b664646f6e5af57a2cb11b3a0eeeb716a4b90150dd43ced7611d225af9611e3ee2c129e7e319b1980af164a9da07da10ea07e5e4934857e907cfad9be3cd9cffe06a45e2d372f3f5d1009b6cfcea0077e170518f733e7df9aef3948bf1a63da4d87878221abb2b3819d514485a8a1a0fb347463f5190020c8a19c6dd80bde1c64933d180dd04d46601a9d5e408d2556a0b7122e4592adb9a5a900692d6ead1b61308a67db9eabd68b3ba25392176fe864a079f9b5f3c9e1412bebfa36b0398597bc160ce27a16ed9aee942ce0939c2abdb6a0455ba8bc19ed0694650d7abd74f165e36972f756de00b0ae703ce0b4e7f2270aa06d99dd723dc551e1d90d460717ca295605beb62c556f470c088e199f22a31b93a0e7c0893e8fb56fe6e7cd58c061afe7a9586a98d0cd523f233a7a28f52a3b0b92a0fca18a282640595d2eacd48a9e24a55f574f1af94bf8d6310d33583d3ed1307d80",
      "0xf90151a0034742c57ad2c035246531ac8f40ebed22bc4ba5044aae0cd713a8696ed84dbba0fc8454c756d97db0054710f570542cb5967813a0094a24b6c5b7034192108bcf80a0a7707a70308b7fd63a2180d106ef76461832386b00da0d0efab5fb3357442f59a04532c9a980baa4c57015c5716654cca8c99ce7ea9b3abd3c09f77fd4fd973d30a078cd9411bbd61a42102a995341e6be5211db2ed790efa091c6c0444db2a30d1a80a04c83e2035ec4adf8bcd99a2c19efa53f877a9433136186f23df7a996574d2f2f808080a0e3aa66350b23f67bfa6d3a072bd1d99fd468fbab3f88bee2a0e9890868436aa480a02dbea3fe10bbf4d9c9bd56d922596ed38d121f750a3f7c4e4297b9412a3d692aa0efe8c022251bc2f61d65cf82aa10cba7264a3c3dff5cb25bdedc2c5b13f01f70a00dc6fa033d9a4816bb2f1c54f0d3a38013d4759a8208d2cf65b2ebe14042f66b80",
      "0xf87180a0be0f769c240f30b07a1d121f98e318c8e58b01cf71ef8ea90e6f41379312d3f08080808080a0d14cfc9480464c953679c1ad3cbd2f7d8c178b9dcdadb77d37eece882a24a6308080808080a08aa4977153a6e2abb079cadecc1583910990e2bd79c4a523eef8a451ae57dd8d808080",
      "0xf8669d2033dd30b02c18479257c7b51fb83d282d46738ce6ef4831a8fb7805fdb846f8440180a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0197506d6551b948e13201746f78ba7bec7c6404eb9804b477e6203f31a4b9e66"
    ],
    "balance": "0x0",
    "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
    "nonce": "0x1",
    "storageHash": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
    "storageProof": []
  }
}

Verification of this result against the provided accountProof fails due to an invalid code hash.

Expected behaviour

Calling the corresponding eth_getCode

$ curl localhost:8545 \ 
      -X POST \
      -H "Content-Type: application/json" \
      -d '{ "method": "eth_getCode", "params": ["0xb55ac2656c53ccdc3b8218f86b5595ac88ad4752", "0xf4d249"], "id": 2, "jsonrpc": "2.0" }'

returns

{
  "jsonrpc": "2.0",
  "id": 2,
  "result": "0x363d3d373d3d3d363d7310692b1c144ef98904335e40ce857369d19b83335af43d82803e903d91602b57fd5bf3"
}

Therefore, the codeHash returned by eth_getProof should correspond to the hash of this result, i.e.
"codeHash": "0x197506d6551b948e13201746f78ba7bec7c6404eb9804b477e6203f31a4b9e66",
instead.

By replacing the empty codeHash in the previous result of eth_getProof with this value, the proof can be verified, e.g:

import { JsonRpcProvider } from "ethers";
import { DefaultStateManager } from "@ethereumjs/statemanager";
import { hexToBytes, bytesToHex, intToHex } from "@ethereumjs/util";
import { keccak256 } from "ethereum-cryptography/keccak.js";

const provider = new JsonRpcProvider(RPC_URL);
const address = "0xB55aC2656c53cCdC3B8218f86B5595AC88Ad4752";
const blockNumber = intToHex(16044617);

const proof = await provider.send("eth_getProof", [address, [], blockNumber]);
const code = await provider.send("eth_getCode", [address, blockNumber]);
const codeHash = bytesToHex(keccak256(hexToBytes(code)));

proof["codeHash"] = codeHash;
assert(await new DefaultStateManager().verifyProof(proof));
@holiman
Copy link
Contributor

holiman commented Oct 16, 2023

Wonky!

The comment and clause here is so strange -- I don't even.. https://github.com/ethereum/go-ethereum/blob/master/internal/ethapi/api.go#L705

Hm, seems I reacted to it at the time too, but I guess I eventually just accepted it with a shrug: #17737 (comment) .

We should just get the codehash unconditionally -- there's not even any reason to avoid it, internally we've already loaded the account from db, so it's not even an extra lookup.

		codeHash = state.GetCodeHash(address)

@holiman
Copy link
Contributor

holiman commented Oct 16, 2023

It would be highly appreciated if you could test against #28357, and see if it fixes it for you.

holiman added a commit that referenced this issue Oct 17, 2023
This change fixes #28355, where eth_getProof failed to return the correct codehash under certain conditions. This PR changes the logic to unconditionally look up the codehash, and also adds some more tests.
@Wollac
Copy link
Author

Wollac commented Oct 17, 2023

The example described in the issue now seems to work for me 👍

@holiman
Copy link
Contributor

holiman commented Oct 17, 2023

Thanks for verifying!

devopsbo3 pushed a commit to HorizenOfficial/go-ethereum that referenced this issue Nov 10, 2023
This change fixes ethereum#28355, where eth_getProof failed to return the correct codehash under certain conditions. This PR changes the logic to unconditionally look up the codehash, and also adds some more tests.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants