Skip to content

Commit

Permalink
Merge branch 'main' into rocksdb-9.2.1
Browse files Browse the repository at this point in the history
  • Loading branch information
yihuang authored Jul 8, 2024
2 parents 9d43725 + 3983714 commit 1e87e45
Show file tree
Hide file tree
Showing 17 changed files with 527 additions and 234 deletions.
4 changes: 4 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@
apps = {
cronosd = mkApp packages.cronosd;
cronosd-testnet = mkApp packages.cronosd-testnet;
stateless-testcase = {
type = "app";
program = "${pkgs.testground-testcase}/bin/stateless-testcase";
};
};
defaultPackage = packages.cronosd;
defaultApp = apps.cronosd;
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ require (
github.com/prometheus/procfs v0.13.0 // indirect
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
github.com/rogpeppe/go-internal v1.12.0 // indirect
github.com/rs/cors v1.10.1 // indirect
github.com/rs/cors v1.11.0 // indirect
github.com/rs/zerolog v1.32.0 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1038,8 +1038,8 @@ github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/f
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo=
github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
github.com/rs/cors v1.11.0 h1:0B9GE/r9Bc2UxRMMtymBkHTenPkHDv0CW4Y98GBY+po=
github.com/rs/cors v1.11.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0=
github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
Expand Down
4 changes: 2 additions & 2 deletions gomod2nix.toml
Original file line number Diff line number Diff line change
Expand Up @@ -530,8 +530,8 @@ schema = 3
version = "v1.12.0"
hash = "sha256-qvDNCe3l84/LgrA8X4O15e1FeDcazyX91m9LmXGXX6M="
[mod."github.com/rs/cors"]
version = "v1.10.1"
hash = "sha256-um4INJM5/675MLK42npIsDbSQ1/Iy5ZiUNuAFReUfeM="
version = "v1.11.0"
hash = "sha256-hF25bVehtWCQsxiOfLuL4Hv8NKVunEqLPk/Vcuheha0="
[mod."github.com/rs/zerolog"]
version = "v1.32.0"
hash = "sha256-9dZjtsES+wLp1cFiSVMuEUbdeXVFcgT0dgg5ACZkILk="
Expand Down
8 changes: 4 additions & 4 deletions integration_tests/poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 27 additions & 0 deletions testground/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# Testground

[Testground documentation](https://docs.testground.ai/)

## Build Image
Expand Down Expand Up @@ -67,3 +69,28 @@ mounts:
writable: true
```



# Stateless Mode

To simplify cluster setup, we are introducing a stateless mode.

## Generate Data Files Locally

You need to have a `cronosd` in `PATH`.

```bash
$ nix run github:crypto-org-chain/cronos#stateless-testcase gen /tmp/data/out 3 7
```

## Run In Local Docker

```bash
$ jsonnet -S testground/benchmark/compositions/docker-compose.jsonnet | docker-compose -f /dev/stdin up
```

It'll mount the data files to all the containers.

## Run In Cluster

TODO
29 changes: 6 additions & 23 deletions testground/benchmark/benchmark/main.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
import os
import subprocess
from concurrent.futures import ThreadPoolExecutor, as_completed
from pathlib import Path

import web3

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

CRONOSD_PATH = "/bin/cronosd"
from .peer import CONTAINER_CRONOSD_PATH, bootstrap
from .sendtx import generate_load
from .utils import wait_for_block, wait_for_port


def influxdb_url():
Expand All @@ -21,15 +18,15 @@ def influxdb_url():
def entrypoint(ctx: Context):
ctx.init_common()

cli = ChainCommand(CRONOSD_PATH)
cli = ChainCommand(CONTAINER_CRONOSD_PATH)

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

# start the node
logfile = Path(ctx.params.test_outputs_path) / "node.log"
proc = subprocess.Popen(
[CRONOSD_PATH, "start"],
[CONTAINER_CRONOSD_PATH, "start"],
stdout=open(logfile, "ab", buffering=0),
)

Expand All @@ -39,21 +36,7 @@ def entrypoint(ctx: Context):

test_finish_entry = f"finish-test-{ctx.params.test_group_id}"
if not ctx.is_validator:
w3 = web3.Web3(web3.providers.HTTPProvider("http://localhost:8545"))
assert w3.eth.chain_id == 777
genesis_account = export_eth_account(cli, "account")
accounts = fund_test_accounts(w3, genesis_account, ctx.params.num_accounts)
with ThreadPoolExecutor(max_workers=ctx.params.num_accounts) as executor:
futs = (
executor.submit(sendtx, w3, acct, ctx.params.num_txs)
for acct in accounts
)
for fut in as_completed(futs):
try:
fut.result()
except Exception as e:
print("test task failed", e)

generate_load(cli, ctx.params.num_accounts, ctx.params.num_txs)
print("finish test", ctx.group_seq)
ctx.sync.signal_and_wait(
test_finish_entry, ctx.params.test_group_instance_count
Expand Down
171 changes: 106 additions & 65 deletions testground/benchmark/benchmark/peer.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,86 +3,129 @@
from pathlib import Path
from typing import List

from .cli import ChainCommand
from .context import Context
from .network import get_data_ip
from .topology import connect_all
from .types import GenesisAccount, PeerPacket
from .utils import patch_json, patch_toml

VAL_ACCOUNT = "validator"
VAL_INITIAL_AMOUNT = "100000000000000000000basecro"
VAL_STAKED_AMOUNT = "10000000000000000000basecro"
ACC_INITIAL_AMOUNT = "100000000000000000000basecro"
ACC_INITIAL_AMOUNT = "100000000000000000000000basecro"
MEMPOOL_SIZE = 50000
DEFAULT_DENOM = "basecro"
VALIDATOR_GROUP = "validators"
FULLNODE_GROUP = "fullnodes"
CONTAINER_CRONOSD_PATH = "/bin/cronosd"


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",
home = Path.home() / ".cronos"
peer = init_node(
cli,
home,
get_data_ip(ctx.params),
ctx.params.chain_id,
ctx.params.test_group_id,
ctx.group_seq,
)

cli("keys", "add", "validator", keyring_backend="test")
cli("keys", "add", "account", keyring_backend="test")
validator_addr = cli(
"keys", "show", "validator", "--address", keyring_backend="test"
data = ctx.sync.publish_subscribe_simple(
"peers", peer.dict(), ctx.params.test_instance_count
)
peers: List[PeerPacket] = [PeerPacket.model_validate(item) for item in data]

if ctx.is_fullnode_leader:
# prepare genesis file and publish
genesis = gen_genesis(cli, home, peers)
ctx.sync.publish("genesis", genesis)
else:
genesis = ctx.sync.subscribe_simple("genesis", 1)[0]
(home / "config" / "genesis.json").write_text(json.dumps(genesis))
cli("genesis", "validate", home=home)

p2p_peers = connect_all(peer, peers)
patch_configs(home, ctx.params.test_group_id, p2p_peers)
return peer


def init_node(
cli: ChainCommand,
home: Path,
ip: str,
chain_id: str,
group: str,
group_seq: int,
) -> PeerPacket:
default_kwargs = {
"home": home,
"chain_id": chain_id,
"keyring_backend": "test",
}
cli(
"init",
f"{group}-{group_seq}",
default_denom=DEFAULT_DENOM,
**default_kwargs,
)
account_addr = cli("keys", "show", "account", "--address", keyring_backend="test")
cli("keys", "add", VAL_ACCOUNT, **default_kwargs)
cli("keys", "add", "account", **default_kwargs)
validator_addr = cli("keys", "show", VAL_ACCOUNT, "--address", **default_kwargs)
account_addr = cli("keys", "show", "account", "--address", **default_kwargs)
accounts = [
GenesisAccount(address=validator_addr, balance=VAL_INITIAL_AMOUNT),
GenesisAccount(address=account_addr, balance=ACC_INITIAL_AMOUNT),
]

node_id = cli("comet", "show-node-id")
node_id = cli("comet", "show-node-id", **default_kwargs)
peer_id = f"{node_id}@{ip}:26656"
current = PeerPacket(
peer = PeerPacket(
ip=str(ip),
node_id=node_id,
peer_id=peer_id,
accounts=accounts,
)

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

data = ctx.sync.publish_subscribe_simple(
"peers", current.dict(), ctx.params.test_instance_count
if group == VALIDATOR_GROUP:
peer.gentx = gentx(cli, **default_kwargs)

return peer


def gen_genesis(cli: ChainCommand, leader_home: Path, peers: List[PeerPacket]):
for peer in peers:
for account in peer.accounts:
cli(
"genesis",
"add-genesis-account",
account.address,
account.balance,
home=leader_home,
)
collect_gen_tx(cli, peers, home=leader_home)
cli("genesis", "validate", home=leader_home)
return patch_json(
leader_home / "config" / "genesis.json",
{
"consensus.params.block.max_gas": "81500000",
"app_state.evm.params.evm_denom": "basecro",
"app_state.feemarket.params.no_base_fee": True,
},
)
peers: List[PeerPacket] = [PeerPacket.model_validate(item) for item in data]

config_path = Path.home() / ".cronos" / "config"
if ctx.is_fullnode_leader:
# prepare genesis file and publish
for peer in peers:
for account in peer.accounts:
cli("genesis", "add-genesis-account", account.address, account.balance)
collect_gen_tx(cli, peers)
cli("genesis", "validate")
genesis = patch_json(
config_path / "genesis.json",
{
"consensus.params.block.max_gas": "81500000",
"app_state.evm.params.evm_denom": "basecro",
"app_state.feemarket.params.no_base_fee": True,
},
)
ctx.sync.publish("genesis", genesis)
else:
genesis = ctx.sync.subscribe_simple("genesis", 1)[0]
genesis_file = config_path / "genesis.json"
genesis_file.write_text(json.dumps(genesis))
cli("genesis", "validate")

def patch_configs(home: Path, group: str, peers: str):
# update persistent_peers and other configs in config.toml
config_patch = {
"p2p.persistent_peers": connect_all(current, peers),
"p2p.persistent_peers": peers,
"p2p.addr_book_strict": False,
"mempool.recheck": "false",
"mempool.size": MEMPOOL_SIZE,
"consensus.timeout_commit": "2s",
}
if ctx.is_validator:
if group == VALIDATOR_GROUP:
config_patch["tx_index.indexer"] = "null"

app_patch = {
Expand All @@ -92,35 +135,33 @@ def bootstrap(ctx: Context, cli) -> PeerPacket:
"mempool.max-txs": MEMPOOL_SIZE,
}

patch_toml(config_path / "config.toml", config_patch)
patch_toml(config_path / "app.toml", app_patch)
patch_toml(home / "config" / "config.toml", config_patch)
patch_toml(home / "config" / "app.toml", app_patch)

return current


def gentx(cli, chain_id):
def gentx(cli, **kwargs):
cli(
"genesis",
"add-genesis-account",
"validator",
VAL_ACCOUNT,
VAL_INITIAL_AMOUNT,
keyring_backend="test",
**kwargs,
)
output = Path("gentx.json")
cli(
"genesis",
"gentx",
"validator",
VAL_STAKED_AMOUNT,
min_self_delegation=1,
chain_id=chain_id,
output_document=output,
keyring_backend="test",
)
return json.loads(output.read_text())
with tempfile.TemporaryDirectory() as tmp:
output = Path(tmp) / "gentx.json"
cli(
"genesis",
"gentx",
VAL_ACCOUNT,
VAL_STAKED_AMOUNT,
min_self_delegation=1,
output_document=output,
**kwargs,
)
return json.loads(output.read_text())


def collect_gen_tx(cli, peers):
def collect_gen_tx(cli, peers, **kwargs):
"""
save gentxs to file and call collect-gentxs
leader node prepare genesis file and broadcast to other nodes
Expand All @@ -130,4 +171,4 @@ def collect_gen_tx(cli, peers):
for i, peer in enumerate(peers):
if peer.gentx is not None:
(tmpdir / f"gentx-{i}.json").write_text(json.dumps(peer.gentx))
cli("genesis", "collect-gentxs", gentx_dir=str(tmpdir))
cli("genesis", "collect-gentxs", gentx_dir=str(tmpdir), **kwargs)
Loading

0 comments on commit 1e87e45

Please sign in to comment.