Skip to content

Commit

Permalink
cli is slow
Browse files Browse the repository at this point in the history
  • Loading branch information
mmsqe committed Sep 13, 2024
1 parent e11bcbd commit 8e116e3
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 177 deletions.
2 changes: 1 addition & 1 deletion testground/benchmark/benchmark/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def entrypoint(ctx: Context):

test_finish_entry = f"finish-test-{ctx.params.test_group_id}"
if not ctx.is_validator:
generate_load(cli, ctx.params.num_accounts)
generate_load(ctx.params.num_accounts)
print("finish test", ctx.group_seq)
ctx.sync.signal_and_wait(
test_finish_entry, ctx.params.test_group_instance_count
Expand Down
79 changes: 37 additions & 42 deletions testground/benchmark/benchmark/peer.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,20 @@ def bootstrap(ctx: Context, cli) -> PeerPacket:
return peer


def create_user_with_txs(tx, num_txs):
txs = []
acct = Account.create()
for i in range(num_txs):
tx["nonce"] = i
raw = Account.from_key(acct.key).sign_transaction(tx).rawTransaction
txs.append(raw.hex())
user = {
"address": eth_to_bech32(acct.address),
"coins": parse_coins(ACC_INITIAL_AMOUNT),
}
return user, txs


def init_node(
cli: ChainCommand,
home: Path,
Expand Down Expand Up @@ -87,38 +101,20 @@ def init_node(
"gasPrice": 1000000000,
"chainId": 777,
}
futs = []
with ThreadPoolExecutor(max_workers=num_accounts * num_txs) as executor:
tmp_txs = []
with ThreadPoolExecutor(max_workers=num_accounts) as executor:
futs = []
for _ in range(num_accounts):
user = Account.create()
users.append(
{
"address": eth_to_bech32(user.address),
"coins": parse_coins(ACC_INITIAL_AMOUNT),
}
)
for i in range(num_txs):
tx["nonce"] = i
raw = Account.from_key(user.key).sign_transaction(tx).rawTransaction
futs.append(
executor.submit(
cli,
"tx",
"evm",
"raw",
raw.hex(),
"-y",
"--generate-only",
"--evm-denom",
DEFAULT_DENOM,
**default_kwargs,
)
)
try:
tmp_txs = [fut.result() for fut in as_completed(futs)]
except Exception as e:
print("generate account failed", e)

futs.append(executor.submit(create_user_with_txs, tx, num_txs))
for fut in as_completed(futs):
try:
user, txs = fut.result()
users.append(user)
tmp_txs.extend(txs)
except Exception as e:
print("create_user_with_txs failed", e)

print(f"generate {len(tmp_txs)} txs")
file = home / "tmp_txs.json"
file.write_text(json.dumps(tmp_txs))
validator_addr = cli("keys", "show", VAL_ACCOUNT, "--address", **default_kwargs)
Expand Down Expand Up @@ -148,12 +144,9 @@ def init_node(
def gen_genesis(
cli: ChainCommand, leader_home: Path, peers: List[PeerPacket], genesis_patch: dict
):
default_kwargs = {
"home": leader_home,
"chain_id": "cronos_777-1",
"keyring_backend": "test",
}
users = []
for peer in peers:
users.extend(peer.users)
for account in peer.accounts:
cli(
"genesis",
Expand All @@ -164,12 +157,14 @@ def gen_genesis(
)
file = peer.home / "users.json"
file.write_text(json.dumps(peer.users))
cli(
"genesis",
"bulk-add-genesis-account",
file,
**default_kwargs,
)
file = leader_home / "all_users.json"
file.write_text(json.dumps(users))
cli(
"genesis",
"bulk-add-genesis-account",
file,
home=leader_home,
)

collect_gen_tx(cli, peers, home=leader_home)
cli("genesis", "validate", home=leader_home)
Expand Down
125 changes: 8 additions & 117 deletions testground/benchmark/benchmark/sendtx.py
Original file line number Diff line number Diff line change
@@ -1,136 +1,27 @@
import json
import tempfile
import time
from concurrent.futures import ThreadPoolExecutor, as_completed

import web3
from eth_account import Account

from .utils import send_transaction, send_transactions
from hexbytes import HexBytes

TEST_AMOUNT = 1000000000000000000
GAS_PRICE = 1000000000


def fund_test_accounts(w3, from_account, num_accounts) -> [Account]:
accounts = []
nonce = w3.eth.get_transaction_count(from_account.address)
txs = []
for i in range(num_accounts):
acct = Account.create()
tx = {
"to": acct.address,
"value": TEST_AMOUNT,
"gas": 21000,
"gasPrice": GAS_PRICE,
"nonce": nonce + i,
}
txs.append(tx)
accounts.append(acct)
receipts = send_transactions(w3, txs, from_account)
for receipt in receipts:
assert receipt["status"] == 1
return accounts


def sendtx(w3: web3.Web3, acct: Account, tx_amount: int):
initial_nonce = w3.eth.get_transaction_count(acct.address)
print(
"test begin, address:",
acct.address,
"balance:",
w3.eth.get_balance(acct.address),
"nonce:",
initial_nonce,
)

nonce = initial_nonce
while nonce < initial_nonce + tx_amount:
tx = {
"to": "0x0000000000000000000000000000000000000000",
"value": 1,
"nonce": nonce,
"gas": 21000,
"gasPrice": GAS_PRICE,
}
try:
send_transaction(w3, tx, acct, wait=False)
except ValueError as e:
msg = str(e)
if "invalid nonce" in msg:
print("invalid nonce and retry", nonce)
time.sleep(1)
continue
if "tx already in mempool" not in msg:
raise

nonce += 1

if nonce % 100 == 0:
print(f"{acct.address} sent {nonce} transactions")

print(
"test end, address:",
acct.address,
"balance:",
w3.eth.get_balance(acct.address),
"nonce:",
w3.eth.get_transaction_count(acct.address),
)


def sendrawtx(cli, tx, **kwargs):
tx = json.loads(tx)
msgs = [tx["body"]["messages"][0]]
fee = tx["auth_info"]["fee"]
total_fee = sum(int(amt["amount"]) for amt in fee["amount"])
gas_limit = int(fee["gas_limit"])
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": "basecro", "amount": str(total_fee)}],
"gas_limit": str(gas_limit),
"payer": "",
"granter": "",
},
},
"signatures": [],
}
with tempfile.NamedTemporaryFile("w") as fp:
json.dump(cosmos_tx, fp)
fp.flush()
rsp = json.loads(cli("tx", "broadcast", fp.name, **kwargs))
cli("tx", "broadcast", fp.name, **kwargs)
if rsp["code"] == 0:
print("txhash", rsp["txhash"])


def sendrawtx_retry(cli, tx, **kwargs):
for i in range(0, 3):
try:
sendrawtx(cli, tx, **kwargs)
break
except Exception as e:
print("sendrawtx failed", i, e)
def sendtx(w3: web3.Web3, tx):
txhash = w3.eth.send_raw_transaction(HexBytes(tx))
print("sendtx", txhash.hex())


def generate_load(cli, num_accounts, **kwargs):
def generate_load(num_accounts, **kwargs):
w3 = web3.Web3(web3.providers.HTTPProvider("http://localhost:8545"))
assert w3.eth.chain_id == 777
home = kwargs.get("home")
tmp_txs = []
with open(home / "tmp_txs.json", "r") as file:
tmp_txs = json.load(file)
with ThreadPoolExecutor(max_workers=num_accounts) as executor:
futs = (executor.submit(sendrawtx_retry, cli, tx, **kwargs) for tx in tmp_txs)
futs = (executor.submit(sendtx, w3, tx) for tx in tmp_txs)
for fut in as_completed(futs):
try:
fut.result()
Expand Down
29 changes: 13 additions & 16 deletions testground/benchmark/benchmark/stateless.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import fire
import requests
import tomlkit
import web3

from .cli import ChainCommand
from .echo import run_echo_server
Expand All @@ -28,7 +29,7 @@
from .sendtx import generate_load
from .topology import connect_all
from .types import PeerPacket
from .utils import wait_for_block, wait_for_port, wait_for_w3
from .utils import bech32_to_eth, wait_for_block, wait_for_port, wait_for_w3

# use cronosd on host machine
LOCAL_CRONOSD_PATH = "cronosd"
Expand Down Expand Up @@ -169,12 +170,12 @@ def run(

if group == FULLNODE_GROUP or cfg.get("validator-generate-load", True):
wait_for_w3()
generate_load(cli, cfg["num_accounts"], home=home, output="json")
generate_load(cfg["num_accounts"], home=home, output="json")

# node quit when the chain is idle or halted for a while
detect_idle_halted(3, 3)

print_balances(cli, home)
print_balances(home)

with (home / "block_stats.log").open("w") as logfile:
dump_block_stats(logfile)
Expand All @@ -194,37 +195,33 @@ def run(
shutil.copy(output, filename)


def print_balances(cli, home):
def print_balances(home):
with open(home / "users.json", "r") as file:
futs = []
users = json.load(file)
w3 = web3.Web3(web3.providers.HTTPProvider("http://localhost:8545"))
with ThreadPoolExecutor(max_workers=len(users)) as executor:
for user in users:
futs.append(
executor.submit(
cli,
"query",
"bank",
"balances",
user["address"],
height=0,
home=home,
output="json",
w3.eth.get_balance,
bech32_to_eth(user["address"]),
)
)

for idx, fut in enumerate(as_completed(futs)):
user = users[idx]
addr = bech32_to_eth(user["address"])
try:
result = json.loads(fut.result())
result = fut.result()
print(
"test end, address:",
user["address"],
addr,
"balance:",
result["balances"][0]["amount"],
result,
)
except Exception as e:
print("get balance failed", user["address"], e)
print("get balance failed", addr, e)


def output_filter(group, group_seq: int):
Expand Down
3 changes: 2 additions & 1 deletion testground/benchmark/benchmark/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import tomlkit
import web3
from eth_account import Account
from eth_utils import to_checksum_address
from hexbytes import HexBytes
from web3._utils.transactions import fill_nonce, fill_transaction_defaults

Expand Down Expand Up @@ -90,7 +91,7 @@ def decode_bech32(addr):


def bech32_to_eth(addr):
return decode_bech32(addr).hex()
return to_checksum_address(decode_bech32(addr).hex())


def sign_transaction(w3, tx, acct):
Expand Down

0 comments on commit 8e116e3

Please sign in to comment.