Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem: cometbft rpc is more efficient to broadcast tx #1651

Merged
merged 5 commits into from
Oct 18, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
* [#1645](https://github.com/crypto-org-chain/cronos/pull/1645) Gen test tx in parallel even in single node.
* (testground)[#1644](https://github.com/crypto-org-chain/cronos/pull/1644) load generator retry with backoff on error.
* [#1648](https://github.com/crypto-org-chain/cronos/pull/1648) Add abort OE in PrepareProposal.
* (testground)[#]() Benchmark use cosmos broadcast rpc.
yihuang marked this conversation as resolved.
Show resolved Hide resolved

*Oct 14, 2024*

Expand Down
86 changes: 86 additions & 0 deletions testground/benchmark/benchmark/cosmostx.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
from typing import Optional

from cprotobuf import Field, ProtoEntity


class Any(ProtoEntity):
type_url = Field("string", 1)
value = Field("bytes", 2)


def build_any(type_url: str, msg: Optional[ProtoEntity] = None) -> Any:
value = b""
if msg is not None:
value = msg.SerializeToString()
return Any(type_url=type_url, value=value)
yihuang marked this conversation as resolved.
Show resolved Hide resolved


class TxBody(ProtoEntity):
messages = Field(Any, 1, repeated=True)
memo = Field("string", 2)
timeout_height = Field("uint64", 3)
extension_options = Field(Any, 1023, repeated=True)
non_critical_extension_options = Field(Any, 2047, repeated=True)


class CompactBitArray(ProtoEntity):
extra_bits_stored = Field("uint32", 1)
elems = Field("bytes", 2)


class ModeInfoSingle(ProtoEntity):
mode = Field("int32", 1)


class ModeInfoMulti(ProtoEntity):
bitarray = Field(CompactBitArray, 1)
mode_infos = Field("ModeInfo", 2, repeated=True)
yihuang marked this conversation as resolved.
Show resolved Hide resolved


class ModeInfo(ProtoEntity):
single = Field("ModeInfo.Single", 1)
multi = Field("ModeInfo.Multi", 2)
yihuang marked this conversation as resolved.
Show resolved Hide resolved


class SignerInfo(ProtoEntity):
public_key = Field(Any, 1)
mode_info = Field(ModeInfo, 2)
sequence = Field("uint64", 3)


class Coin(ProtoEntity):
denom = Field("string", 1)
amount = Field("string", 2)


class Fee(ProtoEntity):
amount = Field(Coin, 1, repeated=True)
gas_limit = Field("uint64", 2)
payer = Field("string", 3)
granter = Field("string", 4)


class Tip(ProtoEntity):
amount = Field(Coin, 1, repeated=True)
tipper = Field("string", 2)


class AuthInfo(ProtoEntity):
signer_infos = Field(SignerInfo, 1, repeated=True)
fee = Field(Fee, 2)
tip = Field(Tip, 3)


class TxRaw(ProtoEntity):
body = Field("bytes", 1)
auth_info = Field("bytes", 2)
signatures = Field("bytes", 3, repeated=True)


class MsgEthereumTx(ProtoEntity):
from_ = Field("bytes", 5)
raw = Field("bytes", 6)


class ExtensionOptionsEthereumTx(ProtoEntity):
pass
yihuang marked this conversation as resolved.
Show resolved Hide resolved
2 changes: 1 addition & 1 deletion testground/benchmark/benchmark/peer.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from .cli import ChainCommand
from .types import Balance, GenesisAccount, PeerPacket
from .utils import (
DEFAULT_DENOM,
bech32_to_eth,
eth_to_bech32,
gen_account,
Expand All @@ -19,7 +20,6 @@
patch_toml,
)

DEFAULT_DENOM = "basecro"
VAL_ACCOUNT = "validator"
VAL_INITIAL_AMOUNT = Balance(amount="100000000000000000000", denom=DEFAULT_DENOM)
VAL_STAKED_AMOUNT = Balance(amount="10000000000000000000", denom=DEFAULT_DENOM)
Expand Down
46 changes: 41 additions & 5 deletions testground/benchmark/benchmark/transaction.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import asyncio
import base64
import itertools
import multiprocessing
import os
Expand All @@ -9,9 +10,11 @@
import backoff
import eth_abi
import ujson
from hexbytes import HexBytes

from . import cosmostx
from .erc20 import CONTRACT_ADDRESS
from .utils import LOCAL_JSON_RPC, gen_account, split
from .utils import DEFAULT_DENOM, LOCAL_RPC, gen_account, split

GAS_PRICE = 1000000000
CHAIN_ID = 777
Expand Down Expand Up @@ -63,7 +66,9 @@ def _do_job(job: Job):
for acct in accounts:
txs = []
for i in range(job.num_txs):
txs.append(acct.sign_transaction(job.create_tx(i)).rawTransaction.hex())
tx = job.create_tx(i)
raw = acct.sign_transaction(tx).rawTransaction
txs.append(build_cosmos_tx(tx, raw, HexBytes(acct.address)))
total += 1
if total % 1000 == 0:
print("generated", total, "txs for node", job.global_seq)
Expand Down Expand Up @@ -107,15 +112,46 @@ def load(datadir: Path, global_seq: int) -> [str]:
return ujson.load(f)


def build_cosmos_tx(tx: dict, raw: bytes, sender: bytes) -> str:
"""
return base64 encoded cosmos tx
"""
msg = cosmostx.build_any(
"/ethermint.evm.v1.MsgEthereumTx",
cosmostx.MsgEthereumTx(
from_=sender,
raw=raw,
),
)
fee = tx["gas"] * tx["gasPrice"]
body = cosmostx.TxBody(
messages=[msg],
extension_options=[
cosmostx.build_any("/ethermint.evm.v1.ExtensionOptionsEthereumTx")
],
)
auth_info = cosmostx.AuthInfo(
fee=cosmostx.Fee(
amount=[cosmostx.Coin(denom=DEFAULT_DENOM, amount=str(fee))],
gas_limit=tx["gas"],
)
)
return base64.b64encode(
cosmostx.TxRaw(
body=body.SerializeToString(), auth_info=auth_info.SerializeToString()
).SerializeToString()
).decode()

yihuang marked this conversation as resolved.
Show resolved Hide resolved

@backoff.on_predicate(backoff.expo, max_time=60, max_value=5)
@backoff.on_exception(backoff.expo, aiohttp.ClientError, max_time=60, max_value=5)
async def async_sendtx(session, raw):
async with session.post(
LOCAL_JSON_RPC,
LOCAL_RPC,
json={
"jsonrpc": "2.0",
"method": "eth_sendRawTransaction",
"params": [raw],
"method": "broadcast_tx_async",
"params": {"tx": raw},
"id": 1,
},
) as rsp:
Expand Down
1 change: 1 addition & 0 deletions testground/benchmark/benchmark/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from hexbytes import HexBytes
from web3._utils.transactions import fill_nonce, fill_transaction_defaults

DEFAULT_DENOM = "basecro"
CRONOS_ADDRESS_PREFIX = "crc"
LOCAL_RPC = "http://127.0.0.1:26657"
LOCAL_JSON_RPC = "http://127.0.0.1:8545"
Expand Down
1 change: 1 addition & 0 deletions testground/benchmark/overlay.nix
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ let
docker = [ "hatchling" "hatch-vcs" ];
pyunormalize = [ "setuptools" ];
pytest-github-actions-annotate-failures = [ "setuptools" ];
cprotobuf = [ "setuptools" ];
};
in
lib.mapAttrs
Expand Down
12 changes: 11 additions & 1 deletion testground/benchmark/poetry.lock

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

1 change: 1 addition & 0 deletions testground/benchmark/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ ujson = "^5.10.0"
jsonmerge = "^1.9.2"

backoff = "^2.2.1"
cprotobuf = "^0.1.11"
[tool.poetry.group.dev.dependencies]
pytest = "^8.2"
pytest-github-actions-annotate-failures = "^0.2.0"
Expand Down
Loading