diff --git a/op-service/eth/account_proof.go b/op-service/eth/account_proof.go index b7d09eeff062..4ddc3eff156b 100644 --- a/op-service/eth/account_proof.go +++ b/op-service/eth/account_proof.go @@ -13,7 +13,7 @@ import ( ) type StorageProofEntry struct { - Key common.Hash `json:"key"` + Key hexutil.Big `json:"key"` Value hexutil.Big `json:"value"` Proof []hexutil.Bytes `json:"proof"` } @@ -46,20 +46,20 @@ func (res *AccountResult) Verify(stateRoot common.Hash) error { return fmt.Errorf("failed to load storage proof node %d of storage value %d into mem db: %w", j, i, err) } } - path := crypto.Keccak256(entry.Key[:]) + path := crypto.Keccak256(entry.Key.ToInt().FillBytes(make([]byte, 32))) val, err := trie.VerifyProof(res.StorageHash, path, db) if err != nil { - return fmt.Errorf("failed to verify storage value %d with key %s (path %x) in storage trie %s: %w", i, entry.Key, path, res.StorageHash, err) + return fmt.Errorf("failed to verify storage value %d with key %s (path %x) in storage trie %s: %w", i, entry.Key.String(), path, res.StorageHash, err) } if val == nil && entry.Value.ToInt().Cmp(common.Big0) == 0 { // empty storage is zero by default continue } comparison, err := rlp.EncodeToBytes(entry.Value.ToInt().Bytes()) if err != nil { - return fmt.Errorf("failed to encode storage value %d with key %s (path %x) in storage trie %s: %w", i, entry.Key, path, res.StorageHash, err) + return fmt.Errorf("failed to encode storage value %d with key %s (path %x) in storage trie %s: %w", i, entry.Key.String(), path, res.StorageHash, err) } if !bytes.Equal(val, comparison) { - return fmt.Errorf("value %d in storage proof does not match proven value at key %s (path %x)", i, entry.Key, path) + return fmt.Errorf("value %d in storage proof does not match proven value at key %s (path %x)", i, entry.Key.String(), path) } } diff --git a/op-service/eth/account_proof_test.go b/op-service/eth/account_proof_test.go index 051023e8e9af..210aebc513b7 100644 --- a/op-service/eth/account_proof_test.go +++ b/op-service/eth/account_proof_test.go @@ -44,6 +44,37 @@ const resultData = ` } ` +// Truncated storage proof key to test unmarshalling. +const invalidResultDataTruncated = ` +{ + "address": "0xae851f927ee40de99aabb7461c00f9622ab91d60", + "balance": "0x0", + "codeHash": "0x1f958654ab06a152993e7a0ae7b6dbb0d4b19265cc9337b8789fe1353bd9dc35", + "nonce": "0x1", + "storageHash": "0x88219055c2fef8800e02f071d053a86a4194e70a81b6e45f1fecca7dae0432da", + "accountProof": [ + "0xf90211a063a66cd84a54f8ee248662f1d4637936c430a0f455eeec8c01ee56db898dddfba0be9003fb3e36a55cfea1eda010c0a459f10729db9809e0bd1e3599f46c5ffed1a0a08d018d3cf38b0d0cbff14288699705dfa7cf27dc20fbbaae9351837eff4751a0eed877086740a930f035b75ebb26ce63df0f61baea52bf05f4c7421014debf33a053ea34e49423e790b10d9a36f498f337b3f079ed611d98a3f8550c34212dcbd7a0c370d5b874f70b9fd1c8a2fe98b0ef60c480fbe00566a7d5a5e682d9859398f2a0da820e94aac0b444a8dcfebc7dc9ec942f04f252da25b10faf50b57f969aa1f5a0413e8039c67d8acbe20993ab364c2c477d1ce85e8ae723c33acd506175ce4bffa0f70e5d5d934c53b2302ec3f98bd3f33f39a15fabb8c32e5e7acc97121d7a9cf3a0b41e7073ae943e498681b5d86941401c29b38c93fa347ace6bb15ba74ccbf45ea0a3b0aa548cac9cbbfcfabd980c1ceae8bdc39ad2682fc6e6d9cf0f4bdb273884a04d7932870a3d25163ea28ae5ebe702b841d755541d2af98c5c1c08090327fab1a06e41c3fb6362dd860a098aacf13a81c9d26e9b822c1066ca76cb98607f3e257aa0079ffe59ddb21ccd03bcbf1cc42fc0fb89dcae93ffeed9b82a848828199ab057a0dce67e92c8991df57ecac2237244d12e92f6514db1c5f076718fe40266bbf741a08dd7d3b3b041889f837217761b4e87510428ea41b3aff4e5725fd8efc2d735b980", + "0xf90211a0809683f3310d75dff5eb95296aa9ff5d74fbde9f873b9a6b245513887f9c6e91a055450f5338cc2f8f4306912e938df3fe490929614604eeea4c03581b98c8ae8ea04e50b57da8fc16a5d5460892196631737eeb1cc1e995e5c1de9c381ed1fb84d4a07d65e61a50579d689422446c23df10c4c0b5ec41239a910ca86634e2fee75320a091c77e1f72302bdb3985b249dba07d1abaa345296080c369bd84c518669297e1a019a185bedc83ab48c51dffe4c58ab88e30c88976a3b059ab524ef7ab42886d61a0a6c249e070db991141ee1289a5ed212f81673f8cd3f7bf35c27c335cc77d3eeca0c7d7a7f5036c8c3185cd0ca231775047192419b8f7e7b5a462c8e713ab2f4fcda006084fdd6777d076850defc5c6f1336535bbc2ec95a0e3f91fc5ac9761aee770a0c85a82f527990667217fac36ebfb9f4af29a6ff7b0b3d41cdcb256a26ca5f621a06a382d1f5a9bb0b712c89e82b0aaf26cf7c5984255377fd7428457d390330d40a0194f1f730e71559662ea2d9bdc681761eaf54decc7041766b5d7b7e8086d2480a05afe23c9ec57c22d9639f9228aa389e7a70a4e1e3e675856792f4a92fe284478a05bcacd2d3d2ac267d5b0367b56f05e4c808e2a5ecd04a10f1399e313fd41b273a09e62b6f5b7b77a1657ded9f0bef2af7fee11f2bf0518a5cceb5ceae2845c16f0a06d0ee25c5a3acd2b8d3253b856a77187b76f90d60b2356fc77f6e79766410cc580", + "0xf90211a0a6b81aae9b8aff6ac275885f6dfa4bc11949e3e8cbfad05714c3233303fa83f5a0e29595c647574b219c3068a768d47347b0e8a272da881aeb4525af051faab847a0441c1549c250c0c1bc0fa1b73e9f9ac9998b5dcef65a57ecd3f748ce02be4251a0353bd042ac0cf9a90a9cc02cc131f5d58f531df8df7ab752f6caa9b6807a506ea07340f489ba55fc8cfde61384c4990f74034f0bc0c7e1d68733284cb5c30d5bbea00ff5d4191ef973be9ae73b3fd9d01f52b54aafa20f147b6a5ca6b9e56a1f9ec4a0e167cd5a249a0dc2afbb9b2aafbd3b6e0160739a99e482d22d722c78fa296772a004202f2695770715d36e9aad418cc005fd8b22b927f1e1383b4e95ca18f41f61a0be38b6340286e0cd2454d90d8ed2f7e26bce5b7774f8adfa8f54a75bc4635d18a0cacc635e487a0d7dd19373bcd0a32e4cea0655f93d61f2940a6063059a044bf7a0bcd8f9ab88356e86cea7cd27454525ade016bccf26f414ad9fa93e0280d40df4a0d5651902739f9dfaff0f1178ea7cba617087234dd0e2895424961fad98605a27a0f76890befb5b3b20695d64b6a7c416709c93032012b46245c5bc00dd104b84f3a00ff372b11e0fb8febd467e060f7ce126e705a07a203a3f6dd93c7e3f36f4608ea0b4ea8133548c9b9d8f62b86aa703f65e3323a92a4b4711f80a734b80814b0825a04db29c4cb760e4831bfe40cdb0f554d74e98da26715c7e6319317c8c9a9c247580", + "0xf90211a026ffcc82ed6e3cd13ea30ed185afae29eed7f7fbde7f46010061791b5441b7dfa086b3018a2c001ffd6cc76e58372c49f5a2ba42335789fdcea878d93ceeeeb969a0589ba5e683afa655b17eb6b6c687a657669f772b1a2f78813ea662e8c316c12ea01c604e2e2f9ace5ef281f09c4b6c24c4c4631810f30b5209a433515a628cb5aca0520abee45bbc79e9f9519ffd4ad199b40383cb9718a3e8392d7193f68b1bc251a0b788e74186f121dd5ad31ef6b69d69147ab1841aa5380928fbe11a65ad67af36a0ef80a7fd5edf9901e2d8fa0cd8d9608e9fde114da1bd0f545e107c6771d5b0e7a05e8d9b24b83dbb8ec946cd42ff04bd0588f15866cd95095a8495242616b9ae71a0d623ee5bd0f3b8513ad7c247d1736841878f7210445209cecf36f0bfa5b8a6b9a03d0b62b3dc96b9c72190ff3484699d4892dea93cd16d9811cd58bd614348db11a0b140f98169be15dc1266be9343a1225fe6339f86e309854b03af9d304e75bd76a04ca100367dd9f12a6e80f48a1fabc19d9d36f07960d1911c3a09199a43eb26d2a05e9c627adafc5393a9b5ddc910f6474c56a10366f9d44248d9c0ce2e0c6b9a94a097e533731c36c43d7cf20379f2349ac1cd7a1165fb3588432be8d315801b2e80a0765168ad98f52483060045ae5208451078b2e6876a6f90d40a5c3e3f31cc559ba0479dd4f67d939fa21dd0528703a68c933f8a3d8e504d48f8c9bf7c41e92deecd80", + "0xf90211a04232cef0e6c4bbd5969f864233a23762543460900e04868931685e0148ae2d10a05353ae18ba63650d7281fefa6fb545b7314cadafd459eed25c7db4915d834e95a022fe8bbf3b304ea8fa6e0cb69c9a3a05cdcf0c3542a5e389a9518177a1925bdca0377ac9d4284000e1f98327783989043f4a6b59d48f5a80579c71adfd880f651ea049da166e0ceb03cf24a2cc03b3bd5e862eddd540a2c517493125322b3a30e85ba0aa9980b3bf84ce0b360f10ca3b230b5dbc9eecba684ed1add96b23167728574ea0f28a3be0e42f13e78f306970fd3a1aac286b30af8af1f460e50eba1d879d61b8a0c84f2fd48976ee7662adc809abb439ea056b3615b622f2938b597782501a4279a0ca13452ffbe75eedde1d870340997ce269c83f6642eefa2d4e9d6bd21c8fc838a0dd918c25e25823548a6a31edb27b65421b2b77063cdc71b13c43eed15b86b924a01a4d8ab05ce030242b59014d96fe1adca52c3f5d13eb09feefbf6eaf97e6fcfba09187e247644a19fe62860dba6e2317f40fe9907c8101bf9e1b04e4b5dadb8ec4a02c299cdc9b87c7f3b1402627f9bcc488d8655a6cbc5d458155024dc8be90ea7aa0373f215d7bc10a74a8e11ddbd3395e27d55cfab62a433b2c6961c1beee9ff3c8a04ec09787d6040119700a0d38154d4a589e1d62245fcd685768cd265cda5ee576a00086a240676e913c0b969397fbc72191719834bc533ba4601406ea062ea76f9b80", + "0xf90151808080a0ae1018f6569474784bbb933125e397f72f160cb86bf9528ba522e2957e6b27b6a07e10da74c2d11b8dda5b0127b4b39a0d7a1f4a1c9f0dc1a05ae1f3fa3346c86ba0884fa49d5faae435667fe982950ccf82aa58a148dffdb99c5eb7da6b01fd9b00a0065e97ea5d45a492c2aa8eade7534551a04e7899f0bcebeeccc42a1cb2292ce3a0c3a2aae48ed7395cc59065eedd5cb40d9a0cb02db9a9afaccd27efd6282464eb808080a0fc9e1fdc7239d8adc047265bb6589ddefac9a63c1c9829ef2b4717a4b9000dd7a0c285558e316f3ea0ceb2ca5681a79e5d3e3d6d6f21054d5056a6e9ad7dcdd6c7a0de8e2f7f5743997eabe69cb1d99ef0aec670da0b31b466bd8e14d24df17542d6a026ad23a1ed5a6f66a4e6e64fa1b3c37c0878975ba0b8872f5d8ae7c215a0f9c5a0f0ac72c6fc609e78ca13cefea04ef39ff7c9c49198a641508bf7d51bc997239180", + "0xf851808080808080a0292e7aa7b0fa371f45a26562a180d952f2f3bd3d7a67eb019747b10876cd61a6a0c7f2b75df52f531ca04c4b7c6449bb8be8eae52bf543dfb78383eda4625d922e808080808080808080", + "0xf8669d37118893aaaf73153bacee2bbd50b8234ab255361cc8614a5713b77282b846f8440180a088219055c2fef8800e02f071d053a86a4194e70a81b6e45f1fecca7dae0432daa01f958654ab06a152993e7a0ae7b6dbb0d4b19265cc9337b8789fe1353bd9dc35" + ], + "storageProof": [ + { + "key": "0x0", + "proof": [ + "0xf901118080a04fc5f13ab2f9ba0c2da88b0151ab0e7cf4d85d08cca45ccd923c6ab76323eb28a09d1f77882a1c2e804de950478b4fdec793decb817e7bbe24a2afd23eb000d648a0f57febb7b16455e051f412a56e54016c676a3d4aa515d2e77a90520dfe36162ea0dce964c738816bb26d659513b793496cac2279d100812e6441aae3f7ffefce2080a0d5223d0cc181c8c0cd1babb8cd0b4d6433eab19a9fcc7836681589aad346556fa0c61ebce1cecbc190ee1163d0ff9ff456cb1fe3409dc546bf2f9118662e6db892a024513ee2bee3b30d4b4e4b600b5a98db38db03f6db556f492d24ac0ff9d6c98fa019bbead828fb8baf57dfda3a30a0b6da048e31faee39f5a76a99b51f28c6c512808080808080", + "0xf7a031a88f3936348d602f3078126bdcd162c575cb17fb9bbfe2dab00b167bd295c39594715b7219d986641df9efd9c7ef01218d528e19ec" + ], + "value": "0x715b7219d986641df9efd9c7ef01218d528e19ec" + } + ] +} +` + var goodRoot = common.HexToHash("0x070ef87d6d3a8a132dfb45cbbc86daf545a45f1a0263bd28a304e465327f3557") func TestAccountResult_Verify(t *testing.T) { @@ -58,10 +89,15 @@ func TestAccountResult_Verify(t *testing.T) { require.NotNil(t, result.Verify(goodRoot), "does not verify against bad proof") } +func TestAccountResult_MarshalTruncated(t *testing.T) { + var result AccountResult + require.NoError(t, json.Unmarshal([]byte(invalidResultDataTruncated), &result)) +} + func FuzzAccountResult_StorageProof(f *testing.F) { f.Fuzz(func(t *testing.T, key []byte, value []byte) { result := makeResult(t) - result.StorageProof[0].Key = common.BytesToHash(key) + result.StorageProof[0].Key = hexutil.Big(*common.BytesToHash(key).Big()) result.StorageProof[0].Value = hexutil.Big(*(new(big.Int).SetBytes(value))) require.NotNil(t, result.Verify(goodRoot), "does not verify against bad proof") }) diff --git a/op-service/sources/eth_client.go b/op-service/sources/eth_client.go index 149a0c08abab..0c83b52336a6 100644 --- a/op-service/sources/eth_client.go +++ b/op-service/sources/eth_client.go @@ -331,8 +331,8 @@ func (s *EthClient) GetProof(ctx context.Context, address common.Address, storag return nil, fmt.Errorf("missing storage proof data, got %d proof entries but requested %d storage keys", len(getProofResponse.StorageProof), len(storage)) } for i, key := range storage { - if key != getProofResponse.StorageProof[i].Key { - return nil, fmt.Errorf("unexpected storage proof key difference for entry %d: got %s but requested %s", i, getProofResponse.StorageProof[i].Key, key) + if key != common.BigToHash(getProofResponse.StorageProof[i].Key.ToInt()) { + return nil, fmt.Errorf("unexpected storage proof key difference for entry %d: got %s but requested %s", i, getProofResponse.StorageProof[i].Key.String(), key) } } return getProofResponse, nil