Skip to content

Commit

Permalink
Problem: get tx receipt api is too slow for indexing service
Browse files Browse the repository at this point in the history
Closes: crypto-org-chain#431
Solution:
- add extension api: cronos_getTransactionReceiptsByBlock
- add integration test
  • Loading branch information
yihuang committed Apr 19, 2022
1 parent 8c4042a commit 7fcc107
Show file tree
Hide file tree
Showing 9 changed files with 395 additions and 55 deletions.
3 changes: 3 additions & 0 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@ import (
// Force-load the tracer engines to trigger registration
_ "github.com/ethereum/go-ethereum/eth/tracers/js"
_ "github.com/ethereum/go-ethereum/eth/tracers/native"

// force register the extension json-rpc.
_ "github.com/crypto-org-chain/cronos/x/cronos/rpc"
)

const (
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ replace (
// See https://github.com/tecbot/gorocksdb/pull/216
github.com/tecbot/gorocksdb => github.com/cosmos/gorocksdb v1.1.1

github.com/tharsis/ethermint => github.com/crypto-org-chain/ethermint v0.10.0-alpha1-cronos-8
github.com/tharsis/ethermint => github.com/yihuang/ethermint v0.10.0-alpha1-cronos-8.0.20220419042208-80726a75b25d

google.golang.org/grpc => google.golang.org/grpc v1.33.2
)
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -246,8 +246,6 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsr
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/crypto-org-chain/ethermint v0.10.0-alpha1-cronos-8 h1:+1FLhY/C+mKUPqKNqtq81tCIorCFcqLZZflHebRDnIc=
github.com/crypto-org-chain/ethermint v0.10.0-alpha1-cronos-8/go.mod h1:3CXBYpzlUtEn6OCr1WFw/951MBEeojZW3hcqPCv5ktw=
github.com/crypto-org-chain/ibc-go/v2 v2.2.0-hooks2 h1:elj+Tb/3O9GA3pv62zkc1B0P8hl1WHmF6vF8PInEJm4=
github.com/crypto-org-chain/ibc-go/v2 v2.2.0-hooks2/go.mod h1:rAHRlBcRiHPP/JszN+08SJx3pegww9bcVncIb9QLx7I=
github.com/crypto-org-chain/keyring v1.1.6-fixes h1:AUFSu56NY6XobY6XfRoDx6v3loiOrHK5MNUm32GEjwA=
Expand Down Expand Up @@ -1072,6 +1070,8 @@ github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q
github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/ybbus/jsonrpc v2.1.2+incompatible/go.mod h1:XJrh1eMSzdIYFbM08flv0wp5G35eRniyeGut1z+LSiE=
github.com/yihuang/ethermint v0.10.0-alpha1-cronos-8.0.20220419042208-80726a75b25d h1:EtR1DZWzbT2eifrK34F3HLPn4WAqHuUiWDtitXk+c5Y=
github.com/yihuang/ethermint v0.10.0-alpha1-cronos-8.0.20220419042208-80726a75b25d/go.mod h1:3CXBYpzlUtEn6OCr1WFw/951MBEeojZW3hcqPCv5ktw=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
Expand Down
6 changes: 6 additions & 0 deletions integration_tests/cosmoscli.py
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,12 @@ def broadcast_tx(self, tx_file, **kwargs):
self.raw("tx", "broadcast", tx_file, node=self.node_rpc, **kwargs)
)

def broadcast_tx_json(self, tx, **kwargs):
with tempfile.NamedTemporaryFile("w") as fp:
json.dump(tx, fp)
fp.flush()
return self.broadcast_tx(fp.name)

def unjail(self, addr):
return json.loads(
self.raw(
Expand Down
104 changes: 53 additions & 51 deletions integration_tests/test_basic.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import concurrent.futures
import json
import tempfile
import time
from pathlib import Path

Expand All @@ -17,6 +16,7 @@
KEYS,
Greeter,
RevertTestContract,
build_batch_tx,
contract_address,
contract_path,
deploy_contract,
Expand Down Expand Up @@ -464,6 +464,7 @@ def test_suicide(cluster):
def test_batch_tx(cronos):
"send multiple eth txs in single cosmos tx"
w3 = cronos.w3
cli = cronos.cosmos_cli()
sender = ADDRS["validator"]
recipient = ADDRS["community"]
nonce = w3.eth.get_transaction_count(sender)
Expand All @@ -480,51 +481,13 @@ def test_batch_tx(cronos):
{"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"]
cosmos_tx, tx_hashes = build_batch_tx(
w3, cli, [deploy_tx, transfer_tx1, transfer_tx2]
)
rsp = cli.broadcast_tx_json(cosmos_tx)
assert rsp["code"] == 0, rsp["raw_log"]

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

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

Expand All @@ -548,10 +511,8 @@ def test_batch_tx(cronos):

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

for rsp, receipt in zip(rsps, receipts):
Expand All @@ -562,8 +523,49 @@ def test_batch_tx(cronos):
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
for tx, h in zip(txs, tx_hashes):
assert tx.hash == h


def test_failed_transfer_tx(cronos):
"""
It's possible to include a failed transfer transaction in batch tx
"""
w3 = cronos.w3
cli = cronos.cosmos_cli()
sender = ADDRS["community"]
recipient = ADDRS["validator"]
nonce = w3.eth.get_transaction_count(sender)
half_balance = w3.eth.get_balance(sender) // 2

# build batch tx, the third tx will fail, but will be included in block
# because of the batch tx.
transfer1 = {"from": sender, "nonce": nonce, "to": recipient, "value": half_balance}
transfer2 = {
"from": sender,
"nonce": nonce + 1,
"to": recipient,
"value": half_balance,
}
transfer3 = {
"from": sender,
"nonce": nonce + 2,
"to": recipient,
"value": half_balance,
}
cosmos_tx, tx_hashes = build_batch_tx(
w3, cli, [transfer1, transfer2, transfer3], KEYS["community"]
)
rsp = cli.broadcast_tx_json(cosmos_tx)
assert rsp["code"] == 0, rsp["raw_log"]

receipts = [w3.eth.wait_for_transaction_receipt(h) for h in tx_hashes]
print("receipts", receipts)
# try the cronos_getTransactionReceiptsByBlock api
rsp = w3.provider.make_request(
"cronos_getTransactionReceiptsByBlock", [receipts[0].blockNumber]
)
assert receipts == rsp["result"]


def test_log0(cluster):
Expand Down
35 changes: 35 additions & 0 deletions integration_tests/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -393,3 +393,38 @@ def modify_command_in_supervisor_config(ini: Path, fn, **kwargs):
**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
2 changes: 1 addition & 1 deletion scripts/devnet.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +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"
api: "eth,net,web3,debug,cronos"
validators:
- coins: 1000000000000000000stake,1000000000000000000basetcro
staked: 1000000000000000000stake
Expand Down
Loading

0 comments on commit 7fcc107

Please sign in to comment.