Skip to content

Commit

Permalink
Problem: batch tx in benchmark is not necessary (#1558)
Browse files Browse the repository at this point in the history
* Problem: batch tx in benchmark is not necessary

Solution:
- batch tx is rarely used in production, try to avoid in benchmark.
- normal async tx sending should be fast enough.

* fix

* use evm indexer
  • Loading branch information
yihuang authored Aug 29, 2024
1 parent 7a04a82 commit eb0a15d
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 89 deletions.
8 changes: 4 additions & 4 deletions testground/benchmark/benchmark/peer.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
VAL_INITIAL_AMOUNT = "100000000000000000000basecro"
VAL_STAKED_AMOUNT = "10000000000000000000basecro"
ACC_INITIAL_AMOUNT = "10000000000000000000000000basecro"
MEMPOOL_SIZE = 50000
MEMPOOL_SIZE = 10000
DEFAULT_DENOM = "basecro"
VALIDATOR_GROUP = "validators"
FULLNODE_GROUP = "fullnodes"
Expand Down Expand Up @@ -124,17 +124,17 @@ def patch_configs(home: Path, group: str, peers: str, block_executor: str):
"p2p.addr_book_strict": False,
"mempool.recheck": "false",
"mempool.size": MEMPOOL_SIZE,
"consensus.timeout_commit": "2s",
"consensus.timeout_commit": "1s",
"tx_index.indexer": "null",
}
if group == VALIDATOR_GROUP:
config_patch["tx_index.indexer"] = "null"

app_patch = {
"minimum-gas-prices": "0basecro",
"index-events": ["ethereum_tx.ethereumTxHash"],
"memiavl.enable": True,
"mempool.max-txs": MEMPOOL_SIZE,
"evm.block-executor": block_executor,
"json-rpc.enable-indexer": True,
}
if block_executor == "block-stm":
app_patch["memiavl.cache-size"] = 0
Expand Down
21 changes: 7 additions & 14 deletions testground/benchmark/benchmark/sendtx.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,15 @@
import web3
from eth_account import Account

from .utils import (
broadcast_tx_json,
build_batch_tx,
export_eth_account,
send_transaction,
)
from .utils import export_eth_account, send_transaction, send_transactions

TEST_AMOUNT = 1000000000000000000
GAS_PRICE = 1000000000


def fund_test_accounts(cli, w3, from_account, num_accounts, **kwargs) -> [Account]:
def fund_test_accounts(w3, from_account, num_accounts) -> [Account]:
accounts = []
sender = from_account.address
nonce = w3.eth.get_transaction_count(sender)
nonce = w3.eth.get_transaction_count(from_account.address)
txs = []
for i in range(num_accounts):
acct = Account.create()
Expand All @@ -31,10 +25,9 @@ def fund_test_accounts(cli, w3, from_account, num_accounts, **kwargs) -> [Accoun
}
txs.append(tx)
accounts.append(acct)
cosmos_tx, hashes = build_batch_tx(w3, cli, txs, from_account, **kwargs)
print("batch size", len(hashes))
rsp = broadcast_tx_json(cli, cosmos_tx, **kwargs)
assert rsp["code"] == 0, rsp["raw_log"]
receipts = send_transactions(w3, txs, from_account)
for receipt in receipts:
assert receipt["status"] == 1
return accounts


Expand Down Expand Up @@ -88,7 +81,7 @@ def generate_load(cli, num_accounts, num_txs, **kwargs):
w3 = web3.Web3(web3.providers.HTTPProvider("http://localhost:8545"))
assert w3.eth.chain_id == 777
genesis_account = export_eth_account(cli, "account", **kwargs)
accounts = fund_test_accounts(cli, w3, genesis_account, num_accounts, **kwargs)
accounts = fund_test_accounts(w3, genesis_account, num_accounts)
with ThreadPoolExecutor(max_workers=num_accounts) as executor:
futs = (executor.submit(sendtx, w3, acct, num_txs) for acct in accounts)
for fut in as_completed(futs):
Expand Down
84 changes: 13 additions & 71 deletions testground/benchmark/benchmark/utils.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import json
import socket
import subprocess
import tempfile
import time
from pathlib import Path

Expand Down Expand Up @@ -110,75 +108,19 @@ def send_transaction(w3, tx, acct, wait=True):
return txhash


def export_eth_account(cli, name: str, **kwargs) -> Account:
kwargs.setdefault("keyring_backend", "test")
return Account.from_key(cli("keys", "unsafe-export-eth-key", name, **kwargs))


def build_batch_tx(w3, cli, txs, acct, **kwargs):
"return cosmos batch tx and eth tx hashes"
def send_transactions(w3, txs, acct, wait=True):
"""
send a batch of transactions from same account
"""
signed_txs = [sign_transaction(w3, tx, acct) for tx in txs]
tmp_txs = [
json.loads(
cli(
"tx",
"evm",
"raw",
signed.rawTransaction.hex(),
"-y",
"--generate-only",
**kwargs,
)
)
for signed in signed_txs
txhashes = [
w3.eth.send_raw_transaction(signed.rawTransaction) for signed in signed_txs
]
if wait:
return [w3.eth.wait_for_transaction_receipt(txhash) for txhash in txhashes]
return txhashes

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": "basecro", "amount": str(fee)}],
"gas_limit": str(gas_limit),
"payer": "",
"granter": "",
},
},
"signatures": [],
}, tx_hashes


def broadcast_tx_json(cli, tx, **kwargs):
with tempfile.NamedTemporaryFile("w") as fp:
json.dump(tx, fp)
fp.flush()
rsp = json.loads(
cli("tx", "broadcast", fp.name, node="tcp://127.0.0.1:26657", **kwargs)
)
if rsp["code"] == 0:
rsp = json.loads(
cli(
"query",
"event-query-tx-for",
rsp["txhash"],
stderr=subprocess.DEVNULL,
timeout="120s",
**kwargs,
)
)
return rsp

def export_eth_account(cli, name: str, **kwargs) -> Account:
kwargs.setdefault("keyring_backend", "test")
return Account.from_key(cli("keys", "unsafe-export-eth-key", name, **kwargs))

0 comments on commit eb0a15d

Please sign in to comment.