forked from cerc-io/laconicd-deprecated
fix: chain-id in grpc query is not initialized without abci event (#1405)
* fix: chain-id in grpc query is not initialized without abci event Closes: #1404 Solution: - pass the chain-id from caller. * Update CHANGELOG.md * only override if input is not empty * add comment to chain id * pass chain-id to state transition * Update x/evm/keeper/grpc_query.go * Apply suggestions from code review * fix golang lint * update gomod2nix.toml * fix unit tests * update gomod2nix * api breaking changelog * add unit tests, and fix TraceBlock by the way * Update CHANGELOG.md * test --grpc-only mode in integration tests * remove tmp var * Update tests/integration_tests/test_grpc_only.py * Update x/evm/keeper/grpc_query_test.go Co-authored-by: mmsqe <tqd0800210105@gmail.com> * fix linters * fix nil pointer in tests * fix conflicts * fix conflicts * fixes * fix lint * fix unit test Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> Co-authored-by: mmsqe <tqd0800210105@gmail.com> Co-authored-by: Freddy Caceres <facs95@gmail.com>
This commit is contained in:
co-authored by
mmsqe
Federico Kunze Küllmer
Freddy Caceres
parent
e2939a3191
commit
ebc47af0bd
@@ -0,0 +1,12 @@
|
||||
pragma solidity >0.5.0;
|
||||
|
||||
contract TestChainID {
|
||||
function currentChainID() public view returns (uint) {
|
||||
uint id;
|
||||
assembly {
|
||||
id := chainid()
|
||||
}
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,6 +95,11 @@ class CosmosCLI:
|
||||
def validate_genesis(self):
|
||||
return self.raw("validate-genesis", home=self.data_dir)
|
||||
|
||||
def consensus_address(self):
|
||||
"get tendermint consensus address"
|
||||
output = self.raw("tendermint", "show-address", home=self.data_dir)
|
||||
return output.decode().strip()
|
||||
|
||||
def add_genesis_account(self, addr, coins, **kwargs):
|
||||
return self.raw(
|
||||
"add-genesis-account",
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
import base64
|
||||
import json
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
import requests
|
||||
from pystarport import ports
|
||||
|
||||
from .network import setup_custom_ethermint
|
||||
from .utils import (
|
||||
CONTRACTS,
|
||||
decode_bech32,
|
||||
deploy_contract,
|
||||
supervisorctl,
|
||||
wait_for_port,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def custom_ethermint(tmp_path_factory):
|
||||
path = tmp_path_factory.mktemp("grpc-only")
|
||||
|
||||
# reuse rollback-test config because it has an extra fullnode
|
||||
yield from setup_custom_ethermint(
|
||||
path,
|
||||
26400,
|
||||
Path(__file__).parent / "configs/rollback-test.jsonnet",
|
||||
)
|
||||
|
||||
|
||||
def grpc_eth_call(port: int, args: dict, chain_id=None, proposer_address=None):
|
||||
"""
|
||||
do a eth_call through grpc gateway directly
|
||||
"""
|
||||
params = {
|
||||
"args": base64.b64encode(json.dumps(args).encode()).decode(),
|
||||
}
|
||||
if chain_id is not None:
|
||||
params["chain_id"] = str(chain_id)
|
||||
if proposer_address is not None:
|
||||
params["proposer_address"] = str(proposer_address)
|
||||
return requests.get(
|
||||
f"http://localhost:{port}/ethermint/evm/v1/eth_call", params
|
||||
).json()
|
||||
|
||||
|
||||
def test_grpc_mode(custom_ethermint):
|
||||
"""
|
||||
- restart a fullnode in grpc-only mode
|
||||
- test the grpc queries all works
|
||||
"""
|
||||
w3 = custom_ethermint.w3
|
||||
contract, _ = deploy_contract(w3, CONTRACTS["TestChainID"])
|
||||
assert 9000 == contract.caller.currentChainID()
|
||||
|
||||
msg = {
|
||||
"to": contract.address,
|
||||
"data": contract.encodeABI(fn_name="currentChainID"),
|
||||
}
|
||||
api_port = ports.api_port(custom_ethermint.base_port(2))
|
||||
# in normal mode, grpc query works even if we don't pass chain_id explicitly
|
||||
rsp = grpc_eth_call(api_port, msg)
|
||||
print(rsp)
|
||||
assert "code" not in rsp, str(rsp)
|
||||
assert 9000 == int.from_bytes(base64.b64decode(rsp["ret"].encode()), "big")
|
||||
|
||||
supervisorctl(
|
||||
custom_ethermint.base_dir / "../tasks.ini", "stop", "ethermint_9000-1-node2"
|
||||
)
|
||||
|
||||
# run grpc-only mode directly with existing chain state
|
||||
with (custom_ethermint.base_dir / "node2.log").open("w") as logfile:
|
||||
proc = subprocess.Popen(
|
||||
[
|
||||
"ethermintd",
|
||||
"start",
|
||||
"--grpc-only",
|
||||
"--home",
|
||||
custom_ethermint.base_dir / "node2",
|
||||
],
|
||||
stdout=logfile,
|
||||
stderr=subprocess.STDOUT,
|
||||
)
|
||||
try:
|
||||
# wait for grpc and rest api ports
|
||||
grpc_port = ports.grpc_port(custom_ethermint.base_port(2))
|
||||
wait_for_port(grpc_port)
|
||||
wait_for_port(api_port)
|
||||
|
||||
# in grpc-only mode, grpc query don't work if we don't pass chain_id
|
||||
rsp = grpc_eth_call(api_port, msg)
|
||||
assert rsp["code"] != 0, str(rsp)
|
||||
assert "invalid chain ID" in rsp["message"]
|
||||
|
||||
# it don't works without proposer address neither
|
||||
rsp = grpc_eth_call(api_port, msg, chain_id=9000)
|
||||
assert rsp["code"] != 0, str(rsp)
|
||||
assert "validator does not exist" in rsp["message"]
|
||||
|
||||
# pass the first validator's consensus address to grpc query
|
||||
cons_addr = decode_bech32(
|
||||
custom_ethermint.cosmos_cli(0).consensus_address()
|
||||
)
|
||||
|
||||
# should work with both chain_id and proposer_address set
|
||||
rsp = grpc_eth_call(
|
||||
api_port,
|
||||
msg,
|
||||
chain_id=100,
|
||||
proposer_address=base64.b64encode(cons_addr).decode(),
|
||||
)
|
||||
assert "code" not in rsp, str(rsp)
|
||||
assert 100 == int.from_bytes(base64.b64decode(rsp["ret"].encode()), "big")
|
||||
finally:
|
||||
proc.terminate()
|
||||
proc.wait()
|
||||
@@ -27,6 +27,7 @@ ETHERMINT_ADDRESS_PREFIX = "ethm"
|
||||
TEST_CONTRACTS = {
|
||||
"TestERC20A": "TestERC20A.sol",
|
||||
"Greeter": "Greeter.sol",
|
||||
"TestChainID": "ChainID.sol",
|
||||
}
|
||||
|
||||
|
||||
@@ -166,6 +167,11 @@ def eth_to_bech32(addr, prefix=ETHERMINT_ADDRESS_PREFIX):
|
||||
return bech32.bech32_encode(prefix, bz)
|
||||
|
||||
|
||||
def decode_bech32(addr):
|
||||
_, bz = bech32.bech32_decode(addr)
|
||||
return HexBytes(bytes(bech32.convertbits(bz, 5, 8)))
|
||||
|
||||
|
||||
def supervisorctl(inipath, *args):
|
||||
subprocess.run(
|
||||
(sys.executable, "-msupervisor.supervisorctl", "-c", inipath, *args),
|
||||
|
||||
Reference in New Issue
Block a user