Skip to content

Commit 670fd8d

Browse files
mmsqehuangyi
andauthored
Problem: test transactions can't be saved and reused (#1575)
* remove unused function * Problem: test transactions can't be saved and reused Solution: - support saving test transactions to files and reuse to speedup local test Co-authored-by: mmsqe <[email protected]> * use constant * add log * fix * fix log * log * fix * add log * log --------- Co-authored-by: huangyi <[email protected]>
1 parent 3c8be96 commit 670fd8d

File tree

2 files changed

+65
-52
lines changed

2 files changed

+65
-52
lines changed

testground/benchmark/benchmark/stateless.py

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import click
1414
import tomlkit
1515

16+
from . import transaction
1617
from .cli import ChainCommand
1718
from .echo import run_echo_server
1819
from .peer import (
@@ -23,7 +24,6 @@
2324
init_node,
2425
patch_configs,
2526
)
26-
from .sendtx import prepare_txs, send_txs
2727
from .stats import dump_block_stats
2828
from .topology import connect_all
2929
from .types import PeerPacket
@@ -184,7 +184,7 @@ def run(outdir: str, datadir: str, cronosd, global_seq):
184184
home = datadir / group / str(group_seq)
185185

186186
try:
187-
return do_run(home, cronosd, group, global_seq, cfg)
187+
return do_run(datadir, home, cronosd, group, global_seq, cfg)
188188
finally:
189189
# collect outputs
190190
output = Path("/data.tar.bz2")
@@ -198,10 +198,45 @@ def run(outdir: str, datadir: str, cronosd, global_seq):
198198
shutil.copy(output, filename)
199199

200200

201-
def do_run(home: str, cronosd: str, group: str, global_seq: int, cfg: dict):
201+
@cli.command()
202+
@click.argument("outdir")
203+
@click.option("--nodes", default=10)
204+
@click.option("--num-accounts", default=10)
205+
@click.option("--num-txs", default=1000)
206+
def gen_txs(**kwargs):
207+
return _gen_txs(**kwargs)
208+
209+
210+
@cli.command()
211+
@click.argument("options", callback=validate_json)
212+
def generic_gen_txs(options: dict):
213+
return _gen_txs(**options)
214+
215+
216+
def _gen_txs(
217+
outdir: str,
218+
nodes: int = 10,
219+
num_accounts: int = 10,
220+
num_txs: int = 1000,
221+
):
222+
outdir = Path(outdir)
223+
for global_seq in range(nodes):
224+
print("generating", num_accounts * num_txs, "txs for node", global_seq)
225+
txs = transaction.gen(global_seq, num_accounts, num_txs)
226+
transaction.save(txs, outdir, global_seq)
227+
print("saved", len(txs), "txs for node", global_seq)
228+
229+
230+
def do_run(
231+
datadir: Path, home: Path, cronosd: str, group: str, global_seq: int, cfg: dict
232+
):
202233
if group == FULLNODE_GROUP or cfg.get("validator-generate-load", True):
203-
print("preparing", cfg["num_accounts"] * cfg["num_txs"], "txs")
204-
txs = prepare_txs(global_seq, cfg["num_accounts"], cfg["num_txs"])
234+
txs = transaction.load(datadir, global_seq)
235+
if txs:
236+
print("loaded", len(txs), "txs")
237+
else:
238+
print("generating", cfg["num_accounts"] * cfg["num_txs"], "txs")
239+
txs = transaction.gen(global_seq, cfg["num_accounts"], cfg["num_txs"])
205240
else:
206241
txs = []
207242

@@ -222,7 +257,8 @@ def do_run(home: str, cronosd: str, group: str, global_seq: int, cfg: dict):
222257
wait_for_block(cli, 3)
223258

224259
if txs:
225-
asyncio.run(send_txs(txs))
260+
asyncio.run(transaction.send(txs))
261+
print("sent", len(txs), "txs")
226262

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

testground/benchmark/benchmark/sendtx.py renamed to testground/benchmark/benchmark/transaction.py

Lines changed: 23 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
11
import asyncio
2-
import time
2+
from pathlib import Path
33

44
import aiohttp
55
import ujson
6-
import web3
7-
from eth_account import Account
86

9-
from .utils import gen_account, send_transaction
7+
from .utils import gen_account
108

119
GAS_PRICE = 1000000000
1210
CHAIN_ID = 777
1311
LOCAL_JSON_RPC = "http://localhost:8545"
1412
CONNECTION_POOL_SIZE = 1024
13+
TXS_DIR = "txs"
1514

1615

1716
def test_tx(nonce: int):
@@ -25,57 +24,35 @@ def test_tx(nonce: int):
2524
}
2625

2726

28-
def sendtx(w3: web3.Web3, acct: Account, tx_amount: int):
29-
initial_nonce = w3.eth.get_transaction_count(acct.address)
30-
print(
31-
"test begin, address:",
32-
acct.address,
33-
"balance:",
34-
w3.eth.get_balance(acct.address),
35-
"nonce:",
36-
initial_nonce,
37-
)
38-
39-
nonce = initial_nonce
40-
while nonce < initial_nonce + tx_amount:
41-
try:
42-
send_transaction(w3, test_tx(nonce), acct, wait=False)
43-
except ValueError as e:
44-
msg = str(e)
45-
if "invalid nonce" in msg:
46-
print("invalid nonce and retry", nonce)
47-
time.sleep(1)
48-
continue
49-
if "tx already in mempool" not in msg:
50-
raise
51-
52-
nonce += 1
53-
54-
if nonce % 100 == 0:
55-
print(f"{acct.address} sent {nonce} transactions")
56-
57-
print(
58-
"test end, address:",
59-
acct.address,
60-
"balance:",
61-
w3.eth.get_balance(acct.address),
62-
"nonce:",
63-
w3.eth.get_transaction_count(acct.address),
64-
)
65-
66-
67-
def prepare_txs(global_seq, num_accounts, num_txs):
27+
def gen(global_seq, num_accounts, num_txs) -> [str]:
6828
accounts = [gen_account(global_seq, i + 1) for i in range(num_accounts)]
6929
txs = []
7030
for i in range(num_txs):
7131
for acct in accounts:
7232
txs.append(acct.sign_transaction(test_tx(i)).rawTransaction.hex())
7333
if len(txs) % 1000 == 0:
74-
print("prepared", len(txs), "txs")
34+
print("generated", len(txs), "txs for node", global_seq)
7535

7636
return txs
7737

7838

39+
def save(txs: [str], datadir: Path, global_seq: int):
40+
d = datadir / TXS_DIR
41+
d.mkdir(parents=True, exist_ok=True)
42+
path = d / f"{global_seq}.json"
43+
with path.open("w") as f:
44+
ujson.dump(txs, f)
45+
46+
47+
def load(datadir: Path, global_seq: int) -> [str]:
48+
path = datadir / TXS_DIR / f"{global_seq}.json"
49+
if not path.exists():
50+
return
51+
52+
with path.open("r") as f:
53+
return ujson.load(f)
54+
55+
7956
async def async_sendtx(session, raw):
8057
async with session.post(
8158
LOCAL_JSON_RPC,
@@ -91,7 +68,7 @@ async def async_sendtx(session, raw):
9168
print("send tx error", data["error"])
9269

9370

94-
async def send_txs(txs):
71+
async def send(txs):
9572
connector = aiohttp.TCPConnector(limit=1024)
9673
async with aiohttp.ClientSession(
9774
connector=connector, json_serialize=ujson.dumps

0 commit comments

Comments
 (0)