Skip to content

Commit

Permalink
Problem: batched eth tx is not tested (#306)
Browse files Browse the repository at this point in the history
Closes: #305
- add batch tx integration test

test trace_transaction and get_transaction_by_block
  • Loading branch information
yihuang authored Jan 17, 2022
1 parent 0ad775a commit e61cb19
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 6 deletions.
23 changes: 19 additions & 4 deletions integration_tests/cosmoscli.py
Original file line number Diff line number Diff line change
Expand Up @@ -496,11 +496,12 @@ def combine_batch_multisig_tx(
)
return r.decode("utf-8")

def broadcast_tx(self, tx_file):
r = self.raw(
"tx", "broadcast", tx_file, node=self.node_rpc, broadcast_mode="block"
def broadcast_tx(self, tx_file, **kwargs):
kwargs.setdefault("broadcast_mode", "block")
kwargs.setdefault("output", "json")
return json.loads(
self.raw("tx", "broadcast", tx_file, node=self.node_rpc, **kwargs)
)
return r.decode("utf-8")

def unjail(self, addr):
return json.loads(
Expand Down Expand Up @@ -1012,3 +1013,17 @@ def update_token_mapping(self, denom, contract, **kwargs):
**kwargs,
)
)

def build_evm_tx(self, raw_tx: str, **kwargs):
return json.loads(
self.raw(
"tx",
"evm",
"raw",
raw_tx,
"-y",
"--generate-only",
home=self.data_dir,
**kwargs,
)
)
109 changes: 109 additions & 0 deletions integration_tests/test_basic.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import concurrent.futures
import json
import tempfile
import time
from pathlib import Path

Expand All @@ -15,9 +17,11 @@
KEYS,
Greeter,
RevertTestContract,
contract_address,
contract_path,
deploy_contract,
send_transaction,
sign_transaction,
wait_for_block,
wait_for_port,
)
Expand Down Expand Up @@ -456,6 +460,111 @@ def test_suicide(cluster):
assert len(w3.eth.get_code(destroyee.address)) == 0


def test_batch_tx(cronos):
"send multiple eth txs in single cosmos tx"
w3 = cronos.w3
sender = ADDRS["validator"]
recipient = ADDRS["community"]
nonce = w3.eth.get_transaction_count(sender)
info = json.load(open(CONTRACTS["TestERC20Utility"]))
contract = w3.eth.contract(abi=info["abi"], bytecode=info["bytecode"])
deploy_tx = contract.constructor().buildTransaction(
{"from": sender, "nonce": nonce}
)
contract = w3.eth.contract(address=contract_address(sender, nonce), abi=info["abi"])
transfer_tx1 = contract.functions.transfer(recipient, 1000).buildTransaction(
{"from": sender, "nonce": nonce + 1, "gas": 200000}
)
transfer_tx2 = contract.functions.transfer(recipient, 1000).buildTransaction(
{"from": sender, "nonce": nonce + 2, "gas": 200000}
)

signed_txs = [
sign_transaction(w3, deploy_tx, KEYS["validator"]),
sign_transaction(w3, transfer_tx1, KEYS["validator"]),
sign_transaction(w3, transfer_tx2, KEYS["validator"]),
]
tmp_txs = [
cronos.cosmos_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)

# build batch cosmos tx
cosmos_tx = {
"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": [],
}
with tempfile.NamedTemporaryFile("w") as fp:
json.dump(cosmos_tx, fp)
fp.flush()
rsp = cronos.cosmos_cli().broadcast_tx(fp.name)
assert rsp["code"] == 0, rsp["raw_log"]

receipts = [
w3.eth.wait_for_transaction_receipt(signed.hash) for signed in signed_txs
]

assert 2000 == contract.caller.balanceOf(recipient)

# check logs
assert receipts[0].contractAddress == contract.address

assert receipts[0].transactionIndex == 0
assert receipts[1].transactionIndex == 1
assert receipts[2].transactionIndex == 2

assert receipts[0].logs[0].logIndex == 0
assert receipts[1].logs[0].logIndex == 1
assert receipts[2].logs[0].logIndex == 2

assert receipts[0].cumulativeGasUsed == receipts[0].gasUsed
assert receipts[1].cumulativeGasUsed == receipts[0].gasUsed + receipts[1].gasUsed
assert (
receipts[2].cumulativeGasUsed
== receipts[0].gasUsed + receipts[1].gasUsed + receipts[2].gasUsed
)

# check traceTransaction
rsps = [
w3.provider.make_request("debug_traceTransaction", [signed.hash.hex()])[
"result"
]
for signed in signed_txs
]

for rsp, receipt in zip(rsps, receipts):
assert not rsp["failed"]
assert receipt.gasUsed == rsp["gas"]

# check get_transaction_by_block
txs = [
w3.eth.get_transaction_by_block(receipts[0].blockNumber, i) for i in range(3)
]
for tx, signed in zip(txs, signed_txs):
assert tx.hash == signed.hash


def test_log0(cluster):
"""
test compliance of empty topics behavior
Expand Down
9 changes: 7 additions & 2 deletions integration_tests/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,12 +238,17 @@ def deploy_contract(w3, jsonfile, args=(), key=KEYS["validator"]):
return w3.eth.contract(address=address, abi=info["abi"])


def send_transaction(w3, tx, key=KEYS["validator"]):
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)
signed = acct.sign_transaction(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)

Expand Down
1 change: 1 addition & 0 deletions scripts/cronos-devnet.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ cronos_777-1:
json-rpc:
address: "0.0.0.0:{EVMRPC_PORT}"
ws-address: "0.0.0.0:{EVMRPC_PORT_WS}"
api: "eth,net,web3,debug"
validators:
- coins: 1000000000000000000stake,10000000000000000000000basetcro
staked: 1000000000000000000stake
Expand Down
1 change: 1 addition & 0 deletions scripts/devnet.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ cronos_777-1:
json-rpc:
address: "0.0.0.0:{EVMRPC_PORT}"
ws-address: "0.0.0.0:{EVMRPC_PORT_WS}"
api: "eth,net,web3,debug"
validators:
- coins: 1000000000000000000stake,1000000000000000000basetcro
staked: 1000000000000000000stake
Expand Down

0 comments on commit e61cb19

Please sign in to comment.