From 3f2682c43d164af00be903e19cf6980c73ef2499 Mon Sep 17 00:00:00 2001 From: ramacarlucho Date: Wed, 27 Jul 2022 17:07:02 -0300 Subject: [PATCH 1/7] types tests --- tests/integration_tests/test_types.py | 326 ++++++++++++++++++++ tests/integration_tests/utils.py | 419 ++++++++++++++++++++++++++ 2 files changed, 745 insertions(+) create mode 100644 tests/integration_tests/test_types.py diff --git a/tests/integration_tests/test_types.py b/tests/integration_tests/test_types.py new file mode 100644 index 0000000000..d541acbb6f --- /dev/null +++ b/tests/integration_tests/test_types.py @@ -0,0 +1,326 @@ +import pytest + +from .utils import ( + KEYS, + CONTRACTS, + ADDRS, + send_transaction, + deploy_contract, + w3_wait_for_new_blocks, +) + +txhash = "" + +def test_block(ethermint, geth): + get_blocks(ethermint, geth, False) + get_blocks(ethermint, geth, True) + +def get_blocks(ethermint, geth, with_transactions): + eth_rpc = ethermint.w3.provider + geth_rpc = geth.w3.provider + make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBlockByNumber", ['0x0', with_transactions]) + + # FIXME: Fails + # {'jsonrpc': '2.0', 'id': 20, 'error': {'code': -32000, 'message': 'height 10000 must be less than or equal to the current blockchain height 18'}} + # {'jsonrpc': '2.0', 'id': 2, 'result': None} + make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBlockByNumber", ['0x2710', with_transactions]) + + ethermint_blk = ethermint.w3.eth.get_block(1) + # Get existing block, no transactions + eth_rsp = eth_rpc.make_request( + "eth_getBlockByHash", [ethermint_blk['hash'].hex(), with_transactions] + ) + geth_rsp = geth_rpc.make_request( + "eth_getBlockByHash", ["0x124d099a1f435d3a6155e5d157ff1078eaefb742435892677ee5b3cb5e6fa055", with_transactions] + ) + res, err = same_types(eth_rsp, geth_rsp) + assert res, err + + # Get not existing block + make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBlockByHash", ['0x4e3a3754410177e6937ef1f84bba68ea139e8d1a2258c5f85db9f1cd715a1bdd', with_transactions]) + + # Bad call + make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBlockByHash", ['0', with_transactions]) + + +def test_accounts(ethermint, geth): + eth_rpc = ethermint.w3.provider + geth_rpc = geth.w3.provider + make_same_rpc_calls(eth_rpc, geth_rpc, "eth_accounts", []) + +def test_syncing(ethermint, geth): + eth_rpc = ethermint.w3.provider + geth_rpc = geth.w3.provider + make_same_rpc_calls(eth_rpc, geth_rpc, "eth_syncing", []) + +def test_coinbase(ethermint, geth): + eth_rpc = ethermint.w3.provider + geth_rpc = geth.w3.provider + make_same_rpc_calls(eth_rpc, geth_rpc, "eth_coinbase", []) + +def test_max_priority_fee(ethermint, geth): + eth_rpc = ethermint.w3.provider + geth_rpc = geth.w3.provider + make_same_rpc_calls(eth_rpc, geth_rpc, "eth_maxPriorityFeePerGas", []) + + +def test_gas_price(ethermint, geth): + eth_rpc = ethermint.w3.provider + geth_rpc = geth.w3.provider + make_same_rpc_calls(eth_rpc, geth_rpc, "eth_gasPrice", []) + + +def test_block_number(ethermint, geth): + eth_rpc = ethermint.w3.provider + geth_rpc = geth.w3.provider + make_same_rpc_calls(eth_rpc, geth_rpc, "eth_blockNumber", []) + +def test_balance(ethermint, geth): + eth_rpc = ethermint.w3.provider + geth_rpc = geth.w3.provider + make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBalance", ["0x57f96e6b86cdefdb3d412547816a82e3e0ebf9d2", 'latest']) + make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBalance", ["0", 'latest']) + make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBalance", ["0x9907a0cf64ec9fbf6ed8fd4971090de88222a9ac", 'latest']) + make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBalance", ["0x57f96e6b86cdefdb3d412547816a82e3e0ebf9d2", '0x0']) + make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBalance", ["0",'0x0']) + make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBalance", ["0x9907a0cf64ec9fbf6ed8fd4971090de88222a9ac",'0x0']) + # FIXME: BAD ERROR + make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBalance", ["0x57f96e6b86cdefdb3d412547816a82e3e0ebf9d2", '0x10000']) + make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBalance", ["0",'0x10000']) + make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBalance", ["0x9907a0cf64ec9fbf6ed8fd4971090de88222a9ac",'0x10000']) + +def deploy_and_wait(w3, number=1): + contract = deploy_contract( + w3, + CONTRACTS["TestERC20A"], + ) + + w3_wait_for_new_blocks(w3, number) + return contract + +def test_getStorageAt(ethermint, geth): + eth_rpc = ethermint.w3.provider + geth_rpc = geth.w3.provider + make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getStorageAt", ["0x57f96e6b86cdefdb3d412547816a82e3e0ebf9d2", '0x0', 'latest']) + + contract = deploy_and_wait(ethermint.w3) + res = eth_rpc.make_request( + 'eth_getStorageAt', [contract.address, '0x0', 'latest'] + ) + expected = '0x00000000000000000000000000000000000000000000000000120a0b063499d4' + res, err = same_types(res['result'], expected) + assert res, err + +def send_and_get_hash(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() + +def test_getProof(ethermint, geth): + eth_rpc = ethermint.w3.provider + geth_rpc = geth.w3.provider + make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getProof", ["0x57f96e6b86cdefdb3d412547816a82e3e0ebf9d2", ['0x0'], 'latest']) + + make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getProof", ["0x57f96e6b86cdefdb3d412547816a82e3e0ebf9d2", ['0x0'], '0x32']) + + _ = send_and_get_hash(ethermint.w3) + + proof = eth_rpc.make_request('eth_getProof', [ADDRS["validator"], ['0x0'], 'latest']) + expected = { + 'address': '0x4CB06C43fcdABeA22541fcF1F856A6a296448B6c', + 'accountProof': ['0xf90211a03841a7ddd65c70c94b8efa79190d00f0ab134b26f18dcad508f60a7e74559d0ba0464b07429a05039e22931492d6c6251a860c018ea390045d596b1ac11b5c7aa7a011f4b89823a03c9c4b5a8ab079ee1bc0e2a83a508bb7a5dc7d7fb4f2e95d3186a0b5f7c51c3b2d51d97f171d2b38a4df1a7c0acc5eb0de46beeff4d07f5ed20e19a0b591a2ce02367eda31cf2d16eca7c27fd44dbf0864b64ea8259ad36696eb2a04a02b646a7552b8392ae94263757f699a27d6e9176b4c06b9fc0a722f893b964795a02df05d68bceb88eebf68aafde61d10ab942097afc1c58b8435ffd3895358a742a0c2f16143c4d1db03276c433696dddb3e9f3b113bcd854b127962262e98f43147a0828820316cc02bfefd899aba41340659fd06df1e0a0796287ec2a4110239f6d2a050496598670b04df7bbff3718887fa36437d6d8c7afb4eff86f76c5c7097dcc4a0c14e9060c6b3784e35b9e6ae2ad2984142a75910ccc89eb89dc1e2f44b6c58c2a009804db571d0ce07913e1cbacc4f1dc4fb8265c936f5c612e3a47e91c64d8e9fa063d96f38b3cb51b1665c6641e25ffe24803f2941e5df79942f6a53b7169647e4a0899f71abb18c6c956118bf567fac629b75f7e9526873e429d3d8abb6dbb58021a00fd717235298742623c0b3cafb3e4bd86c0b5ab1f71097b4dd19f3d6925d758da0096437146c16097f2ccc1d3e910d65a4132803baee2249e72c8bf0bcaaeb37e580', + '0xf90151a097b17a89fd2c03ee98cb6459c08f51b269da5cee46650e84470f62bf83b43efe80a03b269d284a4c3cf8f8deacafb637c6d77f607eec8d75e8548d778e629612310480a01403217a7f1416830c870087c524dabade3985271f6f369a12b010883c71927aa0f592ac54c879817389663be677166f5022943e2fe1b52617a1d15c2f353f27dda0ac8d015a9e668f5877fcc391fae33981c00577096f0455b42df4f8e8089ece24a003ba34a13e2f2fb4bf7096540b42d4955c5269875b9cf0f7b87632585d44c9a580a0b179e3230b07db294473ae57f0170262798f8c551c755b5665ace1215cee10ca80a0552d24252639a6ae775aa1df700ffb92c2411daea7286f158d44081c8172d072a0772a87d08cf38c4c68bfde770968571abd16fd3835cb902486bd2e515d53c12d80a0413774f3d900d2d2be7a3ad999ffa859a471dc03a74fb9a6d8275455f5496a548080', + '0xf869a020d13b52a61d3c1325ce3626a51418adebd6323d4840f1bdd93906359d11c933b846f8440180a01ab7c0b0a2a4bbb5a1495da8c142150891fc64e0c321e1feb70bd5f881951f7ea0551332d96d085185ab4019ad8bcf89c45321e136c261eb6271e574a2edf1461f' + ], + 'balance': 0, + 'codeHash': '0x551332d96d085185ab4019ad8bcf89c45321e136c261eb6271e574a2edf1461f', + 'nonce': 1, + 'storageHash': '0x1ab7c0b0a2a4bbb5a1495da8c142150891fc64e0c321e1feb70bd5f881951f7e', + 'storageProof': [{ + 'key': '0x00', + 'value': '0x48656c6c6f00000000000000000000000000000000000000000000000000000a', + 'proof': ['0xf9019180a01ace80e7bed79fbadbe390876bd1a7d9770edf9462049ef8f4b555d05715d53ea049347a3c2eac6525a3fd7e3454dab19d73b4adeb9aa27d29493b9843f3f88814a085079b4abcd07fd4a5d6c52d35f4c4574aecc85830e90c478ca8c18fcbe590de80a02e3f8ad7ea29e784007f51852b9c3e470aef06b11bac32586a8b691134e4c27da064d2157a14bc31f195f73296ea4dcdbe7698edbf3ca81c44bf7730179d98d94ca09e7dc2597c9b7f72ddf84d7eebb0fe2a2fa2ab54fe668cd14fee44d9b40b1a53a0aa5d4acc7ac636d16bc9655556770bc325e1901fb62dc53770ef9110009e080380a0d5fde962bd2fb5326ddc7a9ca7fe0ee47c5bb3227f838b6d73d3299c22457596a08691410eff46b88f929ef649ea25025f62a5362ca8dc8876e5e1f4fc8e79256d80a0673e88d3a8a4616f676793096b5ae87cff931bd20fb8dd466f97809a1126aad8a08b774a45c2273553e2daf4bbc3a8d44fb542ea29b6f125098f79a4d211b3309ca02fed3139c1791269acb9365eddece93e743900eba6b42a6a8614747752ba268f80', + '0xf891808080a0c7d094301e0c54da37b696d85f72de5520b224ab2cf4f045d8db1a3374caf0488080a0fc5581783bfe27fab9423602e1914d719fd71433e9d7dd63c95fe7e58d10c9c38080a0c64f346fc7a21f6679cba8abdf37ca2de8c4fcd8f8bcaedb261b5f77627c93908080808080a0ddef2936a67a3ac7d3d4ff15a935a45f2cc4976c8f0310aed85daf763780e2b480', + '0xf843a0200decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563a1a048656c6c6f00000000000000000000000000000000000000000000000000000a' + ] + } + ] + } + res, err = same_types(proof['result'], expected) + assert res, err + +def test_getCode(ethermint, geth): + eth_rpc = ethermint.w3.provider + geth_rpc = geth.w3.provider + make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getCode", ["0x57f96e6b86cdefdb3d412547816a82e3e0ebf9d2", "latest"]) + + # Do an ethereum transfer + contract = deploy_and_wait(ethermint.w3) + code = eth_rpc.make_request( + 'eth_getCode', [contract.address, "latest"] + ) + expected = { + "id": "4", + "jsonrpc": "2.0", + "result": "0x" + } + res, err = same_types(code, expected) + assert res, err + + +def test_getBlockTransactionCountByNumber(ethermint, geth): + eth_rpc = ethermint.w3.provider + geth_rpc = geth.w3.provider + make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBlockTransactionCountByNumber", ["0x0"]) + + make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBlockTransactionCountByNumber", ["0x100"]) + + tx_hash = send_and_get_hash(ethermint.w3) + + tx_res = eth_rpc.make_request('eth_getTransactionByHash', [tx_hash]) + block_hash = tx_res['result']['blockNumber'] + block_res = eth_rpc.make_request('eth_getBlockTransactionCountByNumber', [block_hash]) + + + expected = { + "id": "1", + "jsonrpc": "2.0", + "result": "0x0" + } + res, err = same_types(block_res, expected) + assert res, err + + +# TODO: BYHASH +# def test_getBlockTransactionCountByHash + + +def test_getTransaction(ethermint, geth): + eth_rpc = ethermint.w3.provider + geth_rpc = geth.w3.provider + make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getTransactionByHash", ["0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060"]) + + # FIXME: s key on json is not in both results + tx_hash = send_and_get_hash(ethermint.w3) + + tx_res = eth_rpc.make_request('eth_getTransactionByHash', [tx_hash]) + + expected = { + 'blockHash': '0x4e3a3754410177e6937ef1f84bba68ea139e8d1a2258c5f85db9f1cd715a1bdd', + 'blockNumber': 46147, + 'from': '0xA1E4380A3B1f749673E270229993eE55F35663b4', + 'gas': 21000, + 'gasPrice': None, + 'hash': '0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060', + 'input': '0x', + 'maxFeePerGas': 2000000000, + 'maxPriorityFeePerGas': 1000000000, + 'nonce': 0, + 'to': '0x5DF9B87991262F6BA471F09758CDE1c0FC1De734', + 'transactionIndex': 0, + 'value': 31337, + } + res, err = same_types(tx_res['result'], expected) + assert res, err + +# NOT IMPLEMENTED +# def test_getTransactionRaw(ethermint, geth): +# eth_rpc = ethermint.w3.provider +# geth_rpc = geth.w3.provider +# eth_rsp, geth_rsp = make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getRawTransactionByHash", ["0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060"]) +# res, err = same_types(eth_rsp, geth_rsp) +# print(eth_rsp) +# print(geth_rsp) +# assert res, err + +def test_getTransactionReceipt(ethermint, geth): + eth_rpc = ethermint.w3.provider + geth_rpc = geth.w3.provider + make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getTransactionReceipt", ["0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060"]) + + # FIXME: 'type': '0x0' not in expected, status key on json is not in ethermint + tx_hash = send_and_get_hash(ethermint.w3) + + tx_res = eth_rpc.make_request('eth_getTransactionReceipt', [tx_hash]) + + expected = { + 'blockHash': '0x4e3a3754410177e6937ef1f84bba68ea139e8d1a2258c5f85db9f1cd715a1bdd', + 'blockNumber': 46147, + 'contractAddress': None, + 'cumulativeGasUsed': 21000, + 'from': '0xA1E4380A3B1f749673E270229993eE55F35663b4', + 'gasUsed': 21000, + 'logs': [], + 'logsBloom': '0x000000000000000000000000000000000000000000000000...0000', + 'status': 1, # 0 or 1 + 'to': '0x5DF9B87991262F6BA471F09758CDE1c0FC1De734', + 'transactionHash': '0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060', + 'transactionIndex': 0, + } + res, err = same_types(tx_res, expected) + assert res, err + +def test_feeHistory(ethermint, geth): + eth_rpc = ethermint.w3.provider + geth_rpc = geth.w3.provider + make_same_rpc_calls(eth_rpc, geth_rpc, "eth_feeHistory", [4, 'latest',[10,90]]) + + make_same_rpc_calls(eth_rpc, geth_rpc, "eth_feeHistory", [4, '0x5000',[10,90]]) + + fee_history = eth_rpc.make_request('eth_feeHistory', [4, 'latest',[10,90]]) + expected = { + 'oldestBlock': 3, + 'reward': [[220, 7145389], [1000000, 6000213], [550, 550], [125, 12345678]], + 'baseFeePerGas': [202583058, 177634473, 155594425, 136217133, 119442408], + 'gasUsedRatio': [0.007390479689642084, 0.0036988514889990873, 0.0018512333048507866, 0.00741217041320997] + } + res, err = same_types(fee_history['result'], expected) + assert res, err + +def test_estimateGas(ethermint, geth): + tx = {"to": ADDRS["community"], "from": ADDRS["validator"]} + + eth_rpc = ethermint.w3.provider + geth_rpc = geth.w3.provider + make_same_rpc_calls(eth_rpc, geth_rpc, "eth_estimateGas", [tx]) + make_same_rpc_calls(eth_rpc, geth_rpc, "eth_estimateGas", [{}]) + +def make_same_rpc_calls(rpc1, rpc2, method, params): + res1 = rpc1.make_request( + method, params + ) + res2 = rpc2.make_request( + method, params + ) + res, err = same_types(res1, res2) + assert res, err + +def same_types(objectA, objectB): + + if isinstance(objectA, dict): + if not isinstance(objectB, dict): + return False, 'A is dict, B is not' + keys = list(set(list(objectA.keys()) + list(objectB.keys()))) + for key in keys: + if key in objectB and key in objectA: + if not same_types(objectA[key], objectB[key]): + return False, key + ' key on dict are not of same type' + else: + return False, key + ' key on json is not in both results' + return True, "" + elif isinstance(objectA, list): + if not isinstance(objectB, list): + return False, 'A is list, B is not' + if len(objectA) == 0 and len(objectB) == 0: + return True, "" + if len(objectA) > 0 and len(objectB) > 0: + return same_types(objectA[0], objectB[0]) + else: + return True + elif objectA is None and objectB is None: + return True, "" + elif type(objectA) is type(objectB): + return True, "" + else: + return False, 'different types. A is type '+ type(objectA).__name__ + ' B is type '+ type(objectB).__name__ \ No newline at end of file diff --git a/tests/integration_tests/utils.py b/tests/integration_tests/utils.py index c75de5b625..7b8bf96866 100644 --- a/tests/integration_tests/utils.py +++ b/tests/integration_tests/utils.py @@ -1,5 +1,103 @@ +import configparser +import json +import os +import re import socket +import subprocess +import sys import time +from pathlib import Path + +import bech32 +import eth_utils +import rlp +import toml +from dateutil.parser import isoparse +from dotenv import load_dotenv +from eth_account import Account +from hexbytes import HexBytes +from pystarport import ledger +from web3._utils.method_formatters import receipt_formatter +from web3._utils.transactions import fill_nonce, fill_transaction_defaults +from web3.datastructures import AttributeDict + +load_dotenv(Path(__file__).parent.parent.parent / "scripts/.env") +Account.enable_unaudited_hdwallet_features() +ACCOUNTS = { + "validator": Account.from_mnemonic(os.getenv("VALIDATOR1_MNEMONIC")), + "community": Account.from_mnemonic(os.getenv("COMMUNITY_MNEMONIC")), + "signer1": Account.from_mnemonic(os.getenv("SIGNER1_MNEMONIC")), + "signer2": Account.from_mnemonic(os.getenv("SIGNER2_MNEMONIC")), +} +KEYS = {name: account.key for name, account in ACCOUNTS.items()} +ADDRS = {name: account.address for name, account in ACCOUNTS.items()} +ETHERMINT_ADDRESS_PREFIX = "ethm" +TEST_CONTRACTS = { + "TestERC20A": "TestERC20A.sol", +} + + +def contract_path(name, filename): + return ( + Path(__file__).parent + / "contracts/artifacts/" + / filename + / (name + ".json") + ) + + +CONTRACTS = { + **{ + name: contract_path(name, filename) for name, filename in TEST_CONTRACTS.items() + }, +} + + +def wait_for_fn(name, fn, *, timeout=240, interval=1): + for i in range(int(timeout / interval)): + result = fn() + print("check", name, result) + if result: + break + time.sleep(interval) + else: + raise TimeoutError(f"wait for {name} timeout") + + +def wait_for_block(cli, height, timeout=240): + for i in range(timeout * 2): + try: + status = cli.status() + except AssertionError as e: + print(f"get sync status failed: {e}", file=sys.stderr) + else: + current_height = int(status["SyncInfo"]["latest_block_height"]) + if current_height >= height: + break + print("current block height", current_height) + time.sleep(0.5) + else: + raise TimeoutError(f"wait for block {height} timeout") + + +def wait_for_new_blocks(cli, n, sleep=0.5): + begin_height = int((cli.status())["SyncInfo"]["latest_block_height"]) + while True: + time.sleep(sleep) + cur_height = int((cli.status())["SyncInfo"]["latest_block_height"]) + if cur_height - begin_height >= n: + break + + +def wait_for_block_time(cli, t): + print("wait for block time", t) + while True: + now = isoparse((cli.status())["SyncInfo"]["latest_block_time"]) + print("block time now:", now) + if now >= t: + break + time.sleep(0.5) + def wait_for_port(port, host="127.0.0.1", timeout=40.0): start_time = time.perf_counter() @@ -14,3 +112,324 @@ def wait_for_port(port, host="127.0.0.1", timeout=40.0): "Waited too long for the port {} on host {} to start accepting " "connections.".format(port, host) ) from ex + + +def wait_for_ipc(path, timeout=40.0): + print("wait for unix socket", path, "to be available") + start_time = time.perf_counter() + while True: + if os.path.exists(path): + break + time.sleep(0.1) + if time.perf_counter() - start_time >= timeout: + raise TimeoutError( + "Waited too long for the unix socket {path} to be available" + ) + + +def w3_wait_for_block(w3, height, timeout=240): + for i in range(timeout * 2): + try: + current_height = w3.eth.block_number + except AssertionError as e: + print(f"get current block number failed: {e}", file=sys.stderr) + else: + if current_height >= height: + break + print("current block height", current_height) + time.sleep(0.5) + else: + raise TimeoutError(f"wait for block {height} timeout") + + +def w3_wait_for_new_blocks(w3, n): + begin_height = w3.eth.block_number + while True: + time.sleep(0.5) + cur_height = w3.eth.block_number + if cur_height - begin_height >= n: + break + + +def get_ledger(): + return ledger.Ledger() + + +def parse_events(logs): + return { + ev["type"]: {attr["key"]: attr["value"] for attr in ev["attributes"]} + for ev in logs[0]["events"] + } + + +_next_unique = 0 + + +def gen_base_port(worker_index): + global _next_unique + base_port = 10000 + (worker_index * 10 + _next_unique) * 100 + _next_unique += 1 + return base_port + + +def sign_single_tx_with_options(cli, tx_file, singer_name, **options): + return json.loads( + cli.cosmos_cli(0).raw( + "tx", + "sign", + tx_file, + from_=singer_name, + home=cli.cosmos_cli(0).data_dir, + keyring_backend="test", + chain_id=cli.cosmos_cli(0).chain_id, + node=cli.cosmos_cli(0).node_rpc, + **options, + ) + ) + + +def find_balance(balances, denom): + "find a denom in the coin list, return the amount, if not exists, return 0" + for balance in balances: + if balance["denom"] == denom: + return int(balance["amount"]) + return 0 + + +class ContractAddress(rlp.Serializable): + fields = [ + ("from", rlp.sedes.Binary()), + ("nonce", rlp.sedes.big_endian_int), + ] + + +def contract_address(addr, nonce): + return eth_utils.to_checksum_address( + eth_utils.to_hex( + eth_utils.keccak( + rlp.encode(ContractAddress(eth_utils.to_bytes(hexstr=addr), nonce)) + )[12:] + ) + ) + + +def decode_bech32(addr): + _, bz = bech32.bech32_decode(addr) + return HexBytes(bytes(bech32.convertbits(bz, 5, 8))) + + +def bech32_to_eth(addr): + return decode_bech32(addr).hex() + + +def eth_to_bech32(addr, prefix=ETHERMINT_ADDRESS_PREFIX): + bz = bech32.convertbits(HexBytes(addr), 8, 5) + return bech32.bech32_encode(prefix, bz) + + +def add_ini_sections(inipath, sections): + ini = configparser.RawConfigParser() + ini.read(inipath) + for name, value in sections.items(): + ini.add_section(name) + ini[name].update(value) + with inipath.open("w") as fp: + ini.write(fp) + + +def supervisorctl(inipath, *args): + subprocess.run( + (sys.executable, "-msupervisor.supervisorctl", "-c", inipath, *args), + check=True, + ) + + +def deploy_contract(w3, jsonfile, args=(), key=KEYS["validator"]): + """ + deploy contract and return the deployed contract instance + """ + acct = Account.from_key(key) + info = json.loads(jsonfile.read_text()) + contract = w3.eth.contract(abi=info["abi"], bytecode=info["bytecode"]) + tx = contract.constructor(*args).buildTransaction({"from": acct.address}) + txreceipt = send_transaction(w3, tx, key) + assert txreceipt.status == 1 + address = txreceipt.contractAddress + return w3.eth.contract(address=address, abi=info["abi"]) + + +def sign_transaction(w3, tx, key=KEYS["validator"]): + "fill default fields and sign" + acct = Account.from_key(key) + tx["from"] = acct.address + tx = fill_transaction_defaults(w3, tx) + tx = fill_nonce(w3, tx) + return acct.sign_transaction(tx) + + +def send_transaction(w3, tx, key=KEYS["validator"]): + signed = sign_transaction(w3, tx, key) + txhash = w3.eth.send_raw_transaction(signed.rawTransaction) + return w3.eth.wait_for_transaction_receipt(txhash) + + +def cronos_address_from_mnemonics(mnemonics, prefix=ETHERMINT_ADDRESS_PREFIX): + "return cronos address from mnemonics" + acct = Account.from_mnemonic(mnemonics) + return eth_to_bech32(acct.address, prefix) + + +def send_to_cosmos(gravity_contract, token_contract, recipient, amount, key=None): + """ + do approve and sendToCronos on ethereum side + """ + acct = Account.from_key(key) + txreceipt = send_transaction( + token_contract.web3, + token_contract.functions.approve( + gravity_contract.address, amount + ).buildTransaction({"from": acct.address}), + key, + ) + assert txreceipt.status == 1, "approve failed" + + return send_transaction( + gravity_contract.web3, + gravity_contract.functions.sendToCronos( + token_contract.address, HexBytes(recipient), amount + ).buildTransaction({"from": acct.address}), + key, + ) + + +class InlineTable(dict, toml.decoder.InlineTableDict): + "a hack to dump inline table with toml library" + pass + + +def dump_toml(obj): + return toml.dumps(obj, encoder=toml.TomlPreserveInlineDictEncoder()) + + +class Contract: + "General contract." + + def __init__(self, contract_path, private_key=KEYS["validator"], chain_id=777): + self.chain_id = chain_id + self.account = Account.from_key(private_key) + self.address = self.account.address + self.private_key = private_key + with open(contract_path) as f: + json_data = f.read() + contract_json = json.loads(json_data) + self.bytecode = contract_json["bytecode"] + self.abi = contract_json["abi"] + self.contract = None + self.w3 = None + + def deploy(self, w3): + "Deploy Greeter contract on `w3` and return the receipt." + if self.contract is None: + self.w3 = w3 + contract = self.w3.eth.contract(abi=self.abi, bytecode=self.bytecode) + transaction = contract.constructor().buildTransaction( + {"chainId": self.chain_id, "from": self.address} + ) + receipt = send_transaction(self.w3, transaction, self.private_key) + self.contract = self.w3.eth.contract( + address=receipt.contractAddress, abi=self.abi + ) + return receipt + else: + return receipt + + +class Greeter(Contract): + "Greeter contract." + + def transfer(self, string): + "Call contract on `w3` and return the receipt." + transaction = self.contract.functions.setGreeting(string).buildTransaction( + { + "chainId": self.chain_id, + "from": self.address, + } + ) + receipt = send_transaction(self.w3, transaction, self.private_key) + assert string == self.contract.functions.greet().call() + return receipt + + +class RevertTestContract(Contract): + "RevertTestContract contract." + + def transfer(self, value): + "Call contract on `w3` and return the receipt." + transaction = self.contract.functions.transfer(value).buildTransaction( + { + "chainId": self.chain_id, + "from": self.address, + "gas": 100000, # skip estimateGas error + } + ) + receipt = send_transaction(self.w3, transaction, self.private_key) + return receipt + + +def modify_command_in_supervisor_config(ini: Path, fn, **kwargs): + "replace the first node with the instrumented binary" + ini.write_text( + re.sub( + r"^command = (cronosd .*$)", + lambda m: f"command = {fn(m.group(1))}", + ini.read_text(), + flags=re.M, + **kwargs, + ) + ) + + +def build_batch_tx(w3, cli, txs, key=KEYS["validator"]): + "return cosmos batch tx and eth tx hashes" + signed_txs = [sign_transaction(w3, tx, key) for tx in txs] + tmp_txs = [cli.build_evm_tx(signed.rawTransaction.hex()) for signed in signed_txs] + + msgs = [tx["body"]["messages"][0] for tx in tmp_txs] + fee = sum(int(tx["auth_info"]["fee"]["amount"][0]["amount"]) for tx in tmp_txs) + gas_limit = sum(int(tx["auth_info"]["fee"]["gas_limit"]) for tx in tmp_txs) + + tx_hashes = [signed.hash for signed in signed_txs] + + # build batch cosmos tx + return { + "body": { + "messages": msgs, + "memo": "", + "timeout_height": "0", + "extension_options": [ + {"@type": "/ethermint.evm.v1.ExtensionOptionsEthereumTx"} + ], + "non_critical_extension_options": [], + }, + "auth_info": { + "signer_infos": [], + "fee": { + "amount": [{"denom": "basetcro", "amount": str(fee)}], + "gas_limit": str(gas_limit), + "payer": "", + "granter": "", + }, + }, + "signatures": [], + }, tx_hashes + + +def get_receipts_by_block(w3, blk): + if isinstance(blk, int): + blk = hex(blk) + rsp = w3.provider.make_request("cronos_getTransactionReceiptsByBlock", [blk]) + if "error" not in rsp: + rsp["result"] = [ + AttributeDict(receipt_formatter(item)) for item in rsp["result"] + ] + return rsp From e13a825ad30f05863de6f38eca910b6443e78a40 Mon Sep 17 00:00:00 2001 From: ramacarlucho Date: Wed, 27 Jul 2022 17:37:51 -0300 Subject: [PATCH 2/7] cleanup --- tests/integration_tests/utils.py | 348 +------------------------------ 1 file changed, 1 insertion(+), 347 deletions(-) diff --git a/tests/integration_tests/utils.py b/tests/integration_tests/utils.py index 7b8bf96866..6fe1673fa6 100644 --- a/tests/integration_tests/utils.py +++ b/tests/integration_tests/utils.py @@ -1,25 +1,12 @@ -import configparser import json import os -import re import socket -import subprocess -import sys import time from pathlib import Path -import bech32 -import eth_utils -import rlp -import toml -from dateutil.parser import isoparse from dotenv import load_dotenv from eth_account import Account -from hexbytes import HexBytes -from pystarport import ledger -from web3._utils.method_formatters import receipt_formatter from web3._utils.transactions import fill_nonce, fill_transaction_defaults -from web3.datastructures import AttributeDict load_dotenv(Path(__file__).parent.parent.parent / "scripts/.env") Account.enable_unaudited_hdwallet_features() @@ -36,7 +23,6 @@ "TestERC20A": "TestERC20A.sol", } - def contract_path(name, filename): return ( Path(__file__).parent @@ -52,53 +38,6 @@ def contract_path(name, filename): }, } - -def wait_for_fn(name, fn, *, timeout=240, interval=1): - for i in range(int(timeout / interval)): - result = fn() - print("check", name, result) - if result: - break - time.sleep(interval) - else: - raise TimeoutError(f"wait for {name} timeout") - - -def wait_for_block(cli, height, timeout=240): - for i in range(timeout * 2): - try: - status = cli.status() - except AssertionError as e: - print(f"get sync status failed: {e}", file=sys.stderr) - else: - current_height = int(status["SyncInfo"]["latest_block_height"]) - if current_height >= height: - break - print("current block height", current_height) - time.sleep(0.5) - else: - raise TimeoutError(f"wait for block {height} timeout") - - -def wait_for_new_blocks(cli, n, sleep=0.5): - begin_height = int((cli.status())["SyncInfo"]["latest_block_height"]) - while True: - time.sleep(sleep) - cur_height = int((cli.status())["SyncInfo"]["latest_block_height"]) - if cur_height - begin_height >= n: - break - - -def wait_for_block_time(cli, t): - print("wait for block time", t) - while True: - now = isoparse((cli.status())["SyncInfo"]["latest_block_time"]) - print("block time now:", now) - if now >= t: - break - time.sleep(0.5) - - def wait_for_port(port, host="127.0.0.1", timeout=40.0): start_time = time.perf_counter() while True: @@ -113,35 +52,6 @@ def wait_for_port(port, host="127.0.0.1", timeout=40.0): "connections.".format(port, host) ) from ex - -def wait_for_ipc(path, timeout=40.0): - print("wait for unix socket", path, "to be available") - start_time = time.perf_counter() - while True: - if os.path.exists(path): - break - time.sleep(0.1) - if time.perf_counter() - start_time >= timeout: - raise TimeoutError( - "Waited too long for the unix socket {path} to be available" - ) - - -def w3_wait_for_block(w3, height, timeout=240): - for i in range(timeout * 2): - try: - current_height = w3.eth.block_number - except AssertionError as e: - print(f"get current block number failed: {e}", file=sys.stderr) - else: - if current_height >= height: - break - print("current block height", current_height) - time.sleep(0.5) - else: - raise TimeoutError(f"wait for block {height} timeout") - - def w3_wait_for_new_blocks(w3, n): begin_height = w3.eth.block_number while True: @@ -150,100 +60,6 @@ def w3_wait_for_new_blocks(w3, n): if cur_height - begin_height >= n: break - -def get_ledger(): - return ledger.Ledger() - - -def parse_events(logs): - return { - ev["type"]: {attr["key"]: attr["value"] for attr in ev["attributes"]} - for ev in logs[0]["events"] - } - - -_next_unique = 0 - - -def gen_base_port(worker_index): - global _next_unique - base_port = 10000 + (worker_index * 10 + _next_unique) * 100 - _next_unique += 1 - return base_port - - -def sign_single_tx_with_options(cli, tx_file, singer_name, **options): - return json.loads( - cli.cosmos_cli(0).raw( - "tx", - "sign", - tx_file, - from_=singer_name, - home=cli.cosmos_cli(0).data_dir, - keyring_backend="test", - chain_id=cli.cosmos_cli(0).chain_id, - node=cli.cosmos_cli(0).node_rpc, - **options, - ) - ) - - -def find_balance(balances, denom): - "find a denom in the coin list, return the amount, if not exists, return 0" - for balance in balances: - if balance["denom"] == denom: - return int(balance["amount"]) - return 0 - - -class ContractAddress(rlp.Serializable): - fields = [ - ("from", rlp.sedes.Binary()), - ("nonce", rlp.sedes.big_endian_int), - ] - - -def contract_address(addr, nonce): - return eth_utils.to_checksum_address( - eth_utils.to_hex( - eth_utils.keccak( - rlp.encode(ContractAddress(eth_utils.to_bytes(hexstr=addr), nonce)) - )[12:] - ) - ) - - -def decode_bech32(addr): - _, bz = bech32.bech32_decode(addr) - return HexBytes(bytes(bech32.convertbits(bz, 5, 8))) - - -def bech32_to_eth(addr): - return decode_bech32(addr).hex() - - -def eth_to_bech32(addr, prefix=ETHERMINT_ADDRESS_PREFIX): - bz = bech32.convertbits(HexBytes(addr), 8, 5) - return bech32.bech32_encode(prefix, bz) - - -def add_ini_sections(inipath, sections): - ini = configparser.RawConfigParser() - ini.read(inipath) - for name, value in sections.items(): - ini.add_section(name) - ini[name].update(value) - with inipath.open("w") as fp: - ini.write(fp) - - -def supervisorctl(inipath, *args): - subprocess.run( - (sys.executable, "-msupervisor.supervisorctl", "-c", inipath, *args), - check=True, - ) - - def deploy_contract(w3, jsonfile, args=(), key=KEYS["validator"]): """ deploy contract and return the deployed contract instance @@ -270,166 +86,4 @@ def sign_transaction(w3, tx, key=KEYS["validator"]): def send_transaction(w3, tx, key=KEYS["validator"]): signed = sign_transaction(w3, tx, key) txhash = w3.eth.send_raw_transaction(signed.rawTransaction) - return w3.eth.wait_for_transaction_receipt(txhash) - - -def cronos_address_from_mnemonics(mnemonics, prefix=ETHERMINT_ADDRESS_PREFIX): - "return cronos address from mnemonics" - acct = Account.from_mnemonic(mnemonics) - return eth_to_bech32(acct.address, prefix) - - -def send_to_cosmos(gravity_contract, token_contract, recipient, amount, key=None): - """ - do approve and sendToCronos on ethereum side - """ - acct = Account.from_key(key) - txreceipt = send_transaction( - token_contract.web3, - token_contract.functions.approve( - gravity_contract.address, amount - ).buildTransaction({"from": acct.address}), - key, - ) - assert txreceipt.status == 1, "approve failed" - - return send_transaction( - gravity_contract.web3, - gravity_contract.functions.sendToCronos( - token_contract.address, HexBytes(recipient), amount - ).buildTransaction({"from": acct.address}), - key, - ) - - -class InlineTable(dict, toml.decoder.InlineTableDict): - "a hack to dump inline table with toml library" - pass - - -def dump_toml(obj): - return toml.dumps(obj, encoder=toml.TomlPreserveInlineDictEncoder()) - - -class Contract: - "General contract." - - def __init__(self, contract_path, private_key=KEYS["validator"], chain_id=777): - self.chain_id = chain_id - self.account = Account.from_key(private_key) - self.address = self.account.address - self.private_key = private_key - with open(contract_path) as f: - json_data = f.read() - contract_json = json.loads(json_data) - self.bytecode = contract_json["bytecode"] - self.abi = contract_json["abi"] - self.contract = None - self.w3 = None - - def deploy(self, w3): - "Deploy Greeter contract on `w3` and return the receipt." - if self.contract is None: - self.w3 = w3 - contract = self.w3.eth.contract(abi=self.abi, bytecode=self.bytecode) - transaction = contract.constructor().buildTransaction( - {"chainId": self.chain_id, "from": self.address} - ) - receipt = send_transaction(self.w3, transaction, self.private_key) - self.contract = self.w3.eth.contract( - address=receipt.contractAddress, abi=self.abi - ) - return receipt - else: - return receipt - - -class Greeter(Contract): - "Greeter contract." - - def transfer(self, string): - "Call contract on `w3` and return the receipt." - transaction = self.contract.functions.setGreeting(string).buildTransaction( - { - "chainId": self.chain_id, - "from": self.address, - } - ) - receipt = send_transaction(self.w3, transaction, self.private_key) - assert string == self.contract.functions.greet().call() - return receipt - - -class RevertTestContract(Contract): - "RevertTestContract contract." - - def transfer(self, value): - "Call contract on `w3` and return the receipt." - transaction = self.contract.functions.transfer(value).buildTransaction( - { - "chainId": self.chain_id, - "from": self.address, - "gas": 100000, # skip estimateGas error - } - ) - receipt = send_transaction(self.w3, transaction, self.private_key) - return receipt - - -def modify_command_in_supervisor_config(ini: Path, fn, **kwargs): - "replace the first node with the instrumented binary" - ini.write_text( - re.sub( - r"^command = (cronosd .*$)", - lambda m: f"command = {fn(m.group(1))}", - ini.read_text(), - flags=re.M, - **kwargs, - ) - ) - - -def build_batch_tx(w3, cli, txs, key=KEYS["validator"]): - "return cosmos batch tx and eth tx hashes" - signed_txs = [sign_transaction(w3, tx, key) for tx in txs] - tmp_txs = [cli.build_evm_tx(signed.rawTransaction.hex()) for signed in signed_txs] - - msgs = [tx["body"]["messages"][0] for tx in tmp_txs] - fee = sum(int(tx["auth_info"]["fee"]["amount"][0]["amount"]) for tx in tmp_txs) - gas_limit = sum(int(tx["auth_info"]["fee"]["gas_limit"]) for tx in tmp_txs) - - tx_hashes = [signed.hash for signed in signed_txs] - - # build batch cosmos tx - return { - "body": { - "messages": msgs, - "memo": "", - "timeout_height": "0", - "extension_options": [ - {"@type": "/ethermint.evm.v1.ExtensionOptionsEthereumTx"} - ], - "non_critical_extension_options": [], - }, - "auth_info": { - "signer_infos": [], - "fee": { - "amount": [{"denom": "basetcro", "amount": str(fee)}], - "gas_limit": str(gas_limit), - "payer": "", - "granter": "", - }, - }, - "signatures": [], - }, tx_hashes - - -def get_receipts_by_block(w3, blk): - if isinstance(blk, int): - blk = hex(blk) - rsp = w3.provider.make_request("cronos_getTransactionReceiptsByBlock", [blk]) - if "error" not in rsp: - rsp["result"] = [ - AttributeDict(receipt_formatter(item)) for item in rsp["result"] - ] - return rsp + return w3.eth.wait_for_transaction_receipt(txhash) \ No newline at end of file From e245426e595718ca78203190d90d791082dfe1b7 Mon Sep 17 00:00:00 2001 From: ramacarlucho Date: Wed, 27 Jul 2022 19:23:27 -0300 Subject: [PATCH 3/7] cleanup --- tests/integration_tests/test_types.py | 37 +++++++++++++++------------ 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/tests/integration_tests/test_types.py b/tests/integration_tests/test_types.py index d541acbb6f..9649be8349 100644 --- a/tests/integration_tests/test_types.py +++ b/tests/integration_tests/test_types.py @@ -201,27 +201,31 @@ def test_getTransaction(ethermint, geth): geth_rpc = geth.w3.provider make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getTransactionByHash", ["0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060"]) - # FIXME: s key on json is not in both results tx_hash = send_and_get_hash(ethermint.w3) tx_res = eth_rpc.make_request('eth_getTransactionByHash', [tx_hash]) expected = { - 'blockHash': '0x4e3a3754410177e6937ef1f84bba68ea139e8d1a2258c5f85db9f1cd715a1bdd', - 'blockNumber': 46147, - 'from': '0xA1E4380A3B1f749673E270229993eE55F35663b4', - 'gas': 21000, - 'gasPrice': None, - 'hash': '0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060', - 'input': '0x', - 'maxFeePerGas': 2000000000, - 'maxPriorityFeePerGas': 1000000000, - 'nonce': 0, - 'to': '0x5DF9B87991262F6BA471F09758CDE1c0FC1De734', - 'transactionIndex': 0, - 'value': 31337, + "jsonrpc": "2.0", + "id": 0, + "result": { + "hash": "0x88df016429689c079f3b2f6ad39fa052532c56795b733da78a91ebe6a713944b", + "blockHash": "0x1d59ff54b1eb26b013ce3cb5fc9dab3705b415a67127a003c3e61eb445bb8df2", + "blockNumber": "0x5daf3b", + "from": "0xa7d9ddbe1f17865597fbd27ec712455208b6b76d", + "gas": "0xc350", + "gasPrice": "0x4a817c800", + "input": "0x68656c6c6f21", + "nonce": "0x15", + "r": "0x1b5e176d927f8e9ab405058b2d2457392da3e20f328b16ddabcebc33eaac5fea", + "s": "0x4ba69724e8f69de52f0125ad8b3c5c2cef33019bac3249e2c0a2192766d1721c", + "to": "0xf02c1c8e6114b1dbe8937a39260b5b0a374432bb", + "transactionIndex": "0x41", + "v": "0x25", + "value": "0xf3dbb76162000" } - res, err = same_types(tx_res['result'], expected) + } + res, err = same_types(tx_res, expected) assert res, err # NOT IMPLEMENTED @@ -243,7 +247,6 @@ def test_getTransactionReceipt(ethermint, geth): tx_hash = send_and_get_hash(ethermint.w3) tx_res = eth_rpc.make_request('eth_getTransactionReceipt', [tx_hash]) - expected = { 'blockHash': '0x4e3a3754410177e6937ef1f84bba68ea139e8d1a2258c5f85db9f1cd715a1bdd', 'blockNumber': 46147, @@ -258,7 +261,7 @@ def test_getTransactionReceipt(ethermint, geth): 'transactionHash': '0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060', 'transactionIndex': 0, } - res, err = same_types(tx_res, expected) + res, err = same_types(tx_res['result'], expected) assert res, err def test_feeHistory(ethermint, geth): From fdf9610e623db7dd0de9149c2497a720f60e6593 Mon Sep 17 00:00:00 2001 From: Ramiro Carlucho Date: Thu, 4 Aug 2022 13:15:39 +0100 Subject: [PATCH 4/7] fix differences in the rpc calls with geth --- rpc/backend/evm_backend.go | 14 +++++++------- rpc/backend/evm_backend_test.go | 6 +++--- rpc/namespaces/ethereum/eth/api.go | 6 +++++- .../contracts/{TestERC20.sol => TestERC20A.sol} | 0 tests/integration_tests/test_types.py | 5 ----- tests/integration_tests/utils.py | 2 +- 6 files changed, 16 insertions(+), 17 deletions(-) rename tests/integration_tests/contracts/contracts/{TestERC20.sol => TestERC20A.sol} (100%) diff --git a/rpc/backend/evm_backend.go b/rpc/backend/evm_backend.go index 4abad1e8f2..6b678f5c43 100644 --- a/rpc/backend/evm_backend.go +++ b/rpc/backend/evm_backend.go @@ -62,7 +62,7 @@ func (b *Backend) BlockNumber() (hexutil.Uint64, error) { func (b *Backend) GetBlockByNumber(blockNum types.BlockNumber, fullTx bool) (map[string]interface{}, error) { resBlock, err := b.GetTendermintBlockByNumber(blockNum) if err != nil { - return nil, err + return nil, nil } // return if requested block height is greater than the current one @@ -939,18 +939,18 @@ func (b *Backend) FeeHistory( // fetch block for blockID := blockStart; blockID < blockEnd; blockID++ { index := int32(blockID - blockStart) - // eth block - ethBlock, err := b.GetBlockByNumber(types.BlockNumber(blockID), true) - if ethBlock == nil { - return nil, err - } - // tendermint block tendermintblock, err := b.GetTendermintBlockByNumber(types.BlockNumber(blockID)) if tendermintblock == nil { return nil, err } + // eth block + ethBlock, err := b.GetBlockByNumber(types.BlockNumber(blockID), true) + if ethBlock == nil { + return nil, err + } + // tendermint block result tendermintBlockResult, err := b.GetTendermintBlockResultByNumber(&tendermintblock.Block.Height) if tendermintBlockResult == nil { diff --git a/rpc/backend/evm_backend_test.go b/rpc/backend/evm_backend_test.go index 332ec3393f..82f40ddf53 100644 --- a/rpc/backend/evm_backend_test.go +++ b/rpc/backend/evm_backend_test.go @@ -98,7 +98,7 @@ func (suite *BackendTestSuite) TestGetBlockByNumber() { expPass bool }{ { - "fail - tendermint block error", + "pass - tendermint block not found", ethrpc.BlockNumber(1), true, sdk.NewInt(1).BigInt(), @@ -110,8 +110,8 @@ func (suite *BackendTestSuite) TestGetBlockByNumber() { client := suite.backend.clientCtx.Client.(*mocks.Client) RegisterBlockError(client, height) }, - false, - false, + true, + true, }, { "pass - block not found (e.g. request block height that is greater than current one)", diff --git a/rpc/namespaces/ethereum/eth/api.go b/rpc/namespaces/ethereum/eth/api.go index b72687b8c5..ca27a77fef 100644 --- a/rpc/namespaces/ethereum/eth/api.go +++ b/rpc/namespaces/ethereum/eth/api.go @@ -284,6 +284,11 @@ func (e *PublicAPI) GetBalance(address common.Address, blockNrOrHash rpctypes.Bl Address: address.String(), } + _, err = e.backend.GetTendermintBlockByNumber(blockNum) + if err != nil { + return nil, errors.New("header not found") + } + res, err := e.queryClient.Balance(rpctypes.ContextWithHeight(blockNum.Int64()), req) if err != nil { return nil, err @@ -946,7 +951,6 @@ func (e *PublicAPI) GetTransactionReceipt(hash common.Hash) (map[string]interfac "transactionHash": hash, "contractAddress": nil, "gasUsed": hexutil.Uint64(parsedTx.GasUsed), - "type": hexutil.Uint(txData.TxType()), // Inclusion information: These fields provide information about the inclusion of the // transaction corresponding to this receipt. diff --git a/tests/integration_tests/contracts/contracts/TestERC20.sol b/tests/integration_tests/contracts/contracts/TestERC20A.sol similarity index 100% rename from tests/integration_tests/contracts/contracts/TestERC20.sol rename to tests/integration_tests/contracts/contracts/TestERC20A.sol diff --git a/tests/integration_tests/test_types.py b/tests/integration_tests/test_types.py index 9649be8349..d70fb738c4 100644 --- a/tests/integration_tests/test_types.py +++ b/tests/integration_tests/test_types.py @@ -20,9 +20,6 @@ def get_blocks(ethermint, geth, with_transactions): geth_rpc = geth.w3.provider make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBlockByNumber", ['0x0', with_transactions]) - # FIXME: Fails - # {'jsonrpc': '2.0', 'id': 20, 'error': {'code': -32000, 'message': 'height 10000 must be less than or equal to the current blockchain height 18'}} - # {'jsonrpc': '2.0', 'id': 2, 'result': None} make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBlockByNumber", ['0x2710', with_transactions]) ethermint_blk = ethermint.w3.eth.get_block(1) @@ -84,7 +81,6 @@ def test_balance(ethermint, geth): make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBalance", ["0x57f96e6b86cdefdb3d412547816a82e3e0ebf9d2", '0x0']) make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBalance", ["0",'0x0']) make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBalance", ["0x9907a0cf64ec9fbf6ed8fd4971090de88222a9ac",'0x0']) - # FIXME: BAD ERROR make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBalance", ["0x57f96e6b86cdefdb3d412547816a82e3e0ebf9d2", '0x10000']) make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBalance", ["0",'0x10000']) make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBalance", ["0x9907a0cf64ec9fbf6ed8fd4971090de88222a9ac",'0x10000']) @@ -243,7 +239,6 @@ def test_getTransactionReceipt(ethermint, geth): geth_rpc = geth.w3.provider make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getTransactionReceipt", ["0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060"]) - # FIXME: 'type': '0x0' not in expected, status key on json is not in ethermint tx_hash = send_and_get_hash(ethermint.w3) tx_res = eth_rpc.make_request('eth_getTransactionReceipt', [tx_hash]) diff --git a/tests/integration_tests/utils.py b/tests/integration_tests/utils.py index 6fe1673fa6..b41896ec15 100644 --- a/tests/integration_tests/utils.py +++ b/tests/integration_tests/utils.py @@ -26,7 +26,7 @@ def contract_path(name, filename): return ( Path(__file__).parent - / "contracts/artifacts/" + / "contracts/artifacts/contracts" / filename / (name + ".json") ) From 7475cc336159aa843d8f0f67c394bb7558624125 Mon Sep 17 00:00:00 2001 From: Ramiro Carlucho Date: Thu, 4 Aug 2022 16:12:54 +0100 Subject: [PATCH 5/7] cleanup --- tests/integration_tests/test_types.py | 32 ++++++++++++--------------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/tests/integration_tests/test_types.py b/tests/integration_tests/test_types.py index d70fb738c4..e9aad04dd1 100644 --- a/tests/integration_tests/test_types.py +++ b/tests/integration_tests/test_types.py @@ -9,8 +9,6 @@ w3_wait_for_new_blocks, ) -txhash = "" - def test_block(ethermint, geth): get_blocks(ethermint, geth, False) get_blocks(ethermint, geth, True) @@ -175,21 +173,29 @@ def test_getBlockTransactionCountByNumber(ethermint, geth): tx_hash = send_and_get_hash(ethermint.w3) tx_res = eth_rpc.make_request('eth_getTransactionByHash', [tx_hash]) - block_hash = tx_res['result']['blockNumber'] - block_res = eth_rpc.make_request('eth_getBlockTransactionCountByNumber', [block_hash]) - + block_number = tx_res['result']['blockNumber'] + block_hash = tx_res['result']['blockHash'] + block_res = eth_rpc.make_request('eth_getBlockTransactionCountByNumber', [block_number]) + + expected = { + "id": "1", + "jsonrpc": "2.0", + "result": "0x1" + } + res, err = same_types(block_res, expected) + assert res, err + make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBlockTransactionCountByHash", ["0x4e3a3754410177e6937ef1f84bba68ea139e8d1a2258c5f85db9f1cd715a1bdd"]) + block_res = eth_rpc.make_request('eth_getBlockTransactionCountByHash', [block_hash]) expected = { "id": "1", "jsonrpc": "2.0", - "result": "0x0" + "result": "0x1" } res, err = same_types(block_res, expected) assert res, err -# TODO: BYHASH -# def test_getBlockTransactionCountByHash def test_getTransaction(ethermint, geth): @@ -224,16 +230,6 @@ def test_getTransaction(ethermint, geth): res, err = same_types(tx_res, expected) assert res, err -# NOT IMPLEMENTED -# def test_getTransactionRaw(ethermint, geth): -# eth_rpc = ethermint.w3.provider -# geth_rpc = geth.w3.provider -# eth_rsp, geth_rsp = make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getRawTransactionByHash", ["0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060"]) -# res, err = same_types(eth_rsp, geth_rsp) -# print(eth_rsp) -# print(geth_rsp) -# assert res, err - def test_getTransactionReceipt(ethermint, geth): eth_rpc = ethermint.w3.provider geth_rpc = geth.w3.provider From 8a48f1bebaa4627d917d5b8e423276095cad24db Mon Sep 17 00:00:00 2001 From: Ramiro Carlucho Date: Mon, 8 Aug 2022 13:25:49 +0100 Subject: [PATCH 6/7] fix linter. getProof future queries now behave as geth --- rpc/namespaces/ethereum/eth/api.go | 8 +- tests/integration_tests/expected_constants.py | 76 ++++ tests/integration_tests/test_types.py | 367 ++++++++++-------- tests/integration_tests/utils.py | 11 - 4 files changed, 284 insertions(+), 178 deletions(-) create mode 100644 tests/integration_tests/expected_constants.py diff --git a/rpc/namespaces/ethereum/eth/api.go b/rpc/namespaces/ethereum/eth/api.go index 45bfca5509..e03713677b 100644 --- a/rpc/namespaces/ethereum/eth/api.go +++ b/rpc/namespaces/ethereum/eth/api.go @@ -286,7 +286,7 @@ func (e *PublicAPI) GetBalance(address common.Address, blockNrOrHash rpctypes.Bl _, err = e.backend.GetTendermintBlockByNumber(blockNum) if err != nil { - return nil, errors.New("header not found") + return nil, err } res, err := e.queryClient.Balance(rpctypes.ContextWithHeight(blockNum.Int64()), req) @@ -1047,6 +1047,12 @@ func (e *PublicAPI) GetProof(address common.Address, storageKeys []string, block } height := blockNum.Int64() + _, err = e.backend.GetTendermintBlockByNumber(blockNum) + if err != nil { + // Get 'latest' proof if query is in the future + // this imitates geth behaviour + height = 0 + } ctx := rpctypes.ContextWithHeight(height) // if the height is equal to zero, meaning the query condition of the block is either "pending" or "latest" diff --git a/tests/integration_tests/expected_constants.py b/tests/integration_tests/expected_constants.py new file mode 100644 index 0000000000..41abb0ad3a --- /dev/null +++ b/tests/integration_tests/expected_constants.py @@ -0,0 +1,76 @@ +EXPECTED_GET_STORAGE_AT = ( + "0x00000000000000000000000000000000000000000000000000120a0b063499d4" +) + +EXPECTED_GET_PROOF = { + "address": "0x4CB06C43fcdABeA22541fcF1F856A6a296448B6c", + "accountProof": [ + "0xf90211a03841a7ddd65c70c94b8efa79190d00f0ab134b26f18dcad508f60a7e74559d0ba0464b07429a05039e22931492d6c6251a860c018ea390045d596b1ac11b5c7aa7a011f4b89823a03c9c4b5a8ab079ee1bc0e2a83a508bb7a5dc7d7fb4f2e95d3186a0b5f7c51c3b2d51d97f171d2b38a4df1a7c0acc5eb0de46beeff4d07f5ed20e19a0b591a2ce02367eda31cf2d16eca7c27fd44dbf0864b64ea8259ad36696eb2a04a02b646a7552b8392ae94263757f699a27d6e9176b4c06b9fc0a722f893b964795a02df05d68bceb88eebf68aafde61d10ab942097afc1c58b8435ffd3895358a742a0c2f16143c4d1db03276c433696dddb3e9f3b113bcd854b127962262e98f43147a0828820316cc02bfefd899aba41340659fd06df1e0a0796287ec2a4110239f6d2a050496598670b04df7bbff3718887fa36437d6d8c7afb4eff86f76c5c7097dcc4a0c14e9060c6b3784e35b9e6ae2ad2984142a75910ccc89eb89dc1e2f44b6c58c2a009804db571d0ce07913e1cbacc4f1dc4fb8265c936f5c612e3a47e91c64d8e9fa063d96f38b3cb51b1665c6641e25ffe24803f2941e5df79942f6a53b7169647e4a0899f71abb18c6c956118bf567fac629b75f7e9526873e429d3d8abb6dbb58021a00fd717235298742623c0b3cafb3e4bd86c0b5ab1f71097b4dd19f3d6925d758da0096437146c16097f2ccc1d3e910d65a4132803baee2249e72c8bf0bcaaeb37e580", # noqa: E501 + "0xf90151a097b17a89fd2c03ee98cb6459c08f51b269da5cee46650e84470f62bf83b43efe80a03b269d284a4c3cf8f8deacafb637c6d77f607eec8d75e8548d778e629612310480a01403217a7f1416830c870087c524dabade3985271f6f369a12b010883c71927aa0f592ac54c879817389663be677166f5022943e2fe1b52617a1d15c2f353f27dda0ac8d015a9e668f5877fcc391fae33981c00577096f0455b42df4f8e8089ece24a003ba34a13e2f2fb4bf7096540b42d4955c5269875b9cf0f7b87632585d44c9a580a0b179e3230b07db294473ae57f0170262798f8c551c755b5665ace1215cee10ca80a0552d24252639a6ae775aa1df700ffb92c2411daea7286f158d44081c8172d072a0772a87d08cf38c4c68bfde770968571abd16fd3835cb902486bd2e515d53c12d80a0413774f3d900d2d2be7a3ad999ffa859a471dc03a74fb9a6d8275455f5496a548080", # noqa: E501 + "0xf869a020d13b52a61d3c1325ce3626a51418adebd6323d4840f1bdd93906359d11c933b846f8440180a01ab7c0b0a2a4bbb5a1495da8c142150891fc64e0c321e1feb70bd5f881951f7ea0551332d96d085185ab4019ad8bcf89c45321e136c261eb6271e574a2edf1461f", # noqa: E501 + ], + "balance": 0, + "codeHash": "0x551332d96d085185ab4019ad8bcf89c45321e136c261eb6271e574a2edf1461f", # noqa: E501 + "nonce": 1, + "storageHash": "0x1ab7c0b0a2a4bbb5a1495da8c142150891fc64e0c321e1feb70bd5f881951f7e", # noqa: E501 + "storageProof": [ + { + "key": "0x00", + "value": "0x48656c6c6f00000000000000000000000000000000000000000000000000000a", # noqa: E501 + "proof": [ + "0xf9019180a01ace80e7bed79fbadbe390876bd1a7d9770edf9462049ef8f4b555d05715d53ea049347a3c2eac6525a3fd7e3454dab19d73b4adeb9aa27d29493b9843f3f88814a085079b4abcd07fd4a5d6c52d35f4c4574aecc85830e90c478ca8c18fcbe590de80a02e3f8ad7ea29e784007f51852b9c3e470aef06b11bac32586a8b691134e4c27da064d2157a14bc31f195f73296ea4dcdbe7698edbf3ca81c44bf7730179d98d94ca09e7dc2597c9b7f72ddf84d7eebb0fe2a2fa2ab54fe668cd14fee44d9b40b1a53a0aa5d4acc7ac636d16bc9655556770bc325e1901fb62dc53770ef9110009e080380a0d5fde962bd2fb5326ddc7a9ca7fe0ee47c5bb3227f838b6d73d3299c22457596a08691410eff46b88f929ef649ea25025f62a5362ca8dc8876e5e1f4fc8e79256d80a0673e88d3a8a4616f676793096b5ae87cff931bd20fb8dd466f97809a1126aad8a08b774a45c2273553e2daf4bbc3a8d44fb542ea29b6f125098f79a4d211b3309ca02fed3139c1791269acb9365eddece93e743900eba6b42a6a8614747752ba268f80", # noqa: E501 + "0xf891808080a0c7d094301e0c54da37b696d85f72de5520b224ab2cf4f045d8db1a3374caf0488080a0fc5581783bfe27fab9423602e1914d719fd71433e9d7dd63c95fe7e58d10c9c38080a0c64f346fc7a21f6679cba8abdf37ca2de8c4fcd8f8bcaedb261b5f77627c93908080808080a0ddef2936a67a3ac7d3d4ff15a935a45f2cc4976c8f0310aed85daf763780e2b480", # noqa: E501 + "0xf843a0200decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563a1a048656c6c6f00000000000000000000000000000000000000000000000000000a", # noqa: E501 + ], + } + ], +} + +EXPECTED_GET_TRANSACTION = { + "jsonrpc": "2.0", + "id": 0, + "result": { + "hash": "0x88df016429689c079f3b2f6ad39fa052532c56795b733da78a91ebe6a713944b", # noqa: E501 + "blockHash": "0x1d59ff54b1eb26b013ce3cb5fc9dab3705b415a67127a003c3e61eb445bb8df2", # noqa: E501 + "blockNumber": "0x5daf3b", + "from": "0xa7d9ddbe1f17865597fbd27ec712455208b6b76d", + "gas": "0xc350", + "gasPrice": "0x4a817c800", + "input": "0x68656c6c6f21", + "nonce": "0x15", + "r": "0x1b5e176d927f8e9ab405058b2d2457392da3e20f328b16ddabcebc33eaac5fea", + "s": "0x4ba69724e8f69de52f0125ad8b3c5c2cef33019bac3249e2c0a2192766d1721c", + "to": "0xf02c1c8e6114b1dbe8937a39260b5b0a374432bb", + "transactionIndex": "0x41", + "v": "0x25", + "value": "0xf3dbb76162000", + }, +} + +EXPECTED_FEE_HISTORY = { + "oldestBlock": 3, + "reward": [[220, 7145389], [1000000, 6000213], [550, 550], [125, 12345678]], + "baseFeePerGas": [202583058, 177634473, 155594425, 136217133, 119442408], + "gasUsedRatio": [ + 0.007390479689642084, + 0.0036988514889990873, + 0.0018512333048507866, + 0.00741217041320997, + ], +} + + +EXPECTED_GET_TRANSACTION_RECEIPT = { + "blockHash": "0x4e3a3754410177e6937ef1f84bba68ea139e8d1a2258c5f85db9f1cd715a1bdd", + "blockNumber": 46147, + "contractAddress": None, + "cumulativeGasUsed": 21000, + "from": "0xA1E4380A3B1f749673E270229993eE55F35663b4", + "gasUsed": 21000, + "logs": [], + "logsBloom": "0x000000000000000000000000000000000000000000000000...0000", + "status": 1, # 0 or 1 + "to": "0x5DF9B87991262F6BA471F09758CDE1c0FC1De734", + "transactionHash": "0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060", # noqa: E501 + "transactionIndex": 0, +} diff --git a/tests/integration_tests/test_types.py b/tests/integration_tests/test_types.py index e9aad04dd1..a9f53b31d7 100644 --- a/tests/integration_tests/test_types.py +++ b/tests/integration_tests/test_types.py @@ -1,41 +1,66 @@ -import pytest - +from .expected_constants import ( + EXPECTED_FEE_HISTORY, + EXPECTED_GET_PROOF, + EXPECTED_GET_STORAGE_AT, + EXPECTED_GET_TRANSACTION, + EXPECTED_GET_TRANSACTION_RECEIPT, +) from .utils import ( - KEYS, - CONTRACTS, ADDRS, - send_transaction, + CONTRACTS, + KEYS, deploy_contract, + send_transaction, w3_wait_for_new_blocks, ) + def test_block(ethermint, geth): get_blocks(ethermint, geth, False) get_blocks(ethermint, geth, True) + def get_blocks(ethermint, geth, with_transactions): eth_rpc = ethermint.w3.provider geth_rpc = geth.w3.provider - make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBlockByNumber", ['0x0', with_transactions]) - - make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBlockByNumber", ['0x2710', with_transactions]) - + make_same_rpc_calls( + eth_rpc, geth_rpc, "eth_getBlockByNumber", ["0x0", with_transactions] + ) + + make_same_rpc_calls( + eth_rpc, geth_rpc, "eth_getBlockByNumber", ["0x2710", with_transactions] + ) + ethermint_blk = ethermint.w3.eth.get_block(1) # Get existing block, no transactions eth_rsp = eth_rpc.make_request( - "eth_getBlockByHash", [ethermint_blk['hash'].hex(), with_transactions] + "eth_getBlockByHash", [ethermint_blk["hash"].hex(), with_transactions] ) geth_rsp = geth_rpc.make_request( - "eth_getBlockByHash", ["0x124d099a1f435d3a6155e5d157ff1078eaefb742435892677ee5b3cb5e6fa055", with_transactions] + "eth_getBlockByHash", + [ + "0x124d099a1f435d3a6155e5d157ff1078eaefb742435892677ee5b3cb5e6fa055", + with_transactions, + ], ) res, err = same_types(eth_rsp, geth_rsp) assert res, err # Get not existing block - make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBlockByHash", ['0x4e3a3754410177e6937ef1f84bba68ea139e8d1a2258c5f85db9f1cd715a1bdd', with_transactions]) + make_same_rpc_calls( + eth_rpc, + geth_rpc, + "eth_getBlockByHash", + [ + "0x4e3a3754410177e6937ef1f84bba68ea139e8d1a2258c5f85db9f1cd715a1bdd", + with_transactions, + ], + ) # Bad call - make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBlockByHash", ['0', with_transactions]) + make_same_rpc_calls( + eth_rpc, geth_rpc, "eth_getBlockByHash", ["0", with_transactions] + ) def test_accounts(ethermint, geth): @@ -43,16 +68,19 @@ def test_accounts(ethermint, geth): geth_rpc = geth.w3.provider make_same_rpc_calls(eth_rpc, geth_rpc, "eth_accounts", []) + def test_syncing(ethermint, geth): eth_rpc = ethermint.w3.provider geth_rpc = geth.w3.provider make_same_rpc_calls(eth_rpc, geth_rpc, "eth_syncing", []) + def test_coinbase(ethermint, geth): eth_rpc = ethermint.w3.provider geth_rpc = geth.w3.provider make_same_rpc_calls(eth_rpc, geth_rpc, "eth_coinbase", []) + def test_max_priority_fee(ethermint, geth): eth_rpc = ethermint.w3.provider geth_rpc = geth.w3.provider @@ -70,18 +98,50 @@ def test_block_number(ethermint, geth): geth_rpc = geth.w3.provider make_same_rpc_calls(eth_rpc, geth_rpc, "eth_blockNumber", []) + def test_balance(ethermint, geth): eth_rpc = ethermint.w3.provider geth_rpc = geth.w3.provider - make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBalance", ["0x57f96e6b86cdefdb3d412547816a82e3e0ebf9d2", 'latest']) - make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBalance", ["0", 'latest']) - make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBalance", ["0x9907a0cf64ec9fbf6ed8fd4971090de88222a9ac", 'latest']) - make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBalance", ["0x57f96e6b86cdefdb3d412547816a82e3e0ebf9d2", '0x0']) - make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBalance", ["0",'0x0']) - make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBalance", ["0x9907a0cf64ec9fbf6ed8fd4971090de88222a9ac",'0x0']) - make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBalance", ["0x57f96e6b86cdefdb3d412547816a82e3e0ebf9d2", '0x10000']) - make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBalance", ["0",'0x10000']) - make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBalance", ["0x9907a0cf64ec9fbf6ed8fd4971090de88222a9ac",'0x10000']) + make_same_rpc_calls( + eth_rpc, + geth_rpc, + "eth_getBalance", + ["0x57f96e6b86cdefdb3d412547816a82e3e0ebf9d2", "latest"], + ) + make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBalance", ["0", "latest"]) + make_same_rpc_calls( + eth_rpc, + geth_rpc, + "eth_getBalance", + ["0x9907a0cf64ec9fbf6ed8fd4971090de88222a9ac", "latest"], + ) + make_same_rpc_calls( + eth_rpc, + geth_rpc, + "eth_getBalance", + ["0x57f96e6b86cdefdb3d412547816a82e3e0ebf9d2", "0x0"], + ) + make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBalance", ["0", "0x0"]) + make_same_rpc_calls( + eth_rpc, + geth_rpc, + "eth_getBalance", + ["0x9907a0cf64ec9fbf6ed8fd4971090de88222a9ac", "0x0"], + ) + make_same_rpc_calls( + eth_rpc, + geth_rpc, + "eth_getBalance", + ["0x57f96e6b86cdefdb3d412547816a82e3e0ebf9d2", "0x10000"], + ) + make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBalance", ["0", "0x10000"]) + make_same_rpc_calls( + eth_rpc, + geth_rpc, + "eth_getBalance", + ["0x9907a0cf64ec9fbf6ed8fd4971090de88222a9ac", "0x10000"], + ) + def deploy_and_wait(w3, number=1): contract = deploy_contract( @@ -92,187 +152,158 @@ def deploy_and_wait(w3, number=1): w3_wait_for_new_blocks(w3, number) return contract -def test_getStorageAt(ethermint, geth): + +def test_get_storage_at(ethermint, geth): eth_rpc = ethermint.w3.provider geth_rpc = geth.w3.provider - make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getStorageAt", ["0x57f96e6b86cdefdb3d412547816a82e3e0ebf9d2", '0x0', 'latest']) + make_same_rpc_calls( + eth_rpc, + geth_rpc, + "eth_getStorageAt", + ["0x57f96e6b86cdefdb3d412547816a82e3e0ebf9d2", "0x0", "latest"], + ) contract = deploy_and_wait(ethermint.w3) - res = eth_rpc.make_request( - 'eth_getStorageAt', [contract.address, '0x0', 'latest'] - ) - expected = '0x00000000000000000000000000000000000000000000000000120a0b063499d4' - res, err = same_types(res['result'], expected) + res = eth_rpc.make_request("eth_getStorageAt", [contract.address, "0x0", "latest"]) + res, err = same_types(res["result"], EXPECTED_GET_STORAGE_AT) assert res, err + def send_and_get_hash(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() -def test_getProof(ethermint, geth): + +def test_get_proof(ethermint, geth): eth_rpc = ethermint.w3.provider geth_rpc = geth.w3.provider - make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getProof", ["0x57f96e6b86cdefdb3d412547816a82e3e0ebf9d2", ['0x0'], 'latest']) + make_same_rpc_calls( + eth_rpc, + geth_rpc, + "eth_getProof", + ["0x57f96e6b86cdefdb3d412547816a82e3e0ebf9d2", ["0x0"], "latest"], + ) - make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getProof", ["0x57f96e6b86cdefdb3d412547816a82e3e0ebf9d2", ['0x0'], '0x32']) + make_same_rpc_calls( + eth_rpc, + geth_rpc, + "eth_getProof", + ["0x57f96e6b86cdefdb3d412547816a82e3e0ebf9d2", ["0x0"], "0x32"], + ) _ = send_and_get_hash(ethermint.w3) - proof = eth_rpc.make_request('eth_getProof', [ADDRS["validator"], ['0x0'], 'latest']) - expected = { - 'address': '0x4CB06C43fcdABeA22541fcF1F856A6a296448B6c', - 'accountProof': ['0xf90211a03841a7ddd65c70c94b8efa79190d00f0ab134b26f18dcad508f60a7e74559d0ba0464b07429a05039e22931492d6c6251a860c018ea390045d596b1ac11b5c7aa7a011f4b89823a03c9c4b5a8ab079ee1bc0e2a83a508bb7a5dc7d7fb4f2e95d3186a0b5f7c51c3b2d51d97f171d2b38a4df1a7c0acc5eb0de46beeff4d07f5ed20e19a0b591a2ce02367eda31cf2d16eca7c27fd44dbf0864b64ea8259ad36696eb2a04a02b646a7552b8392ae94263757f699a27d6e9176b4c06b9fc0a722f893b964795a02df05d68bceb88eebf68aafde61d10ab942097afc1c58b8435ffd3895358a742a0c2f16143c4d1db03276c433696dddb3e9f3b113bcd854b127962262e98f43147a0828820316cc02bfefd899aba41340659fd06df1e0a0796287ec2a4110239f6d2a050496598670b04df7bbff3718887fa36437d6d8c7afb4eff86f76c5c7097dcc4a0c14e9060c6b3784e35b9e6ae2ad2984142a75910ccc89eb89dc1e2f44b6c58c2a009804db571d0ce07913e1cbacc4f1dc4fb8265c936f5c612e3a47e91c64d8e9fa063d96f38b3cb51b1665c6641e25ffe24803f2941e5df79942f6a53b7169647e4a0899f71abb18c6c956118bf567fac629b75f7e9526873e429d3d8abb6dbb58021a00fd717235298742623c0b3cafb3e4bd86c0b5ab1f71097b4dd19f3d6925d758da0096437146c16097f2ccc1d3e910d65a4132803baee2249e72c8bf0bcaaeb37e580', - '0xf90151a097b17a89fd2c03ee98cb6459c08f51b269da5cee46650e84470f62bf83b43efe80a03b269d284a4c3cf8f8deacafb637c6d77f607eec8d75e8548d778e629612310480a01403217a7f1416830c870087c524dabade3985271f6f369a12b010883c71927aa0f592ac54c879817389663be677166f5022943e2fe1b52617a1d15c2f353f27dda0ac8d015a9e668f5877fcc391fae33981c00577096f0455b42df4f8e8089ece24a003ba34a13e2f2fb4bf7096540b42d4955c5269875b9cf0f7b87632585d44c9a580a0b179e3230b07db294473ae57f0170262798f8c551c755b5665ace1215cee10ca80a0552d24252639a6ae775aa1df700ffb92c2411daea7286f158d44081c8172d072a0772a87d08cf38c4c68bfde770968571abd16fd3835cb902486bd2e515d53c12d80a0413774f3d900d2d2be7a3ad999ffa859a471dc03a74fb9a6d8275455f5496a548080', - '0xf869a020d13b52a61d3c1325ce3626a51418adebd6323d4840f1bdd93906359d11c933b846f8440180a01ab7c0b0a2a4bbb5a1495da8c142150891fc64e0c321e1feb70bd5f881951f7ea0551332d96d085185ab4019ad8bcf89c45321e136c261eb6271e574a2edf1461f' - ], - 'balance': 0, - 'codeHash': '0x551332d96d085185ab4019ad8bcf89c45321e136c261eb6271e574a2edf1461f', - 'nonce': 1, - 'storageHash': '0x1ab7c0b0a2a4bbb5a1495da8c142150891fc64e0c321e1feb70bd5f881951f7e', - 'storageProof': [{ - 'key': '0x00', - 'value': '0x48656c6c6f00000000000000000000000000000000000000000000000000000a', - 'proof': ['0xf9019180a01ace80e7bed79fbadbe390876bd1a7d9770edf9462049ef8f4b555d05715d53ea049347a3c2eac6525a3fd7e3454dab19d73b4adeb9aa27d29493b9843f3f88814a085079b4abcd07fd4a5d6c52d35f4c4574aecc85830e90c478ca8c18fcbe590de80a02e3f8ad7ea29e784007f51852b9c3e470aef06b11bac32586a8b691134e4c27da064d2157a14bc31f195f73296ea4dcdbe7698edbf3ca81c44bf7730179d98d94ca09e7dc2597c9b7f72ddf84d7eebb0fe2a2fa2ab54fe668cd14fee44d9b40b1a53a0aa5d4acc7ac636d16bc9655556770bc325e1901fb62dc53770ef9110009e080380a0d5fde962bd2fb5326ddc7a9ca7fe0ee47c5bb3227f838b6d73d3299c22457596a08691410eff46b88f929ef649ea25025f62a5362ca8dc8876e5e1f4fc8e79256d80a0673e88d3a8a4616f676793096b5ae87cff931bd20fb8dd466f97809a1126aad8a08b774a45c2273553e2daf4bbc3a8d44fb542ea29b6f125098f79a4d211b3309ca02fed3139c1791269acb9365eddece93e743900eba6b42a6a8614747752ba268f80', - '0xf891808080a0c7d094301e0c54da37b696d85f72de5520b224ab2cf4f045d8db1a3374caf0488080a0fc5581783bfe27fab9423602e1914d719fd71433e9d7dd63c95fe7e58d10c9c38080a0c64f346fc7a21f6679cba8abdf37ca2de8c4fcd8f8bcaedb261b5f77627c93908080808080a0ddef2936a67a3ac7d3d4ff15a935a45f2cc4976c8f0310aed85daf763780e2b480', - '0xf843a0200decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563a1a048656c6c6f00000000000000000000000000000000000000000000000000000a' - ] - } - ] - } - res, err = same_types(proof['result'], expected) + proof = eth_rpc.make_request( + "eth_getProof", [ADDRS["validator"], ["0x0"], "latest"] + ) + res, err = same_types(proof["result"], EXPECTED_GET_PROOF) assert res, err -def test_getCode(ethermint, geth): + +def test_get_code(ethermint, geth): eth_rpc = ethermint.w3.provider geth_rpc = geth.w3.provider - make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getCode", ["0x57f96e6b86cdefdb3d412547816a82e3e0ebf9d2", "latest"]) + make_same_rpc_calls( + eth_rpc, + geth_rpc, + "eth_getCode", + ["0x57f96e6b86cdefdb3d412547816a82e3e0ebf9d2", "latest"], + ) # Do an ethereum transfer contract = deploy_and_wait(ethermint.w3) - code = eth_rpc.make_request( - 'eth_getCode', [contract.address, "latest"] - ) - expected = { - "id": "4", - "jsonrpc": "2.0", - "result": "0x" - } + code = eth_rpc.make_request("eth_getCode", [contract.address, "latest"]) + expected = {"id": "4", "jsonrpc": "2.0", "result": "0x"} res, err = same_types(code, expected) assert res, err -def test_getBlockTransactionCountByNumber(ethermint, geth): +def test_get_block_transaction_count(ethermint, geth): eth_rpc = ethermint.w3.provider geth_rpc = geth.w3.provider - make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBlockTransactionCountByNumber", ["0x0"]) + make_same_rpc_calls( + eth_rpc, geth_rpc, "eth_getBlockTransactionCountByNumber", ["0x0"] + ) - make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBlockTransactionCountByNumber", ["0x100"]) + make_same_rpc_calls( + eth_rpc, geth_rpc, "eth_getBlockTransactionCountByNumber", ["0x100"] + ) tx_hash = send_and_get_hash(ethermint.w3) - tx_res = eth_rpc.make_request('eth_getTransactionByHash', [tx_hash]) - block_number = tx_res['result']['blockNumber'] - block_hash = tx_res['result']['blockHash'] - block_res = eth_rpc.make_request('eth_getBlockTransactionCountByNumber', [block_number]) + tx_res = eth_rpc.make_request("eth_getTransactionByHash", [tx_hash]) + block_number = tx_res["result"]["blockNumber"] + block_hash = tx_res["result"]["blockHash"] + block_res = eth_rpc.make_request( + "eth_getBlockTransactionCountByNumber", [block_number] + ) - expected = { - "id": "1", - "jsonrpc": "2.0", - "result": "0x1" - } + expected = {"id": "1", "jsonrpc": "2.0", "result": "0x1"} res, err = same_types(block_res, expected) assert res, err - make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getBlockTransactionCountByHash", ["0x4e3a3754410177e6937ef1f84bba68ea139e8d1a2258c5f85db9f1cd715a1bdd"]) - block_res = eth_rpc.make_request('eth_getBlockTransactionCountByHash', [block_hash]) - expected = { - "id": "1", - "jsonrpc": "2.0", - "result": "0x1" - } + make_same_rpc_calls( + eth_rpc, + geth_rpc, + "eth_getBlockTransactionCountByHash", + ["0x4e3a3754410177e6937ef1f84bba68ea139e8d1a2258c5f85db9f1cd715a1bdd"], + ) + block_res = eth_rpc.make_request("eth_getBlockTransactionCountByHash", [block_hash]) + expected = {"id": "1", "jsonrpc": "2.0", "result": "0x1"} res, err = same_types(block_res, expected) assert res, err - - -def test_getTransaction(ethermint, geth): +def test_get_transaction(ethermint, geth): eth_rpc = ethermint.w3.provider geth_rpc = geth.w3.provider - make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getTransactionByHash", ["0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060"]) + make_same_rpc_calls( + eth_rpc, + geth_rpc, + "eth_getTransactionByHash", + ["0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060"], + ) tx_hash = send_and_get_hash(ethermint.w3) - tx_res = eth_rpc.make_request('eth_getTransactionByHash', [tx_hash]) - - expected = { - "jsonrpc": "2.0", - "id": 0, - "result": { - "hash": "0x88df016429689c079f3b2f6ad39fa052532c56795b733da78a91ebe6a713944b", - "blockHash": "0x1d59ff54b1eb26b013ce3cb5fc9dab3705b415a67127a003c3e61eb445bb8df2", - "blockNumber": "0x5daf3b", - "from": "0xa7d9ddbe1f17865597fbd27ec712455208b6b76d", - "gas": "0xc350", - "gasPrice": "0x4a817c800", - "input": "0x68656c6c6f21", - "nonce": "0x15", - "r": "0x1b5e176d927f8e9ab405058b2d2457392da3e20f328b16ddabcebc33eaac5fea", - "s": "0x4ba69724e8f69de52f0125ad8b3c5c2cef33019bac3249e2c0a2192766d1721c", - "to": "0xf02c1c8e6114b1dbe8937a39260b5b0a374432bb", - "transactionIndex": "0x41", - "v": "0x25", - "value": "0xf3dbb76162000" - } - } - res, err = same_types(tx_res, expected) + tx_res = eth_rpc.make_request("eth_getTransactionByHash", [tx_hash]) + res, err = same_types(tx_res, EXPECTED_GET_TRANSACTION) assert res, err -def test_getTransactionReceipt(ethermint, geth): + +def test_get_transaction_receipt(ethermint, geth): eth_rpc = ethermint.w3.provider geth_rpc = geth.w3.provider - make_same_rpc_calls(eth_rpc, geth_rpc, "eth_getTransactionReceipt", ["0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060"]) + make_same_rpc_calls( + eth_rpc, + geth_rpc, + "eth_getTransactionReceipt", + ["0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060"], + ) tx_hash = send_and_get_hash(ethermint.w3) - tx_res = eth_rpc.make_request('eth_getTransactionReceipt', [tx_hash]) - expected = { - 'blockHash': '0x4e3a3754410177e6937ef1f84bba68ea139e8d1a2258c5f85db9f1cd715a1bdd', - 'blockNumber': 46147, - 'contractAddress': None, - 'cumulativeGasUsed': 21000, - 'from': '0xA1E4380A3B1f749673E270229993eE55F35663b4', - 'gasUsed': 21000, - 'logs': [], - 'logsBloom': '0x000000000000000000000000000000000000000000000000...0000', - 'status': 1, # 0 or 1 - 'to': '0x5DF9B87991262F6BA471F09758CDE1c0FC1De734', - 'transactionHash': '0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060', - 'transactionIndex': 0, - } - res, err = same_types(tx_res['result'], expected) + tx_res = eth_rpc.make_request("eth_getTransactionReceipt", [tx_hash]) + res, err = same_types(tx_res["result"], EXPECTED_GET_TRANSACTION_RECEIPT) assert res, err -def test_feeHistory(ethermint, geth): + +def test_fee_history(ethermint, geth): eth_rpc = ethermint.w3.provider geth_rpc = geth.w3.provider - make_same_rpc_calls(eth_rpc, geth_rpc, "eth_feeHistory", [4, 'latest',[10,90]]) - - make_same_rpc_calls(eth_rpc, geth_rpc, "eth_feeHistory", [4, '0x5000',[10,90]]) - - fee_history = eth_rpc.make_request('eth_feeHistory', [4, 'latest',[10,90]]) - expected = { - 'oldestBlock': 3, - 'reward': [[220, 7145389], [1000000, 6000213], [550, 550], [125, 12345678]], - 'baseFeePerGas': [202583058, 177634473, 155594425, 136217133, 119442408], - 'gasUsedRatio': [0.007390479689642084, 0.0036988514889990873, 0.0018512333048507866, 0.00741217041320997] - } - res, err = same_types(fee_history['result'], expected) + make_same_rpc_calls(eth_rpc, geth_rpc, "eth_feeHistory", [4, "latest", [10, 90]]) + + make_same_rpc_calls(eth_rpc, geth_rpc, "eth_feeHistory", [4, "0x5000", [10, 90]]) + + fee_history = eth_rpc.make_request("eth_feeHistory", [4, "latest", [10, 90]]) + + res, err = same_types(fee_history["result"], EXPECTED_FEE_HISTORY) assert res, err -def test_estimateGas(ethermint, geth): + +def test_estimate_gas(ethermint, geth): tx = {"to": ADDRS["community"], "from": ADDRS["validator"]} eth_rpc = ethermint.w3.provider @@ -280,41 +311,45 @@ def test_estimateGas(ethermint, geth): make_same_rpc_calls(eth_rpc, geth_rpc, "eth_estimateGas", [tx]) make_same_rpc_calls(eth_rpc, geth_rpc, "eth_estimateGas", [{}]) + def make_same_rpc_calls(rpc1, rpc2, method, params): - res1 = rpc1.make_request( - method, params - ) - res2 = rpc2.make_request( - method, params - ) + res1 = rpc1.make_request(method, params) + res2 = rpc2.make_request(method, params) res, err = same_types(res1, res2) assert res, err -def same_types(objectA, objectB): - if isinstance(objectA, dict): - if not isinstance(objectB, dict): - return False, 'A is dict, B is not' - keys = list(set(list(objectA.keys()) + list(objectB.keys()))) +def same_types(object_a, object_b): + + if isinstance(object_a, dict): + if not isinstance(object_b, dict): + return False, "A is dict, B is not" + keys = list(set(list(object_a.keys()) + list(object_b.keys()))) for key in keys: - if key in objectB and key in objectA: - if not same_types(objectA[key], objectB[key]): - return False, key + ' key on dict are not of same type' + if key in object_b and key in object_a: + if not same_types(object_a[key], object_b[key]): + return False, key + " key on dict are not of same type" else: - return False, key + ' key on json is not in both results' + return False, key + " key on json is not in both results" return True, "" - elif isinstance(objectA, list): - if not isinstance(objectB, list): - return False, 'A is list, B is not' - if len(objectA) == 0 and len(objectB) == 0: + elif isinstance(object_a, list): + if not isinstance(object_b, list): + return False, "A is list, B is not" + if len(object_a) == 0 and len(object_b) == 0: return True, "" - if len(objectA) > 0 and len(objectB) > 0: - return same_types(objectA[0], objectB[0]) + if len(object_a) > 0 and len(object_b) > 0: + return same_types(object_a[0], object_b[0]) else: return True - elif objectA is None and objectB is None: + elif object_a is None and object_b is None: return True, "" - elif type(objectA) is type(objectB): + elif type(object_a) is type(object_b): return True, "" else: - return False, 'different types. A is type '+ type(objectA).__name__ + ' B is type '+ type(objectB).__name__ \ No newline at end of file + return ( + False, + "different types. A is type " + + type(object_a).__name__ + + " B is type " + + type(object_b).__name__, + ) diff --git a/tests/integration_tests/utils.py b/tests/integration_tests/utils.py index 7d127c21e8..ed15b35cdd 100644 --- a/tests/integration_tests/utils.py +++ b/tests/integration_tests/utils.py @@ -39,17 +39,6 @@ def contract_path(name, filename): }, } -Account.enable_unaudited_hdwallet_features() - -ACCOUNTS = { - "validator": Account.from_mnemonic(os.getenv("VALIDATOR1_MNEMONIC")), - "community": Account.from_mnemonic(os.getenv("COMMUNITY_MNEMONIC")), - "signer1": Account.from_mnemonic(os.getenv("SIGNER1_MNEMONIC")), - "signer2": Account.from_mnemonic(os.getenv("SIGNER2_MNEMONIC")), -} -KEYS = {name: account.key for name, account in ACCOUNTS.items()} -ADDRS = {name: account.address for name, account in ACCOUNTS.items()} - def wait_for_port(port, host="127.0.0.1", timeout=40.0): start_time = time.perf_counter() From 41484b15c1c2c52424c6c1ace9800251dc95a21f Mon Sep 17 00:00:00 2001 From: Ramiro Carlucho Date: Mon, 8 Aug 2022 13:38:55 +0100 Subject: [PATCH 7/7] fix spelling --- rpc/namespaces/ethereum/eth/api.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpc/namespaces/ethereum/eth/api.go b/rpc/namespaces/ethereum/eth/api.go index e03713677b..60421be318 100644 --- a/rpc/namespaces/ethereum/eth/api.go +++ b/rpc/namespaces/ethereum/eth/api.go @@ -1050,7 +1050,7 @@ func (e *PublicAPI) GetProof(address common.Address, storageKeys []string, block _, err = e.backend.GetTendermintBlockByNumber(blockNum) if err != nil { // Get 'latest' proof if query is in the future - // this imitates geth behaviour + // this imitates geth behavior height = 0 } ctx := rpctypes.ContextWithHeight(height)