From 4745d4231ac26cba2cb2fa98f80f8c20241f416e Mon Sep 17 00:00:00 2001 From: zsystm Date: Sun, 19 Oct 2025 11:16:05 +0900 Subject: [PATCH 01/22] add memlogger testing script --- memlogger-experiment.sh | 365 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 365 insertions(+) create mode 100755 memlogger-experiment.sh diff --git a/memlogger-experiment.sh b/memlogger-experiment.sh new file mode 100755 index 000000000..48c531223 --- /dev/null +++ b/memlogger-experiment.sh @@ -0,0 +1,365 @@ +#!/bin/bash + +CHAINID="${CHAIN_ID:-9001}" +MONIKER="localtestnet" +# Remember to change to other types of keyring like 'file' in-case exposing to outside world, +# otherwise your balance will be wiped quickly +# The keyring test does not require private key to steal tokens from you +KEYRING="test" +KEYALGO="eth_secp256k1" + +LOGLEVEL="info" +# Set dedicated home directory for the evmd instance +CHAINDIR="$HOME/.evmd" + +BASEFEE=10000000 + +# Path variables +CONFIG_TOML=$CHAINDIR/config/config.toml +APP_TOML=$CHAINDIR/config/app.toml +GENESIS=$CHAINDIR/config/genesis.json +TMP_GENESIS=$CHAINDIR/config/tmp_genesis.json + +# validate dependencies are installed +command -v jq >/dev/null 2>&1 || { + echo >&2 "jq not installed. More info: https://stedolan.github.io/jq/download/" + exit 1 +} + +# used to exit on first error (any non-zero exit code) +set -e + +# ------------- Flags ------------- +install=true +overwrite="" +BUILD_FOR_DEBUG=false +ADDITIONAL_USERS=0 +MNEMONIC_FILE="" # output file (defaults later to $CHAINDIR/mnemonics.yaml) +MNEMONICS_INPUT="" # input yaml to prefill dev keys + +usage() { + cat < Overwriting the previous chain data." + overwrite="y"; shift + ;; + -n) + echo "Flag -n passed -> Not overwriting the previous chain data." + overwrite="n"; shift + ;; + --no-install) + echo "Flag --no-install passed -> Skipping installation of the evmd binary." + install=false; shift + ;; + --remote-debugging) + echo "Flag --remote-debugging passed -> Building with remote debugging options." + BUILD_FOR_DEBUG=true; shift + ;; + --additional-users) + if [[ -z "${2:-}" || "$2" =~ ^- ]]; then + echo "Error: --additional-users requires a number."; usage; exit 1 + fi + ADDITIONAL_USERS="$2"; shift 2 + ;; + --mnemonic-file) + if [[ -z "${2:-}" || "$2" =~ ^- ]]; then + echo "Error: --mnemonic-file requires a path."; usage; exit 1 + fi + MNEMONIC_FILE="$2"; shift 2 + ;; + --mnemonics-input) + if [[ -z "${2:-}" || "$2" =~ ^- ]]; then + echo "Error: --mnemonics-input requires a path."; usage; exit 1 + fi + MNEMONICS_INPUT="$2"; shift 2 + ;; + -h|--help) + usage; exit 0 + ;; + *) + echo "Unknown flag passed: $key -> Aborting"; usage; exit 1 + ;; + esac +done + +if [[ -n "$MNEMONICS_INPUT" && "$ADDITIONAL_USERS" -gt 0 ]]; then + echo "Error: --mnemonics-input and --additional-users cannot be used together." + echo "Use --mnemonics-input to provide all dev account mnemonics, or use --additional-users to generate extra accounts." + exit 1 +fi + +if [[ $install == true ]]; then + if [[ $BUILD_FOR_DEBUG == true ]]; then + # for remote debugging the optimization should be disabled and the debug info should not be stripped + make install COSMOS_BUILD_OPTIONS=nooptimization,nostrip + else + make install + fi +fi + +# User prompt if neither -y nor -n was passed as a flag +# and an existing local node configuration is found. +if [[ $overwrite = "" ]]; then + if [ -d "$CHAINDIR" ]; then + printf "\nAn existing folder at '%s' was found. You can choose to delete this folder and start a new local node with new keys from genesis. When declined, the existing local node is started. \n" "$CHAINDIR" + echo "Overwrite the existing configuration and start a new local node? [y/n]" + read -r overwrite + else + overwrite="y" + fi +fi + +# ---------- YAML reader ---------- +# reads a simple yaml with: +# mnemonics: +# - "phrase here" +# - another phrase +read_mnemonics_yaml() { + local file="$1" + awk ' + BEGIN { inlist=0 } + /^[[:space:]]*mnemonics:[[:space:]]*$/ { inlist=1; next } + inlist && /^[[:space:]]*-[[:space:]]*/ { + line=$0 + sub(/^[[:space:]]*-[[:space:]]*/, "", line) + gsub(/^"[[:space:]]*|[[:space:]]*"$/, "", line) + gsub(/^'\''[[:space:]]*|[[:space:]]*'\''$/, "", line) + print line + next + } + inlist && NF==0 { next } + ' "$file" +} + +# ---------- yaml writer ---------- +write_mnemonics_yaml() { + local file_path="$1"; shift + local -a mns=("$@") + mkdir -p "$(dirname "$file_path")" + { + echo "mnemonics:" + for m in "${mns[@]}"; do + printf ' - "%s"\n' "$m" + done + } > "$file_path" + echo "Wrote mnemonics to $file_path" +} + +# ---------- Add funded account ---------- +add_genesis_funds() { + local keyname="$1" + evmd genesis add-genesis-account "$keyname" 1000000000000000000000atest --keyring-backend "$KEYRING" --home "$CHAINDIR" +} + +# Setup local node if overwrite is set to Yes, otherwise skip setup +if [[ $overwrite == "y" || $overwrite == "Y" ]]; then + rm -rf "$CHAINDIR" + + evmd config set client chain-id "$CHAINID" --home "$CHAINDIR" + evmd config set client keyring-backend "$KEYRING" --home "$CHAINDIR" + + # ---------------- Validator key ---------------- + VAL_KEY="mykey" + VAL_MNEMONIC="gesture inject test cycle original hollow east ridge hen combine junk child bacon zero hope comfort vacuum milk pitch cage oppose unhappy lunar seat" + echo "$VAL_MNEMONIC" | evmd keys add "$VAL_KEY" --recover --keyring-backend "$KEYRING" --algo "$KEYALGO" --home "$CHAINDIR" + + # ---------------- dev mnemonics source ---------------- + # dev0 address 0xC6Fe5D33615a1C52c08018c47E8Bc53646A0E101 | cosmos1cml96vmptgw99syqrrz8az79xer2pcgp84pdun + # dev0's private key: 0x88cbead91aee890d27bf06e003ade3d4e952427e88f88d31d61d3ef5e5d54305 # gitleaks:allow + + # dev1 address 0x963EBDf2e1f8DB8707D05FC75bfeFFBa1B5BaC17 | cosmos1jcltmuhplrdcwp7stlr4hlhlhgd4htqh3a79sq + # dev1's private key: 0x741de4f8988ea941d3ff0287911ca4074e62b7d45c991a51186455366f10b544 # gitleaks:allow + + # dev2 address 0x40a0cb1C63e026A81B55EE1308586E21eec1eFa9 | cosmos1gzsvk8rruqn2sx64acfsskrwy8hvrmafqkaze8 + # dev2's private key: 0x3b7955d25189c99a7468192fcbc6429205c158834053ebe3f78f4512ab432db9 # gitleaks:allow + + # dev3 address 0x498B5AeC5D439b733dC2F58AB489783A23FB26dA | cosmos1fx944mzagwdhx0wz7k9tfztc8g3lkfk6rrgv6l + # dev3's private key: 0x8a36c69d940a92fcea94b36d0f2928c7a0ee19a90073eda769693298dfa9603b # gitleaks:allow + default_mnemonics=( + "copper push brief egg scan entry inform record adjust fossil boss egg comic alien upon aspect dry avoid interest fury window hint race symptom" # dev0 + "maximum display century economy unlock van census kite error heart snow filter midnight usage egg venture cash kick motor survey drastic edge muffin visual" # dev1 + "will wear settle write dance topic tape sea glory hotel oppose rebel client problem era video gossip glide during yard balance cancel file rose" # dev2 + "doll midnight silk carpet brush boring pluck office gown inquiry duck chief aim exit gain never tennis crime fragile ship cloud surface exotic patch" # dev3 + ) + + provided_mnemonics=() + if [[ -n "$MNEMONICS_INPUT" ]]; then + if [[ ! -f "$MNEMONICS_INPUT" ]]; then + echo "mnemonics input file not found: $MNEMONICS_INPUT"; exit 1 + fi + + tmpfile="$(mktemp -t mnemonics.XXXXXX)" + read_mnemonics_yaml "$MNEMONICS_INPUT" > "$tmpfile" + + while IFS= read -r line; do + [[ -z "$line" ]] && continue + provided_mnemonics+=( "$line" ) + done < "$tmpfile" + rm -f "$tmpfile" + + if [[ ${#provided_mnemonics[@]} -eq 0 ]]; then + echo "no mnemonics found in $MNEMONICS_INPUT (expected a list under 'mnemonics:')"; exit 1 + fi + fi + + # choose base list: prefer provided over defaults + if [[ ${#provided_mnemonics[@]} -gt 0 ]]; then + echo "using provided mnemonics" + dev_mnemonics=("${provided_mnemonics[@]}") + else + echo "using default mnemonics" + dev_mnemonics=("${default_mnemonics[@]}") + fi + + # init chain w/ validator mnemonic + echo "$VAL_MNEMONIC" | evmd init $MONIKER -o --chain-id "$CHAINID" --home "$CHAINDIR" --recover + + # ---------- Genesis customizations ---------- + jq '.app_state["staking"]["params"]["bond_denom"]="atest"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" + jq '.app_state["gov"]["deposit_params"]["min_deposit"][0]["denom"]="atest"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" + jq '.app_state["gov"]["params"]["min_deposit"][0]["denom"]="atest"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" + jq '.app_state["gov"]["params"]["expedited_min_deposit"][0]["denom"]="atest"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" + jq '.app_state["evm"]["params"]["evm_denom"]="atest"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" + jq '.app_state["mint"]["params"]["mint_denom"]="atest"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" + + jq '.app_state["bank"]["denom_metadata"]=[{"description":"The native staking token for evmd.","denom_units":[{"denom":"atest","exponent":0,"aliases":["attotest"]},{"denom":"test","exponent":18,"aliases":[]}],"base":"atest","display":"test","name":"Test Token","symbol":"TEST","uri":"","uri_hash":""}]' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" + + jq '.app_state["evm"]["params"]["active_static_precompiles"]=["0x0000000000000000000000000000000000000100","0x0000000000000000000000000000000000000400","0x0000000000000000000000000000000000000800","0x0000000000000000000000000000000000000801","0x0000000000000000000000000000000000000802","0x0000000000000000000000000000000000000803","0x0000000000000000000000000000000000000804","0x0000000000000000000000000000000000000805", "0x0000000000000000000000000000000000000806", "0x0000000000000000000000000000000000000807"]' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" + + jq '.app_state["evm"]["params"]["evm_denom"]="atest"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" + + jq '.app_state.erc20.native_precompiles=["0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"]' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" + jq '.app_state.erc20.token_pairs=[{contract_owner:1,erc20_address:"0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",denom:"atest",enabled:true}]' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" + + jq '.consensus.params.block.max_gas="10000000"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" + + # Change proposal periods + sed -i.bak 's/"max_deposit_period": "172800s"/"max_deposit_period": "30s"/g' "$GENESIS" + sed -i.bak 's/"voting_period": "172800s"/"voting_period": "30s"/g' "$GENESIS" + sed -i.bak 's/"expedited_voting_period": "86400s"/"expedited_voting_period": "15s"/g' "$GENESIS" + + # fund validator (devs already funded in the loop) + evmd genesis add-genesis-account "$VAL_KEY" 100000000000000000000000000atest --keyring-backend "$KEYRING" --home "$CHAINDIR" + + # ---------- Config customizations ---------- + sed -i.bak 's/timeout_propose = "3s"/timeout_propose = "2s"/g' "$CONFIG_TOML" + sed -i.bak 's/timeout_propose_delta = "500ms"/timeout_propose_delta = "200ms"/g' "$CONFIG_TOML" + sed -i.bak 's/timeout_prevote = "1s"/timeout_prevote = "500ms"/g' "$CONFIG_TOML" + sed -i.bak 's/timeout_prevote_delta = "500ms"/timeout_prevote_delta = "200ms"/g' "$CONFIG_TOML" + sed -i.bak 's/timeout_precommit = "1s"/timeout_precommit = "500ms"/g' "$CONFIG_TOML" + sed -i.bak 's/timeout_precommit_delta = "500ms"/timeout_precommit_delta = "200ms"/g' "$CONFIG_TOML" + sed -i.bak 's/timeout_commit = "5s"/timeout_commit = "1s"/g' "$CONFIG_TOML" + sed -i.bak 's/timeout_broadcast_tx_commit = "10s"/timeout_broadcast_tx_commit = "5s"/g' "$CONFIG_TOML" + + # enable prometheus metrics and all APIs for dev node + sed -i.bak 's/prometheus = false/prometheus = true/' "$CONFIG_TOML" + sed -i.bak 's/prometheus-retention-time = "0"/prometheus-retention-time = "1000000000000"/g' "$APP_TOML" + sed -i.bak 's/enabled = false/enabled = true/g' "$APP_TOML" + sed -i.bak 's/enable = false/enable = true/g' "$APP_TOML" + + # loggers + sed -i.bak 's/log_level = "info"/log_level = "debug"/g' "$CONFIG_TOML" + sed -i.bak 's/log_format = "plain"/log_format = "json"/g' "$CONFIG_TOML" + + + # --------- maybe generate additional users --------- + # start with provided/default list + final_mnemonics=("${dev_mnemonics[@]}") + + # default output path if not set + if [[ -z "$MNEMONIC_FILE" ]]; then + MNEMONIC_FILE="$CHAINDIR/mnemonics.yaml" + fi + + # Process all dev mnemonics (provided or default) + for ((i=0; i<${#dev_mnemonics[@]}; i++)); do + + keyname="dev${i}" + mnemonic="${dev_mnemonics[i]}" + + echo "adding key for $keyname" + + # Add key to keyring using the mnemonic + echo "$mnemonic" | evmd keys add "$keyname" --recover --keyring-backend "$KEYRING" --algo "$KEYALGO" --home "$CHAINDIR" + + # Fund the account in genesis + add_genesis_funds "$keyname" + done + + if [[ "$ADDITIONAL_USERS" -gt 0 ]]; then + start_index=${#dev_mnemonics[@]} # continue after last provided/default entry + for ((i=0; i&1)" + # try to grab a line that looks like a seed phrase (>=12 words), else last line + user_mnemonic="$(echo "$mnemonic_out" | grep -E '([[:alpha:]]+[[:space:]]+){11,}[[:alpha:]]+$' | tail -1)" + if [[ -z "$user_mnemonic" ]]; then + user_mnemonic="$(echo "$mnemonic_out" | tail -n 1)" + fi + user_mnemonic="$(echo "$user_mnemonic" | tr -d '\r')" + + if [[ -z "$user_mnemonic" ]]; then + echo "failed to capture mnemonic for $keyname"; exit 1 + fi + + final_mnemonics+=("$user_mnemonic") + add_genesis_funds "$keyname" + echo "created $keyname" + done + fi + + # --------- Finalize genesis --------- + evmd genesis gentx "$VAL_KEY" 1000000000000000000000atest --gas-prices ${BASEFEE}atest --keyring-backend "$KEYRING" --chain-id "$CHAINID" --home "$CHAINDIR" + evmd genesis collect-gentxs --home "$CHAINDIR" + evmd genesis validate-genesis --home "$CHAINDIR" + + # --------- Write YAML with mnemonics if the user specified more --------- + if [[ "$ADDITIONAL_USERS" -gt 0 ]]; then + write_mnemonics_yaml "$MNEMONIC_FILE" "${final_mnemonics[@]}" + fi + + if [[ $1 == "pending" ]]; then + echo "pending mode is on, please wait for the first block committed." + fi +fi + + +# Start the node +# Echo the full command with all parameters for transparency (no shell-escaping) +cmd=(evmd start) +if [[ -n "$TRACE" ]]; then + cmd+=("$TRACE") +fi +cmd+=( + --pruning nothing + --log_level "$LOGLEVEL" + --minimum-gas-prices=0atest + --evm.min-tip=0 + --home "$CHAINDIR" + --json-rpc.api "eth,txpool,personal,net,debug,web3" + --chain-id "$CHAINID" +) +printf 'Executing: ' +for arg in "${cmd[@]}"; do + printf '%s ' "$arg" +done +printf '\n' From 8f44a68923cfba7813c6139a5c6c5a19a87b667f Mon Sep 17 00:00:00 2001 From: zsystm Date: Sun, 19 Oct 2025 14:30:08 +0900 Subject: [PATCH 02/22] update dep --- go.mod | 1 + 1 file changed, 1 insertion(+) diff --git a/go.mod b/go.mod index ec6781f79..a0be5eab0 100644 --- a/go.mod +++ b/go.mod @@ -277,6 +277,7 @@ replace ( github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.9.1 // replace broken goleveldb github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 + github.com/cometbft/cometbft => github.com/zsystm/cometbft v0.38.x-memlogger ) retract v0.4.0 From 61649a15bd313dd6f0680fbc59e8720acd710e7d Mon Sep 17 00:00:00 2001 From: zsystm Date: Sun, 19 Oct 2025 14:58:21 +0900 Subject: [PATCH 03/22] add localnet script --- evmd_localnet.sh | 199 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100755 evmd_localnet.sh diff --git a/evmd_localnet.sh b/evmd_localnet.sh new file mode 100755 index 000000000..8780dd04e --- /dev/null +++ b/evmd_localnet.sh @@ -0,0 +1,199 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Simple multi-node localnet launcher for evmd +# - Initializes N validator nodes under BASE_DIR using `evmd testnet init-files --single-host` +# - Optionally computes persistent_peers via `evmd comet show-node-id` if available +# - Starts each node with its own home and port set by init-files +# +# Usage: +# scripts/evmd-localnet.sh start # init (if needed) and start N nodes +# scripts/evmd-localnet.sh stop # stop nodes started by this script (via PID file) +# scripts/evmd-localnet.sh clean # remove BASE_DIR + +BINARY_DEFAULT="evmd" # or override via BINARY env +BASE_DIR_DEFAULT="./.testnets" # or override via BASE_DIR env +NODE_PREFIX_DEFAULT="node" +N_DEFAULT=4 +# Align with local_node.sh default CHAINID (9001) +CHAIN_ID_DEFAULT="9001" +MIN_GAS_PRICES_DEFAULT="0atest" + +# Derive settings from env or defaults +BINARY=${BINARY:-$BINARY_DEFAULT} +BASE_DIR=${BASE_DIR:-$BASE_DIR_DEFAULT} +NODE_PREFIX=${NODE_PREFIX:-$NODE_PREFIX_DEFAULT} +N=${N:-$N_DEFAULT} +CHAIN_ID=${CHAIN_ID:-$CHAIN_ID_DEFAULT} +MIN_GAS_PRICES=${MIN_GAS_PRICES:-$MIN_GAS_PRICES_DEFAULT} + +# Internal +PID_FILE="${BASE_DIR}/evmd_localnet.pids" + +log() { echo "[evmd-localnet] $*"; } +err() { echo "[evmd-localnet:ERROR] $*" >&2; } + +ensure_binary() { + if command -v "$BINARY" >/dev/null 2>&1; then + return 0 + fi + # Fallback to local build path + if [ -x "./build/evmd" ]; then + BINARY="./build/evmd" + return 0 + fi + err "Cannot find evmd binary. Put it on PATH or build via 'make build'." + exit 1 +} + +init_if_needed() { + local first_home_dir="${BASE_DIR}/${NODE_PREFIX}0/evmd" + local genesis_file="${first_home_dir}/config/genesis.json" + if [ -f "$genesis_file" ]; then + # If an existing genesis is present, verify its chain_id matches desired CHAIN_ID. + local existing_chain_id + if command -v jq >/dev/null 2>&1; then + existing_chain_id=$(jq -r '.chain_id' "$genesis_file" 2>/dev/null || true) + fi + if [ -z "${existing_chain_id:-}" ]; then + # Fallback parser if jq is unavailable + existing_chain_id=$(sed -n 's/.*"chain_id"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' "$genesis_file" | head -n1) + fi + + if [ -n "$existing_chain_id" ] && [ "$existing_chain_id" != "$CHAIN_ID" ]; then + log "Existing testnet has chain-id '$existing_chain_id' but requested '$CHAIN_ID'. Re-initializing…" + rm -rf "$BASE_DIR" + else + log "Existing testnet detected at ${BASE_DIR} (chain-id: ${existing_chain_id:-unknown}); skipping init-files." + return 0 + fi + fi + + log "Initializing ${N}-node testnet at ${BASE_DIR} (single host ports)…" + mkdir -p "$BASE_DIR" + + # --single-host ensures distinct ports per node on one machine + "$BINARY" testnet init-files \ + --validator-count "${N}" \ + --output-dir "${BASE_DIR}" \ + --single-host \ + --keyring-backend test \ + --chain-id "${CHAIN_ID}" + + log "Init complete. Genesis and configs written under ${BASE_DIR}/${NODE_PREFIX}{0..$((N-1))}/evmd" +} + +build_peers_if_possible() { + # Try to gather node IDs using `evmd comet show-node-id` if the subcommand exists. + if ! "$BINARY" comet --help >/dev/null 2>&1; then + log "'evmd comet' subcommand not found. Skipping persistent_peers injection (nodes should still connect with generated configs)." + return 0 + fi + + local peers="" + for ((i=0; i< N; i++)); do + local home_dir="${BASE_DIR}/${NODE_PREFIX}${i}/evmd" + local id + if ! id=$("$BINARY" comet show-node-id --home "$home_dir" 2>/dev/null); then + err "Failed to read node ID for ${NODE_PREFIX}${i}; skipping persistent_peers." + return 0 + fi + # Ports per init-files when --single-host is used: + # - P2P starts at 16656 and increments by +1 per node + local p2p_port=$((16656 + i)) + local entry="${id}@127.0.0.1:${p2p_port}" + if [ -z "$peers" ]; then peers="$entry"; else peers+="",$entry; fi + done + + log "persistent_peers=${peers}" + # Inject into each node's config.toml + for ((i=0; i< N; i++)); do + local cfg="${BASE_DIR}/${NODE_PREFIX}${i}/evmd/config/config.toml" + if [ -f "$cfg" ]; then + # Replace existing line or append if missing + if grep -q '^persistent_peers\s*=\s*"' "$cfg"; then + sed -i.bak -E "s|^persistent_peers\s*=\s*\".*\"|persistent_peers = \"${peers}\"|" "$cfg" + else + echo "persistent_peers = \"${peers}\"" >> "$cfg" + fi + fi + done +} + +start_nodes() { + mkdir -p "$(dirname "$PID_FILE")" + : > "$PID_FILE" + + for ((i=0; i< N; i++)); do + local home_dir="${BASE_DIR}/${NODE_PREFIX}${i}/evmd" + local log_file="${home_dir}/evmd.log" + + # Compute display ports that init-files configure for single-host: + local rpc_port=$((26657 + i)) + local p2p_port=$((16656 + i)) + local api_port=$((1317 + i)) + local http_port=$((8545 + i*10)) + local ws_port=$((8546 + i*10)) + + log "Starting ${NODE_PREFIX}${i} (rpc:${rpc_port}, p2p:${p2p_port}, api:${api_port}, http:${http_port}, ws:${ws_port})" + + # Build start command (aligned with local_node.sh defaults) and echo it for reproducibility + cmd=("$BINARY" start \ + --home "$home_dir" \ + --minimum-gas-prices "${MIN_GAS_PRICES}" \ + --evm.min-tip 0 \ + --json-rpc.api "eth,txpool,personal,net,debug,web3" \ + --chain-id "${CHAIN_ID}") + + printf '[evmd-localnet] Exec: ' + for arg in "${cmd[@]}"; do printf '%s ' "$arg"; done; printf '\n' + + # Start in background, capture PID + ("${cmd[@]}" >"$log_file" 2>&1 & echo $! >> "$PID_FILE") + sleep 0.5 + done + + log "All nodes started. PIDs recorded in ${PID_FILE}" +} + +stop_nodes() { + if [ ! -f "$PID_FILE" ]; then + err "PID file not found: $PID_FILE" + exit 1 + fi + tac "$PID_FILE" | while read -r pid; do + if kill -0 "$pid" >/dev/null 2>&1; then + log "Stopping PID $pid" + kill "$pid" || true + fi + done + rm -f "$PID_FILE" + log "All nodes stopped." +} + +clean() { + if [ -d "$BASE_DIR" ]; then + log "Removing ${BASE_DIR}" + rm -rf "$BASE_DIR" + fi +} + +cmd=${1:-start} +case "$cmd" in + start) + ensure_binary + init_if_needed + build_peers_if_possible + start_nodes + ;; + stop) + stop_nodes + ;; + clean) + clean + ;; + *) + echo "Usage: $0 {start|stop|clean}" >&2 + exit 1 + ;; +esac From fd03ba230f744e0453cba798bd90abfbfd6742ee Mon Sep 17 00:00:00 2001 From: zsystm Date: Mon, 20 Oct 2025 04:21:27 +0900 Subject: [PATCH 04/22] apply sdk memlogger --- evmd/go.mod | 2 + evmd/go.sum | 8 ++-- evmd_localnet.sh | 102 +++++++++++++++++++++++++--------------- go.mod | 4 +- go.sum | 12 ++--- memlogger-experiment.sh | 1 + 6 files changed, 80 insertions(+), 49 deletions(-) diff --git a/evmd/go.mod b/evmd/go.mod index 9a3dfb233..55f51017a 100644 --- a/evmd/go.mod +++ b/evmd/go.mod @@ -272,8 +272,10 @@ require ( ) replace ( + cosmossdk.io/log => github.com/zsystm/cosmos-sdk/log v0.0.0-20251019190943-b98a8e980b0c // use cosmos fork of keyring github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0 + github.com/cosmos/cosmos-sdk => github.com/zsystm/cosmos-sdk v0.46.0-beta2.0.20251019190943-b98a8e980b0c github.com/cosmos/evm => ../ // use Cosmos geth fork // branch: release/1.16 diff --git a/evmd/go.sum b/evmd/go.sum index 61062dbe1..b4626e9b6 100644 --- a/evmd/go.sum +++ b/evmd/go.sum @@ -626,8 +626,6 @@ cosmossdk.io/depinject v1.2.1 h1:eD6FxkIjlVaNZT+dXTQuwQTKZrFZ4UrfCq1RKgzyhMw= cosmossdk.io/depinject v1.2.1/go.mod h1:lqQEycz0H2JXqvOgVwTsjEdMI0plswI7p6KX+MVqFOM= cosmossdk.io/errors v1.0.2 h1:wcYiJz08HThbWxd/L4jObeLaLySopyyuUFB5w4AGpCo= cosmossdk.io/errors v1.0.2/go.mod h1:0rjgiHkftRYPj//3DrD6y8hcm40HcPv/dR4R/4efr0k= -cosmossdk.io/log v1.6.1 h1:YXNwAgbDwMEKwDlCdH8vPcoggma48MgZrTQXCfmMBeI= -cosmossdk.io/log v1.6.1/go.mod h1:gMwsWyyDBjpdG9u2avCFdysXqxq28WJapJvu+vF1y+E= cosmossdk.io/math v1.5.3 h1:WH6tu6Z3AUCeHbeOSHg2mt9rnoiUWVWaQ2t6Gkll96U= cosmossdk.io/math v1.5.3/go.mod h1:uqcZv7vexnhMFJF+6zh9EWdm/+Ylyln34IvPnBauPCQ= cosmossdk.io/schema v1.1.0 h1:mmpuz3dzouCoyjjcMcA/xHBEmMChN+EHh8EHxHRHhzE= @@ -855,8 +853,6 @@ github.com/cosmos/cosmos-db v1.1.3 h1:7QNT77+vkefostcKkhrzDK9uoIEryzFrU9eoMeaQOP github.com/cosmos/cosmos-db v1.1.3/go.mod h1:kN+wGsnwUJZYn8Sy5Q2O0vCYA99MJllkKASbs6Unb9U= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= -github.com/cosmos/cosmos-sdk v0.53.4 h1:kPF6vY68+/xi1/VebSZGpoxQqA52qkhUzqkrgeBn3Mg= -github.com/cosmos/cosmos-sdk v0.53.4/go.mod h1:7U3+WHZtI44dEOnU46+lDzBb2tFh1QlMvi8Z5JugopI= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= github.com/cosmos/go-ethereum v1.16.2-cosmos-1 h1:QIaIS6HIdPSBdTvpFhxswhMLUJgcr4irbd2o9ZKldAI= @@ -1738,6 +1734,10 @@ github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw= github.com/zondax/ledger-go v0.14.3/go.mod h1:IKKaoxupuB43g4NxeQmbLXv7T9AlQyie1UpHb342ycI= +github.com/zsystm/cosmos-sdk v0.46.0-beta2.0.20251019190943-b98a8e980b0c h1:aK9BU0ybOOp5IXrz82DCAJ0hBMa2oyDdtJGGZOvxDxg= +github.com/zsystm/cosmos-sdk v0.46.0-beta2.0.20251019190943-b98a8e980b0c/go.mod h1:6k6Po9k9tVsUCRsnjpL6kGzTqjPnwgabQg8htKRMtVc= +github.com/zsystm/cosmos-sdk/log v0.0.0-20251019190943-b98a8e980b0c h1:3R2v6bpbYFNW5IItdckOogI/bXywxkIk0IQtK/9vihE= +github.com/zsystm/cosmos-sdk/log v0.0.0-20251019190943-b98a8e980b0c/go.mod h1:DNJwlhYlZOlSePMdymnpTcI8XDar9qn+m8o1fJC7olc= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.4.0-alpha.1 h1:3yrqQzbRRPFPdOMWS/QQIVxVnzSkAZQYeWlZFv1kbj4= go.etcd.io/bbolt v1.4.0-alpha.1/go.mod h1:S/Z/Nm3iuOnyO1W4XuFfPci51Gj6F1Hv0z8hisyYYOw= diff --git a/evmd_localnet.sh b/evmd_localnet.sh index 8780dd04e..f4b107c97 100755 --- a/evmd_localnet.sh +++ b/evmd_localnet.sh @@ -2,7 +2,8 @@ set -euo pipefail # Simple multi-node localnet launcher for evmd -# - Initializes N validator nodes under BASE_DIR using `evmd testnet init-files --single-host` +# - Initializes N validator nodes under BASE_DIR using `evmd testnet init-files --validator-count N --keyring-backend test` +# - Applies surge faucet to node0 genesis, then replicates the modified genesis to all nodes # - Optionally computes persistent_peers via `evmd comet show-node-id` if available # - Starts each node with its own home and port set by init-files # @@ -15,17 +16,18 @@ BINARY_DEFAULT="evmd" # or override via BINARY env BASE_DIR_DEFAULT="./.testnets" # or override via BASE_DIR env NODE_PREFIX_DEFAULT="node" N_DEFAULT=4 -# Align with local_node.sh default CHAINID (9001) -CHAIN_ID_DEFAULT="9001" +# Start defaults (min gas aligned with local_node.sh) MIN_GAS_PRICES_DEFAULT="0atest" +SURGE_CMD_DEFAULT="surge faucet" # or override via SURGE_CMD env; extra args via SURGE_ARGS # Derive settings from env or defaults BINARY=${BINARY:-$BINARY_DEFAULT} BASE_DIR=${BASE_DIR:-$BASE_DIR_DEFAULT} NODE_PREFIX=${NODE_PREFIX:-$NODE_PREFIX_DEFAULT} N=${N:-$N_DEFAULT} -CHAIN_ID=${CHAIN_ID:-$CHAIN_ID_DEFAULT} MIN_GAS_PRICES=${MIN_GAS_PRICES:-$MIN_GAS_PRICES_DEFAULT} +SURGE_CMD=${SURGE_CMD:-$SURGE_CMD_DEFAULT} +SURGE_ARGS=${SURGE_ARGS:-} # Internal PID_FILE="${BASE_DIR}/evmd_localnet.pids" @@ -46,41 +48,64 @@ ensure_binary() { exit 1 } -init_if_needed() { - local first_home_dir="${BASE_DIR}/${NODE_PREFIX}0/evmd" - local genesis_file="${first_home_dir}/config/genesis.json" - if [ -f "$genesis_file" ]; then - # If an existing genesis is present, verify its chain_id matches desired CHAIN_ID. - local existing_chain_id - if command -v jq >/dev/null 2>&1; then - existing_chain_id=$(jq -r '.chain_id' "$genesis_file" 2>/dev/null || true) - fi - if [ -z "${existing_chain_id:-}" ]; then - # Fallback parser if jq is unavailable - existing_chain_id=$(sed -n 's/.*"chain_id"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' "$genesis_file" | head -n1) - fi - - if [ -n "$existing_chain_id" ] && [ "$existing_chain_id" != "$CHAIN_ID" ]; then - log "Existing testnet has chain-id '$existing_chain_id' but requested '$CHAIN_ID'. Re-initializing…" - rm -rf "$BASE_DIR" - else - log "Existing testnet detected at ${BASE_DIR} (chain-id: ${existing_chain_id:-unknown}); skipping init-files." - return 0 - fi - fi - - log "Initializing ${N}-node testnet at ${BASE_DIR} (single host ports)…" +init_fresh() { + # Always initialize a fresh testnet as requested + rm -rf "$BASE_DIR" + log "Initializing ${N}-node testnet at ${BASE_DIR}…" mkdir -p "$BASE_DIR" - # --single-host ensures distinct ports per node on one machine - "$BINARY" testnet init-files \ + # Per request: use only validator-count and keyring-backend flags (+ output-dir to control location) + local cmd=("$BINARY" testnet init-files \ --validator-count "${N}" \ - --output-dir "${BASE_DIR}" \ - --single-host \ --keyring-backend test \ - --chain-id "${CHAIN_ID}" + --output-dir "${BASE_DIR}") + + printf '[evmd-localnet] Exec: ' + for a in "${cmd[@]}"; do printf '%s ' "$a"; done; printf '\n' + "${cmd[@]}" + + log "Init complete. Genesis and configs under ${BASE_DIR}/${NODE_PREFIX}{0..$((N-1))}/evmd" +} - log "Init complete. Genesis and configs written under ${BASE_DIR}/${NODE_PREFIX}{0..$((N-1))}/evmd" +apply_surge_and_replicate() { + # Apply surge faucet on node0 genesis, then copy to other nodes + local g0="${BASE_DIR}/${NODE_PREFIX}0/evmd/config/genesis.json" + if [ ! -f "$g0" ]; then + err "node0 genesis not found at $g0" + exit 1 + fi + + # Run surge faucet if available/desired + if [ -n "$SURGE_CMD" ]; then + local surge_bin + surge_bin=$(echo "$SURGE_CMD" | awk '{print $1}') + if ! command -v "$surge_bin" >/dev/null 2>&1; then + err "'$surge_bin' not found on PATH. Set SURGE_CMD='' to skip or install surge." + exit 1 + fi + # Echo the exact command + printf '[evmd-localnet] Exec: %s %s %s\n' "$SURGE_CMD" "${SURGE_ARGS}" "$g0" + # Execute with optional extra args + eval "$SURGE_CMD ${SURGE_ARGS} $g0" + else + log "SURGE_CMD empty; skipping surge faucet step." + fi + + # Replicate node0 genesis to all other nodes + for ((i=1; i< N; i++)); do + local gi="${BASE_DIR}/${NODE_PREFIX}${i}/evmd/config/genesis.json" + if [ -f "$gi" ]; then + cp "$g0" "$gi" + fi + done + + # Validate genesis for all nodes (best-effort) + for ((i=0; i< N; i++)); do + local home_dir="${BASE_DIR}/${NODE_PREFIX}${i}/evmd" + if [ -d "$home_dir" ]; then + "$BINARY" genesis validate-genesis --home "$home_dir" >/dev/null 2>&1 || true + fi + done } build_peers_if_possible() { @@ -137,13 +162,13 @@ start_nodes() { log "Starting ${NODE_PREFIX}${i} (rpc:${rpc_port}, p2p:${p2p_port}, api:${api_port}, http:${http_port}, ws:${ws_port})" - # Build start command (aligned with local_node.sh defaults) and echo it for reproducibility + # Build start command (aligned with local_node.sh gas defaults) and echo it for reproducibility cmd=("$BINARY" start \ --home "$home_dir" \ --minimum-gas-prices "${MIN_GAS_PRICES}" \ --evm.min-tip 0 \ - --json-rpc.api "eth,txpool,personal,net,debug,web3" \ - --chain-id "${CHAIN_ID}") + --json-rpc.api "eth,txpool,personal,net,debug,web3" + --memlog) printf '[evmd-localnet] Exec: ' for arg in "${cmd[@]}"; do printf '%s ' "$arg"; done; printf '\n' @@ -182,7 +207,8 @@ cmd=${1:-start} case "$cmd" in start) ensure_binary - init_if_needed + init_fresh + apply_surge_and_replicate build_peers_if_possible start_nodes ;; diff --git a/go.mod b/go.mod index a0be5eab0..7622470d3 100644 --- a/go.mod +++ b/go.mod @@ -268,8 +268,11 @@ require ( ) replace ( + cosmossdk.io/log => github.com/zsystm/cosmos-sdk/log v0.0.0-20251019190943-b98a8e980b0c // use cosmos fork of keyring github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0 + github.com/cometbft/cometbft => github.com/zsystm/cometbft v0.38.20-0.20251019013026-68caee7dcb2f + github.com/cosmos/cosmos-sdk => github.com/zsystm/cosmos-sdk v0.46.0-beta2.0.20251019190943-b98a8e980b0c // use Cosmos geth fork // branch: release/1.16 github.com/ethereum/go-ethereum => github.com/cosmos/go-ethereum v1.16.2-cosmos-1 @@ -277,7 +280,6 @@ replace ( github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.9.1 // replace broken goleveldb github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 - github.com/cometbft/cometbft => github.com/zsystm/cometbft v0.38.x-memlogger ) retract v0.4.0 diff --git a/go.sum b/go.sum index 2ecc636b0..0a3c88cd2 100644 --- a/go.sum +++ b/go.sum @@ -626,8 +626,6 @@ cosmossdk.io/depinject v1.2.1 h1:eD6FxkIjlVaNZT+dXTQuwQTKZrFZ4UrfCq1RKgzyhMw= cosmossdk.io/depinject v1.2.1/go.mod h1:lqQEycz0H2JXqvOgVwTsjEdMI0plswI7p6KX+MVqFOM= cosmossdk.io/errors v1.0.2 h1:wcYiJz08HThbWxd/L4jObeLaLySopyyuUFB5w4AGpCo= cosmossdk.io/errors v1.0.2/go.mod h1:0rjgiHkftRYPj//3DrD6y8hcm40HcPv/dR4R/4efr0k= -cosmossdk.io/log v1.6.1 h1:YXNwAgbDwMEKwDlCdH8vPcoggma48MgZrTQXCfmMBeI= -cosmossdk.io/log v1.6.1/go.mod h1:gMwsWyyDBjpdG9u2avCFdysXqxq28WJapJvu+vF1y+E= cosmossdk.io/math v1.5.3 h1:WH6tu6Z3AUCeHbeOSHg2mt9rnoiUWVWaQ2t6Gkll96U= cosmossdk.io/math v1.5.3/go.mod h1:uqcZv7vexnhMFJF+6zh9EWdm/+Ylyln34IvPnBauPCQ= cosmossdk.io/schema v1.1.0 h1:mmpuz3dzouCoyjjcMcA/xHBEmMChN+EHh8EHxHRHhzE= @@ -834,8 +832,6 @@ github.com/cockroachdb/redact v1.1.6/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZ github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/cometbft/cometbft v0.38.18 h1:1ZHYMdu0S75YxFM13LlPXnOwiIpUW5z9TKMQtTIALpw= -github.com/cometbft/cometbft v0.38.18/go.mod h1:PlOQgf3jQorep+g6oVnJgtP65TJvBJoLiXjGaMdNxBE= github.com/cometbft/cometbft-db v0.14.1 h1:SxoamPghqICBAIcGpleHbmoPqy+crij/++eZz3DlerQ= github.com/cometbft/cometbft-db v0.14.1/go.mod h1:KHP1YghilyGV/xjD5DP3+2hyigWx0WTp9X+0Gnx0RxQ= github.com/consensys/gnark-crypto v0.18.0 h1:vIye/FqI50VeAr0B3dx+YjeIvmc3LWz4yEfbWBpTUf0= @@ -852,8 +848,6 @@ github.com/cosmos/cosmos-db v1.1.3 h1:7QNT77+vkefostcKkhrzDK9uoIEryzFrU9eoMeaQOP github.com/cosmos/cosmos-db v1.1.3/go.mod h1:kN+wGsnwUJZYn8Sy5Q2O0vCYA99MJllkKASbs6Unb9U= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= -github.com/cosmos/cosmos-sdk v0.53.4 h1:kPF6vY68+/xi1/VebSZGpoxQqA52qkhUzqkrgeBn3Mg= -github.com/cosmos/cosmos-sdk v0.53.4/go.mod h1:7U3+WHZtI44dEOnU46+lDzBb2tFh1QlMvi8Z5JugopI= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= github.com/cosmos/go-ethereum v1.16.2-cosmos-1 h1:QIaIS6HIdPSBdTvpFhxswhMLUJgcr4irbd2o9ZKldAI= @@ -1723,6 +1717,12 @@ github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw= github.com/zondax/ledger-go v0.14.3/go.mod h1:IKKaoxupuB43g4NxeQmbLXv7T9AlQyie1UpHb342ycI= +github.com/zsystm/cometbft v0.38.20-0.20251019013026-68caee7dcb2f h1:YX8QsgD87lIxbPPjVPkAn/VT1ErC17mCeDz2/Fmw7WE= +github.com/zsystm/cometbft v0.38.20-0.20251019013026-68caee7dcb2f/go.mod h1:UCu8dlHqvkAsmAFmWDRWNZJPlu6ya2fTWZlDrWsivwo= +github.com/zsystm/cosmos-sdk v0.46.0-beta2.0.20251019190943-b98a8e980b0c h1:aK9BU0ybOOp5IXrz82DCAJ0hBMa2oyDdtJGGZOvxDxg= +github.com/zsystm/cosmos-sdk v0.46.0-beta2.0.20251019190943-b98a8e980b0c/go.mod h1:6k6Po9k9tVsUCRsnjpL6kGzTqjPnwgabQg8htKRMtVc= +github.com/zsystm/cosmos-sdk/log v0.0.0-20251019190943-b98a8e980b0c h1:3R2v6bpbYFNW5IItdckOogI/bXywxkIk0IQtK/9vihE= +github.com/zsystm/cosmos-sdk/log v0.0.0-20251019190943-b98a8e980b0c/go.mod h1:DNJwlhYlZOlSePMdymnpTcI8XDar9qn+m8o1fJC7olc= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.4.0-alpha.1 h1:3yrqQzbRRPFPdOMWS/QQIVxVnzSkAZQYeWlZFv1kbj4= go.etcd.io/bbolt v1.4.0-alpha.1/go.mod h1:S/Z/Nm3iuOnyO1W4XuFfPci51Gj6F1Hv0z8hisyYYOw= diff --git a/memlogger-experiment.sh b/memlogger-experiment.sh index 48c531223..6cb7cb113 100755 --- a/memlogger-experiment.sh +++ b/memlogger-experiment.sh @@ -357,6 +357,7 @@ cmd+=( --home "$CHAINDIR" --json-rpc.api "eth,txpool,personal,net,debug,web3" --chain-id "$CHAINID" + --memlog ) printf 'Executing: ' for arg in "${cmd[@]}"; do From 6e0f95908fba35396324b8d673c72314a39c6804 Mon Sep 17 00:00:00 2001 From: zsystm Date: Mon, 20 Oct 2025 04:25:17 +0900 Subject: [PATCH 05/22] fix flags --- evmd_localnet.sh | 2 +- memlogger-experiment.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/evmd_localnet.sh b/evmd_localnet.sh index f4b107c97..05daa6efb 100755 --- a/evmd_localnet.sh +++ b/evmd_localnet.sh @@ -168,7 +168,7 @@ start_nodes() { --minimum-gas-prices "${MIN_GAS_PRICES}" \ --evm.min-tip 0 \ --json-rpc.api "eth,txpool,personal,net,debug,web3" - --memlog) + --memlog=true) printf '[evmd-localnet] Exec: ' for arg in "${cmd[@]}"; do printf '%s ' "$arg"; done; printf '\n' diff --git a/memlogger-experiment.sh b/memlogger-experiment.sh index 6cb7cb113..ea6d2e49f 100755 --- a/memlogger-experiment.sh +++ b/memlogger-experiment.sh @@ -357,7 +357,7 @@ cmd+=( --home "$CHAINDIR" --json-rpc.api "eth,txpool,personal,net,debug,web3" --chain-id "$CHAINID" - --memlog + --memlog=true ) printf 'Executing: ' for arg in "${cmd[@]}"; do From f501309b3dba046f29314b8e7192499f95e8ef6a Mon Sep 17 00:00:00 2001 From: zsystm Date: Mon, 20 Oct 2025 05:15:21 +0900 Subject: [PATCH 06/22] fix localnet script to enable single host testing --- evmd_localnet.sh | 103 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 101 insertions(+), 2 deletions(-) diff --git a/evmd_localnet.sh b/evmd_localnet.sh index 05daa6efb..b5a8f3232 100755 --- a/evmd_localnet.sh +++ b/evmd_localnet.sh @@ -19,6 +19,8 @@ N_DEFAULT=4 # Start defaults (min gas aligned with local_node.sh) MIN_GAS_PRICES_DEFAULT="0atest" SURGE_CMD_DEFAULT="surge faucet" # or override via SURGE_CMD env; extra args via SURGE_ARGS +CHAIN_ID_DEFAULT="local-4221" # or override via CHAIN_ID env +SINGLE_HOST_DEFAULT="true" # allocate unique ports per node on one host # Derive settings from env or defaults BINARY=${BINARY:-$BINARY_DEFAULT} @@ -28,6 +30,8 @@ N=${N:-$N_DEFAULT} MIN_GAS_PRICES=${MIN_GAS_PRICES:-$MIN_GAS_PRICES_DEFAULT} SURGE_CMD=${SURGE_CMD:-$SURGE_CMD_DEFAULT} SURGE_ARGS=${SURGE_ARGS:-} +CHAIN_ID=${CHAIN_ID:-$CHAIN_ID_DEFAULT} +SINGLE_HOST=${SINGLE_HOST:-$SINGLE_HOST_DEFAULT} # Internal PID_FILE="${BASE_DIR}/evmd_localnet.pids" @@ -60,11 +64,101 @@ init_fresh() { --keyring-backend test \ --output-dir "${BASE_DIR}") + # Add chain-id if supported by the subcommand + if "$BINARY" testnet init-files --help 2>/dev/null | grep -q -- "--chain-id"; then + cmd+=(--chain-id "${CHAIN_ID}") + fi + # Use single-host ports from generator if supported + if [ "${SINGLE_HOST}" = "true" ] && "$BINARY" testnet init-files --help 2>/dev/null | grep -q -- "--single-host"; then + cmd+=(--single-host) + fi + printf '[evmd-localnet] Exec: ' for a in "${cmd[@]}"; do printf '%s ' "$a"; done; printf '\n' "${cmd[@]}" - log "Init complete. Genesis and configs under ${BASE_DIR}/${NODE_PREFIX}{0..$((N-1))}/evmd" + log "Init complete (chain-id: ${CHAIN_ID}). Genesis and configs under ${BASE_DIR}/${NODE_PREFIX}{0..$((N-1))}/evmd" + + # Fallback: if init-files doesn't support --chain-id, patch genesis chain_id via jq + if ! "$BINARY" testnet init-files --help 2>/dev/null | grep -q -- "--chain-id"; then + if command -v jq >/dev/null 2>&1; then + for ((i=0; i< N; i++)); do + gi="${BASE_DIR}/${NODE_PREFIX}${i}/evmd/config/genesis.json" + if [ -f "$gi" ]; then + tmp="$gi.tmp" && jq --arg cid "$CHAIN_ID" '.chain_id=$cid' "$gi" > "$tmp" && mv "$tmp" "$gi" + fi + done + log "Patched genesis chain_id to '${CHAIN_ID}' via jq (fallback path)." + else + log "jq not found; cannot patch genesis chain_id. Using defaults from init-files." + fi + fi +} + +# Update per-node ports for single host to avoid conflicts +adjust_ports_single_host() { + if [ "${SINGLE_HOST}" != "true" ]; then + log "SINGLE_HOST is not enabled; skipping port adjustments." + return 0 + fi + + # Helper to set a key inside a specific TOML section + toml_set_key_in_section() { + local file="$1" section="$2" key="$3" value="$4" + awk -v section="$section" -v key="$key" -v value="$value" ' + BEGIN { insec=0; done=0 } + /^[[:space:]]*\[/ { + if (insec && !done) { print key " = \"" value "\""; done=1 } + insec=0 + if ($0 ~ "^\\[" section "\\]") { insec=1 } + print; next + } + { + if (insec && $0 ~ "^[[:space:]]*" key "[[:space:]]*=") { + print key " = \"" value "\""; done=1; next + } + print + } + END { + if (insec && !done) { print key " = \"" value "\"" } + } + ' "$file" >"$file.tmp" && mv "$file.tmp" "$file" + } + + for ((i=0; i< N; i++)); do + local home_dir="${BASE_DIR}/${NODE_PREFIX}${i}/evmd" + local cfg_tm="${home_dir}/config/config.toml" + local cfg_app="${home_dir}/config/app.toml" + + [ -f "$cfg_tm" ] || { err "Missing $cfg_tm"; continue; } + [ -f "$cfg_app" ] || { err "Missing $cfg_app"; continue; } + + # Compute unique ports + local rpc_port=$((26657 + i)) + local p2p_port=$((16656 + i)) + local pprof_port=$((6060 + i)) + local prom_port=$((26660 + i)) + local api_port=$((1317 + i)) + local grpc_port=$((9090 + i)) + local grpcweb_port=$((9091 + i)) + local http_port=$((8545 + i*10)) + local ws_port=$((8546 + i*10)) + + # Tendermint config.toml + toml_set_key_in_section "$cfg_tm" "rpc" "laddr" "tcp://127.0.0.1:${rpc_port}" + toml_set_key_in_section "$cfg_tm" "rpc" "pprof_laddr" "localhost:${pprof_port}" + toml_set_key_in_section "$cfg_tm" "p2p" "laddr" "tcp://127.0.0.1:${p2p_port}" + toml_set_key_in_section "$cfg_tm" "instrumentation" "prometheus_listen_addr" ":${prom_port}" + + # Application app.toml + toml_set_key_in_section "$cfg_app" "api" "address" "tcp://127.0.0.1:${api_port}" + toml_set_key_in_section "$cfg_app" "grpc" "address" "127.0.0.1:${grpc_port}" + toml_set_key_in_section "$cfg_app" "grpc-web" "address" "127.0.0.1:${grpcweb_port}" + toml_set_key_in_section "$cfg_app" "json-rpc" "address" "127.0.0.1:${http_port}" + toml_set_key_in_section "$cfg_app" "json-rpc" "ws-address" "127.0.0.1:${ws_port}" + + log "Configured ${NODE_PREFIX}${i} ports: rpc:${rpc_port} p2p:${p2p_port} api:${api_port} http:${http_port} ws:${ws_port} grpc:${grpc_port}/${grpcweb_port}" + done } apply_surge_and_replicate() { @@ -162,12 +256,16 @@ start_nodes() { log "Starting ${NODE_PREFIX}${i} (rpc:${rpc_port}, p2p:${p2p_port}, api:${api_port}, http:${http_port}, ws:${ws_port})" + # Ensure client chain-id is set for this home (useful for CLI interactions) + "$BINARY" config set client chain-id "${CHAIN_ID}" --home "$home_dir" >/dev/null 2>&1 || true + # Build start command (aligned with local_node.sh gas defaults) and echo it for reproducibility cmd=("$BINARY" start \ --home "$home_dir" \ --minimum-gas-prices "${MIN_GAS_PRICES}" \ --evm.min-tip 0 \ - --json-rpc.api "eth,txpool,personal,net,debug,web3" + --json-rpc.api "eth,txpool,personal,net,debug,web3" \ + --chain-id "${CHAIN_ID}" --memlog=true) printf '[evmd-localnet] Exec: ' @@ -209,6 +307,7 @@ case "$cmd" in ensure_binary init_fresh apply_surge_and_replicate + adjust_ports_single_host build_peers_if_possible start_nodes ;; From 3bc035a601e5f84c4297ff3f9bbaa3bd622f61ee Mon Sep 17 00:00:00 2001 From: zsystm Date: Mon, 20 Oct 2025 05:27:07 +0900 Subject: [PATCH 07/22] update localnet script --- evmd_localnet.sh | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/evmd_localnet.sh b/evmd_localnet.sh index b5a8f3232..092b5d373 100755 --- a/evmd_localnet.sh +++ b/evmd_localnet.sh @@ -21,6 +21,7 @@ MIN_GAS_PRICES_DEFAULT="0atest" SURGE_CMD_DEFAULT="surge faucet" # or override via SURGE_CMD env; extra args via SURGE_ARGS CHAIN_ID_DEFAULT="local-4221" # or override via CHAIN_ID env SINGLE_HOST_DEFAULT="true" # allocate unique ports per node on one host +STARTING_IP_DEFAULT="127.0.0.1" # starting IP for init-files on single host # Derive settings from env or defaults BINARY=${BINARY:-$BINARY_DEFAULT} @@ -32,6 +33,7 @@ SURGE_CMD=${SURGE_CMD:-$SURGE_CMD_DEFAULT} SURGE_ARGS=${SURGE_ARGS:-} CHAIN_ID=${CHAIN_ID:-$CHAIN_ID_DEFAULT} SINGLE_HOST=${SINGLE_HOST:-$SINGLE_HOST_DEFAULT} +STARTING_IP_ADDRESS=${STARTING_IP_ADDRESS:-$STARTING_IP_DEFAULT} # Internal PID_FILE="${BASE_DIR}/evmd_localnet.pids" @@ -70,7 +72,11 @@ init_fresh() { fi # Use single-host ports from generator if supported if [ "${SINGLE_HOST}" = "true" ] && "$BINARY" testnet init-files --help 2>/dev/null | grep -q -- "--single-host"; then - cmd+=(--single-host) + cmd+=(--single-host=true) + fi + # Set starting IP address if supported (helps ensure 127.0.0.1 mapping) + if [ "${SINGLE_HOST}" = "true" ] && "$BINARY" testnet init-files --help 2>/dev/null | grep -q -- "--starting-ip-address"; then + cmd+=(--starting-ip-address "${STARTING_IP_ADDRESS}") fi printf '[evmd-localnet] Exec: ' @@ -161,6 +167,29 @@ adjust_ports_single_host() { done } +# Apply consensus timeout adjustments similar to local_node.sh +tune_timeouts() { + for ((i=0; i< N; i++)); do + local CONFIG_TOML="${BASE_DIR}/${NODE_PREFIX}${i}/evmd/config/config.toml" + if [ ! -f "$CONFIG_TOML" ]; then + err "Missing $CONFIG_TOML" + continue + fi + # Logging: debug level and json format + sed -i.bak 's/log_level = "info"/log_level = "debug"/g' "$CONFIG_TOML" + sed -i.bak 's/log_format = "plain"/log_format = "json"/g' "$CONFIG_TOML" + sed -i.bak 's/timeout_propose = "3s"/timeout_propose = "2s"/g' "$CONFIG_TOML" + sed -i.bak 's/timeout_propose_delta = "500ms"/timeout_propose_delta = "200ms"/g' "$CONFIG_TOML" + sed -i.bak 's/timeout_prevote = "1s"/timeout_prevote = "500ms"/g' "$CONFIG_TOML" + sed -i.bak 's/timeout_prevote_delta = "500ms"/timeout_prevote_delta = "200ms"/g' "$CONFIG_TOML" + sed -i.bak 's/timeout_precommit = "1s"/timeout_precommit = "500ms"/g' "$CONFIG_TOML" + sed -i.bak 's/timeout_precommit_delta = "500ms"/timeout_precommit_delta = "200ms"/g' "$CONFIG_TOML" + sed -i.bak 's/timeout_commit = "5s"/timeout_commit = "1s"/g' "$CONFIG_TOML" + sed -i.bak 's/timeout_broadcast_tx_commit = "10s"/timeout_broadcast_tx_commit = "5s"/g' "$CONFIG_TOML" + done + log "Applied consensus timeout adjustments to all nodes." +} + apply_surge_and_replicate() { # Apply surge faucet on node0 genesis, then copy to other nodes local g0="${BASE_DIR}/${NODE_PREFIX}0/evmd/config/genesis.json" @@ -308,6 +337,7 @@ case "$cmd" in init_fresh apply_surge_and_replicate adjust_ports_single_host + tune_timeouts build_peers_if_possible start_nodes ;; From 1f5a045c8850cee6d119281d73c6aac797261de6 Mon Sep 17 00:00:00 2001 From: zsystm Date: Mon, 20 Oct 2025 07:08:05 +0900 Subject: [PATCH 08/22] update memlogger dep and apply configs --- evmd/go.mod | 4 +-- evmd/go.sum | 8 +++--- evmd_localnet.sh | 64 ++++++++++++++++++++++++++++++++++++++++++++++++ go.mod | 4 +-- go.sum | 8 +++--- 5 files changed, 76 insertions(+), 12 deletions(-) diff --git a/evmd/go.mod b/evmd/go.mod index 55f51017a..48c408d70 100644 --- a/evmd/go.mod +++ b/evmd/go.mod @@ -272,10 +272,10 @@ require ( ) replace ( - cosmossdk.io/log => github.com/zsystm/cosmos-sdk/log v0.0.0-20251019190943-b98a8e980b0c + cosmossdk.io/log => github.com/zsystm/cosmos-sdk/log v0.0.0-20251019213021-f40f441db0f0 // use cosmos fork of keyring github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0 - github.com/cosmos/cosmos-sdk => github.com/zsystm/cosmos-sdk v0.46.0-beta2.0.20251019190943-b98a8e980b0c + github.com/cosmos/cosmos-sdk => github.com/zsystm/cosmos-sdk v0.53.4-memlogger-0 github.com/cosmos/evm => ../ // use Cosmos geth fork // branch: release/1.16 diff --git a/evmd/go.sum b/evmd/go.sum index b4626e9b6..057f559cf 100644 --- a/evmd/go.sum +++ b/evmd/go.sum @@ -1734,10 +1734,10 @@ github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw= github.com/zondax/ledger-go v0.14.3/go.mod h1:IKKaoxupuB43g4NxeQmbLXv7T9AlQyie1UpHb342ycI= -github.com/zsystm/cosmos-sdk v0.46.0-beta2.0.20251019190943-b98a8e980b0c h1:aK9BU0ybOOp5IXrz82DCAJ0hBMa2oyDdtJGGZOvxDxg= -github.com/zsystm/cosmos-sdk v0.46.0-beta2.0.20251019190943-b98a8e980b0c/go.mod h1:6k6Po9k9tVsUCRsnjpL6kGzTqjPnwgabQg8htKRMtVc= -github.com/zsystm/cosmos-sdk/log v0.0.0-20251019190943-b98a8e980b0c h1:3R2v6bpbYFNW5IItdckOogI/bXywxkIk0IQtK/9vihE= -github.com/zsystm/cosmos-sdk/log v0.0.0-20251019190943-b98a8e980b0c/go.mod h1:DNJwlhYlZOlSePMdymnpTcI8XDar9qn+m8o1fJC7olc= +github.com/zsystm/cosmos-sdk v0.53.4-memlogger-0 h1:4QjE/QAgJ8IJ/Zn0C6ESMDii0DToX9tslx2X6e+g4QM= +github.com/zsystm/cosmos-sdk v0.53.4-memlogger-0/go.mod h1:6k6Po9k9tVsUCRsnjpL6kGzTqjPnwgabQg8htKRMtVc= +github.com/zsystm/cosmos-sdk/log v0.0.0-20251019213021-f40f441db0f0 h1:7w+7l0s/NKC596WeizLvwuMFBKUgHp9rpUVKQpe7hJY= +github.com/zsystm/cosmos-sdk/log v0.0.0-20251019213021-f40f441db0f0/go.mod h1:DNJwlhYlZOlSePMdymnpTcI8XDar9qn+m8o1fJC7olc= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.4.0-alpha.1 h1:3yrqQzbRRPFPdOMWS/QQIVxVnzSkAZQYeWlZFv1kbj4= go.etcd.io/bbolt v1.4.0-alpha.1/go.mod h1:S/Z/Nm3iuOnyO1W4XuFfPci51Gj6F1Hv0z8hisyYYOw= diff --git a/evmd_localnet.sh b/evmd_localnet.sh index 092b5d373..5c70bc7dd 100755 --- a/evmd_localnet.sh +++ b/evmd_localnet.sh @@ -190,6 +190,69 @@ tune_timeouts() { log "Applied consensus timeout adjustments to all nodes." } +# Adjust memlogger settings in app.toml for each node +adjust_memlogger() { + for ((i=0; i< N; i++)); do + local APP_TOML="${BASE_DIR}/${NODE_PREFIX}${i}/evmd/config/app.toml" + if [ ! -f "$APP_TOML" ]; then + err "Missing $APP_TOML" + continue + fi + + # Helpers local to this function + toml_set_key_in_section() { + local file="$1" section="$2" key="$3" value="$4" + awk -v section="$section" -v key="$key" -v value="$value" ' + BEGIN { insec=0; done=0 } + /^[[:space:]]*\[/ { + if (insec && !done) { print key " = \"" value "\""; done=1 } + insec=0 + if ($0 ~ "^\\[" section "\\]") { insec=1 } + print; next + } + { + if (insec && $0 ~ "^[[:space:]]*" key "[[:space:]]*=") { + print key " = \"" value "\""; done=1; next + } + print + } + END { + if (insec && !done) { print key " = \"" value "\"" } + } + ' "$file" >"$file.tmp" && mv "$file.tmp" "$file" + } + + toml_set_key_in_section_raw() { + local file="$1" section="$2" key="$3" rawvalue="$4" + awk -v section="$section" -v key="$key" -v rawvalue="$rawvalue" ' + BEGIN { insec=0; done=0 } + /^[[:space:]]*\[/ { + if (insec && !done) { print key " = " rawvalue; done=1 } + insec=0 + if ($0 ~ "^\\[" section "\\]") { insec=1 } + print; next + } + { + if (insec && $0 ~ "^[[:space:]]*" key "[[:space:]]*=") { + print key " = " rawvalue; done=1; next + } + print + } + END { + if (insec && !done) { print key " = " rawvalue } + } + ' "$file" >"$file.tmp" && mv "$file.tmp" "$file" + } + + # interval: set to 3m (string) + toml_set_key_in_section "$APP_TOML" "memlogger" "interval" "3m" + # max-bytes: set to 2GB (2147483648) numeric + toml_set_key_in_section_raw "$APP_TOML" "memlogger" "max-bytes" "2147483648" + + log "Adjusted memlogger for ${NODE_PREFIX}${i}: interval=3m, max-bytes=2147483648" + done +} + apply_surge_and_replicate() { # Apply surge faucet on node0 genesis, then copy to other nodes local g0="${BASE_DIR}/${NODE_PREFIX}0/evmd/config/genesis.json" @@ -338,6 +401,7 @@ case "$cmd" in apply_surge_and_replicate adjust_ports_single_host tune_timeouts + adjust_memlogger build_peers_if_possible start_nodes ;; diff --git a/go.mod b/go.mod index 7622470d3..9c27b9802 100644 --- a/go.mod +++ b/go.mod @@ -268,11 +268,11 @@ require ( ) replace ( - cosmossdk.io/log => github.com/zsystm/cosmos-sdk/log v0.0.0-20251019190943-b98a8e980b0c + cosmossdk.io/log => github.com/zsystm/cosmos-sdk/log v0.0.0-20251019213021-f40f441db0f0 // use cosmos fork of keyring github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0 github.com/cometbft/cometbft => github.com/zsystm/cometbft v0.38.20-0.20251019013026-68caee7dcb2f - github.com/cosmos/cosmos-sdk => github.com/zsystm/cosmos-sdk v0.46.0-beta2.0.20251019190943-b98a8e980b0c + github.com/cosmos/cosmos-sdk => github.com/zsystm/cosmos-sdk v0.53.4-memlogger-0 // use Cosmos geth fork // branch: release/1.16 github.com/ethereum/go-ethereum => github.com/cosmos/go-ethereum v1.16.2-cosmos-1 diff --git a/go.sum b/go.sum index 0a3c88cd2..b8dd6b99b 100644 --- a/go.sum +++ b/go.sum @@ -1719,10 +1719,10 @@ github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfU github.com/zondax/ledger-go v0.14.3/go.mod h1:IKKaoxupuB43g4NxeQmbLXv7T9AlQyie1UpHb342ycI= github.com/zsystm/cometbft v0.38.20-0.20251019013026-68caee7dcb2f h1:YX8QsgD87lIxbPPjVPkAn/VT1ErC17mCeDz2/Fmw7WE= github.com/zsystm/cometbft v0.38.20-0.20251019013026-68caee7dcb2f/go.mod h1:UCu8dlHqvkAsmAFmWDRWNZJPlu6ya2fTWZlDrWsivwo= -github.com/zsystm/cosmos-sdk v0.46.0-beta2.0.20251019190943-b98a8e980b0c h1:aK9BU0ybOOp5IXrz82DCAJ0hBMa2oyDdtJGGZOvxDxg= -github.com/zsystm/cosmos-sdk v0.46.0-beta2.0.20251019190943-b98a8e980b0c/go.mod h1:6k6Po9k9tVsUCRsnjpL6kGzTqjPnwgabQg8htKRMtVc= -github.com/zsystm/cosmos-sdk/log v0.0.0-20251019190943-b98a8e980b0c h1:3R2v6bpbYFNW5IItdckOogI/bXywxkIk0IQtK/9vihE= -github.com/zsystm/cosmos-sdk/log v0.0.0-20251019190943-b98a8e980b0c/go.mod h1:DNJwlhYlZOlSePMdymnpTcI8XDar9qn+m8o1fJC7olc= +github.com/zsystm/cosmos-sdk v0.53.4-memlogger-0 h1:4QjE/QAgJ8IJ/Zn0C6ESMDii0DToX9tslx2X6e+g4QM= +github.com/zsystm/cosmos-sdk v0.53.4-memlogger-0/go.mod h1:6k6Po9k9tVsUCRsnjpL6kGzTqjPnwgabQg8htKRMtVc= +github.com/zsystm/cosmos-sdk/log v0.0.0-20251019213021-f40f441db0f0 h1:7w+7l0s/NKC596WeizLvwuMFBKUgHp9rpUVKQpe7hJY= +github.com/zsystm/cosmos-sdk/log v0.0.0-20251019213021-f40f441db0f0/go.mod h1:DNJwlhYlZOlSePMdymnpTcI8XDar9qn+m8o1fJC7olc= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.4.0-alpha.1 h1:3yrqQzbRRPFPdOMWS/QQIVxVnzSkAZQYeWlZFv1kbj4= go.etcd.io/bbolt v1.4.0-alpha.1/go.mod h1:S/Z/Nm3iuOnyO1W4XuFfPci51Gj6F1Hv0z8hisyYYOw= From 3c1a21f7f534c803ffc6d21a26c9503f11094cee Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Sat, 1 Nov 2025 14:43:02 +0000 Subject: [PATCH 09/22] add testing scripts --- evmd_localnet_memlogger.sh | 419 ++++++++++++++++++++++++++++++ evmd_localnet_nomemlogger.sh | 419 ++++++++++++++++++++++++++++++ evmd_localnet_nomemlogger_info.sh | 418 +++++++++++++++++++++++++++++ 3 files changed, 1256 insertions(+) create mode 100755 evmd_localnet_memlogger.sh create mode 100755 evmd_localnet_nomemlogger.sh create mode 100755 evmd_localnet_nomemlogger_info.sh diff --git a/evmd_localnet_memlogger.sh b/evmd_localnet_memlogger.sh new file mode 100755 index 000000000..1ec10ebf7 --- /dev/null +++ b/evmd_localnet_memlogger.sh @@ -0,0 +1,419 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Simple multi-node localnet launcher for evmd +# - Initializes N validator nodes under BASE_DIR using `evmd testnet init-files --validator-count N --keyring-backend test` +# - Applies surge faucet to node0 genesis, then replicates the modified genesis to all nodes +# - Optionally computes persistent_peers via `evmd comet show-node-id` if available +# - Starts each node with its own home and port set by init-files +# +# Usage: +# scripts/evmd-localnet.sh start # init (if needed) and start N nodes +# scripts/evmd-localnet.sh stop # stop nodes started by this script (via PID file) +# scripts/evmd-localnet.sh clean # remove BASE_DIR + +BINARY_DEFAULT="evmd" # or override via BINARY env +BASE_DIR_DEFAULT="./.testnets" # or override via BASE_DIR env +NODE_PREFIX_DEFAULT="node" +N_DEFAULT=4 +# Start defaults (min gas aligned with local_node.sh) +MIN_GAS_PRICES_DEFAULT="0atest" +SURGE_CMD_DEFAULT="surge faucet" # or override via SURGE_CMD env; extra args via SURGE_ARGS +CHAIN_ID_DEFAULT="local-4221" # or override via CHAIN_ID env +SINGLE_HOST_DEFAULT="true" # allocate unique ports per node on one host +STARTING_IP_DEFAULT="127.0.0.1" # starting IP for init-files on single host + +# Derive settings from env or defaults +BINARY=${BINARY:-$BINARY_DEFAULT} +BASE_DIR=${BASE_DIR:-$BASE_DIR_DEFAULT} +NODE_PREFIX=${NODE_PREFIX:-$NODE_PREFIX_DEFAULT} +N=${N:-$N_DEFAULT} +MIN_GAS_PRICES=${MIN_GAS_PRICES:-$MIN_GAS_PRICES_DEFAULT} +SURGE_CMD=${SURGE_CMD:-$SURGE_CMD_DEFAULT} +SURGE_ARGS=${SURGE_ARGS:-} +CHAIN_ID=${CHAIN_ID:-$CHAIN_ID_DEFAULT} +SINGLE_HOST=${SINGLE_HOST:-$SINGLE_HOST_DEFAULT} +STARTING_IP_ADDRESS=${STARTING_IP_ADDRESS:-$STARTING_IP_DEFAULT} + +# Internal +PID_FILE="${BASE_DIR}/evmd_localnet.pids" + +log() { echo "[evmd-localnet] $*"; } +err() { echo "[evmd-localnet:ERROR] $*" >&2; } + +ensure_binary() { + if command -v "$BINARY" >/dev/null 2>&1; then + return 0 + fi + # Fallback to local build path + if [ -x "./build/evmd" ]; then + BINARY="./build/evmd" + return 0 + fi + err "Cannot find evmd binary. Put it on PATH or build via 'make build'." + exit 1 +} + +init_fresh() { + # Always initialize a fresh testnet as requested + rm -rf "$BASE_DIR" + log "Initializing ${N}-node testnet at ${BASE_DIR}…" + mkdir -p "$BASE_DIR" + + # Per request: use only validator-count and keyring-backend flags (+ output-dir to control location) + local cmd=("$BINARY" testnet init-files \ + --validator-count "${N}" \ + --keyring-backend test \ + --output-dir "${BASE_DIR}") + + # Add chain-id if supported by the subcommand + if "$BINARY" testnet init-files --help 2>/dev/null | grep -q -- "--chain-id"; then + cmd+=(--chain-id "${CHAIN_ID}") + fi + # Use single-host ports from generator if supported + if [ "${SINGLE_HOST}" = "true" ] && "$BINARY" testnet init-files --help 2>/dev/null | grep -q -- "--single-host"; then + cmd+=(--single-host=true) + fi + # Set starting IP address if supported (helps ensure 127.0.0.1 mapping) + if [ "${SINGLE_HOST}" = "true" ] && "$BINARY" testnet init-files --help 2>/dev/null | grep -q -- "--starting-ip-address"; then + cmd+=(--starting-ip-address "${STARTING_IP_ADDRESS}") + fi + + printf '[evmd-localnet] Exec: ' + for a in "${cmd[@]}"; do printf '%s ' "$a"; done; printf '\n' + "${cmd[@]}" + + log "Init complete (chain-id: ${CHAIN_ID}). Genesis and configs under ${BASE_DIR}/${NODE_PREFIX}{0..$((N-1))}/evmd" + + # Fallback: if init-files doesn't support --chain-id, patch genesis chain_id via jq + if ! "$BINARY" testnet init-files --help 2>/dev/null | grep -q -- "--chain-id"; then + if command -v jq >/dev/null 2>&1; then + for ((i=0; i< N; i++)); do + gi="${BASE_DIR}/${NODE_PREFIX}${i}/evmd/config/genesis.json" + if [ -f "$gi" ]; then + tmp="$gi.tmp" && jq --arg cid "$CHAIN_ID" '.chain_id=$cid' "$gi" > "$tmp" && mv "$tmp" "$gi" + fi + done + log "Patched genesis chain_id to '${CHAIN_ID}' via jq (fallback path)." + else + log "jq not found; cannot patch genesis chain_id. Using defaults from init-files." + fi + fi +} + +# Update per-node ports for single host to avoid conflicts +adjust_ports_single_host() { + if [ "${SINGLE_HOST}" != "true" ]; then + log "SINGLE_HOST is not enabled; skipping port adjustments." + return 0 + fi + + # Helper to set a key inside a specific TOML section + toml_set_key_in_section() { + local file="$1" section="$2" key="$3" value="$4" + awk -v section="$section" -v key="$key" -v value="$value" ' + BEGIN { insec=0; done=0 } + /^[[:space:]]*\[/ { + if (insec && !done) { print key " = \"" value "\""; done=1 } + insec=0 + if ($0 ~ "^\\[" section "\\]") { insec=1 } + print; next + } + { + if (insec && $0 ~ "^[[:space:]]*" key "[[:space:]]*=") { + print key " = \"" value "\""; done=1; next + } + print + } + END { + if (insec && !done) { print key " = \"" value "\"" } + } + ' "$file" >"$file.tmp" && mv "$file.tmp" "$file" + } + + for ((i=0; i< N; i++)); do + local home_dir="${BASE_DIR}/${NODE_PREFIX}${i}/evmd" + local cfg_tm="${home_dir}/config/config.toml" + local cfg_app="${home_dir}/config/app.toml" + + [ -f "$cfg_tm" ] || { err "Missing $cfg_tm"; continue; } + [ -f "$cfg_app" ] || { err "Missing $cfg_app"; continue; } + + # Compute unique ports + local rpc_port=$((26657 + i)) + local p2p_port=$((16656 + i)) + local pprof_port=$((6060 + i)) + local prom_port=$((26660 + i)) + local api_port=$((1317 + i)) + local grpc_port=$((9090 + i)) + local grpcweb_port=$((9091 + i)) + local http_port=$((8545 + i*10)) + local ws_port=$((8546 + i*10)) + + # Tendermint config.toml + toml_set_key_in_section "$cfg_tm" "rpc" "laddr" "tcp://127.0.0.1:${rpc_port}" + toml_set_key_in_section "$cfg_tm" "rpc" "pprof_laddr" "localhost:${pprof_port}" + toml_set_key_in_section "$cfg_tm" "p2p" "laddr" "tcp://127.0.0.1:${p2p_port}" + toml_set_key_in_section "$cfg_tm" "instrumentation" "prometheus_listen_addr" ":${prom_port}" + + # Application app.toml + toml_set_key_in_section "$cfg_app" "api" "address" "tcp://127.0.0.1:${api_port}" + toml_set_key_in_section "$cfg_app" "grpc" "address" "127.0.0.1:${grpc_port}" + toml_set_key_in_section "$cfg_app" "grpc-web" "address" "127.0.0.1:${grpcweb_port}" + toml_set_key_in_section "$cfg_app" "json-rpc" "address" "127.0.0.1:${http_port}" + toml_set_key_in_section "$cfg_app" "json-rpc" "ws-address" "127.0.0.1:${ws_port}" + + log "Configured ${NODE_PREFIX}${i} ports: rpc:${rpc_port} p2p:${p2p_port} api:${api_port} http:${http_port} ws:${ws_port} grpc:${grpc_port}/${grpcweb_port}" + done +} + +# Apply consensus timeout adjustments similar to local_node.sh +tune_timeouts() { + for ((i=0; i< N; i++)); do + local CONFIG_TOML="${BASE_DIR}/${NODE_PREFIX}${i}/evmd/config/config.toml" + if [ ! -f "$CONFIG_TOML" ]; then + err "Missing $CONFIG_TOML" + continue + fi + # Logging: debug level and json format + sed -i.bak 's/log_level = "info"/log_level = "debug"/g' "$CONFIG_TOML" + sed -i.bak 's/log_format = "plain"/log_format = "json"/g' "$CONFIG_TOML" + sed -i.bak 's/timeout_propose = "3s"/timeout_propose = "2s"/g' "$CONFIG_TOML" + sed -i.bak 's/timeout_propose_delta = "500ms"/timeout_propose_delta = "200ms"/g' "$CONFIG_TOML" + sed -i.bak 's/timeout_prevote = "1s"/timeout_prevote = "500ms"/g' "$CONFIG_TOML" + sed -i.bak 's/timeout_prevote_delta = "500ms"/timeout_prevote_delta = "200ms"/g' "$CONFIG_TOML" + sed -i.bak 's/timeout_precommit = "1s"/timeout_precommit = "500ms"/g' "$CONFIG_TOML" + sed -i.bak 's/timeout_precommit_delta = "500ms"/timeout_precommit_delta = "200ms"/g' "$CONFIG_TOML" + sed -i.bak 's/timeout_commit = "5s"/timeout_commit = "1s"/g' "$CONFIG_TOML" + sed -i.bak 's/timeout_broadcast_tx_commit = "10s"/timeout_broadcast_tx_commit = "5s"/g' "$CONFIG_TOML" + done + log "Applied consensus timeout adjustments to all nodes." +} + +# Adjust memlogger settings in app.toml for each node +adjust_memlogger() { + for ((i=0; i< N; i++)); do + local APP_TOML="${BASE_DIR}/${NODE_PREFIX}${i}/evmd/config/app.toml" + if [ ! -f "$APP_TOML" ]; then + err "Missing $APP_TOML" + continue + fi + + # Helpers local to this function + toml_set_key_in_section() { + local file="$1" section="$2" key="$3" value="$4" + awk -v section="$section" -v key="$key" -v value="$value" ' + BEGIN { insec=0; done=0 } + /^[[:space:]]*\[/ { + if (insec && !done) { print key " = \"" value "\""; done=1 } + insec=0 + if ($0 ~ "^\\[" section "\\]") { insec=1 } + print; next + } + { + if (insec && $0 ~ "^[[:space:]]*" key "[[:space:]]*=") { + print key " = \"" value "\""; done=1; next + } + print + } + END { + if (insec && !done) { print key " = \"" value "\"" } + } + ' "$file" >"$file.tmp" && mv "$file.tmp" "$file" + } + + toml_set_key_in_section_raw() { + local file="$1" section="$2" key="$3" rawvalue="$4" + awk -v section="$section" -v key="$key" -v rawvalue="$rawvalue" ' + BEGIN { insec=0; done=0 } + /^[[:space:]]*\[/ { + if (insec && !done) { print key " = " rawvalue; done=1 } + insec=0 + if ($0 ~ "^\\[" section "\\]") { insec=1 } + print; next + } + { + if (insec && $0 ~ "^[[:space:]]*" key "[[:space:]]*=") { + print key " = " rawvalue; done=1; next + } + print + } + END { + if (insec && !done) { print key " = " rawvalue } + } + ' "$file" >"$file.tmp" && mv "$file.tmp" "$file" + } + + # enable memlogger + toml_set_key_in_section "$APP_TOML" "memlogger" "enabled" "true" + # interval: set to 3m (string) + toml_set_key_in_section "$APP_TOML" "memlogger" "interval" "3m" + # max-bytes: set to 2GB (2147483648) numeric + toml_set_key_in_section_raw "$APP_TOML" "memlogger" "max-bytes" "2147483648" + + log "Adjusted memlogger for ${NODE_PREFIX}${i}: interval=3m, max-bytes=2147483648" + done +} + +apply_surge_and_replicate() { + # Apply surge faucet on node0 genesis, then copy to other nodes + local g0="${BASE_DIR}/${NODE_PREFIX}0/evmd/config/genesis.json" + if [ ! -f "$g0" ]; then + err "node0 genesis not found at $g0" + exit 1 + fi + + # Run surge faucet if available/desired + if [ -n "$SURGE_CMD" ]; then + local surge_bin + surge_bin=$(echo "$SURGE_CMD" | awk '{print $1}') + if ! command -v "$surge_bin" >/dev/null 2>&1; then + err "'$surge_bin' not found on PATH. Set SURGE_CMD='' to skip or install surge." + exit 1 + fi + # Echo the exact command + printf '[evmd-localnet] Exec: %s %s %s\n' "$SURGE_CMD" "${SURGE_ARGS}" "$g0" + # Execute with optional extra args + eval "$SURGE_CMD ${SURGE_ARGS} $g0" + else + log "SURGE_CMD empty; skipping surge faucet step." + fi + + # Replicate node0 genesis to all other nodes + for ((i=1; i< N; i++)); do + local gi="${BASE_DIR}/${NODE_PREFIX}${i}/evmd/config/genesis.json" + if [ -f "$gi" ]; then + cp "$g0" "$gi" + fi + done + + # Validate genesis for all nodes (best-effort) + for ((i=0; i< N; i++)); do + local home_dir="${BASE_DIR}/${NODE_PREFIX}${i}/evmd" + if [ -d "$home_dir" ]; then + "$BINARY" genesis validate-genesis --home "$home_dir" >/dev/null 2>&1 || true + fi + done +} + +build_peers_if_possible() { + # Try to gather node IDs using `evmd comet show-node-id` if the subcommand exists. + if ! "$BINARY" comet --help >/dev/null 2>&1; then + log "'evmd comet' subcommand not found. Skipping persistent_peers injection (nodes should still connect with generated configs)." + return 0 + fi + + local peers="" + for ((i=0; i< N; i++)); do + local home_dir="${BASE_DIR}/${NODE_PREFIX}${i}/evmd" + local id + if ! id=$("$BINARY" comet show-node-id --home "$home_dir" 2>/dev/null); then + err "Failed to read node ID for ${NODE_PREFIX}${i}; skipping persistent_peers." + return 0 + fi + # Ports per init-files when --single-host is used: + # - P2P starts at 16656 and increments by +1 per node + local p2p_port=$((16656 + i)) + local entry="${id}@127.0.0.1:${p2p_port}" + if [ -z "$peers" ]; then peers="$entry"; else peers+="",$entry; fi + done + + log "persistent_peers=${peers}" + # Inject into each node's config.toml + for ((i=0; i< N; i++)); do + local cfg="${BASE_DIR}/${NODE_PREFIX}${i}/evmd/config/config.toml" + if [ -f "$cfg" ]; then + # Replace existing line or append if missing + if grep -q '^persistent_peers\s*=\s*"' "$cfg"; then + sed -i.bak -E "s|^persistent_peers\s*=\s*\".*\"|persistent_peers = \"${peers}\"|" "$cfg" + else + echo "persistent_peers = \"${peers}\"" >> "$cfg" + fi + fi + done +} + +start_nodes() { + mkdir -p "$(dirname "$PID_FILE")" + : > "$PID_FILE" + + for ((i=0; i< N; i++)); do + local home_dir="${BASE_DIR}/${NODE_PREFIX}${i}/evmd" + local log_file="${home_dir}/evmd.log" + + # Compute display ports that init-files configure for single-host: + local rpc_port=$((26657 + i)) + local p2p_port=$((16656 + i)) + local api_port=$((1317 + i)) + local http_port=$((8545 + i*10)) + local ws_port=$((8546 + i*10)) + + log "Starting ${NODE_PREFIX}${i} (rpc:${rpc_port}, p2p:${p2p_port}, api:${api_port}, http:${http_port}, ws:${ws_port})" + + # Ensure client chain-id is set for this home (useful for CLI interactions) + "$BINARY" config set client chain-id "${CHAIN_ID}" --home "$home_dir" >/dev/null 2>&1 || true + + # Build start command (aligned with local_node.sh gas defaults) and echo it for reproducibility + cmd=("$BINARY" start \ + --home "$home_dir" \ + --minimum-gas-prices "${MIN_GAS_PRICES}" \ + --evm.min-tip 0 \ + --json-rpc.api "eth,txpool,personal,net,debug,web3" \ + --chain-id "${CHAIN_ID}") + + printf '[evmd-localnet] Exec: ' + for arg in "${cmd[@]}"; do printf '%s ' "$arg"; done; printf '\n' + + # Start in background, capture PID + ("${cmd[@]}" >"$log_file" 2>&1 & echo $! >> "$PID_FILE") + sleep 0.5 + done + + log "All nodes started. PIDs recorded in ${PID_FILE}" +} + +stop_nodes() { + if [ ! -f "$PID_FILE" ]; then + err "PID file not found: $PID_FILE" + exit 1 + fi + tac "$PID_FILE" | while read -r pid; do + if kill -0 "$pid" >/dev/null 2>&1; then + log "Stopping PID $pid" + kill "$pid" || true + fi + done + rm -f "$PID_FILE" + log "All nodes stopped." +} + +clean() { + if [ -d "$BASE_DIR" ]; then + log "Removing ${BASE_DIR}" + rm -rf "$BASE_DIR" + fi +} + +cmd=${1:-start} +case "$cmd" in + start) + ensure_binary + init_fresh + apply_surge_and_replicate + adjust_ports_single_host + tune_timeouts + adjust_memlogger + build_peers_if_possible + start_nodes + ;; + stop) + stop_nodes + ;; + clean) + clean + ;; + *) + echo "Usage: $0 {start|stop|clean}" >&2 + exit 1 + ;; +esac diff --git a/evmd_localnet_nomemlogger.sh b/evmd_localnet_nomemlogger.sh new file mode 100755 index 000000000..76316de0a --- /dev/null +++ b/evmd_localnet_nomemlogger.sh @@ -0,0 +1,419 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Simple multi-node localnet launcher for evmd +# - Initializes N validator nodes under BASE_DIR using `evmd testnet init-files --validator-count N --keyring-backend test` +# - Applies surge faucet to node0 genesis, then replicates the modified genesis to all nodes +# - Optionally computes persistent_peers via `evmd comet show-node-id` if available +# - Starts each node with its own home and port set by init-files +# +# Usage: +# scripts/evmd-localnet.sh start # init (if needed) and start N nodes +# scripts/evmd-localnet.sh stop # stop nodes started by this script (via PID file) +# scripts/evmd-localnet.sh clean # remove BASE_DIR + +BINARY_DEFAULT="evmd" # or override via BINARY env +BASE_DIR_DEFAULT="./.testnets" # or override via BASE_DIR env +NODE_PREFIX_DEFAULT="node" +N_DEFAULT=4 +# Start defaults (min gas aligned with local_node.sh) +MIN_GAS_PRICES_DEFAULT="0atest" +SURGE_CMD_DEFAULT="surge faucet" # or override via SURGE_CMD env; extra args via SURGE_ARGS +CHAIN_ID_DEFAULT="local-4221" # or override via CHAIN_ID env +SINGLE_HOST_DEFAULT="true" # allocate unique ports per node on one host +STARTING_IP_DEFAULT="127.0.0.1" # starting IP for init-files on single host + +# Derive settings from env or defaults +BINARY=${BINARY:-$BINARY_DEFAULT} +BASE_DIR=${BASE_DIR:-$BASE_DIR_DEFAULT} +NODE_PREFIX=${NODE_PREFIX:-$NODE_PREFIX_DEFAULT} +N=${N:-$N_DEFAULT} +MIN_GAS_PRICES=${MIN_GAS_PRICES:-$MIN_GAS_PRICES_DEFAULT} +SURGE_CMD=${SURGE_CMD:-$SURGE_CMD_DEFAULT} +SURGE_ARGS=${SURGE_ARGS:-} +CHAIN_ID=${CHAIN_ID:-$CHAIN_ID_DEFAULT} +SINGLE_HOST=${SINGLE_HOST:-$SINGLE_HOST_DEFAULT} +STARTING_IP_ADDRESS=${STARTING_IP_ADDRESS:-$STARTING_IP_DEFAULT} + +# Internal +PID_FILE="${BASE_DIR}/evmd_localnet.pids" + +log() { echo "[evmd-localnet] $*"; } +err() { echo "[evmd-localnet:ERROR] $*" >&2; } + +ensure_binary() { + if command -v "$BINARY" >/dev/null 2>&1; then + return 0 + fi + # Fallback to local build path + if [ -x "./build/evmd" ]; then + BINARY="./build/evmd" + return 0 + fi + err "Cannot find evmd binary. Put it on PATH or build via 'make build'." + exit 1 +} + +init_fresh() { + # Always initialize a fresh testnet as requested + rm -rf "$BASE_DIR" + log "Initializing ${N}-node testnet at ${BASE_DIR}…" + mkdir -p "$BASE_DIR" + + # Per request: use only validator-count and keyring-backend flags (+ output-dir to control location) + local cmd=("$BINARY" testnet init-files \ + --validator-count "${N}" \ + --keyring-backend test \ + --output-dir "${BASE_DIR}") + + # Add chain-id if supported by the subcommand + if "$BINARY" testnet init-files --help 2>/dev/null | grep -q -- "--chain-id"; then + cmd+=(--chain-id "${CHAIN_ID}") + fi + # Use single-host ports from generator if supported + if [ "${SINGLE_HOST}" = "true" ] && "$BINARY" testnet init-files --help 2>/dev/null | grep -q -- "--single-host"; then + cmd+=(--single-host=true) + fi + # Set starting IP address if supported (helps ensure 127.0.0.1 mapping) + if [ "${SINGLE_HOST}" = "true" ] && "$BINARY" testnet init-files --help 2>/dev/null | grep -q -- "--starting-ip-address"; then + cmd+=(--starting-ip-address "${STARTING_IP_ADDRESS}") + fi + + printf '[evmd-localnet] Exec: ' + for a in "${cmd[@]}"; do printf '%s ' "$a"; done; printf '\n' + "${cmd[@]}" + + log "Init complete (chain-id: ${CHAIN_ID}). Genesis and configs under ${BASE_DIR}/${NODE_PREFIX}{0..$((N-1))}/evmd" + + # Fallback: if init-files doesn't support --chain-id, patch genesis chain_id via jq + if ! "$BINARY" testnet init-files --help 2>/dev/null | grep -q -- "--chain-id"; then + if command -v jq >/dev/null 2>&1; then + for ((i=0; i< N; i++)); do + gi="${BASE_DIR}/${NODE_PREFIX}${i}/evmd/config/genesis.json" + if [ -f "$gi" ]; then + tmp="$gi.tmp" && jq --arg cid "$CHAIN_ID" '.chain_id=$cid' "$gi" > "$tmp" && mv "$tmp" "$gi" + fi + done + log "Patched genesis chain_id to '${CHAIN_ID}' via jq (fallback path)." + else + log "jq not found; cannot patch genesis chain_id. Using defaults from init-files." + fi + fi +} + +# Update per-node ports for single host to avoid conflicts +adjust_ports_single_host() { + if [ "${SINGLE_HOST}" != "true" ]; then + log "SINGLE_HOST is not enabled; skipping port adjustments." + return 0 + fi + + # Helper to set a key inside a specific TOML section + toml_set_key_in_section() { + local file="$1" section="$2" key="$3" value="$4" + awk -v section="$section" -v key="$key" -v value="$value" ' + BEGIN { insec=0; done=0 } + /^[[:space:]]*\[/ { + if (insec && !done) { print key " = \"" value "\""; done=1 } + insec=0 + if ($0 ~ "^\\[" section "\\]") { insec=1 } + print; next + } + { + if (insec && $0 ~ "^[[:space:]]*" key "[[:space:]]*=") { + print key " = \"" value "\""; done=1; next + } + print + } + END { + if (insec && !done) { print key " = \"" value "\"" } + } + ' "$file" >"$file.tmp" && mv "$file.tmp" "$file" + } + + for ((i=0; i< N; i++)); do + local home_dir="${BASE_DIR}/${NODE_PREFIX}${i}/evmd" + local cfg_tm="${home_dir}/config/config.toml" + local cfg_app="${home_dir}/config/app.toml" + + [ -f "$cfg_tm" ] || { err "Missing $cfg_tm"; continue; } + [ -f "$cfg_app" ] || { err "Missing $cfg_app"; continue; } + + # Compute unique ports + local rpc_port=$((26657 + i)) + local p2p_port=$((16656 + i)) + local pprof_port=$((6060 + i)) + local prom_port=$((26660 + i)) + local api_port=$((1317 + i)) + local grpc_port=$((9090 + i)) + local grpcweb_port=$((9091 + i)) + local http_port=$((8545 + i*10)) + local ws_port=$((8546 + i*10)) + + # Tendermint config.toml + toml_set_key_in_section "$cfg_tm" "rpc" "laddr" "tcp://127.0.0.1:${rpc_port}" + toml_set_key_in_section "$cfg_tm" "rpc" "pprof_laddr" "localhost:${pprof_port}" + toml_set_key_in_section "$cfg_tm" "p2p" "laddr" "tcp://127.0.0.1:${p2p_port}" + toml_set_key_in_section "$cfg_tm" "instrumentation" "prometheus_listen_addr" ":${prom_port}" + + # Application app.toml + toml_set_key_in_section "$cfg_app" "api" "address" "tcp://127.0.0.1:${api_port}" + toml_set_key_in_section "$cfg_app" "grpc" "address" "127.0.0.1:${grpc_port}" + toml_set_key_in_section "$cfg_app" "grpc-web" "address" "127.0.0.1:${grpcweb_port}" + toml_set_key_in_section "$cfg_app" "json-rpc" "address" "127.0.0.1:${http_port}" + toml_set_key_in_section "$cfg_app" "json-rpc" "ws-address" "127.0.0.1:${ws_port}" + + log "Configured ${NODE_PREFIX}${i} ports: rpc:${rpc_port} p2p:${p2p_port} api:${api_port} http:${http_port} ws:${ws_port} grpc:${grpc_port}/${grpcweb_port}" + done +} + +# Apply consensus timeout adjustments similar to local_node.sh +tune_timeouts() { + for ((i=0; i< N; i++)); do + local CONFIG_TOML="${BASE_DIR}/${NODE_PREFIX}${i}/evmd/config/config.toml" + if [ ! -f "$CONFIG_TOML" ]; then + err "Missing $CONFIG_TOML" + continue + fi + # Logging: debug level and json format + sed -i.bak 's/log_level = "info"/log_level = "debug"/g' "$CONFIG_TOML" + sed -i.bak 's/log_format = "plain"/log_format = "json"/g' "$CONFIG_TOML" + sed -i.bak 's/timeout_propose = "3s"/timeout_propose = "2s"/g' "$CONFIG_TOML" + sed -i.bak 's/timeout_propose_delta = "500ms"/timeout_propose_delta = "200ms"/g' "$CONFIG_TOML" + sed -i.bak 's/timeout_prevote = "1s"/timeout_prevote = "500ms"/g' "$CONFIG_TOML" + sed -i.bak 's/timeout_prevote_delta = "500ms"/timeout_prevote_delta = "200ms"/g' "$CONFIG_TOML" + sed -i.bak 's/timeout_precommit = "1s"/timeout_precommit = "500ms"/g' "$CONFIG_TOML" + sed -i.bak 's/timeout_precommit_delta = "500ms"/timeout_precommit_delta = "200ms"/g' "$CONFIG_TOML" + sed -i.bak 's/timeout_commit = "5s"/timeout_commit = "1s"/g' "$CONFIG_TOML" + sed -i.bak 's/timeout_broadcast_tx_commit = "10s"/timeout_broadcast_tx_commit = "5s"/g' "$CONFIG_TOML" + done + log "Applied consensus timeout adjustments to all nodes." +} + +# Adjust memlogger settings in app.toml for each node +adjust_memlogger() { + for ((i=0; i< N; i++)); do + local APP_TOML="${BASE_DIR}/${NODE_PREFIX}${i}/evmd/config/app.toml" + if [ ! -f "$APP_TOML" ]; then + err "Missing $APP_TOML" + continue + fi + + # Helpers local to this function + toml_set_key_in_section() { + local file="$1" section="$2" key="$3" value="$4" + awk -v section="$section" -v key="$key" -v value="$value" ' + BEGIN { insec=0; done=0 } + /^[[:space:]]*\[/ { + if (insec && !done) { print key " = \"" value "\""; done=1 } + insec=0 + if ($0 ~ "^\\[" section "\\]") { insec=1 } + print; next + } + { + if (insec && $0 ~ "^[[:space:]]*" key "[[:space:]]*=") { + print key " = \"" value "\""; done=1; next + } + print + } + END { + if (insec && !done) { print key " = \"" value "\"" } + } + ' "$file" >"$file.tmp" && mv "$file.tmp" "$file" + } + + toml_set_key_in_section_raw() { + local file="$1" section="$2" key="$3" rawvalue="$4" + awk -v section="$section" -v key="$key" -v rawvalue="$rawvalue" ' + BEGIN { insec=0; done=0 } + /^[[:space:]]*\[/ { + if (insec && !done) { print key " = " rawvalue; done=1 } + insec=0 + if ($0 ~ "^\\[" section "\\]") { insec=1 } + print; next + } + { + if (insec && $0 ~ "^[[:space:]]*" key "[[:space:]]*=") { + print key " = " rawvalue; done=1; next + } + print + } + END { + if (insec && !done) { print key " = " rawvalue } + } + ' "$file" >"$file.tmp" && mv "$file.tmp" "$file" + } + + # disable + toml_set_key_in_section "$APP_TOML" "memlogger" "enabled" "false" + # interval: set to 3m (string) + toml_set_key_in_section "$APP_TOML" "memlogger" "interval" "3m" + # max-bytes: set to 2GB (2147483648) numeric + toml_set_key_in_section_raw "$APP_TOML" "memlogger" "max-bytes" "2147483648" + + log "Adjusted memlogger for ${NODE_PREFIX}${i}: interval=3m, max-bytes=2147483648" + done +} + +apply_surge_and_replicate() { + # Apply surge faucet on node0 genesis, then copy to other nodes + local g0="${BASE_DIR}/${NODE_PREFIX}0/evmd/config/genesis.json" + if [ ! -f "$g0" ]; then + err "node0 genesis not found at $g0" + exit 1 + fi + + # Run surge faucet if available/desired + if [ -n "$SURGE_CMD" ]; then + local surge_bin + surge_bin=$(echo "$SURGE_CMD" | awk '{print $1}') + if ! command -v "$surge_bin" >/dev/null 2>&1; then + err "'$surge_bin' not found on PATH. Set SURGE_CMD='' to skip or install surge." + exit 1 + fi + # Echo the exact command + printf '[evmd-localnet] Exec: %s %s %s\n' "$SURGE_CMD" "${SURGE_ARGS}" "$g0" + # Execute with optional extra args + eval "$SURGE_CMD ${SURGE_ARGS} $g0" + else + log "SURGE_CMD empty; skipping surge faucet step." + fi + + # Replicate node0 genesis to all other nodes + for ((i=1; i< N; i++)); do + local gi="${BASE_DIR}/${NODE_PREFIX}${i}/evmd/config/genesis.json" + if [ -f "$gi" ]; then + cp "$g0" "$gi" + fi + done + + # Validate genesis for all nodes (best-effort) + for ((i=0; i< N; i++)); do + local home_dir="${BASE_DIR}/${NODE_PREFIX}${i}/evmd" + if [ -d "$home_dir" ]; then + "$BINARY" genesis validate-genesis --home "$home_dir" >/dev/null 2>&1 || true + fi + done +} + +build_peers_if_possible() { + # Try to gather node IDs using `evmd comet show-node-id` if the subcommand exists. + if ! "$BINARY" comet --help >/dev/null 2>&1; then + log "'evmd comet' subcommand not found. Skipping persistent_peers injection (nodes should still connect with generated configs)." + return 0 + fi + + local peers="" + for ((i=0; i< N; i++)); do + local home_dir="${BASE_DIR}/${NODE_PREFIX}${i}/evmd" + local id + if ! id=$("$BINARY" comet show-node-id --home "$home_dir" 2>/dev/null); then + err "Failed to read node ID for ${NODE_PREFIX}${i}; skipping persistent_peers." + return 0 + fi + # Ports per init-files when --single-host is used: + # - P2P starts at 16656 and increments by +1 per node + local p2p_port=$((16656 + i)) + local entry="${id}@127.0.0.1:${p2p_port}" + if [ -z "$peers" ]; then peers="$entry"; else peers+="",$entry; fi + done + + log "persistent_peers=${peers}" + # Inject into each node's config.toml + for ((i=0; i< N; i++)); do + local cfg="${BASE_DIR}/${NODE_PREFIX}${i}/evmd/config/config.toml" + if [ -f "$cfg" ]; then + # Replace existing line or append if missing + if grep -q '^persistent_peers\s*=\s*"' "$cfg"; then + sed -i.bak -E "s|^persistent_peers\s*=\s*\".*\"|persistent_peers = \"${peers}\"|" "$cfg" + else + echo "persistent_peers = \"${peers}\"" >> "$cfg" + fi + fi + done +} + +start_nodes() { + mkdir -p "$(dirname "$PID_FILE")" + : > "$PID_FILE" + + for ((i=0; i< N; i++)); do + local home_dir="${BASE_DIR}/${NODE_PREFIX}${i}/evmd" + local log_file="${home_dir}/evmd.log" + + # Compute display ports that init-files configure for single-host: + local rpc_port=$((26657 + i)) + local p2p_port=$((16656 + i)) + local api_port=$((1317 + i)) + local http_port=$((8545 + i*10)) + local ws_port=$((8546 + i*10)) + + log "Starting ${NODE_PREFIX}${i} (rpc:${rpc_port}, p2p:${p2p_port}, api:${api_port}, http:${http_port}, ws:${ws_port})" + + # Ensure client chain-id is set for this home (useful for CLI interactions) + "$BINARY" config set client chain-id "${CHAIN_ID}" --home "$home_dir" >/dev/null 2>&1 || true + + # Build start command (aligned with local_node.sh gas defaults) and echo it for reproducibility + cmd=("$BINARY" start \ + --home "$home_dir" \ + --minimum-gas-prices "${MIN_GAS_PRICES}" \ + --evm.min-tip 0 \ + --json-rpc.api "eth,txpool,personal,net,debug,web3" \ + --chain-id "${CHAIN_ID}") + + printf '[evmd-localnet] Exec: ' + for arg in "${cmd[@]}"; do printf '%s ' "$arg"; done; printf '\n' + + # Start in background, capture PID + ("${cmd[@]}" >"$log_file" 2>&1 & echo $! >> "$PID_FILE") + sleep 0.5 + done + + log "All nodes started. PIDs recorded in ${PID_FILE}" +} + +stop_nodes() { + if [ ! -f "$PID_FILE" ]; then + err "PID file not found: $PID_FILE" + exit 1 + fi + tac "$PID_FILE" | while read -r pid; do + if kill -0 "$pid" >/dev/null 2>&1; then + log "Stopping PID $pid" + kill "$pid" || true + fi + done + rm -f "$PID_FILE" + log "All nodes stopped." +} + +clean() { + if [ -d "$BASE_DIR" ]; then + log "Removing ${BASE_DIR}" + rm -rf "$BASE_DIR" + fi +} + +cmd=${1:-start} +case "$cmd" in + start) + ensure_binary + init_fresh + apply_surge_and_replicate + adjust_ports_single_host + tune_timeouts + adjust_memlogger + build_peers_if_possible + start_nodes + ;; + stop) + stop_nodes + ;; + clean) + clean + ;; + *) + echo "Usage: $0 {start|stop|clean}" >&2 + exit 1 + ;; +esac diff --git a/evmd_localnet_nomemlogger_info.sh b/evmd_localnet_nomemlogger_info.sh new file mode 100755 index 000000000..3c3bbc1d2 --- /dev/null +++ b/evmd_localnet_nomemlogger_info.sh @@ -0,0 +1,418 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Simple multi-node localnet launcher for evmd +# - Initializes N validator nodes under BASE_DIR using `evmd testnet init-files --validator-count N --keyring-backend test` +# - Applies surge faucet to node0 genesis, then replicates the modified genesis to all nodes +# - Optionally computes persistent_peers via `evmd comet show-node-id` if available +# - Starts each node with its own home and port set by init-files +# +# Usage: +# scripts/evmd-localnet.sh start # init (if needed) and start N nodes +# scripts/evmd-localnet.sh stop # stop nodes started by this script (via PID file) +# scripts/evmd-localnet.sh clean # remove BASE_DIR + +BINARY_DEFAULT="evmd" # or override via BINARY env +BASE_DIR_DEFAULT="./.testnets" # or override via BASE_DIR env +NODE_PREFIX_DEFAULT="node" +N_DEFAULT=4 +# Start defaults (min gas aligned with local_node.sh) +MIN_GAS_PRICES_DEFAULT="0atest" +SURGE_CMD_DEFAULT="surge faucet" # or override via SURGE_CMD env; extra args via SURGE_ARGS +CHAIN_ID_DEFAULT="local-4221" # or override via CHAIN_ID env +SINGLE_HOST_DEFAULT="true" # allocate unique ports per node on one host +STARTING_IP_DEFAULT="127.0.0.1" # starting IP for init-files on single host + +# Derive settings from env or defaults +BINARY=${BINARY:-$BINARY_DEFAULT} +BASE_DIR=${BASE_DIR:-$BASE_DIR_DEFAULT} +NODE_PREFIX=${NODE_PREFIX:-$NODE_PREFIX_DEFAULT} +N=${N:-$N_DEFAULT} +MIN_GAS_PRICES=${MIN_GAS_PRICES:-$MIN_GAS_PRICES_DEFAULT} +SURGE_CMD=${SURGE_CMD:-$SURGE_CMD_DEFAULT} +SURGE_ARGS=${SURGE_ARGS:-} +CHAIN_ID=${CHAIN_ID:-$CHAIN_ID_DEFAULT} +SINGLE_HOST=${SINGLE_HOST:-$SINGLE_HOST_DEFAULT} +STARTING_IP_ADDRESS=${STARTING_IP_ADDRESS:-$STARTING_IP_DEFAULT} + +# Internal +PID_FILE="${BASE_DIR}/evmd_localnet.pids" + +log() { echo "[evmd-localnet] $*"; } +err() { echo "[evmd-localnet:ERROR] $*" >&2; } + +ensure_binary() { + if command -v "$BINARY" >/dev/null 2>&1; then + return 0 + fi + # Fallback to local build path + if [ -x "./build/evmd" ]; then + BINARY="./build/evmd" + return 0 + fi + err "Cannot find evmd binary. Put it on PATH or build via 'make build'." + exit 1 +} + +init_fresh() { + # Always initialize a fresh testnet as requested + rm -rf "$BASE_DIR" + log "Initializing ${N}-node testnet at ${BASE_DIR}…" + mkdir -p "$BASE_DIR" + + # Per request: use only validator-count and keyring-backend flags (+ output-dir to control location) + local cmd=("$BINARY" testnet init-files \ + --validator-count "${N}" \ + --keyring-backend test \ + --output-dir "${BASE_DIR}") + + # Add chain-id if supported by the subcommand + if "$BINARY" testnet init-files --help 2>/dev/null | grep -q -- "--chain-id"; then + cmd+=(--chain-id "${CHAIN_ID}") + fi + # Use single-host ports from generator if supported + if [ "${SINGLE_HOST}" = "true" ] && "$BINARY" testnet init-files --help 2>/dev/null | grep -q -- "--single-host"; then + cmd+=(--single-host=true) + fi + # Set starting IP address if supported (helps ensure 127.0.0.1 mapping) + if [ "${SINGLE_HOST}" = "true" ] && "$BINARY" testnet init-files --help 2>/dev/null | grep -q -- "--starting-ip-address"; then + cmd+=(--starting-ip-address "${STARTING_IP_ADDRESS}") + fi + + printf '[evmd-localnet] Exec: ' + for a in "${cmd[@]}"; do printf '%s ' "$a"; done; printf '\n' + "${cmd[@]}" + + log "Init complete (chain-id: ${CHAIN_ID}). Genesis and configs under ${BASE_DIR}/${NODE_PREFIX}{0..$((N-1))}/evmd" + + # Fallback: if init-files doesn't support --chain-id, patch genesis chain_id via jq + if ! "$BINARY" testnet init-files --help 2>/dev/null | grep -q -- "--chain-id"; then + if command -v jq >/dev/null 2>&1; then + for ((i=0; i< N; i++)); do + gi="${BASE_DIR}/${NODE_PREFIX}${i}/evmd/config/genesis.json" + if [ -f "$gi" ]; then + tmp="$gi.tmp" && jq --arg cid "$CHAIN_ID" '.chain_id=$cid' "$gi" > "$tmp" && mv "$tmp" "$gi" + fi + done + log "Patched genesis chain_id to '${CHAIN_ID}' via jq (fallback path)." + else + log "jq not found; cannot patch genesis chain_id. Using defaults from init-files." + fi + fi +} + +# Update per-node ports for single host to avoid conflicts +adjust_ports_single_host() { + if [ "${SINGLE_HOST}" != "true" ]; then + log "SINGLE_HOST is not enabled; skipping port adjustments." + return 0 + fi + + # Helper to set a key inside a specific TOML section + toml_set_key_in_section() { + local file="$1" section="$2" key="$3" value="$4" + awk -v section="$section" -v key="$key" -v value="$value" ' + BEGIN { insec=0; done=0 } + /^[[:space:]]*\[/ { + if (insec && !done) { print key " = \"" value "\""; done=1 } + insec=0 + if ($0 ~ "^\\[" section "\\]") { insec=1 } + print; next + } + { + if (insec && $0 ~ "^[[:space:]]*" key "[[:space:]]*=") { + print key " = \"" value "\""; done=1; next + } + print + } + END { + if (insec && !done) { print key " = \"" value "\"" } + } + ' "$file" >"$file.tmp" && mv "$file.tmp" "$file" + } + + for ((i=0; i< N; i++)); do + local home_dir="${BASE_DIR}/${NODE_PREFIX}${i}/evmd" + local cfg_tm="${home_dir}/config/config.toml" + local cfg_app="${home_dir}/config/app.toml" + + [ -f "$cfg_tm" ] || { err "Missing $cfg_tm"; continue; } + [ -f "$cfg_app" ] || { err "Missing $cfg_app"; continue; } + + # Compute unique ports + local rpc_port=$((26657 + i)) + local p2p_port=$((16656 + i)) + local pprof_port=$((6060 + i)) + local prom_port=$((26660 + i)) + local api_port=$((1317 + i)) + local grpc_port=$((9090 + i)) + local grpcweb_port=$((9091 + i)) + local http_port=$((8545 + i*10)) + local ws_port=$((8546 + i*10)) + + # Tendermint config.toml + toml_set_key_in_section "$cfg_tm" "rpc" "laddr" "tcp://127.0.0.1:${rpc_port}" + toml_set_key_in_section "$cfg_tm" "rpc" "pprof_laddr" "localhost:${pprof_port}" + toml_set_key_in_section "$cfg_tm" "p2p" "laddr" "tcp://127.0.0.1:${p2p_port}" + toml_set_key_in_section "$cfg_tm" "instrumentation" "prometheus_listen_addr" ":${prom_port}" + + # Application app.toml + toml_set_key_in_section "$cfg_app" "api" "address" "tcp://127.0.0.1:${api_port}" + toml_set_key_in_section "$cfg_app" "grpc" "address" "127.0.0.1:${grpc_port}" + toml_set_key_in_section "$cfg_app" "grpc-web" "address" "127.0.0.1:${grpcweb_port}" + toml_set_key_in_section "$cfg_app" "json-rpc" "address" "127.0.0.1:${http_port}" + toml_set_key_in_section "$cfg_app" "json-rpc" "ws-address" "127.0.0.1:${ws_port}" + + log "Configured ${NODE_PREFIX}${i} ports: rpc:${rpc_port} p2p:${p2p_port} api:${api_port} http:${http_port} ws:${ws_port} grpc:${grpc_port}/${grpcweb_port}" + done +} + +# Apply consensus timeout adjustments similar to local_node.sh +tune_timeouts() { + for ((i=0; i< N; i++)); do + local CONFIG_TOML="${BASE_DIR}/${NODE_PREFIX}${i}/evmd/config/config.toml" + if [ ! -f "$CONFIG_TOML" ]; then + err "Missing $CONFIG_TOML" + continue + fi + # Logging: debug level and json format + sed -i.bak 's/log_format = "plain"/log_format = "json"/g' "$CONFIG_TOML" + sed -i.bak 's/timeout_propose = "3s"/timeout_propose = "2s"/g' "$CONFIG_TOML" + sed -i.bak 's/timeout_propose_delta = "500ms"/timeout_propose_delta = "200ms"/g' "$CONFIG_TOML" + sed -i.bak 's/timeout_prevote = "1s"/timeout_prevote = "500ms"/g' "$CONFIG_TOML" + sed -i.bak 's/timeout_prevote_delta = "500ms"/timeout_prevote_delta = "200ms"/g' "$CONFIG_TOML" + sed -i.bak 's/timeout_precommit = "1s"/timeout_precommit = "500ms"/g' "$CONFIG_TOML" + sed -i.bak 's/timeout_precommit_delta = "500ms"/timeout_precommit_delta = "200ms"/g' "$CONFIG_TOML" + sed -i.bak 's/timeout_commit = "5s"/timeout_commit = "1s"/g' "$CONFIG_TOML" + sed -i.bak 's/timeout_broadcast_tx_commit = "10s"/timeout_broadcast_tx_commit = "5s"/g' "$CONFIG_TOML" + done + log "Applied consensus timeout adjustments to all nodes." +} + +# Adjust memlogger settings in app.toml for each node +adjust_memlogger() { + for ((i=0; i< N; i++)); do + local APP_TOML="${BASE_DIR}/${NODE_PREFIX}${i}/evmd/config/app.toml" + if [ ! -f "$APP_TOML" ]; then + err "Missing $APP_TOML" + continue + fi + + # Helpers local to this function + toml_set_key_in_section() { + local file="$1" section="$2" key="$3" value="$4" + awk -v section="$section" -v key="$key" -v value="$value" ' + BEGIN { insec=0; done=0 } + /^[[:space:]]*\[/ { + if (insec && !done) { print key " = \"" value "\""; done=1 } + insec=0 + if ($0 ~ "^\\[" section "\\]") { insec=1 } + print; next + } + { + if (insec && $0 ~ "^[[:space:]]*" key "[[:space:]]*=") { + print key " = \"" value "\""; done=1; next + } + print + } + END { + if (insec && !done) { print key " = \"" value "\"" } + } + ' "$file" >"$file.tmp" && mv "$file.tmp" "$file" + } + + toml_set_key_in_section_raw() { + local file="$1" section="$2" key="$3" rawvalue="$4" + awk -v section="$section" -v key="$key" -v rawvalue="$rawvalue" ' + BEGIN { insec=0; done=0 } + /^[[:space:]]*\[/ { + if (insec && !done) { print key " = " rawvalue; done=1 } + insec=0 + if ($0 ~ "^\\[" section "\\]") { insec=1 } + print; next + } + { + if (insec && $0 ~ "^[[:space:]]*" key "[[:space:]]*=") { + print key " = " rawvalue; done=1; next + } + print + } + END { + if (insec && !done) { print key " = " rawvalue } + } + ' "$file" >"$file.tmp" && mv "$file.tmp" "$file" + } + + # disable + toml_set_key_in_section "$APP_TOML" "memlogger" "enabled" "false" + # interval: set to 3m (string) + toml_set_key_in_section "$APP_TOML" "memlogger" "interval" "3m" + # max-bytes: set to 2GB (2147483648) numeric + toml_set_key_in_section_raw "$APP_TOML" "memlogger" "max-bytes" "2147483648" + + log "Adjusted memlogger for ${NODE_PREFIX}${i}: interval=3m, max-bytes=2147483648" + done +} + +apply_surge_and_replicate() { + # Apply surge faucet on node0 genesis, then copy to other nodes + local g0="${BASE_DIR}/${NODE_PREFIX}0/evmd/config/genesis.json" + if [ ! -f "$g0" ]; then + err "node0 genesis not found at $g0" + exit 1 + fi + + # Run surge faucet if available/desired + if [ -n "$SURGE_CMD" ]; then + local surge_bin + surge_bin=$(echo "$SURGE_CMD" | awk '{print $1}') + if ! command -v "$surge_bin" >/dev/null 2>&1; then + err "'$surge_bin' not found on PATH. Set SURGE_CMD='' to skip or install surge." + exit 1 + fi + # Echo the exact command + printf '[evmd-localnet] Exec: %s %s %s\n' "$SURGE_CMD" "${SURGE_ARGS}" "$g0" + # Execute with optional extra args + eval "$SURGE_CMD ${SURGE_ARGS} $g0" + else + log "SURGE_CMD empty; skipping surge faucet step." + fi + + # Replicate node0 genesis to all other nodes + for ((i=1; i< N; i++)); do + local gi="${BASE_DIR}/${NODE_PREFIX}${i}/evmd/config/genesis.json" + if [ -f "$gi" ]; then + cp "$g0" "$gi" + fi + done + + # Validate genesis for all nodes (best-effort) + for ((i=0; i< N; i++)); do + local home_dir="${BASE_DIR}/${NODE_PREFIX}${i}/evmd" + if [ -d "$home_dir" ]; then + "$BINARY" genesis validate-genesis --home "$home_dir" >/dev/null 2>&1 || true + fi + done +} + +build_peers_if_possible() { + # Try to gather node IDs using `evmd comet show-node-id` if the subcommand exists. + if ! "$BINARY" comet --help >/dev/null 2>&1; then + log "'evmd comet' subcommand not found. Skipping persistent_peers injection (nodes should still connect with generated configs)." + return 0 + fi + + local peers="" + for ((i=0; i< N; i++)); do + local home_dir="${BASE_DIR}/${NODE_PREFIX}${i}/evmd" + local id + if ! id=$("$BINARY" comet show-node-id --home "$home_dir" 2>/dev/null); then + err "Failed to read node ID for ${NODE_PREFIX}${i}; skipping persistent_peers." + return 0 + fi + # Ports per init-files when --single-host is used: + # - P2P starts at 16656 and increments by +1 per node + local p2p_port=$((16656 + i)) + local entry="${id}@127.0.0.1:${p2p_port}" + if [ -z "$peers" ]; then peers="$entry"; else peers+="",$entry; fi + done + + log "persistent_peers=${peers}" + # Inject into each node's config.toml + for ((i=0; i< N; i++)); do + local cfg="${BASE_DIR}/${NODE_PREFIX}${i}/evmd/config/config.toml" + if [ -f "$cfg" ]; then + # Replace existing line or append if missing + if grep -q '^persistent_peers\s*=\s*"' "$cfg"; then + sed -i.bak -E "s|^persistent_peers\s*=\s*\".*\"|persistent_peers = \"${peers}\"|" "$cfg" + else + echo "persistent_peers = \"${peers}\"" >> "$cfg" + fi + fi + done +} + +start_nodes() { + mkdir -p "$(dirname "$PID_FILE")" + : > "$PID_FILE" + + for ((i=0; i< N; i++)); do + local home_dir="${BASE_DIR}/${NODE_PREFIX}${i}/evmd" + local log_file="${home_dir}/evmd.log" + + # Compute display ports that init-files configure for single-host: + local rpc_port=$((26657 + i)) + local p2p_port=$((16656 + i)) + local api_port=$((1317 + i)) + local http_port=$((8545 + i*10)) + local ws_port=$((8546 + i*10)) + + log "Starting ${NODE_PREFIX}${i} (rpc:${rpc_port}, p2p:${p2p_port}, api:${api_port}, http:${http_port}, ws:${ws_port})" + + # Ensure client chain-id is set for this home (useful for CLI interactions) + "$BINARY" config set client chain-id "${CHAIN_ID}" --home "$home_dir" >/dev/null 2>&1 || true + + # Build start command (aligned with local_node.sh gas defaults) and echo it for reproducibility + cmd=("$BINARY" start \ + --home "$home_dir" \ + --minimum-gas-prices "${MIN_GAS_PRICES}" \ + --evm.min-tip 0 \ + --json-rpc.api "eth,txpool,personal,net,debug,web3" \ + --chain-id "${CHAIN_ID}") + + printf '[evmd-localnet] Exec: ' + for arg in "${cmd[@]}"; do printf '%s ' "$arg"; done; printf '\n' + + # Start in background, capture PID + ("${cmd[@]}" >"$log_file" 2>&1 & echo $! >> "$PID_FILE") + sleep 0.5 + done + + log "All nodes started. PIDs recorded in ${PID_FILE}" +} + +stop_nodes() { + if [ ! -f "$PID_FILE" ]; then + err "PID file not found: $PID_FILE" + exit 1 + fi + tac "$PID_FILE" | while read -r pid; do + if kill -0 "$pid" >/dev/null 2>&1; then + log "Stopping PID $pid" + kill "$pid" || true + fi + done + rm -f "$PID_FILE" + log "All nodes stopped." +} + +clean() { + if [ -d "$BASE_DIR" ]; then + log "Removing ${BASE_DIR}" + rm -rf "$BASE_DIR" + fi +} + +cmd=${1:-start} +case "$cmd" in + start) + ensure_binary + init_fresh + apply_surge_and_replicate + adjust_ports_single_host + tune_timeouts + adjust_memlogger + build_peers_if_possible + start_nodes + ;; + stop) + stop_nodes + ;; + clean) + clean + ;; + *) + echo "Usage: $0 {start|stop|clean}" >&2 + exit 1 + ;; +esac From 7481cea09564c126c01f7e7b983bbad4a8d5b58e Mon Sep 17 00:00:00 2001 From: zsystm Date: Sat, 1 Nov 2025 23:53:23 +0900 Subject: [PATCH 10/22] applying changed config from memlogger --- evmd_localnet_memlogger.sh | 6 +++--- evmd_localnet_nomemlogger.sh | 6 ------ evmd_localnet_nomemlogger_info.sh | 6 ------ 3 files changed, 3 insertions(+), 15 deletions(-) diff --git a/evmd_localnet_memlogger.sh b/evmd_localnet_memlogger.sh index 1ec10ebf7..67c766209 100755 --- a/evmd_localnet_memlogger.sh +++ b/evmd_localnet_memlogger.sh @@ -247,11 +247,11 @@ adjust_memlogger() { # enable memlogger toml_set_key_in_section "$APP_TOML" "memlogger" "enabled" "true" # interval: set to 3m (string) - toml_set_key_in_section "$APP_TOML" "memlogger" "interval" "3m" + toml_set_key_in_section "$APP_TOML" "memlogger" "interval" "1m" # max-bytes: set to 2GB (2147483648) numeric - toml_set_key_in_section_raw "$APP_TOML" "memlogger" "max-bytes" "2147483648" + toml_set_key_in_section_raw "$APP_TOML" "memlogger" "memory-bytes" "2147483648" - log "Adjusted memlogger for ${NODE_PREFIX}${i}: interval=3m, max-bytes=2147483648" + log "Adjusted memlogger for ${NODE_PREFIX}${i}: interval=3m, memory-bytes=2147483648" done } diff --git a/evmd_localnet_nomemlogger.sh b/evmd_localnet_nomemlogger.sh index 76316de0a..0de6dc5e6 100755 --- a/evmd_localnet_nomemlogger.sh +++ b/evmd_localnet_nomemlogger.sh @@ -246,12 +246,6 @@ adjust_memlogger() { # disable toml_set_key_in_section "$APP_TOML" "memlogger" "enabled" "false" - # interval: set to 3m (string) - toml_set_key_in_section "$APP_TOML" "memlogger" "interval" "3m" - # max-bytes: set to 2GB (2147483648) numeric - toml_set_key_in_section_raw "$APP_TOML" "memlogger" "max-bytes" "2147483648" - - log "Adjusted memlogger for ${NODE_PREFIX}${i}: interval=3m, max-bytes=2147483648" done } diff --git a/evmd_localnet_nomemlogger_info.sh b/evmd_localnet_nomemlogger_info.sh index 3c3bbc1d2..5aae2e134 100755 --- a/evmd_localnet_nomemlogger_info.sh +++ b/evmd_localnet_nomemlogger_info.sh @@ -245,12 +245,6 @@ adjust_memlogger() { # disable toml_set_key_in_section "$APP_TOML" "memlogger" "enabled" "false" - # interval: set to 3m (string) - toml_set_key_in_section "$APP_TOML" "memlogger" "interval" "3m" - # max-bytes: set to 2GB (2147483648) numeric - toml_set_key_in_section_raw "$APP_TOML" "memlogger" "max-bytes" "2147483648" - - log "Adjusted memlogger for ${NODE_PREFIX}${i}: interval=3m, max-bytes=2147483648" done } From 8431f61dc69ff763b7f0eef7bd4e7a1107a477a2 Mon Sep 17 00:00:00 2001 From: zsystm Date: Sun, 2 Nov 2025 11:18:25 +0900 Subject: [PATCH 11/22] update dep & testing script --- evmd/go.mod | 17 +- evmd/go.sum | 36 ++-- evmd_localnet_memlogger.sh | 8 +- go.mod | 17 +- go.sum | 36 ++-- local_node.sh | 348 ------------------------------------- 6 files changed, 51 insertions(+), 411 deletions(-) delete mode 100755 local_node.sh diff --git a/evmd/go.mod b/evmd/go.mod index 48c408d70..e07aac452 100644 --- a/evmd/go.mod +++ b/evmd/go.mod @@ -79,7 +79,7 @@ require ( github.com/cockroachdb/pebble v1.1.5 // indirect github.com/cockroachdb/redact v1.1.6 // indirect github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect - github.com/cometbft/cometbft-db v0.14.1 // indirect + github.com/cometbft/cometbft-db v1.0.1 // indirect github.com/consensys/gnark-crypto v0.18.0 // indirect github.com/cosmos/btcutil v1.0.5 // indirect github.com/cosmos/cosmos-proto v1.0.0-beta.5 // indirect @@ -97,8 +97,8 @@ require ( github.com/deckarep/golang-set/v2 v2.6.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect github.com/desertbit/timer v1.0.1 // indirect - github.com/dgraph-io/badger/v4 v4.2.0 // indirect - github.com/dgraph-io/ristretto v0.1.1 // indirect + github.com/dgraph-io/badger/v4 v4.5.1 // indirect + github.com/dgraph-io/ristretto/v2 v2.1.0 // indirect github.com/dlclark/regexp2 v1.7.0 // indirect github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 // indirect github.com/dustin/go-humanize v1.0.1 // indirect @@ -127,12 +127,11 @@ require ( github.com/gofrs/flock v0.12.1 // indirect github.com/gogo/googleapis v1.4.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/glog v1.2.5 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.5-0.20231225225746-43d5d4cd4e0e // indirect github.com/google/btree v1.1.3 // indirect - github.com/google/flatbuffers v24.3.25+incompatible // indirect + github.com/google/flatbuffers v24.12.23+incompatible // indirect github.com/google/go-cmp v0.7.0 // indirect github.com/google/orderedcode v0.0.1 // indirect github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect @@ -173,7 +172,7 @@ require ( github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/lib/pq v1.10.9 // indirect - github.com/linxGnu/grocksdb v1.9.2 // indirect + github.com/linxGnu/grocksdb v1.9.3 // indirect github.com/manifoldco/promptui v0.9.0 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect @@ -272,10 +271,12 @@ require ( ) replace ( - cosmossdk.io/log => github.com/zsystm/cosmos-sdk/log v0.0.0-20251019213021-f40f441db0f0 + cosmossdk.io/log => github.com/bft-labs/cosmos-sdk/log v1.5.2-0.20251108150151-281dceda5730 + cosmossdk.io/store => github.com/bft-labs/cosmos-sdk/store v1.10.0-rc.1.0.20251108150151-281dceda5730 + // use cosmos fork of keyring github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0 - github.com/cosmos/cosmos-sdk => github.com/zsystm/cosmos-sdk v0.53.4-memlogger-0 + github.com/cosmos/cosmos-sdk => github.com/bft-labs/cosmos-sdk v0.53.4-memlogger-4 github.com/cosmos/evm => ../ // use Cosmos geth fork // branch: release/1.16 diff --git a/evmd/go.sum b/evmd/go.sum index 057f559cf..de2374cac 100644 --- a/evmd/go.sum +++ b/evmd/go.sum @@ -630,8 +630,6 @@ cosmossdk.io/math v1.5.3 h1:WH6tu6Z3AUCeHbeOSHg2mt9rnoiUWVWaQ2t6Gkll96U= cosmossdk.io/math v1.5.3/go.mod h1:uqcZv7vexnhMFJF+6zh9EWdm/+Ylyln34IvPnBauPCQ= cosmossdk.io/schema v1.1.0 h1:mmpuz3dzouCoyjjcMcA/xHBEmMChN+EHh8EHxHRHhzE= cosmossdk.io/schema v1.1.0/go.mod h1:Gb7pqO+tpR+jLW5qDcNOSv0KtppYs7881kfzakguhhI= -cosmossdk.io/store v1.1.2 h1:3HOZG8+CuThREKv6cn3WSohAc6yccxO3hLzwK6rBC7o= -cosmossdk.io/store v1.1.2/go.mod h1:60rAGzTHevGm592kFhiUVkNC9w7gooSEn5iUBPzHQ6A= cosmossdk.io/tools/confix v0.1.2 h1:2hoM1oFCNisd0ltSAAZw2i4ponARPmlhuNu3yy0VwI4= cosmossdk.io/tools/confix v0.1.2/go.mod h1:7XfcbK9sC/KNgVGxgLM0BrFbVcR/+6Dg7MFfpx7duYo= cosmossdk.io/x/evidence v0.2.0 h1:o72zbmgCM7U0v7z7b0XnMB+NqX0tFamqb1HHkQbhrZ0= @@ -719,6 +717,12 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bft-labs/cosmos-sdk v0.53.4-memlogger-4 h1:rw+QqieYGCALStm7c3bAhz62PDQFy0JvI2+dkf0EQgI= +github.com/bft-labs/cosmos-sdk v0.53.4-memlogger-4/go.mod h1:6k6Po9k9tVsUCRsnjpL6kGzTqjPnwgabQg8htKRMtVc= +github.com/bft-labs/cosmos-sdk/log v1.5.2-0.20251108150151-281dceda5730 h1:9miML98CAFnuMQfP3tcblxDqdQKnE2FqpLbyaajhnEA= +github.com/bft-labs/cosmos-sdk/log v1.5.2-0.20251108150151-281dceda5730/go.mod h1:DNJwlhYlZOlSePMdymnpTcI8XDar9qn+m8o1fJC7olc= +github.com/bft-labs/cosmos-sdk/store v1.10.0-rc.1.0.20251108150151-281dceda5730 h1:VZZ0mdooD1YgZiEv/qJYJVdo6ErekQd9WRvbyESBSCo= +github.com/bft-labs/cosmos-sdk/store v1.10.0-rc.1.0.20251108150151-281dceda5730/go.mod h1:7a15p+QsM5UXf7VMhO3ylmqj85k9UBN/h1kwMcLiffA= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= @@ -837,8 +841,8 @@ github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1: github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/cometbft/cometbft v0.38.18 h1:1ZHYMdu0S75YxFM13LlPXnOwiIpUW5z9TKMQtTIALpw= github.com/cometbft/cometbft v0.38.18/go.mod h1:PlOQgf3jQorep+g6oVnJgtP65TJvBJoLiXjGaMdNxBE= -github.com/cometbft/cometbft-db v0.14.1 h1:SxoamPghqICBAIcGpleHbmoPqy+crij/++eZz3DlerQ= -github.com/cometbft/cometbft-db v0.14.1/go.mod h1:KHP1YghilyGV/xjD5DP3+2hyigWx0WTp9X+0Gnx0RxQ= +github.com/cometbft/cometbft-db v1.0.1 h1:SylKuLseMLQKw3+i8y8KozZyJcQSL98qEe2CGMCGTYE= +github.com/cometbft/cometbft-db v1.0.1/go.mod h1:EBrFs1GDRiTqrWXYi4v90Awf/gcdD5ExzdPbg4X8+mk= github.com/consensys/gnark-crypto v0.18.0 h1:vIye/FqI50VeAr0B3dx+YjeIvmc3LWz4yEfbWBpTUf0= github.com/consensys/gnark-crypto v0.18.0/go.mod h1:L3mXGFTe1ZN+RSJ+CLjUt9x7PNdx8ubaYfDROyp2Z8c= github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= @@ -908,12 +912,11 @@ github.com/deepmap/oapi-codegen v1.6.0/go.mod h1:ryDa9AgbELGeB+YEXE1dR53yAjHwFvE github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= github.com/desertbit/timer v1.0.1 h1:yRpYNn5Vaaj6QXecdLMPMJsW81JLiI1eokUft5nBmeo= github.com/desertbit/timer v1.0.1/go.mod h1:htRrYeY5V/t4iu1xCJ5XsQvp4xve8QulXXctAzxqcwE= -github.com/dgraph-io/badger/v4 v4.2.0 h1:kJrlajbXXL9DFTNuhhu9yCx7JJa4qpYWxtE8BzuWsEs= -github.com/dgraph-io/badger/v4 v4.2.0/go.mod h1:qfCqhPoWDFJRx1gp5QwwyGo8xk1lbHUxvK9nK0OGAak= -github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= -github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= +github.com/dgraph-io/badger/v4 v4.5.1 h1:7DCIXrQjo1LKmM96YD+hLVJ2EEsyyoWxJfpdd56HLps= +github.com/dgraph-io/badger/v4 v4.5.1/go.mod h1:qn3Be0j3TfV4kPbVoK0arXCD1/nr1ftth6sbL5jxdoA= +github.com/dgraph-io/ristretto/v2 v2.1.0 h1:59LjpOJLNDULHh8MC4UaegN52lC4JnO2dITsie/Pa8I= +github.com/dgraph-io/ristretto/v2 v2.1.0/go.mod h1:uejeqfYXpUomfse0+lO+13ATz4TypQYLJZzBSAemuB4= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= @@ -1072,8 +1075,6 @@ github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGw github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= -github.com/golang/glog v1.2.5 h1:DrW6hGnjIhtvhOIiAKT6Psh/Kd/ldepEa81DKeiRJ5I= -github.com/golang/glog v1.2.5/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -1121,8 +1122,8 @@ github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/flatbuffers v2.0.8+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= -github.com/google/flatbuffers v24.3.25+incompatible h1:CX395cjN9Kke9mmalRoL3d81AtFUxJM+yDthflgJGkI= -github.com/google/flatbuffers v24.3.25+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/flatbuffers v24.12.23+incompatible h1:ubBKR94NR4pXUCY/MUsRVzd9umNW7ht7EG9hHfS9FX8= +github.com/google/flatbuffers v24.12.23+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -1383,8 +1384,8 @@ github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= -github.com/linxGnu/grocksdb v1.9.2 h1:O3mzvO0wuzQ9mtlHbDrShixyVjVbmuqTjFrzlf43wZ8= -github.com/linxGnu/grocksdb v1.9.2/go.mod h1:QYiYypR2d4v63Wj1adOOfzglnoII0gLj3PNh4fZkcFA= +github.com/linxGnu/grocksdb v1.9.3 h1:s1cbPcOd0cU2SKXRG1nEqCOWYAELQjdqg3RVI2MH9ik= +github.com/linxGnu/grocksdb v1.9.3/go.mod h1:QYiYypR2d4v63Wj1adOOfzglnoII0gLj3PNh4fZkcFA= github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= github.com/lyft/protoc-gen-star/v2 v2.0.1/go.mod h1:RcCdONR2ScXaYnQC5tUzxzlpA3WVYF7/opLeUgcQs/o= @@ -1734,10 +1735,6 @@ github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw= github.com/zondax/ledger-go v0.14.3/go.mod h1:IKKaoxupuB43g4NxeQmbLXv7T9AlQyie1UpHb342ycI= -github.com/zsystm/cosmos-sdk v0.53.4-memlogger-0 h1:4QjE/QAgJ8IJ/Zn0C6ESMDii0DToX9tslx2X6e+g4QM= -github.com/zsystm/cosmos-sdk v0.53.4-memlogger-0/go.mod h1:6k6Po9k9tVsUCRsnjpL6kGzTqjPnwgabQg8htKRMtVc= -github.com/zsystm/cosmos-sdk/log v0.0.0-20251019213021-f40f441db0f0 h1:7w+7l0s/NKC596WeizLvwuMFBKUgHp9rpUVKQpe7hJY= -github.com/zsystm/cosmos-sdk/log v0.0.0-20251019213021-f40f441db0f0/go.mod h1:DNJwlhYlZOlSePMdymnpTcI8XDar9qn+m8o1fJC7olc= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.4.0-alpha.1 h1:3yrqQzbRRPFPdOMWS/QQIVxVnzSkAZQYeWlZFv1kbj4= go.etcd.io/bbolt v1.4.0-alpha.1/go.mod h1:S/Z/Nm3iuOnyO1W4XuFfPci51Gj6F1Hv0z8hisyYYOw= @@ -2122,7 +2119,6 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/evmd_localnet_memlogger.sh b/evmd_localnet_memlogger.sh index 67c766209..eae9ead38 100755 --- a/evmd_localnet_memlogger.sh +++ b/evmd_localnet_memlogger.sh @@ -246,12 +246,8 @@ adjust_memlogger() { # enable memlogger toml_set_key_in_section "$APP_TOML" "memlogger" "enabled" "true" - # interval: set to 3m (string) - toml_set_key_in_section "$APP_TOML" "memlogger" "interval" "1m" - # max-bytes: set to 2GB (2147483648) numeric - toml_set_key_in_section_raw "$APP_TOML" "memlogger" "memory-bytes" "2147483648" - - log "Adjusted memlogger for ${NODE_PREFIX}${i}: interval=3m, memory-bytes=2147483648" + toml_set_key_in_section "$APP_TOML" "memlogger" "interval" "2s" + toml_set_key_in_section_raw "$APP_TOML" "memlogger" "memory-bytes" "104857600" done } diff --git a/go.mod b/go.mod index 9c27b9802..d87b32f23 100644 --- a/go.mod +++ b/go.mod @@ -35,7 +35,7 @@ require ( github.com/hashicorp/go-metrics v0.5.4 github.com/holiman/uint256 v1.3.2 github.com/improbable-eng/grpc-web v0.15.0 - github.com/linxGnu/grocksdb v1.9.2 + github.com/linxGnu/grocksdb v1.9.3 github.com/onsi/ginkgo/v2 v2.23.4 github.com/onsi/gomega v1.38.0 github.com/pkg/errors v0.9.1 @@ -103,7 +103,7 @@ require ( github.com/cockroachdb/pebble v1.1.5 // indirect github.com/cockroachdb/redact v1.1.6 // indirect github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect - github.com/cometbft/cometbft-db v0.14.1 // indirect + github.com/cometbft/cometbft-db v1.0.1 // indirect github.com/consensys/gnark-crypto v0.18.0 // indirect github.com/cosmos/btcutil v1.0.5 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect @@ -117,8 +117,8 @@ require ( github.com/deckarep/golang-set/v2 v2.6.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect github.com/desertbit/timer v1.0.1 // indirect - github.com/dgraph-io/badger/v4 v4.2.0 // indirect - github.com/dgraph-io/ristretto v0.1.1 // indirect + github.com/dgraph-io/badger/v4 v4.5.1 // indirect + github.com/dgraph-io/ristretto/v2 v2.1.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/dvsekhvalnov/jose2go v1.7.0 // indirect github.com/emicklei/dot v1.6.2 // indirect @@ -143,11 +143,10 @@ require ( github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gofrs/flock v0.12.1 // indirect github.com/gogo/googleapis v1.4.1 // indirect - github.com/golang/glog v1.2.5 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/snappy v0.0.5-0.20231225225746-43d5d4cd4e0e // indirect github.com/google/btree v1.1.3 // indirect - github.com/google/flatbuffers v24.3.25+incompatible // indirect + github.com/google/flatbuffers v24.12.23+incompatible // indirect github.com/google/go-cmp v0.7.0 // indirect github.com/google/orderedcode v0.0.1 // indirect github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect @@ -268,11 +267,11 @@ require ( ) replace ( - cosmossdk.io/log => github.com/zsystm/cosmos-sdk/log v0.0.0-20251019213021-f40f441db0f0 + cosmossdk.io/log => github.com/bft-labs/cosmos-sdk/log v1.5.2-0.20251102063934-dab46c0df9d1 + // use cosmos fork of keyring github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0 - github.com/cometbft/cometbft => github.com/zsystm/cometbft v0.38.20-0.20251019013026-68caee7dcb2f - github.com/cosmos/cosmos-sdk => github.com/zsystm/cosmos-sdk v0.53.4-memlogger-0 + github.com/cosmos/cosmos-sdk => github.com/bft-labs/cosmos-sdk v0.53.4-memlogger-4 // use Cosmos geth fork // branch: release/1.16 github.com/ethereum/go-ethereum => github.com/cosmos/go-ethereum v1.16.2-cosmos-1 diff --git a/go.sum b/go.sum index b8dd6b99b..5189a00aa 100644 --- a/go.sum +++ b/go.sum @@ -719,6 +719,10 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bft-labs/cosmos-sdk v0.53.4-memlogger-4 h1:rw+QqieYGCALStm7c3bAhz62PDQFy0JvI2+dkf0EQgI= +github.com/bft-labs/cosmos-sdk v0.53.4-memlogger-4/go.mod h1:6k6Po9k9tVsUCRsnjpL6kGzTqjPnwgabQg8htKRMtVc= +github.com/bft-labs/cosmos-sdk/log v1.5.2-0.20251102063934-dab46c0df9d1 h1:PwAbsEgQ7WQpnJBNOQJMuFc84TLJzmC7bJpTaqrXNcE= +github.com/bft-labs/cosmos-sdk/log v1.5.2-0.20251102063934-dab46c0df9d1/go.mod h1:DNJwlhYlZOlSePMdymnpTcI8XDar9qn+m8o1fJC7olc= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= @@ -832,8 +836,10 @@ github.com/cockroachdb/redact v1.1.6/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZ github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/cometbft/cometbft-db v0.14.1 h1:SxoamPghqICBAIcGpleHbmoPqy+crij/++eZz3DlerQ= -github.com/cometbft/cometbft-db v0.14.1/go.mod h1:KHP1YghilyGV/xjD5DP3+2hyigWx0WTp9X+0Gnx0RxQ= +github.com/cometbft/cometbft v0.38.18 h1:1ZHYMdu0S75YxFM13LlPXnOwiIpUW5z9TKMQtTIALpw= +github.com/cometbft/cometbft v0.38.18/go.mod h1:PlOQgf3jQorep+g6oVnJgtP65TJvBJoLiXjGaMdNxBE= +github.com/cometbft/cometbft-db v1.0.1 h1:SylKuLseMLQKw3+i8y8KozZyJcQSL98qEe2CGMCGTYE= +github.com/cometbft/cometbft-db v1.0.1/go.mod h1:EBrFs1GDRiTqrWXYi4v90Awf/gcdD5ExzdPbg4X8+mk= github.com/consensys/gnark-crypto v0.18.0 h1:vIye/FqI50VeAr0B3dx+YjeIvmc3LWz4yEfbWBpTUf0= github.com/consensys/gnark-crypto v0.18.0/go.mod h1:L3mXGFTe1ZN+RSJ+CLjUt9x7PNdx8ubaYfDROyp2Z8c= github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= @@ -903,12 +909,11 @@ github.com/deepmap/oapi-codegen v1.6.0/go.mod h1:ryDa9AgbELGeB+YEXE1dR53yAjHwFvE github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= github.com/desertbit/timer v1.0.1 h1:yRpYNn5Vaaj6QXecdLMPMJsW81JLiI1eokUft5nBmeo= github.com/desertbit/timer v1.0.1/go.mod h1:htRrYeY5V/t4iu1xCJ5XsQvp4xve8QulXXctAzxqcwE= -github.com/dgraph-io/badger/v4 v4.2.0 h1:kJrlajbXXL9DFTNuhhu9yCx7JJa4qpYWxtE8BzuWsEs= -github.com/dgraph-io/badger/v4 v4.2.0/go.mod h1:qfCqhPoWDFJRx1gp5QwwyGo8xk1lbHUxvK9nK0OGAak= -github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= -github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= +github.com/dgraph-io/badger/v4 v4.5.1 h1:7DCIXrQjo1LKmM96YD+hLVJ2EEsyyoWxJfpdd56HLps= +github.com/dgraph-io/badger/v4 v4.5.1/go.mod h1:qn3Be0j3TfV4kPbVoK0arXCD1/nr1ftth6sbL5jxdoA= +github.com/dgraph-io/ristretto/v2 v2.1.0 h1:59LjpOJLNDULHh8MC4UaegN52lC4JnO2dITsie/Pa8I= +github.com/dgraph-io/ristretto/v2 v2.1.0/go.mod h1:uejeqfYXpUomfse0+lO+13ATz4TypQYLJZzBSAemuB4= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= @@ -1057,8 +1062,6 @@ github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGw github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= -github.com/golang/glog v1.2.5 h1:DrW6hGnjIhtvhOIiAKT6Psh/Kd/ldepEa81DKeiRJ5I= -github.com/golang/glog v1.2.5/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -1106,8 +1109,8 @@ github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/flatbuffers v2.0.8+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= -github.com/google/flatbuffers v24.3.25+incompatible h1:CX395cjN9Kke9mmalRoL3d81AtFUxJM+yDthflgJGkI= -github.com/google/flatbuffers v24.3.25+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/flatbuffers v24.12.23+incompatible h1:ubBKR94NR4pXUCY/MUsRVzd9umNW7ht7EG9hHfS9FX8= +github.com/google/flatbuffers v24.12.23+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -1366,8 +1369,8 @@ github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= -github.com/linxGnu/grocksdb v1.9.2 h1:O3mzvO0wuzQ9mtlHbDrShixyVjVbmuqTjFrzlf43wZ8= -github.com/linxGnu/grocksdb v1.9.2/go.mod h1:QYiYypR2d4v63Wj1adOOfzglnoII0gLj3PNh4fZkcFA= +github.com/linxGnu/grocksdb v1.9.3 h1:s1cbPcOd0cU2SKXRG1nEqCOWYAELQjdqg3RVI2MH9ik= +github.com/linxGnu/grocksdb v1.9.3/go.mod h1:QYiYypR2d4v63Wj1adOOfzglnoII0gLj3PNh4fZkcFA= github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= github.com/lyft/protoc-gen-star/v2 v2.0.1/go.mod h1:RcCdONR2ScXaYnQC5tUzxzlpA3WVYF7/opLeUgcQs/o= @@ -1717,12 +1720,6 @@ github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw= github.com/zondax/ledger-go v0.14.3/go.mod h1:IKKaoxupuB43g4NxeQmbLXv7T9AlQyie1UpHb342ycI= -github.com/zsystm/cometbft v0.38.20-0.20251019013026-68caee7dcb2f h1:YX8QsgD87lIxbPPjVPkAn/VT1ErC17mCeDz2/Fmw7WE= -github.com/zsystm/cometbft v0.38.20-0.20251019013026-68caee7dcb2f/go.mod h1:UCu8dlHqvkAsmAFmWDRWNZJPlu6ya2fTWZlDrWsivwo= -github.com/zsystm/cosmos-sdk v0.53.4-memlogger-0 h1:4QjE/QAgJ8IJ/Zn0C6ESMDii0DToX9tslx2X6e+g4QM= -github.com/zsystm/cosmos-sdk v0.53.4-memlogger-0/go.mod h1:6k6Po9k9tVsUCRsnjpL6kGzTqjPnwgabQg8htKRMtVc= -github.com/zsystm/cosmos-sdk/log v0.0.0-20251019213021-f40f441db0f0 h1:7w+7l0s/NKC596WeizLvwuMFBKUgHp9rpUVKQpe7hJY= -github.com/zsystm/cosmos-sdk/log v0.0.0-20251019213021-f40f441db0f0/go.mod h1:DNJwlhYlZOlSePMdymnpTcI8XDar9qn+m8o1fJC7olc= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.4.0-alpha.1 h1:3yrqQzbRRPFPdOMWS/QQIVxVnzSkAZQYeWlZFv1kbj4= go.etcd.io/bbolt v1.4.0-alpha.1/go.mod h1:S/Z/Nm3iuOnyO1W4XuFfPci51Gj6F1Hv0z8hisyYYOw= @@ -2107,7 +2104,6 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/local_node.sh b/local_node.sh deleted file mode 100755 index a7e410825..000000000 --- a/local_node.sh +++ /dev/null @@ -1,348 +0,0 @@ -#!/bin/bash - -CHAINID="${CHAIN_ID:-9001}" -MONIKER="localtestnet" -# Remember to change to other types of keyring like 'file' in-case exposing to outside world, -# otherwise your balance will be wiped quickly -# The keyring test does not require private key to steal tokens from you -KEYRING="test" -KEYALGO="eth_secp256k1" - -LOGLEVEL="info" -# Set dedicated home directory for the evmd instance -CHAINDIR="$HOME/.evmd" - -BASEFEE=10000000 - -# Path variables -CONFIG_TOML=$CHAINDIR/config/config.toml -APP_TOML=$CHAINDIR/config/app.toml -GENESIS=$CHAINDIR/config/genesis.json -TMP_GENESIS=$CHAINDIR/config/tmp_genesis.json - -# validate dependencies are installed -command -v jq >/dev/null 2>&1 || { - echo >&2 "jq not installed. More info: https://stedolan.github.io/jq/download/" - exit 1 -} - -# used to exit on first error (any non-zero exit code) -set -e - -# ------------- Flags ------------- -install=true -overwrite="" -BUILD_FOR_DEBUG=false -ADDITIONAL_USERS=0 -MNEMONIC_FILE="" # output file (defaults later to $CHAINDIR/mnemonics.yaml) -MNEMONICS_INPUT="" # input yaml to prefill dev keys - -usage() { - cat < Overwriting the previous chain data." - overwrite="y"; shift - ;; - -n) - echo "Flag -n passed -> Not overwriting the previous chain data." - overwrite="n"; shift - ;; - --no-install) - echo "Flag --no-install passed -> Skipping installation of the evmd binary." - install=false; shift - ;; - --remote-debugging) - echo "Flag --remote-debugging passed -> Building with remote debugging options." - BUILD_FOR_DEBUG=true; shift - ;; - --additional-users) - if [[ -z "${2:-}" || "$2" =~ ^- ]]; then - echo "Error: --additional-users requires a number."; usage; exit 1 - fi - ADDITIONAL_USERS="$2"; shift 2 - ;; - --mnemonic-file) - if [[ -z "${2:-}" || "$2" =~ ^- ]]; then - echo "Error: --mnemonic-file requires a path."; usage; exit 1 - fi - MNEMONIC_FILE="$2"; shift 2 - ;; - --mnemonics-input) - if [[ -z "${2:-}" || "$2" =~ ^- ]]; then - echo "Error: --mnemonics-input requires a path."; usage; exit 1 - fi - MNEMONICS_INPUT="$2"; shift 2 - ;; - -h|--help) - usage; exit 0 - ;; - *) - echo "Unknown flag passed: $key -> Aborting"; usage; exit 1 - ;; - esac -done - -if [[ -n "$MNEMONICS_INPUT" && "$ADDITIONAL_USERS" -gt 0 ]]; then - echo "Error: --mnemonics-input and --additional-users cannot be used together." - echo "Use --mnemonics-input to provide all dev account mnemonics, or use --additional-users to generate extra accounts." - exit 1 -fi - -if [[ $install == true ]]; then - if [[ $BUILD_FOR_DEBUG == true ]]; then - # for remote debugging the optimization should be disabled and the debug info should not be stripped - make install COSMOS_BUILD_OPTIONS=nooptimization,nostrip - else - make install - fi -fi - -# User prompt if neither -y nor -n was passed as a flag -# and an existing local node configuration is found. -if [[ $overwrite = "" ]]; then - if [ -d "$CHAINDIR" ]; then - printf "\nAn existing folder at '%s' was found. You can choose to delete this folder and start a new local node with new keys from genesis. When declined, the existing local node is started. \n" "$CHAINDIR" - echo "Overwrite the existing configuration and start a new local node? [y/n]" - read -r overwrite - else - overwrite="y" - fi -fi - -# ---------- YAML reader ---------- -# reads a simple yaml with: -# mnemonics: -# - "phrase here" -# - another phrase -read_mnemonics_yaml() { - local file="$1" - awk ' - BEGIN { inlist=0 } - /^[[:space:]]*mnemonics:[[:space:]]*$/ { inlist=1; next } - inlist && /^[[:space:]]*-[[:space:]]*/ { - line=$0 - sub(/^[[:space:]]*-[[:space:]]*/, "", line) - gsub(/^"[[:space:]]*|[[:space:]]*"$/, "", line) - gsub(/^'\''[[:space:]]*|[[:space:]]*'\''$/, "", line) - print line - next - } - inlist && NF==0 { next } - ' "$file" -} - -# ---------- yaml writer ---------- -write_mnemonics_yaml() { - local file_path="$1"; shift - local -a mns=("$@") - mkdir -p "$(dirname "$file_path")" - { - echo "mnemonics:" - for m in "${mns[@]}"; do - printf ' - "%s"\n' "$m" - done - } > "$file_path" - echo "Wrote mnemonics to $file_path" -} - -# ---------- Add funded account ---------- -add_genesis_funds() { - local keyname="$1" - evmd genesis add-genesis-account "$keyname" 1000000000000000000000atest --keyring-backend "$KEYRING" --home "$CHAINDIR" -} - -# Setup local node if overwrite is set to Yes, otherwise skip setup -if [[ $overwrite == "y" || $overwrite == "Y" ]]; then - rm -rf "$CHAINDIR" - - evmd config set client chain-id "$CHAINID" --home "$CHAINDIR" - evmd config set client keyring-backend "$KEYRING" --home "$CHAINDIR" - - # ---------------- Validator key ---------------- - VAL_KEY="mykey" - VAL_MNEMONIC="gesture inject test cycle original hollow east ridge hen combine junk child bacon zero hope comfort vacuum milk pitch cage oppose unhappy lunar seat" - echo "$VAL_MNEMONIC" | evmd keys add "$VAL_KEY" --recover --keyring-backend "$KEYRING" --algo "$KEYALGO" --home "$CHAINDIR" - - # ---------------- dev mnemonics source ---------------- - # dev0 address 0xC6Fe5D33615a1C52c08018c47E8Bc53646A0E101 | cosmos1cml96vmptgw99syqrrz8az79xer2pcgp84pdun - # dev0's private key: 0x88cbead91aee890d27bf06e003ade3d4e952427e88f88d31d61d3ef5e5d54305 # gitleaks:allow - - # dev1 address 0x963EBDf2e1f8DB8707D05FC75bfeFFBa1B5BaC17 | cosmos1jcltmuhplrdcwp7stlr4hlhlhgd4htqh3a79sq - # dev1's private key: 0x741de4f8988ea941d3ff0287911ca4074e62b7d45c991a51186455366f10b544 # gitleaks:allow - - # dev2 address 0x40a0cb1C63e026A81B55EE1308586E21eec1eFa9 | cosmos1gzsvk8rruqn2sx64acfsskrwy8hvrmafqkaze8 - # dev2's private key: 0x3b7955d25189c99a7468192fcbc6429205c158834053ebe3f78f4512ab432db9 # gitleaks:allow - - # dev3 address 0x498B5AeC5D439b733dC2F58AB489783A23FB26dA | cosmos1fx944mzagwdhx0wz7k9tfztc8g3lkfk6rrgv6l - # dev3's private key: 0x8a36c69d940a92fcea94b36d0f2928c7a0ee19a90073eda769693298dfa9603b # gitleaks:allow - default_mnemonics=( - "copper push brief egg scan entry inform record adjust fossil boss egg comic alien upon aspect dry avoid interest fury window hint race symptom" # dev0 - "maximum display century economy unlock van census kite error heart snow filter midnight usage egg venture cash kick motor survey drastic edge muffin visual" # dev1 - "will wear settle write dance topic tape sea glory hotel oppose rebel client problem era video gossip glide during yard balance cancel file rose" # dev2 - "doll midnight silk carpet brush boring pluck office gown inquiry duck chief aim exit gain never tennis crime fragile ship cloud surface exotic patch" # dev3 - ) - - provided_mnemonics=() - if [[ -n "$MNEMONICS_INPUT" ]]; then - if [[ ! -f "$MNEMONICS_INPUT" ]]; then - echo "mnemonics input file not found: $MNEMONICS_INPUT"; exit 1 - fi - - tmpfile="$(mktemp -t mnemonics.XXXXXX)" - read_mnemonics_yaml "$MNEMONICS_INPUT" > "$tmpfile" - - while IFS= read -r line; do - [[ -z "$line" ]] && continue - provided_mnemonics+=( "$line" ) - done < "$tmpfile" - rm -f "$tmpfile" - - if [[ ${#provided_mnemonics[@]} -eq 0 ]]; then - echo "no mnemonics found in $MNEMONICS_INPUT (expected a list under 'mnemonics:')"; exit 1 - fi - fi - - # choose base list: prefer provided over defaults - if [[ ${#provided_mnemonics[@]} -gt 0 ]]; then - echo "using provided mnemonics" - dev_mnemonics=("${provided_mnemonics[@]}") - else - echo "using default mnemonics" - dev_mnemonics=("${default_mnemonics[@]}") - fi - - # init chain w/ validator mnemonic - echo "$VAL_MNEMONIC" | evmd init $MONIKER -o --chain-id "$CHAINID" --home "$CHAINDIR" --recover - - # ---------- Genesis customizations ---------- - jq '.app_state["staking"]["params"]["bond_denom"]="atest"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" - jq '.app_state["gov"]["deposit_params"]["min_deposit"][0]["denom"]="atest"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" - jq '.app_state["gov"]["params"]["min_deposit"][0]["denom"]="atest"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" - jq '.app_state["gov"]["params"]["expedited_min_deposit"][0]["denom"]="atest"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" - jq '.app_state["evm"]["params"]["evm_denom"]="atest"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" - jq '.app_state["mint"]["params"]["mint_denom"]="atest"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" - - jq '.app_state["bank"]["denom_metadata"]=[{"description":"The native staking token for evmd.","denom_units":[{"denom":"atest","exponent":0,"aliases":["attotest"]},{"denom":"test","exponent":18,"aliases":[]}],"base":"atest","display":"test","name":"Test Token","symbol":"TEST","uri":"","uri_hash":""}]' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" - - jq '.app_state["evm"]["params"]["active_static_precompiles"]=["0x0000000000000000000000000000000000000100","0x0000000000000000000000000000000000000400","0x0000000000000000000000000000000000000800","0x0000000000000000000000000000000000000801","0x0000000000000000000000000000000000000802","0x0000000000000000000000000000000000000803","0x0000000000000000000000000000000000000804","0x0000000000000000000000000000000000000805", "0x0000000000000000000000000000000000000806", "0x0000000000000000000000000000000000000807"]' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" - - jq '.app_state["evm"]["params"]["evm_denom"]="atest"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" - - jq '.app_state.erc20.native_precompiles=["0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"]' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" - jq '.app_state.erc20.token_pairs=[{contract_owner:1,erc20_address:"0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",denom:"atest",enabled:true}]' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" - - jq '.consensus.params.block.max_gas="10000000"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" - - # Change proposal periods - sed -i.bak 's/"max_deposit_period": "172800s"/"max_deposit_period": "30s"/g' "$GENESIS" - sed -i.bak 's/"voting_period": "172800s"/"voting_period": "30s"/g' "$GENESIS" - sed -i.bak 's/"expedited_voting_period": "86400s"/"expedited_voting_period": "15s"/g' "$GENESIS" - - # fund validator (devs already funded in the loop) - evmd genesis add-genesis-account "$VAL_KEY" 100000000000000000000000000atest --keyring-backend "$KEYRING" --home "$CHAINDIR" - - # ---------- Config customizations ---------- - sed -i.bak 's/timeout_propose = "3s"/timeout_propose = "2s"/g' "$CONFIG_TOML" - sed -i.bak 's/timeout_propose_delta = "500ms"/timeout_propose_delta = "200ms"/g' "$CONFIG_TOML" - sed -i.bak 's/timeout_prevote = "1s"/timeout_prevote = "500ms"/g' "$CONFIG_TOML" - sed -i.bak 's/timeout_prevote_delta = "500ms"/timeout_prevote_delta = "200ms"/g' "$CONFIG_TOML" - sed -i.bak 's/timeout_precommit = "1s"/timeout_precommit = "500ms"/g' "$CONFIG_TOML" - sed -i.bak 's/timeout_precommit_delta = "500ms"/timeout_precommit_delta = "200ms"/g' "$CONFIG_TOML" - sed -i.bak 's/timeout_commit = "5s"/timeout_commit = "1s"/g' "$CONFIG_TOML" - sed -i.bak 's/timeout_broadcast_tx_commit = "10s"/timeout_broadcast_tx_commit = "5s"/g' "$CONFIG_TOML" - - # enable prometheus metrics and all APIs for dev node - sed -i.bak 's/prometheus = false/prometheus = true/' "$CONFIG_TOML" - sed -i.bak 's/prometheus-retention-time = "0"/prometheus-retention-time = "1000000000000"/g' "$APP_TOML" - sed -i.bak 's/enabled = false/enabled = true/g' "$APP_TOML" - sed -i.bak 's/enable = false/enable = true/g' "$APP_TOML" - - # --------- maybe generate additional users --------- - # start with provided/default list - final_mnemonics=("${dev_mnemonics[@]}") - - # default output path if not set - if [[ -z "$MNEMONIC_FILE" ]]; then - MNEMONIC_FILE="$CHAINDIR/mnemonics.yaml" - fi - - # Process all dev mnemonics (provided or default) - for ((i=0; i<${#dev_mnemonics[@]}; i++)); do - - keyname="dev${i}" - mnemonic="${dev_mnemonics[i]}" - - echo "adding key for $keyname" - - # Add key to keyring using the mnemonic - echo "$mnemonic" | evmd keys add "$keyname" --recover --keyring-backend "$KEYRING" --algo "$KEYALGO" --home "$CHAINDIR" - - # Fund the account in genesis - add_genesis_funds "$keyname" - done - - if [[ "$ADDITIONAL_USERS" -gt 0 ]]; then - start_index=${#dev_mnemonics[@]} # continue after last provided/default entry - for ((i=0; i&1)" - # try to grab a line that looks like a seed phrase (>=12 words), else last line - user_mnemonic="$(echo "$mnemonic_out" | grep -E '([[:alpha:]]+[[:space:]]+){11,}[[:alpha:]]+$' | tail -1)" - if [[ -z "$user_mnemonic" ]]; then - user_mnemonic="$(echo "$mnemonic_out" | tail -n 1)" - fi - user_mnemonic="$(echo "$user_mnemonic" | tr -d '\r')" - - if [[ -z "$user_mnemonic" ]]; then - echo "failed to capture mnemonic for $keyname"; exit 1 - fi - - final_mnemonics+=("$user_mnemonic") - add_genesis_funds "$keyname" - echo "created $keyname" - done - fi - - # --------- Finalize genesis --------- - evmd genesis gentx "$VAL_KEY" 1000000000000000000000atest --gas-prices ${BASEFEE}atest --keyring-backend "$KEYRING" --chain-id "$CHAINID" --home "$CHAINDIR" - evmd genesis collect-gentxs --home "$CHAINDIR" - evmd genesis validate-genesis --home "$CHAINDIR" - - # --------- Write YAML with mnemonics if the user specified more --------- - if [[ "$ADDITIONAL_USERS" -gt 0 ]]; then - write_mnemonics_yaml "$MNEMONIC_FILE" "${final_mnemonics[@]}" - fi - - if [[ $1 == "pending" ]]; then - echo "pending mode is on, please wait for the first block committed." - fi -fi - -# Start the node -evmd start "$TRACE" \ - --pruning nothing \ - --log_level $LOGLEVEL \ - --minimum-gas-prices=0atest \ - --evm.min-tip=0 \ - --home "$CHAINDIR" \ - --json-rpc.api eth,txpool,personal,net,debug,web3 \ - --chain-id "$CHAINID" From 581e1b0349e086fe3856c0978890e5de9ebe0838 Mon Sep 17 00:00:00 2001 From: zsystm Date: Mon, 10 Nov 2025 19:43:21 +0900 Subject: [PATCH 12/22] listen commit and log changesets --- evmd/app.go | 18 ++++++++++- evmd/changelogger.go | 74 ++++++++++++++++++++++++++++++++++++++++++++ evmd/go.sum | 3 -- go.sum | 2 -- 4 files changed, 91 insertions(+), 6 deletions(-) create mode 100644 evmd/changelogger.go diff --git a/evmd/app.go b/evmd/app.go index f07b0a471..8199d78c6 100644 --- a/evmd/app.go +++ b/evmd/app.go @@ -253,6 +253,22 @@ func NewExampleApp( os.Exit(1) } + // Always enable in-memory listeners on all KV stores so we can retrieve the + // per-block change set at commit time, regardless of external streaming config. + { + var exposeStoreKeys []storetypes.StoreKey + for _, k := range keys { + exposeStoreKeys = append(exposeStoreKeys, k) + } + bApp.CommitMultiStore().AddListeners(exposeStoreKeys) + + // Append our in-process debug change logger to the streaming manager so it + // receives the commit-time change set and logs a summary. + sm := bApp.StreamingManager() + sm.ABCIListeners = append(sm.ABCIListeners, &DebugChangeLogger{}) + bApp.SetStreamingManager(sm) + } + // wire up the versiondb's `StreamingService` and `MultiStore`. if cast.ToBool(appOpts.Get("versiondb.enable")) { panic("version db not supported in this example chain") @@ -405,7 +421,7 @@ func NewExampleApp( app.GovKeeper = *govKeeper.SetHooks( govtypes.NewMultiGovHooks( - // register the governance hooks + // register the governance hooks ), ) diff --git a/evmd/changelogger.go b/evmd/changelogger.go new file mode 100644 index 000000000..c925162ba --- /dev/null +++ b/evmd/changelogger.go @@ -0,0 +1,74 @@ +package evmd + +import ( + "context" + "encoding/hex" + + abci "github.com/cometbft/cometbft/abci/types" + + storetypes "cosmossdk.io/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// DebugChangeLogger implements storetypes.ABCIListener and logs a per-block summary +// of KV-store changes at commit time using the app logger at Debug level. +type DebugChangeLogger struct{} + +var _ storetypes.ABCIListener = (*DebugChangeLogger)(nil) + +func (d *DebugChangeLogger) ListenFinalizeBlock(ctx context.Context, _ abci.RequestFinalizeBlock, _ abci.ResponseFinalizeBlock) error { + // No-op: we only care about commit-time change sets + return nil +} + +func (d *DebugChangeLogger) ListenCommit(ctx context.Context, _ abci.ResponseCommit, changeSet []*storetypes.StoreKVPair) error { + // sdk.Context is attached by BaseApp + sdkCtx := ctx.(sdk.Context) + if len(changeSet) == 0 { + return nil + } + + // Build a detailed list of all K/V changes in this block. + type kvlog struct { + Store string `json:"store"` + Op string `json:"op"` // set | delete + Key string `json:"key"` + Value string `json:"value,omitempty"` + Size int `json:"size"` // bytes for key+value on set, key only on delete + } + + changes := make([]kvlog, 0, len(changeSet)) + totalBytes := 0 + for _, c := range changeSet { + if c.Delete { + changes = append(changes, kvlog{ + Store: c.StoreKey, + Op: "delete", + Key: hex.EncodeToString(c.Key), + Size: len(c.Key), + }) + totalBytes += len(c.Key) + continue + } + + b := len(c.Key) + len(c.Value) + changes = append(changes, kvlog{ + Store: c.StoreKey, + Op: "set", + Key: hex.EncodeToString(c.Key), + Value: hex.EncodeToString(c.Value), + Size: b, + }) + totalBytes += b + } + + // Log full change set at commit time. + sdkCtx.Logger().Debug("store change set", + "height", sdkCtx.BlockHeight(), + "count", len(changes), + "bytes", totalBytes, + "changes", changes, + ) + + return nil +} diff --git a/evmd/go.sum b/evmd/go.sum index de2374cac..69c0c6eab 100644 --- a/evmd/go.sum +++ b/evmd/go.sum @@ -717,11 +717,8 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bft-labs/cosmos-sdk v0.53.4-memlogger-4 h1:rw+QqieYGCALStm7c3bAhz62PDQFy0JvI2+dkf0EQgI= github.com/bft-labs/cosmos-sdk v0.53.4-memlogger-4/go.mod h1:6k6Po9k9tVsUCRsnjpL6kGzTqjPnwgabQg8htKRMtVc= -github.com/bft-labs/cosmos-sdk/log v1.5.2-0.20251108150151-281dceda5730 h1:9miML98CAFnuMQfP3tcblxDqdQKnE2FqpLbyaajhnEA= github.com/bft-labs/cosmos-sdk/log v1.5.2-0.20251108150151-281dceda5730/go.mod h1:DNJwlhYlZOlSePMdymnpTcI8XDar9qn+m8o1fJC7olc= -github.com/bft-labs/cosmos-sdk/store v1.10.0-rc.1.0.20251108150151-281dceda5730 h1:VZZ0mdooD1YgZiEv/qJYJVdo6ErekQd9WRvbyESBSCo= github.com/bft-labs/cosmos-sdk/store v1.10.0-rc.1.0.20251108150151-281dceda5730/go.mod h1:7a15p+QsM5UXf7VMhO3ylmqj85k9UBN/h1kwMcLiffA= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4= diff --git a/go.sum b/go.sum index 5189a00aa..a2f7e50b5 100644 --- a/go.sum +++ b/go.sum @@ -719,9 +719,7 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bft-labs/cosmos-sdk v0.53.4-memlogger-4 h1:rw+QqieYGCALStm7c3bAhz62PDQFy0JvI2+dkf0EQgI= github.com/bft-labs/cosmos-sdk v0.53.4-memlogger-4/go.mod h1:6k6Po9k9tVsUCRsnjpL6kGzTqjPnwgabQg8htKRMtVc= -github.com/bft-labs/cosmos-sdk/log v1.5.2-0.20251102063934-dab46c0df9d1 h1:PwAbsEgQ7WQpnJBNOQJMuFc84TLJzmC7bJpTaqrXNcE= github.com/bft-labs/cosmos-sdk/log v1.5.2-0.20251102063934-dab46c0df9d1/go.mod h1:DNJwlhYlZOlSePMdymnpTcI8XDar9qn+m8o1fJC7olc= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4= From 32ffb471c06d9bd4c74a610d559d8509b17b75f0 Mon Sep 17 00:00:00 2001 From: Leo Date: Sat, 15 Nov 2025 01:14:25 +0900 Subject: [PATCH 13/22] chore: fix go sum --- evmd/go.sum | 3 +++ go.sum | 2 ++ 2 files changed, 5 insertions(+) diff --git a/evmd/go.sum b/evmd/go.sum index 69c0c6eab..de2374cac 100644 --- a/evmd/go.sum +++ b/evmd/go.sum @@ -717,8 +717,11 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bft-labs/cosmos-sdk v0.53.4-memlogger-4 h1:rw+QqieYGCALStm7c3bAhz62PDQFy0JvI2+dkf0EQgI= github.com/bft-labs/cosmos-sdk v0.53.4-memlogger-4/go.mod h1:6k6Po9k9tVsUCRsnjpL6kGzTqjPnwgabQg8htKRMtVc= +github.com/bft-labs/cosmos-sdk/log v1.5.2-0.20251108150151-281dceda5730 h1:9miML98CAFnuMQfP3tcblxDqdQKnE2FqpLbyaajhnEA= github.com/bft-labs/cosmos-sdk/log v1.5.2-0.20251108150151-281dceda5730/go.mod h1:DNJwlhYlZOlSePMdymnpTcI8XDar9qn+m8o1fJC7olc= +github.com/bft-labs/cosmos-sdk/store v1.10.0-rc.1.0.20251108150151-281dceda5730 h1:VZZ0mdooD1YgZiEv/qJYJVdo6ErekQd9WRvbyESBSCo= github.com/bft-labs/cosmos-sdk/store v1.10.0-rc.1.0.20251108150151-281dceda5730/go.mod h1:7a15p+QsM5UXf7VMhO3ylmqj85k9UBN/h1kwMcLiffA= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4= diff --git a/go.sum b/go.sum index a2f7e50b5..5189a00aa 100644 --- a/go.sum +++ b/go.sum @@ -719,7 +719,9 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bft-labs/cosmos-sdk v0.53.4-memlogger-4 h1:rw+QqieYGCALStm7c3bAhz62PDQFy0JvI2+dkf0EQgI= github.com/bft-labs/cosmos-sdk v0.53.4-memlogger-4/go.mod h1:6k6Po9k9tVsUCRsnjpL6kGzTqjPnwgabQg8htKRMtVc= +github.com/bft-labs/cosmos-sdk/log v1.5.2-0.20251102063934-dab46c0df9d1 h1:PwAbsEgQ7WQpnJBNOQJMuFc84TLJzmC7bJpTaqrXNcE= github.com/bft-labs/cosmos-sdk/log v1.5.2-0.20251102063934-dab46c0df9d1/go.mod h1:DNJwlhYlZOlSePMdymnpTcI8XDar9qn+m8o1fJC7olc= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4= From 9a336c55e16bb6cc4b4a69e9b022b2819f38b5f9 Mon Sep 17 00:00:00 2001 From: Leo Date: Sun, 23 Nov 2025 02:11:45 +0900 Subject: [PATCH 14/22] feat: consensus broken script --- evmd_broken_localnet.sh | 510 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 510 insertions(+) create mode 100755 evmd_broken_localnet.sh diff --git a/evmd_broken_localnet.sh b/evmd_broken_localnet.sh new file mode 100755 index 000000000..5ffbca743 --- /dev/null +++ b/evmd_broken_localnet.sh @@ -0,0 +1,510 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Multi-node localnet launcher with mixed binaries (normal + consensus-breaking) +# - setup: Builds both normal and broken evmd binaries +# - start: Runs 3 normal nodes + 1 broken node +# - stop: Stops all nodes +# - clean: Removes all test data +# +# Usage: +# ./evmd_localnet_mixed.sh setup # Build both binaries +# ./evmd_localnet_mixed.sh start # Start 4 nodes (3 normal, 1 broken) +# ./evmd_localnet_mixed.sh stop # Stop all nodes +# ./evmd_localnet_mixed.sh clean # Remove .testnets directory + +BASE_DIR_DEFAULT="./.testnets" +NODE_PREFIX_DEFAULT="node" +N_DEFAULT=4 +MIN_GAS_PRICES_DEFAULT="0atest" +SURGE_CMD_DEFAULT="surge faucet" +CHAIN_ID_DEFAULT="local-4221" +SINGLE_HOST_DEFAULT="true" +STARTING_IP_DEFAULT="127.0.0.1" + +# Cosmos SDK versions +COSMOS_SDK_NORMAL="github.com/bft-labs/cosmos-sdk v0.53.4-memlogger-4" +COSMOS_SDK_BROKEN="github.com/bft-labs/cosmos-sdk v0.53.4-memlogger-break-0" + +# Derive settings from env or defaults +BASE_DIR=${BASE_DIR:-$BASE_DIR_DEFAULT} +NODE_PREFIX=${NODE_PREFIX:-$NODE_PREFIX_DEFAULT} +N=${N:-$N_DEFAULT} +MIN_GAS_PRICES=${MIN_GAS_PRICES:-$MIN_GAS_PRICES_DEFAULT} +SURGE_CMD=${SURGE_CMD:-$SURGE_CMD_DEFAULT} +SURGE_ARGS=${SURGE_ARGS:-} +CHAIN_ID=${CHAIN_ID:-$CHAIN_ID_DEFAULT} +SINGLE_HOST=${SINGLE_HOST:-$SINGLE_HOST_DEFAULT} +STARTING_IP_ADDRESS=${STARTING_IP_ADDRESS:-$STARTING_IP_DEFAULT} + +# Binary paths +BUILDS_DIR="${BASE_DIR}/builds" +BINARY_NORMAL="${BUILDS_DIR}/evmd" +BINARY_BROKEN="${BUILDS_DIR}/broken_evmd" +BUILD_OUTPUT="./build/evmd" + +# Internal +PID_FILE="${BASE_DIR}/evmd_localnet_mixed.pids" +GO_MOD_BACKUP="${BASE_DIR}/go.mod.backup" +EVMD_GO_MOD_BACKUP="${BASE_DIR}/evmd_go.mod.backup" + +log() { echo "[evmd-localnet-mixed] $*"; } +err() { echo "[evmd-localnet-mixed:ERROR] $*" >&2; } + +setup_binaries() { + log "Setting up binaries in ${BUILDS_DIR}" + mkdir -p "$BUILDS_DIR" + mkdir -p "./build" + + # Backup original go.mod files if not already backed up + if [ ! -f "$GO_MOD_BACKUP" ]; then + log "Backing up go.mod" + cp go.mod "$GO_MOD_BACKUP" + fi + if [ ! -f "$EVMD_GO_MOD_BACKUP" ]; then + log "Backing up evmd/go.mod" + cp evmd/go.mod "$EVMD_GO_MOD_BACKUP" + fi + + # Build normal binary + log "Building normal evmd binary (cosmos-sdk v0.53.4-memlogger-4)..." + log "Updating go.mod files to use ${COSMOS_SDK_NORMAL}" + sed -i '' "s|github.com/cosmos/cosmos-sdk => github.com/bft-labs/cosmos-sdk v0.53.4-memlogger-break-[0-9]*|github.com/cosmos/cosmos-sdk => ${COSMOS_SDK_NORMAL}|" go.mod + sed -i '' "s|github.com/cosmos/cosmos-sdk => github.com/bft-labs/cosmos-sdk v0.53.4-memlogger-[0-9]*|github.com/cosmos/cosmos-sdk => ${COSMOS_SDK_NORMAL}|" go.mod + sed -i '' "s|github.com/cosmos/cosmos-sdk => github.com/bft-labs/cosmos-sdk v0.53.4-memlogger-break-[0-9]*|github.com/cosmos/cosmos-sdk => ${COSMOS_SDK_NORMAL}|" evmd/go.mod + sed -i '' "s|github.com/cosmos/cosmos-sdk => github.com/bft-labs/cosmos-sdk v0.53.4-memlogger-[0-9]*|github.com/cosmos/cosmos-sdk => ${COSMOS_SDK_NORMAL}|" evmd/go.mod + + log "Running go mod tidy in root..." + go mod tidy + log "Running go mod tidy in evmd/..." + cd evmd && go mod tidy && cd .. + + log "Building normal binary with go build..." + cd evmd && CGO_ENABLED="1" go build -tags "netgo" -ldflags '-w -s' -trimpath -o ../build/evmd ./cmd/evmd + cd .. + + if [ ! -f "$BUILD_OUTPUT" ]; then + err "Failed to build normal binary" + exit 1 + fi + cp "$BUILD_OUTPUT" "$BINARY_NORMAL" + log "Normal binary saved to ${BINARY_NORMAL}" + + # Build broken binary with consensus_break tag + log "Building broken evmd binary (cosmos-sdk v0.53.4-memlogger-break-0 + BUILD_TAGS=consensus_break)..." + log "Updating go.mod files to use ${COSMOS_SDK_BROKEN}" + sed -i '' "s|github.com/cosmos/cosmos-sdk => github.com/bft-labs/cosmos-sdk v0.53.4-memlogger-[0-9]*|github.com/cosmos/cosmos-sdk => ${COSMOS_SDK_BROKEN}|" go.mod + sed -i '' "s|github.com/cosmos/cosmos-sdk => github.com/bft-labs/cosmos-sdk v0.53.4-memlogger-[0-9]*|github.com/cosmos/cosmos-sdk => ${COSMOS_SDK_BROKEN}|" evmd/go.mod + + log "Running go mod tidy in root..." + go mod tidy + log "Running go mod tidy in evmd/..." + cd evmd && go mod tidy && cd .. + + log "Building broken binary with BUILD_TAGS=consensus_break..." + cd evmd && CGO_ENABLED="1" go build -tags "netgo,consensus_break" -ldflags '-w -s' -trimpath -o ../build/evmd ./cmd/evmd + cd .. + + if [ ! -f "$BUILD_OUTPUT" ]; then + err "Failed to build broken binary" + exit 1 + fi + cp "$BUILD_OUTPUT" "$BINARY_BROKEN" + log "Broken binary saved to ${BINARY_BROKEN}" + + # Restore original go.mod files + log "Restoring original go.mod files" + cp "$GO_MOD_BACKUP" go.mod + cp "$EVMD_GO_MOD_BACKUP" evmd/go.mod + + log "Running go mod tidy to restore dependencies..." + go mod tidy + cd evmd && go mod tidy && cd .. + + # Verify both binaries exist + if [ -f "$BINARY_NORMAL" ] && [ -f "$BINARY_BROKEN" ]; then + log "Setup complete! Binaries ready:" + log " Normal: ${BINARY_NORMAL}" + log " Broken: ${BINARY_BROKEN}" + else + err "Binary setup failed" + exit 1 + fi +} + +verify_binaries() { + if [ ! -f "$BINARY_NORMAL" ]; then + err "Normal binary not found at ${BINARY_NORMAL}" + err "Run './evmd_localnet_mixed.sh setup' first" + exit 1 + fi + if [ ! -f "$BINARY_BROKEN" ]; then + err "Broken binary not found at ${BINARY_BROKEN}" + err "Run './evmd_localnet_mixed.sh setup' first" + exit 1 + fi + log "Binaries verified: normal and broken evmd found" +} + +init_fresh() { + # Remove old testnet data (but preserve builds directory) + for ((i=0; i/dev/null | grep -q -- "--chain-id"; then + cmd+=(--chain-id "${CHAIN_ID}") + fi + if [ "${SINGLE_HOST}" = "true" ] && "$BINARY_NORMAL" testnet init-files --help 2>/dev/null | grep -q -- "--single-host"; then + cmd+=(--single-host=true) + fi + if [ "${SINGLE_HOST}" = "true" ] && "$BINARY_NORMAL" testnet init-files --help 2>/dev/null | grep -q -- "--starting-ip-address"; then + cmd+=(--starting-ip-address "${STARTING_IP_ADDRESS}") + fi + + printf '[evmd-localnet-mixed] Exec: ' + for a in "${cmd[@]}"; do printf '%s ' "$a"; done; printf '\n' + "${cmd[@]}" + + log "Init complete (chain-id: ${CHAIN_ID}). Genesis and configs under ${BASE_DIR}/${NODE_PREFIX}{0..$((N-1))}/evmd" + + # Fallback: patch genesis chain_id via jq if init-files doesn't support --chain-id + if ! "$BINARY_NORMAL" testnet init-files --help 2>/dev/null | grep -q -- "--chain-id"; then + if command -v jq >/dev/null 2>&1; then + for ((i=0; i "$tmp" && mv "$tmp" "$gi" + fi + done + log "Patched genesis chain_id to '${CHAIN_ID}' via jq (fallback path)." + else + log "jq not found; cannot patch genesis chain_id. Using defaults from init-files." + fi + fi +} + +adjust_ports_single_host() { + if [ "${SINGLE_HOST}" != "true" ]; then + log "SINGLE_HOST is not enabled; skipping port adjustments." + return 0 + fi + + toml_set_key_in_section() { + local file="$1" section="$2" key="$3" value="$4" + awk -v section="$section" -v key="$key" -v value="$value" ' + BEGIN { insec=0; done=0 } + /^[[:space:]]*\[/ { + if (insec && !done) { print key " = \"" value "\""; done=1 } + insec=0 + if ($0 ~ "^\\[" section "\\]") { insec=1 } + print; next + } + { + if (insec && $0 ~ "^[[:space:]]*" key "[[:space:]]*=") { + print key " = \"" value "\""; done=1; next + } + print + } + END { + if (insec && !done) { print key " = \"" value "\"" } + } + ' "$file" >"$file.tmp" && mv "$file.tmp" "$file" + } + + for ((i=0; i"$file.tmp" && mv "$file.tmp" "$file" + } + + toml_set_key_in_section_raw() { + local file="$1" section="$2" key="$3" rawvalue="$4" + awk -v section="$section" -v key="$key" -v rawvalue="$rawvalue" ' + BEGIN { insec=0; done=0 } + /^[[:space:]]*\[/ { + if (insec && !done) { print key " = " rawvalue; done=1 } + insec=0 + if ($0 ~ "^\\[" section "\\]") { insec=1 } + print; next + } + { + if (insec && $0 ~ "^[[:space:]]*" key "[[:space:]]*=") { + print key " = " rawvalue; done=1; next + } + print + } + END { + if (insec && !done) { print key " = " rawvalue } + } + ' "$file" >"$file.tmp" && mv "$file.tmp" "$file" + } + + toml_set_key_in_section "$APP_TOML" "memlogger" "enabled" "true" + toml_set_key_in_section "$APP_TOML" "memlogger" "interval" "2s" + toml_set_key_in_section_raw "$APP_TOML" "memlogger" "memory-bytes" "104857600" + done + log "Enabled memlogger for all nodes." +} + +apply_surge_and_replicate() { + local g0="${BASE_DIR}/${NODE_PREFIX}0/evmd/config/genesis.json" + if [ ! -f "$g0" ]; then + err "node0 genesis not found at $g0" + exit 1 + fi + + if [ -n "$SURGE_CMD" ]; then + local surge_bin + surge_bin=$(echo "$SURGE_CMD" | awk '{print $1}') + if ! command -v "$surge_bin" >/dev/null 2>&1; then + err "'$surge_bin' not found on PATH. Set SURGE_CMD='' to skip or install surge." + exit 1 + fi + printf '[evmd-localnet-mixed] Exec: %s %s %s\n' "$SURGE_CMD" "${SURGE_ARGS}" "$g0" + eval "$SURGE_CMD ${SURGE_ARGS} $g0" + else + log "SURGE_CMD empty; skipping surge faucet step." + fi + + for ((i=1; i/dev/null 2>&1 || true + fi + done +} + +build_peers_if_possible() { + if ! "$BINARY_NORMAL" comet --help >/dev/null 2>&1; then + log "'evmd comet' subcommand not found. Skipping persistent_peers injection." + return 0 + fi + + local peers="" + for ((i=0; i/dev/null); then + err "Failed to read node ID for ${NODE_PREFIX}${i}; skipping persistent_peers." + return 0 + fi + local p2p_port=$((16656 + i)) + local entry="${id}@127.0.0.1:${p2p_port}" + if [ -z "$peers" ]; then peers="$entry"; else peers+=",$entry"; fi + done + + log "persistent_peers=${peers}" + for ((i=0; i> "$cfg" + fi + fi + done +} + +start_nodes() { + mkdir -p "$(dirname "$PID_FILE")" + : > "$PID_FILE" + + for ((i=0; i/dev/null 2>&1 || true + + cmd=("$BINARY" start \ + --home "$home_dir" \ + --minimum-gas-prices "${MIN_GAS_PRICES}" \ + --evm.min-tip 0 \ + --json-rpc.api "eth,txpool,personal,net,debug,web3" \ + --chain-id "${CHAIN_ID}") + + printf '[evmd-localnet-mixed] Exec: ' + for arg in "${cmd[@]}"; do printf '%s ' "$arg"; done; printf '\n' + + ("${cmd[@]}" >"$log_file" 2>&1 & echo $! >> "$PID_FILE") + sleep 0.5 + done + + log "All nodes started. PIDs recorded in ${PID_FILE}" + log "Node0 (broken) running on: rpc=26657, http=8545" + log "Node1 (normal) running on: rpc=26658, http=8555" + log "Node2 (normal) running on: rpc=26659, http=8565" + log "Node3 (normal) running on: rpc=26660, http=8575" +} + +stop_nodes() { + if [ ! -f "$PID_FILE" ]; then + err "PID file not found: $PID_FILE" + exit 1 + fi + tac "$PID_FILE" | while read -r pid; do + if kill -0 "$pid" >/dev/null 2>&1; then + log "Stopping PID $pid" + kill "$pid" || true + fi + done + rm -f "$PID_FILE" + log "All nodes stopped." +} + +clean() { + if [ -d "$BASE_DIR" ]; then + log "Removing ${BASE_DIR}" + rm -rf "$BASE_DIR" + fi + log "Clean complete." +} + +cmd=${1:-start} +case "$cmd" in + setup) + setup_binaries + ;; + start) + verify_binaries + init_fresh + apply_surge_and_replicate + adjust_ports_single_host + tune_timeouts + adjust_memlogger + build_peers_if_possible + start_nodes + ;; + stop) + stop_nodes + ;; + clean) + clean + ;; + *) + echo "Usage: $0 {setup|start|stop|clean}" >&2 + echo "" >&2 + echo "Commands:" >&2 + echo " setup - Build both normal and broken evmd binaries" >&2 + echo " start - Initialize and start 4 nodes (1 broken, 3 normal)" >&2 + echo " stop - Stop all running nodes" >&2 + echo " clean - Remove all test data and binaries" >&2 + exit 1 + ;; +esac From 892aa6ee720b853081a3beb708c3d80492c57537 Mon Sep 17 00:00:00 2001 From: zsystm Date: Sun, 23 Nov 2025 16:20:49 +0900 Subject: [PATCH 15/22] update dependency change logger removed from appchain side. it should use sdk's change logger --- evmd/app.go | 3 +- evmd/changelogger.go | 74 -------------------------------------------- evmd/go.mod | 13 ++++---- evmd/go.sum | 31 +++++++++---------- go.mod | 11 ++++--- go.sum | 27 ++++++++-------- 6 files changed, 43 insertions(+), 116 deletions(-) delete mode 100644 evmd/changelogger.go diff --git a/evmd/app.go b/evmd/app.go index 8199d78c6..d1336a3ed 100644 --- a/evmd/app.go +++ b/evmd/app.go @@ -9,6 +9,7 @@ import ( "os" + streamingabci "cosmossdk.io/store/streaming/abci" "github.com/spf13/cast" // Force-load the tracer engines to trigger registration due to Go-Ethereum v1.10.15 changes @@ -265,7 +266,7 @@ func NewExampleApp( // Append our in-process debug change logger to the streaming manager so it // receives the commit-time change set and logs a summary. sm := bApp.StreamingManager() - sm.ABCIListeners = append(sm.ABCIListeners, &DebugChangeLogger{}) + sm.ABCIListeners = append(sm.ABCIListeners, &streamingabci.DebugChangeLogger{}) bApp.SetStreamingManager(sm) } diff --git a/evmd/changelogger.go b/evmd/changelogger.go deleted file mode 100644 index c925162ba..000000000 --- a/evmd/changelogger.go +++ /dev/null @@ -1,74 +0,0 @@ -package evmd - -import ( - "context" - "encoding/hex" - - abci "github.com/cometbft/cometbft/abci/types" - - storetypes "cosmossdk.io/store/types" - sdk "github.com/cosmos/cosmos-sdk/types" -) - -// DebugChangeLogger implements storetypes.ABCIListener and logs a per-block summary -// of KV-store changes at commit time using the app logger at Debug level. -type DebugChangeLogger struct{} - -var _ storetypes.ABCIListener = (*DebugChangeLogger)(nil) - -func (d *DebugChangeLogger) ListenFinalizeBlock(ctx context.Context, _ abci.RequestFinalizeBlock, _ abci.ResponseFinalizeBlock) error { - // No-op: we only care about commit-time change sets - return nil -} - -func (d *DebugChangeLogger) ListenCommit(ctx context.Context, _ abci.ResponseCommit, changeSet []*storetypes.StoreKVPair) error { - // sdk.Context is attached by BaseApp - sdkCtx := ctx.(sdk.Context) - if len(changeSet) == 0 { - return nil - } - - // Build a detailed list of all K/V changes in this block. - type kvlog struct { - Store string `json:"store"` - Op string `json:"op"` // set | delete - Key string `json:"key"` - Value string `json:"value,omitempty"` - Size int `json:"size"` // bytes for key+value on set, key only on delete - } - - changes := make([]kvlog, 0, len(changeSet)) - totalBytes := 0 - for _, c := range changeSet { - if c.Delete { - changes = append(changes, kvlog{ - Store: c.StoreKey, - Op: "delete", - Key: hex.EncodeToString(c.Key), - Size: len(c.Key), - }) - totalBytes += len(c.Key) - continue - } - - b := len(c.Key) + len(c.Value) - changes = append(changes, kvlog{ - Store: c.StoreKey, - Op: "set", - Key: hex.EncodeToString(c.Key), - Value: hex.EncodeToString(c.Value), - Size: b, - }) - totalBytes += b - } - - // Log full change set at commit time. - sdkCtx.Logger().Debug("store change set", - "height", sdkCtx.BlockHeight(), - "count", len(changes), - "bytes", totalBytes, - "changes", changes, - ) - - return nil -} diff --git a/evmd/go.mod b/evmd/go.mod index e07aac452..9287df174 100644 --- a/evmd/go.mod +++ b/evmd/go.mod @@ -65,12 +65,13 @@ require ( github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect github.com/btcsuite/btcd/btcutil v1.1.6 // indirect github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect - github.com/bytedance/sonic v1.14.0 // indirect - github.com/bytedance/sonic/loader v0.3.0 // indirect + github.com/bytedance/gopkg v0.1.3 // indirect + github.com/bytedance/sonic v1.14.2 // indirect + github.com/bytedance/sonic/loader v0.4.0 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/chzyer/readline v1.5.1 // indirect - github.com/cloudwego/base64x v0.1.5 // indirect + github.com/cloudwego/base64x v0.1.6 // indirect github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443 // indirect github.com/cockroachdb/apd/v2 v2.0.2 // indirect github.com/cockroachdb/errors v1.12.0 // indirect @@ -271,12 +272,12 @@ require ( ) replace ( - cosmossdk.io/log => github.com/bft-labs/cosmos-sdk/log v1.5.2-0.20251108150151-281dceda5730 - cosmossdk.io/store => github.com/bft-labs/cosmos-sdk/store v1.10.0-rc.1.0.20251108150151-281dceda5730 + cosmossdk.io/log => github.com/bft-labs/cosmos-sdk/log v1.5.2-0.20251123071421-2a53c378ae57 + cosmossdk.io/store => github.com/bft-labs/cosmos-sdk/store v1.10.0-rc.1.0.20251123071421-2a53c378ae57 // use cosmos fork of keyring github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0 - github.com/cosmos/cosmos-sdk => github.com/bft-labs/cosmos-sdk v0.53.4-memlogger-4 + github.com/cosmos/cosmos-sdk => github.com/bft-labs/cosmos-sdk v0.53.4-bft-labs-memlogger github.com/cosmos/evm => ../ // use Cosmos geth fork // branch: release/1.16 diff --git a/evmd/go.sum b/evmd/go.sum index de2374cac..7214c6ca3 100644 --- a/evmd/go.sum +++ b/evmd/go.sum @@ -717,12 +717,12 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bft-labs/cosmos-sdk v0.53.4-memlogger-4 h1:rw+QqieYGCALStm7c3bAhz62PDQFy0JvI2+dkf0EQgI= -github.com/bft-labs/cosmos-sdk v0.53.4-memlogger-4/go.mod h1:6k6Po9k9tVsUCRsnjpL6kGzTqjPnwgabQg8htKRMtVc= -github.com/bft-labs/cosmos-sdk/log v1.5.2-0.20251108150151-281dceda5730 h1:9miML98CAFnuMQfP3tcblxDqdQKnE2FqpLbyaajhnEA= -github.com/bft-labs/cosmos-sdk/log v1.5.2-0.20251108150151-281dceda5730/go.mod h1:DNJwlhYlZOlSePMdymnpTcI8XDar9qn+m8o1fJC7olc= -github.com/bft-labs/cosmos-sdk/store v1.10.0-rc.1.0.20251108150151-281dceda5730 h1:VZZ0mdooD1YgZiEv/qJYJVdo6ErekQd9WRvbyESBSCo= -github.com/bft-labs/cosmos-sdk/store v1.10.0-rc.1.0.20251108150151-281dceda5730/go.mod h1:7a15p+QsM5UXf7VMhO3ylmqj85k9UBN/h1kwMcLiffA= +github.com/bft-labs/cosmos-sdk v0.53.4-bft-labs-memlogger h1:5pRPFmW3HddXynFY41gT0pGW8VK+lATJTDYS2Be9uUE= +github.com/bft-labs/cosmos-sdk v0.53.4-bft-labs-memlogger/go.mod h1:SICzd8okv4I/osxz6esxbcQiHimH0CYIP6SBK8CfR7c= +github.com/bft-labs/cosmos-sdk/log v1.5.2-0.20251123071421-2a53c378ae57 h1:lu67DO6o5HkwXpM+foswKUMiiaKuV/as6SC/Luv0Gm4= +github.com/bft-labs/cosmos-sdk/log v1.5.2-0.20251123071421-2a53c378ae57/go.mod h1:/nr+xEg1LA3FHTsBBwwzrft0oQXsoFfdAwuSNXBQn0U= +github.com/bft-labs/cosmos-sdk/store v1.10.0-rc.1.0.20251123071421-2a53c378ae57 h1:isQ928HvH1wP9SS2fr8cGoALSMg6crdiOfX/bFflwYM= +github.com/bft-labs/cosmos-sdk/store v1.10.0-rc.1.0.20251123071421-2a53c378ae57/go.mod h1:i2O3FQWKx1kawKvwQ5dTOdYEfh2SKvPVrgMP154uqPE= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= @@ -761,13 +761,14 @@ github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtE github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/bufbuild/protocompile v0.14.1 h1:iA73zAf/fyljNjQKwYzUHD6AD4R8KMasmwa/FBatYVw= github.com/bufbuild/protocompile v0.14.1/go.mod h1:ppVdAIhbr2H8asPk6k4pY7t9zB1OU5DoEw9xY/FUi1c= +github.com/bytedance/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M= +github.com/bytedance/gopkg v0.1.3/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM= github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= -github.com/bytedance/sonic v1.14.0 h1:/OfKt8HFw0kh2rj8N0F6C/qPGRESq0BbaNZgcNXXzQQ= -github.com/bytedance/sonic v1.14.0/go.mod h1:WoEbx8WTcFJfzCe0hbmyTGrfjt8PzNEBdxlNUO24NhA= -github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= -github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA= -github.com/bytedance/sonic/loader v0.3.0/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI= +github.com/bytedance/sonic v1.14.2 h1:k1twIoe97C1DtYUo+fZQy865IuHia4PR5RPiuGPPIIE= +github.com/bytedance/sonic v1.14.2/go.mod h1:T80iDELeHiHKSc0C9tubFygiuXoGzrkjKzX2quAx980= +github.com/bytedance/sonic/loader v0.4.0 h1:olZ7lEqcxtZygCK9EKYKADnpQoYkRQxaeY2NYzevs+o= +github.com/bytedance/sonic/loader v0.4.0/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= @@ -803,9 +804,8 @@ github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6D github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4= -github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= -github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= +github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M= +github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -1361,7 +1361,6 @@ github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02 github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE= github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= -github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= @@ -1677,6 +1676,7 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= @@ -2639,7 +2639,6 @@ modernc.org/z v1.5.1/go.mod h1:eWFB510QWW5Th9YGZT81s+LwvaAs3Q2yr4sP0rmLkv8= nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= nhooyr.io/websocket v1.8.11 h1:f/qXNc2/3DpoSZkHt1DQu6rj4zGC8JmkkLkWss0MgN0= nhooyr.io/websocket v1.8.11/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c= -nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= pgregory.net/rapid v1.2.0 h1:keKAYRcjm+e1F0oAuU5F5+YPAWcyxNNRK2wud503Gnk= pgregory.net/rapid v1.2.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= diff --git a/go.mod b/go.mod index d87b32f23..e88fc5f64 100644 --- a/go.mod +++ b/go.mod @@ -89,12 +89,13 @@ require ( github.com/bits-and-blooms/bitset v1.22.0 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect - github.com/bytedance/sonic v1.14.0 // indirect - github.com/bytedance/sonic/loader v0.3.0 // indirect + github.com/bytedance/gopkg v0.1.3 // indirect + github.com/bytedance/sonic v1.14.2 // indirect + github.com/bytedance/sonic/loader v0.4.0 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/chzyer/readline v1.5.1 // indirect - github.com/cloudwego/base64x v0.1.5 // indirect + github.com/cloudwego/base64x v0.1.6 // indirect github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443 // indirect github.com/cockroachdb/apd/v2 v2.0.2 // indirect github.com/cockroachdb/errors v1.12.0 // indirect @@ -267,11 +268,11 @@ require ( ) replace ( - cosmossdk.io/log => github.com/bft-labs/cosmos-sdk/log v1.5.2-0.20251102063934-dab46c0df9d1 + cosmossdk.io/log => github.com/bft-labs/cosmos-sdk/log v1.5.2-0.20251123071421-2a53c378ae57 // use cosmos fork of keyring github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0 - github.com/cosmos/cosmos-sdk => github.com/bft-labs/cosmos-sdk v0.53.4-memlogger-4 + github.com/cosmos/cosmos-sdk => github.com/bft-labs/cosmos-sdk v0.53.4-bft-labs-memlogger // use Cosmos geth fork // branch: release/1.16 github.com/ethereum/go-ethereum => github.com/cosmos/go-ethereum v1.16.2-cosmos-1 diff --git a/go.sum b/go.sum index 5189a00aa..bd155f10d 100644 --- a/go.sum +++ b/go.sum @@ -719,10 +719,10 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bft-labs/cosmos-sdk v0.53.4-memlogger-4 h1:rw+QqieYGCALStm7c3bAhz62PDQFy0JvI2+dkf0EQgI= -github.com/bft-labs/cosmos-sdk v0.53.4-memlogger-4/go.mod h1:6k6Po9k9tVsUCRsnjpL6kGzTqjPnwgabQg8htKRMtVc= -github.com/bft-labs/cosmos-sdk/log v1.5.2-0.20251102063934-dab46c0df9d1 h1:PwAbsEgQ7WQpnJBNOQJMuFc84TLJzmC7bJpTaqrXNcE= -github.com/bft-labs/cosmos-sdk/log v1.5.2-0.20251102063934-dab46c0df9d1/go.mod h1:DNJwlhYlZOlSePMdymnpTcI8XDar9qn+m8o1fJC7olc= +github.com/bft-labs/cosmos-sdk v0.53.4-bft-labs-memlogger h1:5pRPFmW3HddXynFY41gT0pGW8VK+lATJTDYS2Be9uUE= +github.com/bft-labs/cosmos-sdk v0.53.4-bft-labs-memlogger/go.mod h1:SICzd8okv4I/osxz6esxbcQiHimH0CYIP6SBK8CfR7c= +github.com/bft-labs/cosmos-sdk/log v1.5.2-0.20251123071421-2a53c378ae57 h1:lu67DO6o5HkwXpM+foswKUMiiaKuV/as6SC/Luv0Gm4= +github.com/bft-labs/cosmos-sdk/log v1.5.2-0.20251123071421-2a53c378ae57/go.mod h1:/nr+xEg1LA3FHTsBBwwzrft0oQXsoFfdAwuSNXBQn0U= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= @@ -761,13 +761,14 @@ github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtE github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/bufbuild/protocompile v0.14.1 h1:iA73zAf/fyljNjQKwYzUHD6AD4R8KMasmwa/FBatYVw= github.com/bufbuild/protocompile v0.14.1/go.mod h1:ppVdAIhbr2H8asPk6k4pY7t9zB1OU5DoEw9xY/FUi1c= +github.com/bytedance/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M= +github.com/bytedance/gopkg v0.1.3/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM= github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= -github.com/bytedance/sonic v1.14.0 h1:/OfKt8HFw0kh2rj8N0F6C/qPGRESq0BbaNZgcNXXzQQ= -github.com/bytedance/sonic v1.14.0/go.mod h1:WoEbx8WTcFJfzCe0hbmyTGrfjt8PzNEBdxlNUO24NhA= -github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= -github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA= -github.com/bytedance/sonic/loader v0.3.0/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI= +github.com/bytedance/sonic v1.14.2 h1:k1twIoe97C1DtYUo+fZQy865IuHia4PR5RPiuGPPIIE= +github.com/bytedance/sonic v1.14.2/go.mod h1:T80iDELeHiHKSc0C9tubFygiuXoGzrkjKzX2quAx980= +github.com/bytedance/sonic/loader v0.4.0 h1:olZ7lEqcxtZygCK9EKYKADnpQoYkRQxaeY2NYzevs+o= +github.com/bytedance/sonic/loader v0.4.0/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= @@ -800,9 +801,8 @@ github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6D github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4= -github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= -github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= +github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M= +github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -1346,7 +1346,6 @@ github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02 github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE= github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= -github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= @@ -1662,6 +1661,7 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= @@ -2624,7 +2624,6 @@ modernc.org/z v1.5.1/go.mod h1:eWFB510QWW5Th9YGZT81s+LwvaAs3Q2yr4sP0rmLkv8= nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= nhooyr.io/websocket v1.8.11 h1:f/qXNc2/3DpoSZkHt1DQu6rj4zGC8JmkkLkWss0MgN0= nhooyr.io/websocket v1.8.11/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c= -nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= pgregory.net/rapid v1.2.0 h1:keKAYRcjm+e1F0oAuU5F5+YPAWcyxNNRK2wud503Gnk= pgregory.net/rapid v1.2.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= From d2da9b4e64bbbeac010bf1030f993a4046583126 Mon Sep 17 00:00:00 2001 From: zsystm Date: Sun, 23 Nov 2025 17:24:48 +0900 Subject: [PATCH 16/22] apply updated tag to evmd_broken_localnet script --- evmd_broken_localnet.sh | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/evmd_broken_localnet.sh b/evmd_broken_localnet.sh index 5ffbca743..497e414f7 100755 --- a/evmd_broken_localnet.sh +++ b/evmd_broken_localnet.sh @@ -23,8 +23,8 @@ SINGLE_HOST_DEFAULT="true" STARTING_IP_DEFAULT="127.0.0.1" # Cosmos SDK versions -COSMOS_SDK_NORMAL="github.com/bft-labs/cosmos-sdk v0.53.4-memlogger-4" -COSMOS_SDK_BROKEN="github.com/bft-labs/cosmos-sdk v0.53.4-memlogger-break-0" +COSMOS_SDK_NORMAL="github.com/bft-labs/cosmos-sdk v0.53.4-bft-labs-memlogger" +COSMOS_SDK_BROKEN="github.com/bft-labs/cosmos-sdk v0.53.4-bft-labs-memlogger-apphash-break-0" # Derive settings from env or defaults BASE_DIR=${BASE_DIR:-$BASE_DIR_DEFAULT} @@ -67,12 +67,10 @@ setup_binaries() { fi # Build normal binary - log "Building normal evmd binary (cosmos-sdk v0.53.4-memlogger-4)..." + log "Building normal evmd binary (cosmos-sdk ${COSMOS_SDK_NORMAL})..." log "Updating go.mod files to use ${COSMOS_SDK_NORMAL}" - sed -i '' "s|github.com/cosmos/cosmos-sdk => github.com/bft-labs/cosmos-sdk v0.53.4-memlogger-break-[0-9]*|github.com/cosmos/cosmos-sdk => ${COSMOS_SDK_NORMAL}|" go.mod - sed -i '' "s|github.com/cosmos/cosmos-sdk => github.com/bft-labs/cosmos-sdk v0.53.4-memlogger-[0-9]*|github.com/cosmos/cosmos-sdk => ${COSMOS_SDK_NORMAL}|" go.mod - sed -i '' "s|github.com/cosmos/cosmos-sdk => github.com/bft-labs/cosmos-sdk v0.53.4-memlogger-break-[0-9]*|github.com/cosmos/cosmos-sdk => ${COSMOS_SDK_NORMAL}|" evmd/go.mod - sed -i '' "s|github.com/cosmos/cosmos-sdk => github.com/bft-labs/cosmos-sdk v0.53.4-memlogger-[0-9]*|github.com/cosmos/cosmos-sdk => ${COSMOS_SDK_NORMAL}|" evmd/go.mod + sed -i '' "s|github.com/cosmos/cosmos-sdk => github.com/bft-labs/cosmos-sdk v0.53.4-bft-labs-memlogger.*|github.com/cosmos/cosmos-sdk => ${COSMOS_SDK_NORMAL}|" go.mod + sed -i '' "s|github.com/cosmos/cosmos-sdk => github.com/bft-labs/cosmos-sdk v0.53.4-bft-labs-memlogger.*|github.com/cosmos/cosmos-sdk => ${COSMOS_SDK_NORMAL}|" evmd/go.mod log "Running go mod tidy in root..." go mod tidy @@ -91,10 +89,10 @@ setup_binaries() { log "Normal binary saved to ${BINARY_NORMAL}" # Build broken binary with consensus_break tag - log "Building broken evmd binary (cosmos-sdk v0.53.4-memlogger-break-0 + BUILD_TAGS=consensus_break)..." + log "Building broken evmd binary (cosmos-sdk ${COSMOS_SDK_BROKEN} + BUILD_TAGS=consensus_break)..." log "Updating go.mod files to use ${COSMOS_SDK_BROKEN}" - sed -i '' "s|github.com/cosmos/cosmos-sdk => github.com/bft-labs/cosmos-sdk v0.53.4-memlogger-[0-9]*|github.com/cosmos/cosmos-sdk => ${COSMOS_SDK_BROKEN}|" go.mod - sed -i '' "s|github.com/cosmos/cosmos-sdk => github.com/bft-labs/cosmos-sdk v0.53.4-memlogger-[0-9]*|github.com/cosmos/cosmos-sdk => ${COSMOS_SDK_BROKEN}|" evmd/go.mod + sed -i '' "s|github.com/cosmos/cosmos-sdk => github.com/bft-labs/cosmos-sdk v0.53.4-bft-labs-memlogger.*|github.com/cosmos/cosmos-sdk => ${COSMOS_SDK_BROKEN}|" go.mod + sed -i '' "s|github.com/cosmos/cosmos-sdk => github.com/bft-labs/cosmos-sdk v0.53.4-bft-labs-memlogger.*|github.com/cosmos/cosmos-sdk => ${COSMOS_SDK_BROKEN}|" evmd/go.mod log "Running go mod tidy in root..." go mod tidy From 3f8be5bf31fe3a4f21b36e593807acadcbd58f6a Mon Sep 17 00:00:00 2001 From: bonomoon Date: Mon, 24 Nov 2025 19:07:57 +0900 Subject: [PATCH 17/22] Add docker-compose scripts to run normal and apphash scenarios --- docker-compose.apphash-crash.yml | 213 ++++++++++++++++++++++++++++++ docker-compose.demo.yml | 218 +++++++++++++++++++++++++++++++ 2 files changed, 431 insertions(+) create mode 100644 docker-compose.apphash-crash.yml create mode 100644 docker-compose.demo.yml diff --git a/docker-compose.apphash-crash.yml b/docker-compose.apphash-crash.yml new file mode 100644 index 000000000..0d32c337a --- /dev/null +++ b/docker-compose.apphash-crash.yml @@ -0,0 +1,213 @@ +version: "3" + +services: + # -------------------------------------------------------------------------- + # Setup Service (Initialize Data) + # -------------------------------------------------------------------------- + setup: + build: + context: ../../../evm + dockerfile: contrib/images/evmd-env/Dockerfile + user: root + entrypoint: [] + command: | + sh -c " + # Initialize 4 nodes normally + evmd testnet init-files --validator-count 4 --output-dir /data --chain-id crash-test --keyring-backend test + + echo 'Enabling MemLogger...' + find /data -name app.toml -exec sed -i 's/enabled = false/enabled = true/g' {} + + + # Configure first 3 nodes normally + for i in 0 1 2; do + sed -i 's/127.0.0.1/0.0.0.0/g' /data/node$$i/evmd/config/config.toml + done + + echo 'Enabling MemLogger...' + find /data -name app.toml -exec sed -i 's/enabled = false/enabled = true/g' {} + + + # Node 3: Intentionally corrupt genesis to cause apphash mismatch + echo 'Corrupting node3 genesis to trigger apphash crash...' + # Change initial_height to cause state mismatch (match numeric value) + sed -i 's/\"initial_height\": 1,/\"initial_height\": 999,/' /data/node3/evmd/config/genesis.json + echo 'Changed initial_height from 1 to 999' + + chown -R 1025:1025 /data + " + volumes: + - ./crash-test-data:/data:Z + + # -------------------------------------------------------------------------- + # EVM Node 0 & Shipper 0 + # -------------------------------------------------------------------------- + evmdnode0: + container_name: evmdnode0 + build: + context: ../evm + dockerfile: contrib/images/evmd-env/Dockerfile + environment: + - DEBUG=0 + - ID=0 + - LOG=${LOG:-evmd.log} + depends_on: + setup: + condition: service_completed_successfully + command: start --chain-id crash-test --minimum-gas-prices 0atest --json-rpc.enable true --json-rpc.api eth,txpool,personal,net,debug,web3 + ports: + - "26656-26657:26656-26657" + - "1317:1317" + - "8545:8545" + volumes: + - ./crash-test-data:/data:Z + networks: + - localnet + + walship0: + container_name: walship0 + restart: always + build: + context: ../cosmos-analyzer-shipper + dockerfile: Dockerfile + depends_on: + - evmdnode0 + volumes: + # Mount the same data directory to access node config and WAL + - ./crash-test-data:/data:ro + environment: + # Point to the specific node's root directory inside the volume + - WALSHIP_ROOT=/data/node0/evmd + # Remote analytics backend URL + - WALSHIP_REMOTE_URL=${WALSHIP_REMOTE_URL:-http://host.docker.internal:8080/v1/ingest/wal-frames} + - WALSHIP_AUTH_KEY=${WALSHIP_AUTH_KEY:-dev-local-test-1234} + networks: + - localnet + + # -------------------------------------------------------------------------- + # EVM Node 1 & Shipper 1 + # -------------------------------------------------------------------------- + evmdnode1: + container_name: evmdnode1 + build: + context: ../evm + dockerfile: contrib/images/evmd-env/Dockerfile + environment: + - DEBUG=0 + - ID=1 + - LOG=${LOG:-evmd.log} + depends_on: + setup: + condition: service_completed_successfully + command: start --chain-id crash-test --minimum-gas-prices 0atest --json-rpc.enable true --json-rpc.api eth,txpool,personal,net,debug,web3 + ports: + - "26666-26667:26656-26657" + - "1318:1317" + - "8555:8545" + volumes: + - ./crash-test-data:/data:Z + networks: + - localnet + + walship1: + container_name: walship1 + restart: always + build: + context: ../cosmos-analyzer-shipper + dockerfile: Dockerfile + depends_on: + - evmdnode1 + volumes: + - ./crash-test-data:/data:ro + environment: + - WALSHIP_ROOT=/data/node1/evmd + - WALSHIP_REMOTE_URL=${WALSHIP_REMOTE_URL:-http://host.docker.internal:8080/v1/ingest/wal-frames} + - WALSHIP_AUTH_KEY=${WALSHIP_AUTH_KEY:-dev-local-test-1234} + networks: + - localnet + + # -------------------------------------------------------------------------- + # EVM Node 2 & Shipper 2 + # -------------------------------------------------------------------------- + evmdnode2: + container_name: evmdnode2 + build: + context: ../evm + dockerfile: contrib/images/evmd-env/Dockerfile + environment: + - DEBUG=0 + - ID=2 + - LOG=${LOG:-evmd.log} + depends_on: + setup: + condition: service_completed_successfully + command: start --chain-id crash-test --minimum-gas-prices 0atest --json-rpc.enable true --json-rpc.api eth,txpool,personal,net,debug,web3 + ports: + - "26676-26677:26656-26657" + - "1319:1317" + - "8565:8545" + volumes: + - ./crash-test-data:/data:Z + networks: + - localnet + + walship2: + container_name: walship2 + restart: always + build: + context: ../cosmos-analyzer-shipper + dockerfile: Dockerfile + depends_on: + - evmdnode2 + volumes: + - ./crash-test-data:/data:ro + environment: + - WALSHIP_ROOT=/data/node2/evmd + - WALSHIP_REMOTE_URL=${WALSHIP_REMOTE_URL:-http://host.docker.internal:8080/v1/ingest/wal-frames} + - WALSHIP_AUTH_KEY=${WALSHIP_AUTH_KEY:-dev-local-test-1234} + networks: + - localnet + + # -------------------------------------------------------------------------- + # EVM Node 3 & Shipper 3 + # -------------------------------------------------------------------------- + evmdnode3: + container_name: evmdnode3 + build: + context: ../evm + dockerfile: contrib/images/evmd-env/Dockerfile + environment: + - DEBUG=0 + - ID=3 + - LOG=${LOG:-evmd.log} + depends_on: + setup: + condition: service_completed_successfully + command: start --chain-id crash-test --minimum-gas-prices 0atest --json-rpc.enable true --json-rpc.api eth,txpool,personal,net,debug,web3 + ports: + - "26686-26687:26656-26657" + - "1320:1317" + - "8575:8545" + volumes: + - ./crash-test-data:/data:Z + networks: + - localnet + + walship3: + container_name: walship3 + restart: always + build: + context: ../cosmos-analyzer-shipper + dockerfile: Dockerfile + depends_on: + - evmdnode3 + volumes: + - ./crash-test-data:/data:ro + environment: + - WALSHIP_ROOT=/data/node3/evmd + - WALSHIP_REMOTE_URL=${WALSHIP_REMOTE_URL:-http://host.docker.internal:8080/v1/ingest/wal-frames} + - WALSHIP_AUTH_KEY=${WALSHIP_AUTH_KEY:-dev-local-test-1234} + networks: + - localnet + +networks: + localnet: + driver: bridge diff --git a/docker-compose.demo.yml b/docker-compose.demo.yml new file mode 100644 index 000000000..79bf8d6b5 --- /dev/null +++ b/docker-compose.demo.yml @@ -0,0 +1,218 @@ +version: "3" + +services: + # -------------------------------------------------------------------------- + # Setup Service (Initialize Data) + # -------------------------------------------------------------------------- + setup: + container_name: setup + build: + context: ../evm + dockerfile: contrib/images/evmd-env/Dockerfile + user: root + entrypoint: [] + command: | + sh -c " + if [ ! -f /data/node0/evmd/config/genesis.json ]; then + echo 'Initializing testnet data...' + evmd testnet init-files --validator-count 4 --output-dir /data --chain-id ${CHAIN_ID:-local-test-1234} --keyring-backend test + + echo 'Configuring network binding...' + find /data -name config.toml -exec sed -i 's/127.0.0.1/0.0.0.0/g' {} + + + echo 'Enabling MemLogger...' + find /data -name app.toml -exec sed -i 's/enabled = false/enabled = true/g' {} + + + echo 'Configuring persistent peers...' + PEERS=\"\" + for i in 0 1 2 3; do + NODE_ID=$$(evmd comet show-node-id --home /data/node$$i/evmd) + PEER=\"$$NODE_ID@evmdnode$$i:26656\" + if [ -z \"$$PEERS\" ]; then PEERS=\"$$PEER\"; else PEERS=\"$$PEERS,$$PEER\"; fi + done + echo \"Peers: $$PEERS\" + find /data -name config.toml -exec sed -i \"s/^persistent_peers = .*/persistent_peers = \\\"$$PEERS\\\"/\" {} + + + echo 'Fixing permissions...' + chown -R 1025:1025 /data + else + echo 'Testnet data already exists.' + fi + " + volumes: + - ./.testnets:/data:Z + + # -------------------------------------------------------------------------- + # EVM Node 0 & Shipper 0 + # -------------------------------------------------------------------------- + evmdnode0: + container_name: evmdnode0 + build: + context: ../evm + dockerfile: contrib/images/evmd-env/Dockerfile + environment: + - DEBUG=0 + - ID=0 + - LOG=${LOG:-evmd.log} + depends_on: + setup: + condition: service_completed_successfully + command: start --chain-id ${CHAIN_ID:-local-test-1234} --minimum-gas-prices 0atest --json-rpc.enable true --json-rpc.api eth,txpool,personal,net,debug,web3 + ports: + - "26656-26657:26656-26657" + - "1317:1317" + - "8545:8545" + volumes: + - ./.testnets:/data:Z + networks: + - localnet + + walship0: + container_name: walship0 + restart: always + build: + context: ../cosmos-analyzer-shipper + dockerfile: Dockerfile + depends_on: + - evmdnode0 + volumes: + # Mount the same data directory to access node config and WAL + - ./.testnets:/data:ro + environment: + # Point to the specific node's root directory inside the volume + - WALSHIP_ROOT=/data/node0/evmd + # Remote analytics backend URL + - WALSHIP_REMOTE_URL=${WALSHIP_REMOTE_URL:-http://host.docker.internal:8080/v1/ingest/wal-frames} + - WALSHIP_AUTH_KEY=${WALSHIP_AUTH_KEY:-dev-local-test-1234} + networks: + - localnet + + # -------------------------------------------------------------------------- + # EVM Node 1 & Shipper 1 + # -------------------------------------------------------------------------- + evmdnode1: + container_name: evmdnode1 + build: + context: ../evm + dockerfile: contrib/images/evmd-env/Dockerfile + environment: + - DEBUG=0 + - ID=1 + - LOG=${LOG:-evmd.log} + depends_on: + setup: + condition: service_completed_successfully + command: start --chain-id ${CHAIN_ID:-local-test-1234} --minimum-gas-prices 0atest --json-rpc.enable true --json-rpc.api eth,txpool,personal,net,debug,web3 + ports: + - "26666-26667:26656-26657" + - "1318:1317" + - "8555:8545" + volumes: + - ./.testnets:/data:Z + networks: + - localnet + + walship1: + container_name: walship1 + restart: always + build: + context: ../cosmos-analyzer-shipper + dockerfile: Dockerfile + depends_on: + - evmdnode1 + volumes: + - ./.testnets:/data:ro + environment: + - WALSHIP_ROOT=/data/node1/evmd + - WALSHIP_REMOTE_URL=${WALSHIP_REMOTE_URL:-http://host.docker.internal:8080/v1/ingest/wal-frames} + - WALSHIP_AUTH_KEY=${WALSHIP_AUTH_KEY:-dev-local-test-1234} + networks: + - localnet + + # -------------------------------------------------------------------------- + # EVM Node 2 & Shipper 2 + # -------------------------------------------------------------------------- + evmdnode2: + container_name: evmdnode2 + build: + context: ../evm + dockerfile: contrib/images/evmd-env/Dockerfile + environment: + - DEBUG=0 + - ID=2 + - LOG=${LOG:-evmd.log} + depends_on: + setup: + condition: service_completed_successfully + command: start --chain-id ${CHAIN_ID:-local-test-1234} --minimum-gas-prices 0atest --json-rpc.enable true --json-rpc.api eth,txpool,personal,net,debug,web3 + ports: + - "26676-26677:26656-26657" + - "1319:1317" + - "8565:8545" + volumes: + - ./.testnets:/data:Z + networks: + - localnet + + walship2: + container_name: walship2 + restart: always + build: + context: ../cosmos-analyzer-shipper + dockerfile: Dockerfile + depends_on: + - evmdnode2 + volumes: + - ./.testnets:/data:ro + environment: + - WALSHIP_ROOT=/data/node2/evmd + - WALSHIP_REMOTE_URL=${WALSHIP_REMOTE_URL:-http://host.docker.internal:8080/v1/ingest/wal-frames} + - WALSHIP_AUTH_KEY=${WALSHIP_AUTH_KEY:-dev-local-test-1234} + networks: + - localnet + + # -------------------------------------------------------------------------- + # EVM Node 3 & Shipper 3 + # -------------------------------------------------------------------------- + evmdnode3: + container_name: evmdnode3 + build: + context: ../evm + dockerfile: contrib/images/evmd-env/Dockerfile + environment: + - DEBUG=0 + - ID=3 + - LOG=${LOG:-evmd.log} + depends_on: + setup: + condition: service_completed_successfully + command: start --chain-id ${CHAIN_ID:-local-test-1234} --minimum-gas-prices 0atest --json-rpc.enable true --json-rpc.api eth,txpool,personal,net,debug,web3 + ports: + - "26686-26687:26656-26657" + - "1320:1317" + - "8575:8545" + volumes: + - ./.testnets:/data:Z + networks: + - localnet + + walship3: + container_name: walship3 + restart: always + build: + context: ../cosmos-analyzer-shipper + dockerfile: Dockerfile + depends_on: + - evmdnode3 + volumes: + - ./.testnets:/data:ro + environment: + - WALSHIP_ROOT=/data/node3/evmd + - WALSHIP_REMOTE_URL=${WALSHIP_REMOTE_URL:-http://host.docker.internal:8080/v1/ingest/wal-frames} + - WALSHIP_AUTH_KEY=${WALSHIP_AUTH_KEY:-dev-local-test-1234} + networks: + - localnet + +networks: + localnet: + driver: bridge From 4d1a62844bec2d150fce55224116249ba2459671 Mon Sep 17 00:00:00 2001 From: zsystm Date: Sat, 29 Nov 2025 12:47:39 +0900 Subject: [PATCH 18/22] update docker compose --- docker-compose.demo.yml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/docker-compose.demo.yml b/docker-compose.demo.yml index 79bf8d6b5..2fbb70aef 100644 --- a/docker-compose.demo.yml +++ b/docker-compose.demo.yml @@ -31,7 +31,9 @@ services: if [ -z \"$$PEERS\" ]; then PEERS=\"$$PEER\"; else PEERS=\"$$PEERS,$$PEER\"; fi done echo \"Peers: $$PEERS\" - find /data -name config.toml -exec sed -i \"s/^persistent_peers = .*/persistent_peers = \\\"$$PEERS\\\"/\" {} + + for i in 0 1 2 3; do + sed -i \"s|^persistent_peers = .*|persistent_peers = \\\"$$PEERS\\\"|\" /data/node$$i/evmd/config/config.toml + done echo 'Fixing permissions...' chown -R 1025:1025 /data @@ -83,7 +85,7 @@ services: - WALSHIP_ROOT=/data/node0/evmd # Remote analytics backend URL - WALSHIP_REMOTE_URL=${WALSHIP_REMOTE_URL:-http://host.docker.internal:8080/v1/ingest/wal-frames} - - WALSHIP_AUTH_KEY=${WALSHIP_AUTH_KEY:-dev-local-test-1234} + - WALSHIP_AUTH_KEY=${WALSHIP_AUTH_KEY:-5a21c5c5dcf34b1aad1eafff1d0e6653} networks: - localnet @@ -125,7 +127,7 @@ services: environment: - WALSHIP_ROOT=/data/node1/evmd - WALSHIP_REMOTE_URL=${WALSHIP_REMOTE_URL:-http://host.docker.internal:8080/v1/ingest/wal-frames} - - WALSHIP_AUTH_KEY=${WALSHIP_AUTH_KEY:-dev-local-test-1234} + - WALSHIP_AUTH_KEY=${WALSHIP_AUTH_KEY:-5a21c5c5dcf34b1aad1eafff1d0e6653} networks: - localnet @@ -167,7 +169,7 @@ services: environment: - WALSHIP_ROOT=/data/node2/evmd - WALSHIP_REMOTE_URL=${WALSHIP_REMOTE_URL:-http://host.docker.internal:8080/v1/ingest/wal-frames} - - WALSHIP_AUTH_KEY=${WALSHIP_AUTH_KEY:-dev-local-test-1234} + - WALSHIP_AUTH_KEY=${WALSHIP_AUTH_KEY:-5a21c5c5dcf34b1aad1eafff1d0e6653} networks: - localnet @@ -209,7 +211,7 @@ services: environment: - WALSHIP_ROOT=/data/node3/evmd - WALSHIP_REMOTE_URL=${WALSHIP_REMOTE_URL:-http://host.docker.internal:8080/v1/ingest/wal-frames} - - WALSHIP_AUTH_KEY=${WALSHIP_AUTH_KEY:-dev-local-test-1234} + - WALSHIP_AUTH_KEY=${WALSHIP_AUTH_KEY:-5a21c5c5dcf34b1aad1eafff1d0e6653} networks: - localnet From 85418f5428c0836d94ae24f3d052ef3698dda612 Mon Sep 17 00:00:00 2001 From: zsystm Date: Sat, 29 Nov 2025 12:50:33 +0900 Subject: [PATCH 19/22] update context --- docker-compose.demo.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docker-compose.demo.yml b/docker-compose.demo.yml index 2fbb70aef..5b75fc049 100644 --- a/docker-compose.demo.yml +++ b/docker-compose.demo.yml @@ -7,7 +7,7 @@ services: setup: container_name: setup build: - context: ../evm + context: . dockerfile: contrib/images/evmd-env/Dockerfile user: root entrypoint: [] @@ -50,7 +50,7 @@ services: evmdnode0: container_name: evmdnode0 build: - context: ../evm + context: . dockerfile: contrib/images/evmd-env/Dockerfile environment: - DEBUG=0 @@ -95,7 +95,7 @@ services: evmdnode1: container_name: evmdnode1 build: - context: ../evm + context: . dockerfile: contrib/images/evmd-env/Dockerfile environment: - DEBUG=0 @@ -137,7 +137,7 @@ services: evmdnode2: container_name: evmdnode2 build: - context: ../evm + context: . dockerfile: contrib/images/evmd-env/Dockerfile environment: - DEBUG=0 @@ -179,7 +179,7 @@ services: evmdnode3: container_name: evmdnode3 build: - context: ../evm + context: . dockerfile: contrib/images/evmd-env/Dockerfile environment: - DEBUG=0 From 70d3d4106d0376abeb408c2734ca567c37b0ddb7 Mon Sep 17 00:00:00 2001 From: zsystm Date: Sat, 29 Nov 2025 12:53:12 +0900 Subject: [PATCH 20/22] remove un-necessary scripts --- evmd_localnet_memlogger.sh | 415 ------------------------------ evmd_localnet_nomemlogger.sh | 413 ----------------------------- evmd_localnet_nomemlogger_info.sh | 412 ----------------------------- 3 files changed, 1240 deletions(-) delete mode 100755 evmd_localnet_memlogger.sh delete mode 100755 evmd_localnet_nomemlogger.sh delete mode 100755 evmd_localnet_nomemlogger_info.sh diff --git a/evmd_localnet_memlogger.sh b/evmd_localnet_memlogger.sh deleted file mode 100755 index eae9ead38..000000000 --- a/evmd_localnet_memlogger.sh +++ /dev/null @@ -1,415 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# Simple multi-node localnet launcher for evmd -# - Initializes N validator nodes under BASE_DIR using `evmd testnet init-files --validator-count N --keyring-backend test` -# - Applies surge faucet to node0 genesis, then replicates the modified genesis to all nodes -# - Optionally computes persistent_peers via `evmd comet show-node-id` if available -# - Starts each node with its own home and port set by init-files -# -# Usage: -# scripts/evmd-localnet.sh start # init (if needed) and start N nodes -# scripts/evmd-localnet.sh stop # stop nodes started by this script (via PID file) -# scripts/evmd-localnet.sh clean # remove BASE_DIR - -BINARY_DEFAULT="evmd" # or override via BINARY env -BASE_DIR_DEFAULT="./.testnets" # or override via BASE_DIR env -NODE_PREFIX_DEFAULT="node" -N_DEFAULT=4 -# Start defaults (min gas aligned with local_node.sh) -MIN_GAS_PRICES_DEFAULT="0atest" -SURGE_CMD_DEFAULT="surge faucet" # or override via SURGE_CMD env; extra args via SURGE_ARGS -CHAIN_ID_DEFAULT="local-4221" # or override via CHAIN_ID env -SINGLE_HOST_DEFAULT="true" # allocate unique ports per node on one host -STARTING_IP_DEFAULT="127.0.0.1" # starting IP for init-files on single host - -# Derive settings from env or defaults -BINARY=${BINARY:-$BINARY_DEFAULT} -BASE_DIR=${BASE_DIR:-$BASE_DIR_DEFAULT} -NODE_PREFIX=${NODE_PREFIX:-$NODE_PREFIX_DEFAULT} -N=${N:-$N_DEFAULT} -MIN_GAS_PRICES=${MIN_GAS_PRICES:-$MIN_GAS_PRICES_DEFAULT} -SURGE_CMD=${SURGE_CMD:-$SURGE_CMD_DEFAULT} -SURGE_ARGS=${SURGE_ARGS:-} -CHAIN_ID=${CHAIN_ID:-$CHAIN_ID_DEFAULT} -SINGLE_HOST=${SINGLE_HOST:-$SINGLE_HOST_DEFAULT} -STARTING_IP_ADDRESS=${STARTING_IP_ADDRESS:-$STARTING_IP_DEFAULT} - -# Internal -PID_FILE="${BASE_DIR}/evmd_localnet.pids" - -log() { echo "[evmd-localnet] $*"; } -err() { echo "[evmd-localnet:ERROR] $*" >&2; } - -ensure_binary() { - if command -v "$BINARY" >/dev/null 2>&1; then - return 0 - fi - # Fallback to local build path - if [ -x "./build/evmd" ]; then - BINARY="./build/evmd" - return 0 - fi - err "Cannot find evmd binary. Put it on PATH or build via 'make build'." - exit 1 -} - -init_fresh() { - # Always initialize a fresh testnet as requested - rm -rf "$BASE_DIR" - log "Initializing ${N}-node testnet at ${BASE_DIR}…" - mkdir -p "$BASE_DIR" - - # Per request: use only validator-count and keyring-backend flags (+ output-dir to control location) - local cmd=("$BINARY" testnet init-files \ - --validator-count "${N}" \ - --keyring-backend test \ - --output-dir "${BASE_DIR}") - - # Add chain-id if supported by the subcommand - if "$BINARY" testnet init-files --help 2>/dev/null | grep -q -- "--chain-id"; then - cmd+=(--chain-id "${CHAIN_ID}") - fi - # Use single-host ports from generator if supported - if [ "${SINGLE_HOST}" = "true" ] && "$BINARY" testnet init-files --help 2>/dev/null | grep -q -- "--single-host"; then - cmd+=(--single-host=true) - fi - # Set starting IP address if supported (helps ensure 127.0.0.1 mapping) - if [ "${SINGLE_HOST}" = "true" ] && "$BINARY" testnet init-files --help 2>/dev/null | grep -q -- "--starting-ip-address"; then - cmd+=(--starting-ip-address "${STARTING_IP_ADDRESS}") - fi - - printf '[evmd-localnet] Exec: ' - for a in "${cmd[@]}"; do printf '%s ' "$a"; done; printf '\n' - "${cmd[@]}" - - log "Init complete (chain-id: ${CHAIN_ID}). Genesis and configs under ${BASE_DIR}/${NODE_PREFIX}{0..$((N-1))}/evmd" - - # Fallback: if init-files doesn't support --chain-id, patch genesis chain_id via jq - if ! "$BINARY" testnet init-files --help 2>/dev/null | grep -q -- "--chain-id"; then - if command -v jq >/dev/null 2>&1; then - for ((i=0; i< N; i++)); do - gi="${BASE_DIR}/${NODE_PREFIX}${i}/evmd/config/genesis.json" - if [ -f "$gi" ]; then - tmp="$gi.tmp" && jq --arg cid "$CHAIN_ID" '.chain_id=$cid' "$gi" > "$tmp" && mv "$tmp" "$gi" - fi - done - log "Patched genesis chain_id to '${CHAIN_ID}' via jq (fallback path)." - else - log "jq not found; cannot patch genesis chain_id. Using defaults from init-files." - fi - fi -} - -# Update per-node ports for single host to avoid conflicts -adjust_ports_single_host() { - if [ "${SINGLE_HOST}" != "true" ]; then - log "SINGLE_HOST is not enabled; skipping port adjustments." - return 0 - fi - - # Helper to set a key inside a specific TOML section - toml_set_key_in_section() { - local file="$1" section="$2" key="$3" value="$4" - awk -v section="$section" -v key="$key" -v value="$value" ' - BEGIN { insec=0; done=0 } - /^[[:space:]]*\[/ { - if (insec && !done) { print key " = \"" value "\""; done=1 } - insec=0 - if ($0 ~ "^\\[" section "\\]") { insec=1 } - print; next - } - { - if (insec && $0 ~ "^[[:space:]]*" key "[[:space:]]*=") { - print key " = \"" value "\""; done=1; next - } - print - } - END { - if (insec && !done) { print key " = \"" value "\"" } - } - ' "$file" >"$file.tmp" && mv "$file.tmp" "$file" - } - - for ((i=0; i< N; i++)); do - local home_dir="${BASE_DIR}/${NODE_PREFIX}${i}/evmd" - local cfg_tm="${home_dir}/config/config.toml" - local cfg_app="${home_dir}/config/app.toml" - - [ -f "$cfg_tm" ] || { err "Missing $cfg_tm"; continue; } - [ -f "$cfg_app" ] || { err "Missing $cfg_app"; continue; } - - # Compute unique ports - local rpc_port=$((26657 + i)) - local p2p_port=$((16656 + i)) - local pprof_port=$((6060 + i)) - local prom_port=$((26660 + i)) - local api_port=$((1317 + i)) - local grpc_port=$((9090 + i)) - local grpcweb_port=$((9091 + i)) - local http_port=$((8545 + i*10)) - local ws_port=$((8546 + i*10)) - - # Tendermint config.toml - toml_set_key_in_section "$cfg_tm" "rpc" "laddr" "tcp://127.0.0.1:${rpc_port}" - toml_set_key_in_section "$cfg_tm" "rpc" "pprof_laddr" "localhost:${pprof_port}" - toml_set_key_in_section "$cfg_tm" "p2p" "laddr" "tcp://127.0.0.1:${p2p_port}" - toml_set_key_in_section "$cfg_tm" "instrumentation" "prometheus_listen_addr" ":${prom_port}" - - # Application app.toml - toml_set_key_in_section "$cfg_app" "api" "address" "tcp://127.0.0.1:${api_port}" - toml_set_key_in_section "$cfg_app" "grpc" "address" "127.0.0.1:${grpc_port}" - toml_set_key_in_section "$cfg_app" "grpc-web" "address" "127.0.0.1:${grpcweb_port}" - toml_set_key_in_section "$cfg_app" "json-rpc" "address" "127.0.0.1:${http_port}" - toml_set_key_in_section "$cfg_app" "json-rpc" "ws-address" "127.0.0.1:${ws_port}" - - log "Configured ${NODE_PREFIX}${i} ports: rpc:${rpc_port} p2p:${p2p_port} api:${api_port} http:${http_port} ws:${ws_port} grpc:${grpc_port}/${grpcweb_port}" - done -} - -# Apply consensus timeout adjustments similar to local_node.sh -tune_timeouts() { - for ((i=0; i< N; i++)); do - local CONFIG_TOML="${BASE_DIR}/${NODE_PREFIX}${i}/evmd/config/config.toml" - if [ ! -f "$CONFIG_TOML" ]; then - err "Missing $CONFIG_TOML" - continue - fi - # Logging: debug level and json format - sed -i.bak 's/log_level = "info"/log_level = "debug"/g' "$CONFIG_TOML" - sed -i.bak 's/log_format = "plain"/log_format = "json"/g' "$CONFIG_TOML" - sed -i.bak 's/timeout_propose = "3s"/timeout_propose = "2s"/g' "$CONFIG_TOML" - sed -i.bak 's/timeout_propose_delta = "500ms"/timeout_propose_delta = "200ms"/g' "$CONFIG_TOML" - sed -i.bak 's/timeout_prevote = "1s"/timeout_prevote = "500ms"/g' "$CONFIG_TOML" - sed -i.bak 's/timeout_prevote_delta = "500ms"/timeout_prevote_delta = "200ms"/g' "$CONFIG_TOML" - sed -i.bak 's/timeout_precommit = "1s"/timeout_precommit = "500ms"/g' "$CONFIG_TOML" - sed -i.bak 's/timeout_precommit_delta = "500ms"/timeout_precommit_delta = "200ms"/g' "$CONFIG_TOML" - sed -i.bak 's/timeout_commit = "5s"/timeout_commit = "1s"/g' "$CONFIG_TOML" - sed -i.bak 's/timeout_broadcast_tx_commit = "10s"/timeout_broadcast_tx_commit = "5s"/g' "$CONFIG_TOML" - done - log "Applied consensus timeout adjustments to all nodes." -} - -# Adjust memlogger settings in app.toml for each node -adjust_memlogger() { - for ((i=0; i< N; i++)); do - local APP_TOML="${BASE_DIR}/${NODE_PREFIX}${i}/evmd/config/app.toml" - if [ ! -f "$APP_TOML" ]; then - err "Missing $APP_TOML" - continue - fi - - # Helpers local to this function - toml_set_key_in_section() { - local file="$1" section="$2" key="$3" value="$4" - awk -v section="$section" -v key="$key" -v value="$value" ' - BEGIN { insec=0; done=0 } - /^[[:space:]]*\[/ { - if (insec && !done) { print key " = \"" value "\""; done=1 } - insec=0 - if ($0 ~ "^\\[" section "\\]") { insec=1 } - print; next - } - { - if (insec && $0 ~ "^[[:space:]]*" key "[[:space:]]*=") { - print key " = \"" value "\""; done=1; next - } - print - } - END { - if (insec && !done) { print key " = \"" value "\"" } - } - ' "$file" >"$file.tmp" && mv "$file.tmp" "$file" - } - - toml_set_key_in_section_raw() { - local file="$1" section="$2" key="$3" rawvalue="$4" - awk -v section="$section" -v key="$key" -v rawvalue="$rawvalue" ' - BEGIN { insec=0; done=0 } - /^[[:space:]]*\[/ { - if (insec && !done) { print key " = " rawvalue; done=1 } - insec=0 - if ($0 ~ "^\\[" section "\\]") { insec=1 } - print; next - } - { - if (insec && $0 ~ "^[[:space:]]*" key "[[:space:]]*=") { - print key " = " rawvalue; done=1; next - } - print - } - END { - if (insec && !done) { print key " = " rawvalue } - } - ' "$file" >"$file.tmp" && mv "$file.tmp" "$file" - } - - # enable memlogger - toml_set_key_in_section "$APP_TOML" "memlogger" "enabled" "true" - toml_set_key_in_section "$APP_TOML" "memlogger" "interval" "2s" - toml_set_key_in_section_raw "$APP_TOML" "memlogger" "memory-bytes" "104857600" - done -} - -apply_surge_and_replicate() { - # Apply surge faucet on node0 genesis, then copy to other nodes - local g0="${BASE_DIR}/${NODE_PREFIX}0/evmd/config/genesis.json" - if [ ! -f "$g0" ]; then - err "node0 genesis not found at $g0" - exit 1 - fi - - # Run surge faucet if available/desired - if [ -n "$SURGE_CMD" ]; then - local surge_bin - surge_bin=$(echo "$SURGE_CMD" | awk '{print $1}') - if ! command -v "$surge_bin" >/dev/null 2>&1; then - err "'$surge_bin' not found on PATH. Set SURGE_CMD='' to skip or install surge." - exit 1 - fi - # Echo the exact command - printf '[evmd-localnet] Exec: %s %s %s\n' "$SURGE_CMD" "${SURGE_ARGS}" "$g0" - # Execute with optional extra args - eval "$SURGE_CMD ${SURGE_ARGS} $g0" - else - log "SURGE_CMD empty; skipping surge faucet step." - fi - - # Replicate node0 genesis to all other nodes - for ((i=1; i< N; i++)); do - local gi="${BASE_DIR}/${NODE_PREFIX}${i}/evmd/config/genesis.json" - if [ -f "$gi" ]; then - cp "$g0" "$gi" - fi - done - - # Validate genesis for all nodes (best-effort) - for ((i=0; i< N; i++)); do - local home_dir="${BASE_DIR}/${NODE_PREFIX}${i}/evmd" - if [ -d "$home_dir" ]; then - "$BINARY" genesis validate-genesis --home "$home_dir" >/dev/null 2>&1 || true - fi - done -} - -build_peers_if_possible() { - # Try to gather node IDs using `evmd comet show-node-id` if the subcommand exists. - if ! "$BINARY" comet --help >/dev/null 2>&1; then - log "'evmd comet' subcommand not found. Skipping persistent_peers injection (nodes should still connect with generated configs)." - return 0 - fi - - local peers="" - for ((i=0; i< N; i++)); do - local home_dir="${BASE_DIR}/${NODE_PREFIX}${i}/evmd" - local id - if ! id=$("$BINARY" comet show-node-id --home "$home_dir" 2>/dev/null); then - err "Failed to read node ID for ${NODE_PREFIX}${i}; skipping persistent_peers." - return 0 - fi - # Ports per init-files when --single-host is used: - # - P2P starts at 16656 and increments by +1 per node - local p2p_port=$((16656 + i)) - local entry="${id}@127.0.0.1:${p2p_port}" - if [ -z "$peers" ]; then peers="$entry"; else peers+="",$entry; fi - done - - log "persistent_peers=${peers}" - # Inject into each node's config.toml - for ((i=0; i< N; i++)); do - local cfg="${BASE_DIR}/${NODE_PREFIX}${i}/evmd/config/config.toml" - if [ -f "$cfg" ]; then - # Replace existing line or append if missing - if grep -q '^persistent_peers\s*=\s*"' "$cfg"; then - sed -i.bak -E "s|^persistent_peers\s*=\s*\".*\"|persistent_peers = \"${peers}\"|" "$cfg" - else - echo "persistent_peers = \"${peers}\"" >> "$cfg" - fi - fi - done -} - -start_nodes() { - mkdir -p "$(dirname "$PID_FILE")" - : > "$PID_FILE" - - for ((i=0; i< N; i++)); do - local home_dir="${BASE_DIR}/${NODE_PREFIX}${i}/evmd" - local log_file="${home_dir}/evmd.log" - - # Compute display ports that init-files configure for single-host: - local rpc_port=$((26657 + i)) - local p2p_port=$((16656 + i)) - local api_port=$((1317 + i)) - local http_port=$((8545 + i*10)) - local ws_port=$((8546 + i*10)) - - log "Starting ${NODE_PREFIX}${i} (rpc:${rpc_port}, p2p:${p2p_port}, api:${api_port}, http:${http_port}, ws:${ws_port})" - - # Ensure client chain-id is set for this home (useful for CLI interactions) - "$BINARY" config set client chain-id "${CHAIN_ID}" --home "$home_dir" >/dev/null 2>&1 || true - - # Build start command (aligned with local_node.sh gas defaults) and echo it for reproducibility - cmd=("$BINARY" start \ - --home "$home_dir" \ - --minimum-gas-prices "${MIN_GAS_PRICES}" \ - --evm.min-tip 0 \ - --json-rpc.api "eth,txpool,personal,net,debug,web3" \ - --chain-id "${CHAIN_ID}") - - printf '[evmd-localnet] Exec: ' - for arg in "${cmd[@]}"; do printf '%s ' "$arg"; done; printf '\n' - - # Start in background, capture PID - ("${cmd[@]}" >"$log_file" 2>&1 & echo $! >> "$PID_FILE") - sleep 0.5 - done - - log "All nodes started. PIDs recorded in ${PID_FILE}" -} - -stop_nodes() { - if [ ! -f "$PID_FILE" ]; then - err "PID file not found: $PID_FILE" - exit 1 - fi - tac "$PID_FILE" | while read -r pid; do - if kill -0 "$pid" >/dev/null 2>&1; then - log "Stopping PID $pid" - kill "$pid" || true - fi - done - rm -f "$PID_FILE" - log "All nodes stopped." -} - -clean() { - if [ -d "$BASE_DIR" ]; then - log "Removing ${BASE_DIR}" - rm -rf "$BASE_DIR" - fi -} - -cmd=${1:-start} -case "$cmd" in - start) - ensure_binary - init_fresh - apply_surge_and_replicate - adjust_ports_single_host - tune_timeouts - adjust_memlogger - build_peers_if_possible - start_nodes - ;; - stop) - stop_nodes - ;; - clean) - clean - ;; - *) - echo "Usage: $0 {start|stop|clean}" >&2 - exit 1 - ;; -esac diff --git a/evmd_localnet_nomemlogger.sh b/evmd_localnet_nomemlogger.sh deleted file mode 100755 index 0de6dc5e6..000000000 --- a/evmd_localnet_nomemlogger.sh +++ /dev/null @@ -1,413 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# Simple multi-node localnet launcher for evmd -# - Initializes N validator nodes under BASE_DIR using `evmd testnet init-files --validator-count N --keyring-backend test` -# - Applies surge faucet to node0 genesis, then replicates the modified genesis to all nodes -# - Optionally computes persistent_peers via `evmd comet show-node-id` if available -# - Starts each node with its own home and port set by init-files -# -# Usage: -# scripts/evmd-localnet.sh start # init (if needed) and start N nodes -# scripts/evmd-localnet.sh stop # stop nodes started by this script (via PID file) -# scripts/evmd-localnet.sh clean # remove BASE_DIR - -BINARY_DEFAULT="evmd" # or override via BINARY env -BASE_DIR_DEFAULT="./.testnets" # or override via BASE_DIR env -NODE_PREFIX_DEFAULT="node" -N_DEFAULT=4 -# Start defaults (min gas aligned with local_node.sh) -MIN_GAS_PRICES_DEFAULT="0atest" -SURGE_CMD_DEFAULT="surge faucet" # or override via SURGE_CMD env; extra args via SURGE_ARGS -CHAIN_ID_DEFAULT="local-4221" # or override via CHAIN_ID env -SINGLE_HOST_DEFAULT="true" # allocate unique ports per node on one host -STARTING_IP_DEFAULT="127.0.0.1" # starting IP for init-files on single host - -# Derive settings from env or defaults -BINARY=${BINARY:-$BINARY_DEFAULT} -BASE_DIR=${BASE_DIR:-$BASE_DIR_DEFAULT} -NODE_PREFIX=${NODE_PREFIX:-$NODE_PREFIX_DEFAULT} -N=${N:-$N_DEFAULT} -MIN_GAS_PRICES=${MIN_GAS_PRICES:-$MIN_GAS_PRICES_DEFAULT} -SURGE_CMD=${SURGE_CMD:-$SURGE_CMD_DEFAULT} -SURGE_ARGS=${SURGE_ARGS:-} -CHAIN_ID=${CHAIN_ID:-$CHAIN_ID_DEFAULT} -SINGLE_HOST=${SINGLE_HOST:-$SINGLE_HOST_DEFAULT} -STARTING_IP_ADDRESS=${STARTING_IP_ADDRESS:-$STARTING_IP_DEFAULT} - -# Internal -PID_FILE="${BASE_DIR}/evmd_localnet.pids" - -log() { echo "[evmd-localnet] $*"; } -err() { echo "[evmd-localnet:ERROR] $*" >&2; } - -ensure_binary() { - if command -v "$BINARY" >/dev/null 2>&1; then - return 0 - fi - # Fallback to local build path - if [ -x "./build/evmd" ]; then - BINARY="./build/evmd" - return 0 - fi - err "Cannot find evmd binary. Put it on PATH or build via 'make build'." - exit 1 -} - -init_fresh() { - # Always initialize a fresh testnet as requested - rm -rf "$BASE_DIR" - log "Initializing ${N}-node testnet at ${BASE_DIR}…" - mkdir -p "$BASE_DIR" - - # Per request: use only validator-count and keyring-backend flags (+ output-dir to control location) - local cmd=("$BINARY" testnet init-files \ - --validator-count "${N}" \ - --keyring-backend test \ - --output-dir "${BASE_DIR}") - - # Add chain-id if supported by the subcommand - if "$BINARY" testnet init-files --help 2>/dev/null | grep -q -- "--chain-id"; then - cmd+=(--chain-id "${CHAIN_ID}") - fi - # Use single-host ports from generator if supported - if [ "${SINGLE_HOST}" = "true" ] && "$BINARY" testnet init-files --help 2>/dev/null | grep -q -- "--single-host"; then - cmd+=(--single-host=true) - fi - # Set starting IP address if supported (helps ensure 127.0.0.1 mapping) - if [ "${SINGLE_HOST}" = "true" ] && "$BINARY" testnet init-files --help 2>/dev/null | grep -q -- "--starting-ip-address"; then - cmd+=(--starting-ip-address "${STARTING_IP_ADDRESS}") - fi - - printf '[evmd-localnet] Exec: ' - for a in "${cmd[@]}"; do printf '%s ' "$a"; done; printf '\n' - "${cmd[@]}" - - log "Init complete (chain-id: ${CHAIN_ID}). Genesis and configs under ${BASE_DIR}/${NODE_PREFIX}{0..$((N-1))}/evmd" - - # Fallback: if init-files doesn't support --chain-id, patch genesis chain_id via jq - if ! "$BINARY" testnet init-files --help 2>/dev/null | grep -q -- "--chain-id"; then - if command -v jq >/dev/null 2>&1; then - for ((i=0; i< N; i++)); do - gi="${BASE_DIR}/${NODE_PREFIX}${i}/evmd/config/genesis.json" - if [ -f "$gi" ]; then - tmp="$gi.tmp" && jq --arg cid "$CHAIN_ID" '.chain_id=$cid' "$gi" > "$tmp" && mv "$tmp" "$gi" - fi - done - log "Patched genesis chain_id to '${CHAIN_ID}' via jq (fallback path)." - else - log "jq not found; cannot patch genesis chain_id. Using defaults from init-files." - fi - fi -} - -# Update per-node ports for single host to avoid conflicts -adjust_ports_single_host() { - if [ "${SINGLE_HOST}" != "true" ]; then - log "SINGLE_HOST is not enabled; skipping port adjustments." - return 0 - fi - - # Helper to set a key inside a specific TOML section - toml_set_key_in_section() { - local file="$1" section="$2" key="$3" value="$4" - awk -v section="$section" -v key="$key" -v value="$value" ' - BEGIN { insec=0; done=0 } - /^[[:space:]]*\[/ { - if (insec && !done) { print key " = \"" value "\""; done=1 } - insec=0 - if ($0 ~ "^\\[" section "\\]") { insec=1 } - print; next - } - { - if (insec && $0 ~ "^[[:space:]]*" key "[[:space:]]*=") { - print key " = \"" value "\""; done=1; next - } - print - } - END { - if (insec && !done) { print key " = \"" value "\"" } - } - ' "$file" >"$file.tmp" && mv "$file.tmp" "$file" - } - - for ((i=0; i< N; i++)); do - local home_dir="${BASE_DIR}/${NODE_PREFIX}${i}/evmd" - local cfg_tm="${home_dir}/config/config.toml" - local cfg_app="${home_dir}/config/app.toml" - - [ -f "$cfg_tm" ] || { err "Missing $cfg_tm"; continue; } - [ -f "$cfg_app" ] || { err "Missing $cfg_app"; continue; } - - # Compute unique ports - local rpc_port=$((26657 + i)) - local p2p_port=$((16656 + i)) - local pprof_port=$((6060 + i)) - local prom_port=$((26660 + i)) - local api_port=$((1317 + i)) - local grpc_port=$((9090 + i)) - local grpcweb_port=$((9091 + i)) - local http_port=$((8545 + i*10)) - local ws_port=$((8546 + i*10)) - - # Tendermint config.toml - toml_set_key_in_section "$cfg_tm" "rpc" "laddr" "tcp://127.0.0.1:${rpc_port}" - toml_set_key_in_section "$cfg_tm" "rpc" "pprof_laddr" "localhost:${pprof_port}" - toml_set_key_in_section "$cfg_tm" "p2p" "laddr" "tcp://127.0.0.1:${p2p_port}" - toml_set_key_in_section "$cfg_tm" "instrumentation" "prometheus_listen_addr" ":${prom_port}" - - # Application app.toml - toml_set_key_in_section "$cfg_app" "api" "address" "tcp://127.0.0.1:${api_port}" - toml_set_key_in_section "$cfg_app" "grpc" "address" "127.0.0.1:${grpc_port}" - toml_set_key_in_section "$cfg_app" "grpc-web" "address" "127.0.0.1:${grpcweb_port}" - toml_set_key_in_section "$cfg_app" "json-rpc" "address" "127.0.0.1:${http_port}" - toml_set_key_in_section "$cfg_app" "json-rpc" "ws-address" "127.0.0.1:${ws_port}" - - log "Configured ${NODE_PREFIX}${i} ports: rpc:${rpc_port} p2p:${p2p_port} api:${api_port} http:${http_port} ws:${ws_port} grpc:${grpc_port}/${grpcweb_port}" - done -} - -# Apply consensus timeout adjustments similar to local_node.sh -tune_timeouts() { - for ((i=0; i< N; i++)); do - local CONFIG_TOML="${BASE_DIR}/${NODE_PREFIX}${i}/evmd/config/config.toml" - if [ ! -f "$CONFIG_TOML" ]; then - err "Missing $CONFIG_TOML" - continue - fi - # Logging: debug level and json format - sed -i.bak 's/log_level = "info"/log_level = "debug"/g' "$CONFIG_TOML" - sed -i.bak 's/log_format = "plain"/log_format = "json"/g' "$CONFIG_TOML" - sed -i.bak 's/timeout_propose = "3s"/timeout_propose = "2s"/g' "$CONFIG_TOML" - sed -i.bak 's/timeout_propose_delta = "500ms"/timeout_propose_delta = "200ms"/g' "$CONFIG_TOML" - sed -i.bak 's/timeout_prevote = "1s"/timeout_prevote = "500ms"/g' "$CONFIG_TOML" - sed -i.bak 's/timeout_prevote_delta = "500ms"/timeout_prevote_delta = "200ms"/g' "$CONFIG_TOML" - sed -i.bak 's/timeout_precommit = "1s"/timeout_precommit = "500ms"/g' "$CONFIG_TOML" - sed -i.bak 's/timeout_precommit_delta = "500ms"/timeout_precommit_delta = "200ms"/g' "$CONFIG_TOML" - sed -i.bak 's/timeout_commit = "5s"/timeout_commit = "1s"/g' "$CONFIG_TOML" - sed -i.bak 's/timeout_broadcast_tx_commit = "10s"/timeout_broadcast_tx_commit = "5s"/g' "$CONFIG_TOML" - done - log "Applied consensus timeout adjustments to all nodes." -} - -# Adjust memlogger settings in app.toml for each node -adjust_memlogger() { - for ((i=0; i< N; i++)); do - local APP_TOML="${BASE_DIR}/${NODE_PREFIX}${i}/evmd/config/app.toml" - if [ ! -f "$APP_TOML" ]; then - err "Missing $APP_TOML" - continue - fi - - # Helpers local to this function - toml_set_key_in_section() { - local file="$1" section="$2" key="$3" value="$4" - awk -v section="$section" -v key="$key" -v value="$value" ' - BEGIN { insec=0; done=0 } - /^[[:space:]]*\[/ { - if (insec && !done) { print key " = \"" value "\""; done=1 } - insec=0 - if ($0 ~ "^\\[" section "\\]") { insec=1 } - print; next - } - { - if (insec && $0 ~ "^[[:space:]]*" key "[[:space:]]*=") { - print key " = \"" value "\""; done=1; next - } - print - } - END { - if (insec && !done) { print key " = \"" value "\"" } - } - ' "$file" >"$file.tmp" && mv "$file.tmp" "$file" - } - - toml_set_key_in_section_raw() { - local file="$1" section="$2" key="$3" rawvalue="$4" - awk -v section="$section" -v key="$key" -v rawvalue="$rawvalue" ' - BEGIN { insec=0; done=0 } - /^[[:space:]]*\[/ { - if (insec && !done) { print key " = " rawvalue; done=1 } - insec=0 - if ($0 ~ "^\\[" section "\\]") { insec=1 } - print; next - } - { - if (insec && $0 ~ "^[[:space:]]*" key "[[:space:]]*=") { - print key " = " rawvalue; done=1; next - } - print - } - END { - if (insec && !done) { print key " = " rawvalue } - } - ' "$file" >"$file.tmp" && mv "$file.tmp" "$file" - } - - # disable - toml_set_key_in_section "$APP_TOML" "memlogger" "enabled" "false" - done -} - -apply_surge_and_replicate() { - # Apply surge faucet on node0 genesis, then copy to other nodes - local g0="${BASE_DIR}/${NODE_PREFIX}0/evmd/config/genesis.json" - if [ ! -f "$g0" ]; then - err "node0 genesis not found at $g0" - exit 1 - fi - - # Run surge faucet if available/desired - if [ -n "$SURGE_CMD" ]; then - local surge_bin - surge_bin=$(echo "$SURGE_CMD" | awk '{print $1}') - if ! command -v "$surge_bin" >/dev/null 2>&1; then - err "'$surge_bin' not found on PATH. Set SURGE_CMD='' to skip or install surge." - exit 1 - fi - # Echo the exact command - printf '[evmd-localnet] Exec: %s %s %s\n' "$SURGE_CMD" "${SURGE_ARGS}" "$g0" - # Execute with optional extra args - eval "$SURGE_CMD ${SURGE_ARGS} $g0" - else - log "SURGE_CMD empty; skipping surge faucet step." - fi - - # Replicate node0 genesis to all other nodes - for ((i=1; i< N; i++)); do - local gi="${BASE_DIR}/${NODE_PREFIX}${i}/evmd/config/genesis.json" - if [ -f "$gi" ]; then - cp "$g0" "$gi" - fi - done - - # Validate genesis for all nodes (best-effort) - for ((i=0; i< N; i++)); do - local home_dir="${BASE_DIR}/${NODE_PREFIX}${i}/evmd" - if [ -d "$home_dir" ]; then - "$BINARY" genesis validate-genesis --home "$home_dir" >/dev/null 2>&1 || true - fi - done -} - -build_peers_if_possible() { - # Try to gather node IDs using `evmd comet show-node-id` if the subcommand exists. - if ! "$BINARY" comet --help >/dev/null 2>&1; then - log "'evmd comet' subcommand not found. Skipping persistent_peers injection (nodes should still connect with generated configs)." - return 0 - fi - - local peers="" - for ((i=0; i< N; i++)); do - local home_dir="${BASE_DIR}/${NODE_PREFIX}${i}/evmd" - local id - if ! id=$("$BINARY" comet show-node-id --home "$home_dir" 2>/dev/null); then - err "Failed to read node ID for ${NODE_PREFIX}${i}; skipping persistent_peers." - return 0 - fi - # Ports per init-files when --single-host is used: - # - P2P starts at 16656 and increments by +1 per node - local p2p_port=$((16656 + i)) - local entry="${id}@127.0.0.1:${p2p_port}" - if [ -z "$peers" ]; then peers="$entry"; else peers+="",$entry; fi - done - - log "persistent_peers=${peers}" - # Inject into each node's config.toml - for ((i=0; i< N; i++)); do - local cfg="${BASE_DIR}/${NODE_PREFIX}${i}/evmd/config/config.toml" - if [ -f "$cfg" ]; then - # Replace existing line or append if missing - if grep -q '^persistent_peers\s*=\s*"' "$cfg"; then - sed -i.bak -E "s|^persistent_peers\s*=\s*\".*\"|persistent_peers = \"${peers}\"|" "$cfg" - else - echo "persistent_peers = \"${peers}\"" >> "$cfg" - fi - fi - done -} - -start_nodes() { - mkdir -p "$(dirname "$PID_FILE")" - : > "$PID_FILE" - - for ((i=0; i< N; i++)); do - local home_dir="${BASE_DIR}/${NODE_PREFIX}${i}/evmd" - local log_file="${home_dir}/evmd.log" - - # Compute display ports that init-files configure for single-host: - local rpc_port=$((26657 + i)) - local p2p_port=$((16656 + i)) - local api_port=$((1317 + i)) - local http_port=$((8545 + i*10)) - local ws_port=$((8546 + i*10)) - - log "Starting ${NODE_PREFIX}${i} (rpc:${rpc_port}, p2p:${p2p_port}, api:${api_port}, http:${http_port}, ws:${ws_port})" - - # Ensure client chain-id is set for this home (useful for CLI interactions) - "$BINARY" config set client chain-id "${CHAIN_ID}" --home "$home_dir" >/dev/null 2>&1 || true - - # Build start command (aligned with local_node.sh gas defaults) and echo it for reproducibility - cmd=("$BINARY" start \ - --home "$home_dir" \ - --minimum-gas-prices "${MIN_GAS_PRICES}" \ - --evm.min-tip 0 \ - --json-rpc.api "eth,txpool,personal,net,debug,web3" \ - --chain-id "${CHAIN_ID}") - - printf '[evmd-localnet] Exec: ' - for arg in "${cmd[@]}"; do printf '%s ' "$arg"; done; printf '\n' - - # Start in background, capture PID - ("${cmd[@]}" >"$log_file" 2>&1 & echo $! >> "$PID_FILE") - sleep 0.5 - done - - log "All nodes started. PIDs recorded in ${PID_FILE}" -} - -stop_nodes() { - if [ ! -f "$PID_FILE" ]; then - err "PID file not found: $PID_FILE" - exit 1 - fi - tac "$PID_FILE" | while read -r pid; do - if kill -0 "$pid" >/dev/null 2>&1; then - log "Stopping PID $pid" - kill "$pid" || true - fi - done - rm -f "$PID_FILE" - log "All nodes stopped." -} - -clean() { - if [ -d "$BASE_DIR" ]; then - log "Removing ${BASE_DIR}" - rm -rf "$BASE_DIR" - fi -} - -cmd=${1:-start} -case "$cmd" in - start) - ensure_binary - init_fresh - apply_surge_and_replicate - adjust_ports_single_host - tune_timeouts - adjust_memlogger - build_peers_if_possible - start_nodes - ;; - stop) - stop_nodes - ;; - clean) - clean - ;; - *) - echo "Usage: $0 {start|stop|clean}" >&2 - exit 1 - ;; -esac diff --git a/evmd_localnet_nomemlogger_info.sh b/evmd_localnet_nomemlogger_info.sh deleted file mode 100755 index 5aae2e134..000000000 --- a/evmd_localnet_nomemlogger_info.sh +++ /dev/null @@ -1,412 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# Simple multi-node localnet launcher for evmd -# - Initializes N validator nodes under BASE_DIR using `evmd testnet init-files --validator-count N --keyring-backend test` -# - Applies surge faucet to node0 genesis, then replicates the modified genesis to all nodes -# - Optionally computes persistent_peers via `evmd comet show-node-id` if available -# - Starts each node with its own home and port set by init-files -# -# Usage: -# scripts/evmd-localnet.sh start # init (if needed) and start N nodes -# scripts/evmd-localnet.sh stop # stop nodes started by this script (via PID file) -# scripts/evmd-localnet.sh clean # remove BASE_DIR - -BINARY_DEFAULT="evmd" # or override via BINARY env -BASE_DIR_DEFAULT="./.testnets" # or override via BASE_DIR env -NODE_PREFIX_DEFAULT="node" -N_DEFAULT=4 -# Start defaults (min gas aligned with local_node.sh) -MIN_GAS_PRICES_DEFAULT="0atest" -SURGE_CMD_DEFAULT="surge faucet" # or override via SURGE_CMD env; extra args via SURGE_ARGS -CHAIN_ID_DEFAULT="local-4221" # or override via CHAIN_ID env -SINGLE_HOST_DEFAULT="true" # allocate unique ports per node on one host -STARTING_IP_DEFAULT="127.0.0.1" # starting IP for init-files on single host - -# Derive settings from env or defaults -BINARY=${BINARY:-$BINARY_DEFAULT} -BASE_DIR=${BASE_DIR:-$BASE_DIR_DEFAULT} -NODE_PREFIX=${NODE_PREFIX:-$NODE_PREFIX_DEFAULT} -N=${N:-$N_DEFAULT} -MIN_GAS_PRICES=${MIN_GAS_PRICES:-$MIN_GAS_PRICES_DEFAULT} -SURGE_CMD=${SURGE_CMD:-$SURGE_CMD_DEFAULT} -SURGE_ARGS=${SURGE_ARGS:-} -CHAIN_ID=${CHAIN_ID:-$CHAIN_ID_DEFAULT} -SINGLE_HOST=${SINGLE_HOST:-$SINGLE_HOST_DEFAULT} -STARTING_IP_ADDRESS=${STARTING_IP_ADDRESS:-$STARTING_IP_DEFAULT} - -# Internal -PID_FILE="${BASE_DIR}/evmd_localnet.pids" - -log() { echo "[evmd-localnet] $*"; } -err() { echo "[evmd-localnet:ERROR] $*" >&2; } - -ensure_binary() { - if command -v "$BINARY" >/dev/null 2>&1; then - return 0 - fi - # Fallback to local build path - if [ -x "./build/evmd" ]; then - BINARY="./build/evmd" - return 0 - fi - err "Cannot find evmd binary. Put it on PATH or build via 'make build'." - exit 1 -} - -init_fresh() { - # Always initialize a fresh testnet as requested - rm -rf "$BASE_DIR" - log "Initializing ${N}-node testnet at ${BASE_DIR}…" - mkdir -p "$BASE_DIR" - - # Per request: use only validator-count and keyring-backend flags (+ output-dir to control location) - local cmd=("$BINARY" testnet init-files \ - --validator-count "${N}" \ - --keyring-backend test \ - --output-dir "${BASE_DIR}") - - # Add chain-id if supported by the subcommand - if "$BINARY" testnet init-files --help 2>/dev/null | grep -q -- "--chain-id"; then - cmd+=(--chain-id "${CHAIN_ID}") - fi - # Use single-host ports from generator if supported - if [ "${SINGLE_HOST}" = "true" ] && "$BINARY" testnet init-files --help 2>/dev/null | grep -q -- "--single-host"; then - cmd+=(--single-host=true) - fi - # Set starting IP address if supported (helps ensure 127.0.0.1 mapping) - if [ "${SINGLE_HOST}" = "true" ] && "$BINARY" testnet init-files --help 2>/dev/null | grep -q -- "--starting-ip-address"; then - cmd+=(--starting-ip-address "${STARTING_IP_ADDRESS}") - fi - - printf '[evmd-localnet] Exec: ' - for a in "${cmd[@]}"; do printf '%s ' "$a"; done; printf '\n' - "${cmd[@]}" - - log "Init complete (chain-id: ${CHAIN_ID}). Genesis and configs under ${BASE_DIR}/${NODE_PREFIX}{0..$((N-1))}/evmd" - - # Fallback: if init-files doesn't support --chain-id, patch genesis chain_id via jq - if ! "$BINARY" testnet init-files --help 2>/dev/null | grep -q -- "--chain-id"; then - if command -v jq >/dev/null 2>&1; then - for ((i=0; i< N; i++)); do - gi="${BASE_DIR}/${NODE_PREFIX}${i}/evmd/config/genesis.json" - if [ -f "$gi" ]; then - tmp="$gi.tmp" && jq --arg cid "$CHAIN_ID" '.chain_id=$cid' "$gi" > "$tmp" && mv "$tmp" "$gi" - fi - done - log "Patched genesis chain_id to '${CHAIN_ID}' via jq (fallback path)." - else - log "jq not found; cannot patch genesis chain_id. Using defaults from init-files." - fi - fi -} - -# Update per-node ports for single host to avoid conflicts -adjust_ports_single_host() { - if [ "${SINGLE_HOST}" != "true" ]; then - log "SINGLE_HOST is not enabled; skipping port adjustments." - return 0 - fi - - # Helper to set a key inside a specific TOML section - toml_set_key_in_section() { - local file="$1" section="$2" key="$3" value="$4" - awk -v section="$section" -v key="$key" -v value="$value" ' - BEGIN { insec=0; done=0 } - /^[[:space:]]*\[/ { - if (insec && !done) { print key " = \"" value "\""; done=1 } - insec=0 - if ($0 ~ "^\\[" section "\\]") { insec=1 } - print; next - } - { - if (insec && $0 ~ "^[[:space:]]*" key "[[:space:]]*=") { - print key " = \"" value "\""; done=1; next - } - print - } - END { - if (insec && !done) { print key " = \"" value "\"" } - } - ' "$file" >"$file.tmp" && mv "$file.tmp" "$file" - } - - for ((i=0; i< N; i++)); do - local home_dir="${BASE_DIR}/${NODE_PREFIX}${i}/evmd" - local cfg_tm="${home_dir}/config/config.toml" - local cfg_app="${home_dir}/config/app.toml" - - [ -f "$cfg_tm" ] || { err "Missing $cfg_tm"; continue; } - [ -f "$cfg_app" ] || { err "Missing $cfg_app"; continue; } - - # Compute unique ports - local rpc_port=$((26657 + i)) - local p2p_port=$((16656 + i)) - local pprof_port=$((6060 + i)) - local prom_port=$((26660 + i)) - local api_port=$((1317 + i)) - local grpc_port=$((9090 + i)) - local grpcweb_port=$((9091 + i)) - local http_port=$((8545 + i*10)) - local ws_port=$((8546 + i*10)) - - # Tendermint config.toml - toml_set_key_in_section "$cfg_tm" "rpc" "laddr" "tcp://127.0.0.1:${rpc_port}" - toml_set_key_in_section "$cfg_tm" "rpc" "pprof_laddr" "localhost:${pprof_port}" - toml_set_key_in_section "$cfg_tm" "p2p" "laddr" "tcp://127.0.0.1:${p2p_port}" - toml_set_key_in_section "$cfg_tm" "instrumentation" "prometheus_listen_addr" ":${prom_port}" - - # Application app.toml - toml_set_key_in_section "$cfg_app" "api" "address" "tcp://127.0.0.1:${api_port}" - toml_set_key_in_section "$cfg_app" "grpc" "address" "127.0.0.1:${grpc_port}" - toml_set_key_in_section "$cfg_app" "grpc-web" "address" "127.0.0.1:${grpcweb_port}" - toml_set_key_in_section "$cfg_app" "json-rpc" "address" "127.0.0.1:${http_port}" - toml_set_key_in_section "$cfg_app" "json-rpc" "ws-address" "127.0.0.1:${ws_port}" - - log "Configured ${NODE_PREFIX}${i} ports: rpc:${rpc_port} p2p:${p2p_port} api:${api_port} http:${http_port} ws:${ws_port} grpc:${grpc_port}/${grpcweb_port}" - done -} - -# Apply consensus timeout adjustments similar to local_node.sh -tune_timeouts() { - for ((i=0; i< N; i++)); do - local CONFIG_TOML="${BASE_DIR}/${NODE_PREFIX}${i}/evmd/config/config.toml" - if [ ! -f "$CONFIG_TOML" ]; then - err "Missing $CONFIG_TOML" - continue - fi - # Logging: debug level and json format - sed -i.bak 's/log_format = "plain"/log_format = "json"/g' "$CONFIG_TOML" - sed -i.bak 's/timeout_propose = "3s"/timeout_propose = "2s"/g' "$CONFIG_TOML" - sed -i.bak 's/timeout_propose_delta = "500ms"/timeout_propose_delta = "200ms"/g' "$CONFIG_TOML" - sed -i.bak 's/timeout_prevote = "1s"/timeout_prevote = "500ms"/g' "$CONFIG_TOML" - sed -i.bak 's/timeout_prevote_delta = "500ms"/timeout_prevote_delta = "200ms"/g' "$CONFIG_TOML" - sed -i.bak 's/timeout_precommit = "1s"/timeout_precommit = "500ms"/g' "$CONFIG_TOML" - sed -i.bak 's/timeout_precommit_delta = "500ms"/timeout_precommit_delta = "200ms"/g' "$CONFIG_TOML" - sed -i.bak 's/timeout_commit = "5s"/timeout_commit = "1s"/g' "$CONFIG_TOML" - sed -i.bak 's/timeout_broadcast_tx_commit = "10s"/timeout_broadcast_tx_commit = "5s"/g' "$CONFIG_TOML" - done - log "Applied consensus timeout adjustments to all nodes." -} - -# Adjust memlogger settings in app.toml for each node -adjust_memlogger() { - for ((i=0; i< N; i++)); do - local APP_TOML="${BASE_DIR}/${NODE_PREFIX}${i}/evmd/config/app.toml" - if [ ! -f "$APP_TOML" ]; then - err "Missing $APP_TOML" - continue - fi - - # Helpers local to this function - toml_set_key_in_section() { - local file="$1" section="$2" key="$3" value="$4" - awk -v section="$section" -v key="$key" -v value="$value" ' - BEGIN { insec=0; done=0 } - /^[[:space:]]*\[/ { - if (insec && !done) { print key " = \"" value "\""; done=1 } - insec=0 - if ($0 ~ "^\\[" section "\\]") { insec=1 } - print; next - } - { - if (insec && $0 ~ "^[[:space:]]*" key "[[:space:]]*=") { - print key " = \"" value "\""; done=1; next - } - print - } - END { - if (insec && !done) { print key " = \"" value "\"" } - } - ' "$file" >"$file.tmp" && mv "$file.tmp" "$file" - } - - toml_set_key_in_section_raw() { - local file="$1" section="$2" key="$3" rawvalue="$4" - awk -v section="$section" -v key="$key" -v rawvalue="$rawvalue" ' - BEGIN { insec=0; done=0 } - /^[[:space:]]*\[/ { - if (insec && !done) { print key " = " rawvalue; done=1 } - insec=0 - if ($0 ~ "^\\[" section "\\]") { insec=1 } - print; next - } - { - if (insec && $0 ~ "^[[:space:]]*" key "[[:space:]]*=") { - print key " = " rawvalue; done=1; next - } - print - } - END { - if (insec && !done) { print key " = " rawvalue } - } - ' "$file" >"$file.tmp" && mv "$file.tmp" "$file" - } - - # disable - toml_set_key_in_section "$APP_TOML" "memlogger" "enabled" "false" - done -} - -apply_surge_and_replicate() { - # Apply surge faucet on node0 genesis, then copy to other nodes - local g0="${BASE_DIR}/${NODE_PREFIX}0/evmd/config/genesis.json" - if [ ! -f "$g0" ]; then - err "node0 genesis not found at $g0" - exit 1 - fi - - # Run surge faucet if available/desired - if [ -n "$SURGE_CMD" ]; then - local surge_bin - surge_bin=$(echo "$SURGE_CMD" | awk '{print $1}') - if ! command -v "$surge_bin" >/dev/null 2>&1; then - err "'$surge_bin' not found on PATH. Set SURGE_CMD='' to skip or install surge." - exit 1 - fi - # Echo the exact command - printf '[evmd-localnet] Exec: %s %s %s\n' "$SURGE_CMD" "${SURGE_ARGS}" "$g0" - # Execute with optional extra args - eval "$SURGE_CMD ${SURGE_ARGS} $g0" - else - log "SURGE_CMD empty; skipping surge faucet step." - fi - - # Replicate node0 genesis to all other nodes - for ((i=1; i< N; i++)); do - local gi="${BASE_DIR}/${NODE_PREFIX}${i}/evmd/config/genesis.json" - if [ -f "$gi" ]; then - cp "$g0" "$gi" - fi - done - - # Validate genesis for all nodes (best-effort) - for ((i=0; i< N; i++)); do - local home_dir="${BASE_DIR}/${NODE_PREFIX}${i}/evmd" - if [ -d "$home_dir" ]; then - "$BINARY" genesis validate-genesis --home "$home_dir" >/dev/null 2>&1 || true - fi - done -} - -build_peers_if_possible() { - # Try to gather node IDs using `evmd comet show-node-id` if the subcommand exists. - if ! "$BINARY" comet --help >/dev/null 2>&1; then - log "'evmd comet' subcommand not found. Skipping persistent_peers injection (nodes should still connect with generated configs)." - return 0 - fi - - local peers="" - for ((i=0; i< N; i++)); do - local home_dir="${BASE_DIR}/${NODE_PREFIX}${i}/evmd" - local id - if ! id=$("$BINARY" comet show-node-id --home "$home_dir" 2>/dev/null); then - err "Failed to read node ID for ${NODE_PREFIX}${i}; skipping persistent_peers." - return 0 - fi - # Ports per init-files when --single-host is used: - # - P2P starts at 16656 and increments by +1 per node - local p2p_port=$((16656 + i)) - local entry="${id}@127.0.0.1:${p2p_port}" - if [ -z "$peers" ]; then peers="$entry"; else peers+="",$entry; fi - done - - log "persistent_peers=${peers}" - # Inject into each node's config.toml - for ((i=0; i< N; i++)); do - local cfg="${BASE_DIR}/${NODE_PREFIX}${i}/evmd/config/config.toml" - if [ -f "$cfg" ]; then - # Replace existing line or append if missing - if grep -q '^persistent_peers\s*=\s*"' "$cfg"; then - sed -i.bak -E "s|^persistent_peers\s*=\s*\".*\"|persistent_peers = \"${peers}\"|" "$cfg" - else - echo "persistent_peers = \"${peers}\"" >> "$cfg" - fi - fi - done -} - -start_nodes() { - mkdir -p "$(dirname "$PID_FILE")" - : > "$PID_FILE" - - for ((i=0; i< N; i++)); do - local home_dir="${BASE_DIR}/${NODE_PREFIX}${i}/evmd" - local log_file="${home_dir}/evmd.log" - - # Compute display ports that init-files configure for single-host: - local rpc_port=$((26657 + i)) - local p2p_port=$((16656 + i)) - local api_port=$((1317 + i)) - local http_port=$((8545 + i*10)) - local ws_port=$((8546 + i*10)) - - log "Starting ${NODE_PREFIX}${i} (rpc:${rpc_port}, p2p:${p2p_port}, api:${api_port}, http:${http_port}, ws:${ws_port})" - - # Ensure client chain-id is set for this home (useful for CLI interactions) - "$BINARY" config set client chain-id "${CHAIN_ID}" --home "$home_dir" >/dev/null 2>&1 || true - - # Build start command (aligned with local_node.sh gas defaults) and echo it for reproducibility - cmd=("$BINARY" start \ - --home "$home_dir" \ - --minimum-gas-prices "${MIN_GAS_PRICES}" \ - --evm.min-tip 0 \ - --json-rpc.api "eth,txpool,personal,net,debug,web3" \ - --chain-id "${CHAIN_ID}") - - printf '[evmd-localnet] Exec: ' - for arg in "${cmd[@]}"; do printf '%s ' "$arg"; done; printf '\n' - - # Start in background, capture PID - ("${cmd[@]}" >"$log_file" 2>&1 & echo $! >> "$PID_FILE") - sleep 0.5 - done - - log "All nodes started. PIDs recorded in ${PID_FILE}" -} - -stop_nodes() { - if [ ! -f "$PID_FILE" ]; then - err "PID file not found: $PID_FILE" - exit 1 - fi - tac "$PID_FILE" | while read -r pid; do - if kill -0 "$pid" >/dev/null 2>&1; then - log "Stopping PID $pid" - kill "$pid" || true - fi - done - rm -f "$PID_FILE" - log "All nodes stopped." -} - -clean() { - if [ -d "$BASE_DIR" ]; then - log "Removing ${BASE_DIR}" - rm -rf "$BASE_DIR" - fi -} - -cmd=${1:-start} -case "$cmd" in - start) - ensure_binary - init_fresh - apply_surge_and_replicate - adjust_ports_single_host - tune_timeouts - adjust_memlogger - build_peers_if_possible - start_nodes - ;; - stop) - stop_nodes - ;; - clean) - clean - ;; - *) - echo "Usage: $0 {start|stop|clean}" >&2 - exit 1 - ;; -esac From 05910c82e4bbc386cd03a05c733ba6805ecd7a85 Mon Sep 17 00:00:00 2001 From: bonomoon Date: Sun, 30 Nov 2025 03:51:01 +0900 Subject: [PATCH 21/22] Add interactive testnet launcher script with apphash.io integration --- start-testnet.sh | 232 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 232 insertions(+) create mode 100755 start-testnet.sh diff --git a/start-testnet.sh b/start-testnet.sh new file mode 100755 index 000000000..65a2dd9f2 --- /dev/null +++ b/start-testnet.sh @@ -0,0 +1,232 @@ +#!/bin/bash + +# Interactive script to start a new testnet with apphash.io integration +set -e + +# Parse arguments +NODE_COUNT=4 +SERVICE_BASE="http://host.docker.internal:8080" +AUTH_KEY="" +CUSTOM_CHAIN_ID="" + +while [[ $# -gt 0 ]]; do + case $1 in + --nodes|-n) + NODE_COUNT="$2" + shift 2 + ;; + --url|-u) + SERVICE_BASE="$2" + shift 2 + ;; + --chain-id|-c) + CUSTOM_CHAIN_ID="$2" + shift 2 + ;; + --auth-key|-k) + AUTH_KEY="$2" + shift 2 + ;; + *) + NODE_COUNT="$1" + shift + ;; + esac +done + +echo "=============================================" +echo " EVM Testnet Launcher with apphash.io" +echo "=============================================" +echo "" + +# Step 1: Configure Chain ID +if [ -n "$CUSTOM_CHAIN_ID" ]; then + CHAIN_ID="$CUSTOM_CHAIN_ID" +else + DEFAULT_CHAIN_ID="testnet-$(date +%s)" + if [ -n "$AUTH_KEY" ]; then + CHAIN_ID="$DEFAULT_CHAIN_ID" + else + echo "Step 1: Configure Chain ID" + echo "" + read -p "Enter Chain ID (default: $DEFAULT_CHAIN_ID): " USER_CHAIN_ID + CHAIN_ID="${USER_CHAIN_ID:-$DEFAULT_CHAIN_ID}" + echo "" + fi +fi + +echo "Using Chain ID: $CHAIN_ID" +echo "" + +COMPOSE_FILE="docker-compose.${CHAIN_ID}.yml" + +# Step 2: Get Auth Key (if not provided) +if [ -z "$AUTH_KEY" ]; then + echo "=============================================" + echo "Step 2: Create project on apphash.io" + echo "=============================================" + echo "" + echo " 1. Go to: https://apphash.io" + echo " 2. Click 'New Project'" + echo " 3. Enter Chain ID: $CHAIN_ID" + echo " 4. Copy the generated Auth Key" + echo "" + read -p "Paste the Auth Key here: " AUTH_KEY + + if [ -z "$AUTH_KEY" ]; then + echo "Error: Auth Key cannot be empty" + exit 1 + fi + echo "" +fi + +# Step 3: Clean up old data +echo "Step 3: Cleaning up old data..." +docker compose -f "$COMPOSE_FILE" down -v 2>/dev/null || true +rm -rf .testnets +mkdir -p .testnets +echo "" + +# Step 4: Generate docker-compose and start testnet +echo "Step 4: Generating docker-compose and starting testnet..." +echo " Chain ID: $CHAIN_ID" +echo " Validators: $NODE_COUNT" +echo "" + +# Generate docker-compose.yml with init + setup + nodes + shippers +cat > "$COMPOSE_FILE" <> "$COMPOSE_FILE" <> "$COMPOSE_FILE" <> "$COMPOSE_FILE" <&1 | grep -v "View in Docker Desktop" | grep -v "View Config" | grep -v "Enable Watch" + +echo "" +echo "=============================================" +echo " Testnet is running!" +echo "=============================================" +echo "" +echo "Chain ID: $CHAIN_ID" +echo "Nodes: $NODE_COUNT" +echo "Auth Key: ${AUTH_KEY:0:8}...${AUTH_KEY: -8}" +echo "" +echo "Monitor your testnet:" +echo " https://apphash.io" +echo "" +echo "View logs:" +echo " docker compose -f $COMPOSE_FILE logs -f" +echo "" +echo "Stop testnet:" +echo " docker compose -f $COMPOSE_FILE down" +echo "" +echo "Clean up all data:" +echo " docker compose -f $COMPOSE_FILE down -v && rm -rf .testnets" +echo "" From d9017532071cd7c92a523a09fce9df2d8bd5822d Mon Sep 17 00:00:00 2001 From: bonomoon Date: Sun, 30 Nov 2025 04:43:55 +0900 Subject: [PATCH 22/22] Register shipper docker image --- start-testnet.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/start-testnet.sh b/start-testnet.sh index 65a2dd9f2..6172a4cce 100755 --- a/start-testnet.sh +++ b/start-testnet.sh @@ -176,11 +176,9 @@ NODE_SERVICE cat >> "$COMPOSE_FILE" <