From 41425fc6d46427330f2452a570590b30fbf24d87 Mon Sep 17 00:00:00 2001 From: mmsqe Date: Sun, 6 Nov 2022 16:27:33 +0800 Subject: [PATCH] fix(rpc): different result from `eth_getProof` comparing with Ethereum (#1431) * align with eth_getProof for more info, see https://eips.ethereum.org/EIPS/eip-1186 * add GetHexProofs * add change doc * keep default res * fix lint * add e2e test * Apply suggestions from code review * fix lint * nix run -f ./nix gomod2nix --- CHANGELOG.md | 1 + gomod2nix.toml | 4 +- rpc/backend/account_info.go | 16 +----- rpc/backend/utils.go | 18 +++++++ rpc/backend/utils_test.go | 52 +++++++++++++++++++ tests/integration_tests/expected_constants.py | 10 ++++ tests/integration_tests/test_types.py | 49 ++++++++++------- 7 files changed, 114 insertions(+), 36 deletions(-) create mode 100644 rpc/backend/utils_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e58c4bf..d7721e07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -77,6 +77,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (cli) [#1362](https://github.com/evmos/ethermint/pull/1362) Fix `index-eth-tx` error when the indexer db is empty. * (state) [#1320](https://github.com/evmos/ethermint/pull/1320) Fix codehash check mismatch when the code has been deleted in the evm state. * (rpc) [#1392](https://github.com/evmos/ethermint/pull/1392) Allow fill the proposer address in json-rpc through tendermint api, and pass explicitly to grpc query handler. +* (rpc) [#1431](https://github.com/evmos/ethermint/pull/1431) Align hex-strings proof fields in `eth_getProof` as Ethereum. ## [v0.19.3] - 2022-10-14 diff --git a/gomod2nix.toml b/gomod2nix.toml index 671eed03..a9e456de 100644 --- a/gomod2nix.toml +++ b/gomod2nix.toml @@ -362,8 +362,8 @@ schema = 3 version = "v2.4.0" hash = "sha256-Z+bch118Akc5wGkOM7ZePNqw7vW5euXE7ec4Y297HNw=" [mod."github.com/onsi/gomega"] - version = "v1.23.0" - hash = "sha256-g5FaFLUK8ZAR9VgFTTH0ax0t45tZkYbIHbq/gANIOTM=" + version = "v1.24.0" + hash = "sha256-pOth47IZsI9c16TKLqW8HMObd1KiqWbe0iem+ue4bTw=" [mod."github.com/pelletier/go-toml"] version = "v1.9.5" hash = "sha256-RJ9K1BTId0Mled7S66iGgxHkZ5JKEIsrrNaEfM8aImc=" diff --git a/rpc/backend/account_info.go b/rpc/backend/account_info.go index 9067d5e6..5455b66f 100644 --- a/rpc/backend/account_info.go +++ b/rpc/backend/account_info.go @@ -75,16 +75,10 @@ func (b *Backend) GetProof(address common.Address, storageKeys []string, blockNr return nil, err } - // check for proof - var proofStr string - if proof != nil { - proofStr = proof.String() - } - storageProofs[i] = rpctypes.StorageResult{ Key: key, Value: (*hexutil.Big)(new(big.Int).SetBytes(valueBz)), - Proof: []string{proofStr}, + Proof: GetHexProofs(proof), } } @@ -105,12 +99,6 @@ func (b *Backend) GetProof(address common.Address, storageKeys []string, blockNr return nil, err } - // check for proof - var accProofStr string - if proof != nil { - accProofStr = proof.String() - } - balance, ok := sdkmath.NewIntFromString(res.Balance) if !ok { return nil, errors.New("invalid balance") @@ -118,7 +106,7 @@ func (b *Backend) GetProof(address common.Address, storageKeys []string, blockNr return &rpctypes.AccountResult{ Address: address, - AccountProof: []string{accProofStr}, + AccountProof: GetHexProofs(proof), Balance: (*hexutil.Big)(balance.BigInt()), CodeHash: common.HexToHash(res.CodeHash), Nonce: hexutil.Uint64(res.Nonce), diff --git a/rpc/backend/utils.go b/rpc/backend/utils.go index d95a6854..afd52776 100644 --- a/rpc/backend/utils.go +++ b/rpc/backend/utils.go @@ -21,6 +21,7 @@ import ( "github.com/evmos/ethermint/rpc/types" evmtypes "github.com/evmos/ethermint/x/evm/types" + "github.com/tendermint/tendermint/proto/tendermint/crypto" ) type txGasAndReward struct { @@ -263,3 +264,20 @@ func GetLogsFromBlockResults(blockRes *tmrpctypes.ResultBlockResults) ([][]*etht return blockLogs, nil } + +// GetHexProofs returns list of hex data of proof op +func GetHexProofs(proof *crypto.ProofOps) []string { + if proof == nil { + return []string{""} + } + proofs := []string{} + // check for proof + for _, p := range proof.Ops { + proof := "" + if len(p.Data) > 0 { + proof = hexutil.Encode(p.Data) + } + proofs = append(proofs, proof) + } + return proofs +} diff --git a/rpc/backend/utils_test.go b/rpc/backend/utils_test.go new file mode 100644 index 00000000..3358cc08 --- /dev/null +++ b/rpc/backend/utils_test.go @@ -0,0 +1,52 @@ +package backend + +import ( + "fmt" + + "github.com/tendermint/tendermint/proto/tendermint/crypto" +) + +func mookProofs(num int, withData bool) *crypto.ProofOps { + var proofOps *crypto.ProofOps + if num > 0 { + proofOps = new(crypto.ProofOps) + for i := 0; i < num; i++ { + proof := crypto.ProofOp{} + if withData { + proof.Data = []byte("\n\031\n\003KEY\022\005VALUE\032\013\010\001\030\001 \001*\003\000\002\002") + } + proofOps.Ops = append(proofOps.Ops, proof) + } + } + return proofOps +} + +func (suite *BackendTestSuite) TestGetHexProofs() { + defaultRes := []string{""} + testCases := []struct { + name string + proof *crypto.ProofOps + exp []string + }{ + { + "no proof provided", + mookProofs(0, false), + defaultRes, + }, + { + "no proof data provided", + mookProofs(1, false), + defaultRes, + }, + { + "valid proof provided", + mookProofs(1, true), + []string{"0x0a190a034b4559120556414c55451a0b0801180120012a03000202"}, + }, + } + for _, tc := range testCases { + suite.Run(fmt.Sprintf("Case %s", tc.name), func() { + suite.Require().Equal(tc.exp, GetHexProofs(tc.proof)) + }) + } +} diff --git a/tests/integration_tests/expected_constants.py b/tests/integration_tests/expected_constants.py index 41abb0ad..85bee9b6 100644 --- a/tests/integration_tests/expected_constants.py +++ b/tests/integration_tests/expected_constants.py @@ -26,6 +26,16 @@ EXPECTED_GET_PROOF = { ], } +EXPECTED_ACCOUNT_PROOF = [ + "0x0ac1030a150157f96e6b86cdefdb3d412547816a82e3e0ebf9d212e8010a1e2f65746865726d696e742e74797065732e76312e4574684163636f756e7412c5010a7f0a2a63726331326c756b75367578656868616b303270793472637a36357a753073776837776a737277307070124f0a282f65746865726d696e742e63727970746f2e76312e657468736563703235366b312e5075624b657912230a21026e710a62a342de0ed4d7c4532dcbcbbafbf19652ed67b237efab70e8b207efac200112423078633564323436303138366637323333633932376537646232646363373033633065353030623635336361383232373362376266616438303435643835613437301a0b0801180120012a03000202222b08011204020402201a2120e2a580b805b8b4d1f80793092cefe57965d9582ba8e31505a72cf31a55fa173d222b08011204040802201a21206c0bd60f0d887a5f99dd023f133dfd12412b074c0c442ab8a25b17048ff34ae022290801122506100220a66ec49c8058aef1eabb21a9610e16227d95982482db0ab5b032f823d457c2b920222b080112040a2e02201a2120af3944b847407590f1b2a95edcd1c2c5408e27a404e0b22267bcc2d46df700ed", # noqa: E501 + "0x0aff010a0361636312205632d1620b29d277324e7473898ac9e587a99a62022931b33ce6d0be3b19137b1a090801180120012a0100222708011201011a20f5b8da7f66d134e34242575499b1f125c07af21b36685c31f9a8999c71a21daf222708011201011a20b8ef619094b2b40ae87dd1d3413c5af70d9c43256dfea123ca835baa53ad54a4222708011201011a20b7d06a60784c017041761d99ed17a2d2d68ceb4eccf39bd9a527773f21e5b688222708011201011a20a54531b68a71accb459f478724bde077a82c9079ef2be7e0b8dc47764f1b96d2222708011201011a204f83dd3fed3f48e1dff2fe125c5d22f578b613ddb45bdc12d4bc1841232d9a8b", # noqa: E501 +] + +EXPECTED_STORAGE_PROOF = [ + "0x12370a350257f96e6b86cdefdb3d412547816a82e3e0ebf9d20000000000000000000000000000000000000000000000000000000000000000", # noqa: E501 + "0x0af9010a0365766d1220e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b8551a090801180120012a0100222508011221010842b5561422ad68d28682baffad7f99cd8a64a339d4bd62b72916894d3d9a19222508011221010b1d3ff3c723ae07cea430234113b9d2b3b4218b7661f596b39b0592aedf9b60222508011221019975643a5ffdd52f7ef9a9cc57244008e5e7269e55587af4e4f137e5ef8ed6d3222708011201011a20a54531b68a71accb459f478724bde077a82c9079ef2be7e0b8dc47764f1b96d2222708011201011a204f83dd3fed3f48e1dff2fe125c5d22f578b613ddb45bdc12d4bc1841232d9a8b", # noqa: E501 +] + EXPECTED_GET_TRANSACTION = { "jsonrpc": "2.0", "id": 0, diff --git a/tests/integration_tests/test_types.py b/tests/integration_tests/test_types.py index 2e04dd10..2f41c66c 100644 --- a/tests/integration_tests/test_types.py +++ b/tests/integration_tests/test_types.py @@ -1,11 +1,13 @@ from web3 import Web3 from .expected_constants import ( + EXPECTED_ACCOUNT_PROOF, EXPECTED_FEE_HISTORY, EXPECTED_GET_PROOF, EXPECTED_GET_STORAGE_AT, EXPECTED_GET_TRANSACTION, EXPECTED_GET_TRANSACTION_RECEIPT, + EXPECTED_STORAGE_PROOF, ) from .utils import ( ADDRS, @@ -181,11 +183,15 @@ def test_get_storage_at(ethermint_rpc_ws, geth): assert res, err -def send_and_get_hash(w3, tx_value=10): +def send_tnx(w3, tx_value=10): # Do an ethereum transfer gas_price = w3.eth.gas_price tx = {"to": ADDRS["community"], "value": tx_value, "gasPrice": gas_price} - return send_transaction(w3, tx, KEYS["validator"])["transactionHash"].hex() + return send_transaction(w3, tx, KEYS["validator"]) + + +def send_and_get_hash(w3, tx_value=10): + return send_tnx(w3, tx_value)["transactionHash"].hex() def test_get_proof(ethermint_rpc_ws, geth): @@ -195,26 +201,29 @@ def test_get_proof(ethermint_rpc_ws, geth): eth_rpc = w3.provider w3_wait_for_block(w3, 3) geth_rpc = geth.w3.provider - make_same_rpc_calls( - eth_rpc, - geth_rpc, - "eth_getProof", - ["0x57f96e6b86cdefdb3d412547816a82e3e0ebf9d2", ["0x0"], "latest"], - ) + validator = ADDRS["validator"] + method = "eth_getProof" + for quantity in ["latest", "0x1024"]: + res = make_same_rpc_calls( + eth_rpc, + geth_rpc, + method, + [validator, ["0x0"], quantity], + ) + res = send_tnx(w3) - make_same_rpc_calls( - eth_rpc, - geth_rpc, - "eth_getProof", - ["0x57f96e6b86cdefdb3d412547816a82e3e0ebf9d2", ["0x0"], "0x1024"], - ) + proof = (eth_rpc.make_request( + method, [validator, ["0x0"], hex(res["blockNumber"])] + ))["result"] + res, err = same_types(proof, EXPECTED_GET_PROOF) + assert res, err + assert proof["accountProof"], EXPECTED_ACCOUNT_PROOF + assert proof["storageProof"][0]["proof"], EXPECTED_STORAGE_PROOF - _ = send_and_get_hash(w3) - - proof = eth_rpc.make_request( - "eth_getProof", [ADDRS["validator"], ["0x0"], "latest"] - ) - res, err = same_types(proof["result"], EXPECTED_GET_PROOF) + proof = (geth_rpc.make_request( + method, [validator, ["0x0"], "latest"] + ))["result"] + res, err = same_types(proof, EXPECTED_GET_PROOF) assert res, err