Skip to content

Commit

Permalink
tx sending
Browse files Browse the repository at this point in the history
  • Loading branch information
yihuang committed May 29, 2024
1 parent 03a821c commit eefcf48
Show file tree
Hide file tree
Showing 10 changed files with 1,880 additions and 130 deletions.
30 changes: 17 additions & 13 deletions testground/benchmark/benchmark/main.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import json
import os
import subprocess

from .cli import ChainCommand
from .context import Context
from .peer import bootstrap
from .utils import wait_for_port
from .sendtx import sendtx
from .utils import wait_for_block, wait_for_port

CRONOSD_PATH = "/bin/cronosd"

Expand All @@ -20,25 +20,29 @@ def entrypoint(ctx: Context):
cli = ChainCommand(CRONOSD_PATH)

# build the genesis file collectively, and setup the network topology
bootstrap(ctx, cli)
peer = bootstrap(ctx, cli)

# start the node
proc = subprocess.Popen([CRONOSD_PATH, "start"])
kwargs = {"stdout": subprocess.DEVNULL}
if ctx.is_leader:
del kwargs["stdout"]
proc = subprocess.Popen([CRONOSD_PATH, "start"], **kwargs)

# wait until halt-height
wait_for_port(26657)
while True:
status = json.loads(cli("status", output="json"))
height = int(status["sync_info"]["latest_block_height"])
wait_for_port(8545)
wait_for_block(cli, 1)

if height >= ctx.params.halt_height:
break
if not ctx.is_validator:
sendtx(cli, peer)

# halt together
# halt after all tasks are done
ctx.sync.signal_and_wait("halt", ctx.params.test_instance_count)

proc.terminate()
proc.wait(5)
proc.kill()
try:
proc.wait(5)
except subprocess.TimeoutExpired:
pass
ctx.record_success()


Expand Down
31 changes: 21 additions & 10 deletions testground/benchmark/benchmark/peer.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,35 @@
from .types import GenesisAccount, PeerPacket
from .utils import patch_json, patch_toml

INITIAL_AMOUNT = "10000000basecro"
STAKED_AMOUNT = "10000000basecro"
VAL_INITIAL_AMOUNT = "100000000000000000000basecro"
VAL_STAKED_AMOUNT = "10000000000000000000basecro"
ACC_INITIAL_AMOUNT = "100000000000000000000basecro"


def bootstrap(ctx: Context, cli) -> List[PeerPacket]:
def bootstrap(ctx: Context, cli) -> PeerPacket:
ip = get_data_ip(ctx.params)
cli(
"init",
f"node{ctx.global_seq}",
chain_id=ctx.params.chain_id,
default_denom="basecro",
)
cli("keys", "add", "validator", keyring_backend="test")

cli("keys", "add", "validator", keyring_backend="test")
cli("keys", "add", "account", keyring_backend="test")
validator_addr = cli(
"keys", "show", "validator", "--address", keyring_backend="test"
)
account_addr = cli("keys", "show", "account", "--address", keyring_backend="test")
accounts = [
GenesisAccount(
address=validator_addr,
balance=INITIAL_AMOUNT,
)
balance=VAL_INITIAL_AMOUNT,
),
GenesisAccount(
address=account_addr,
balance=ACC_INITIAL_AMOUNT,
),
]

node_id = cli("comet", "show-node-id")
Expand All @@ -41,6 +48,7 @@ def bootstrap(ctx: Context, cli) -> List[PeerPacket]:
peer_id=peer_id,
accounts=accounts,
)

if ctx.is_validator:
peer.gentx = gentx(cli, ctx.params.chain_id)

Expand All @@ -61,13 +69,13 @@ def bootstrap(ctx: Context, cli) -> List[PeerPacket]:
cli("genesis", "add-genesis-account", account.address, account.balance)
collect_gen_tx(cli, peers)
cli("genesis", "validate")
patch_json(
genesis = patch_json(
config_path / "genesis.json",
{
"consensus.params.block.max_gas": "81500000",
"app_state.evm.params.evm_denom": "basecro",
},
)
genesis = json.loads((config_path / "genesis.json").read_text())
ctx.sync.publish("genesis", genesis)
else:
genesis = ctx.sync.subscribe_simple("genesis", 1)[0]
Expand All @@ -80,6 +88,7 @@ def bootstrap(ctx: Context, cli) -> List[PeerPacket]:
config_path / "config.toml",
{
"p2p.persistent_peers": connect_all(peer, peers),
"mempool.recheck": "false",
},
)
patch_toml(
Expand All @@ -89,21 +98,23 @@ def bootstrap(ctx: Context, cli) -> List[PeerPacket]:
},
)

return peer


def gentx(cli, chain_id):
cli(
"genesis",
"add-genesis-account",
"validator",
INITIAL_AMOUNT,
VAL_INITIAL_AMOUNT,
keyring_backend="test",
)
output = Path("gentx.json")
cli(
"genesis",
"gentx",
"validator",
STAKED_AMOUNT,
VAL_STAKED_AMOUNT,
min_self_delegation=1,
chain_id=chain_id,
output_document=output,
Expand Down
40 changes: 40 additions & 0 deletions testground/benchmark/benchmark/sendtx.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import web3
from eth_account import Account

from .types import PeerPacket
from .utils import send_transaction

TX_AMOUNT = 1000


def sendtx(cli, peer: PeerPacket):
w3 = web3.Web3(web3.providers.HTTPProvider("http://localhost:8545"))
assert w3.eth.chain_id == 777
acct = export_eth_account(cli, "account")
print("test address", acct.address, "balance", w3.eth.get_balance(acct.address))

nonce = w3.eth.get_transaction_count(acct.address)
for i in range(TX_AMOUNT):
tx = {
"to": "0x0000000000000000000000000000000000000000",
"value": 1,
"nonce": nonce,
"gas": 21000,
}
try:
send_transaction(w3, tx, acct, wait=False)
except ValueError as e:
if "invalid nonce" in str(e):
# reset nonce and continue
nonce = w3.eth.get_transaction_count(acct.address)
continue
raise
nonce += 1

assert nonce == w3.eth.get_transaction_count(acct.address)


def export_eth_account(cli, name: str) -> Account:
return Account.from_key(
cli("keys", "unsafe-export-eth-key", name, keyring_backend="test")
)
6 changes: 6 additions & 0 deletions testground/benchmark/benchmark/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@

from pydantic import BaseModel

from .utils import bech32_to_eth


class GenesisAccount(BaseModel):
address: str
balance: str

@property
def eth_address(self) -> str:
return bech32_to_eth(self.address)


class PeerPacket(BaseModel):
ip: str
Expand Down
49 changes: 49 additions & 0 deletions testground/benchmark/benchmark/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
import time
from pathlib import Path

import bech32
import tomlkit
from hexbytes import HexBytes
from web3._utils.transactions import fill_nonce, fill_transaction_defaults


def patch_dict(doc, kwargs):
Expand All @@ -20,12 +23,14 @@ def patch_toml(path: Path, kwargs):
doc = tomlkit.parse(path.read_text())
patch_dict(doc, kwargs)
path.write_text(tomlkit.dumps(doc))
return doc


def patch_json(path: Path, kwargs):
doc = json.loads(path.read_text())
patch_dict(doc, kwargs)
path.write_text(json.dumps(doc))
return doc


def wait_for_port(port, host="127.0.0.1", timeout=40.0):
Expand All @@ -41,3 +46,47 @@ def wait_for_port(port, host="127.0.0.1", timeout=40.0):
"Waited too long for the port {} on host {} to start accepting "
"connections.".format(port, host)
) from ex


def wait_for_block(cli, target: int, timeout=40):
height = -1
for i in range(timeout):
status = json.loads(cli("status", output="json"))
height = int(status["sync_info"]["latest_block_height"])

if height >= target:
break

time.sleep(1)
else:
raise TimeoutError(
f"Waited too long for block {target} to be reached. "
f"Current height: {height}"
)

return height


def decode_bech32(addr):
_, bz = bech32.bech32_decode(addr)
return HexBytes(bytes(bech32.convertbits(bz, 5, 8)))


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


def sign_transaction(w3, tx, acct):
"fill default fields and sign"
tx["from"] = acct.address
tx = fill_transaction_defaults(w3, tx)
tx = fill_nonce(w3, tx)
return acct.sign_transaction(tx)


def send_transaction(w3, tx, acct, wait=True):
signed = sign_transaction(w3, tx, acct)
txhash = w3.eth.send_raw_transaction(signed.rawTransaction)
if wait:
return w3.eth.wait_for_transaction_receipt(txhash)
return txhash
6 changes: 3 additions & 3 deletions testground/benchmark/compositions/local.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@ disable_metrics = false

[global.run.test_params]
chain_id = "cronos_777-1"
halt_height = "10"
halt_height = "5"

[[groups]]
id = "validators"
builder = "docker:nix"
[groups.instances]
percentage = 0.5
count = 1

[[groups]]
id = "fullnodes"
builder = "docker:nix"
[groups.instances]
percentage = 0.5
count = 9
Loading

0 comments on commit eefcf48

Please sign in to comment.