From cfa1b090328f7ea4911f67cccdc561e0ddef7524 Mon Sep 17 00:00:00 2001 From: Arya Lanjewar <102943033+AryaLanjewar3005@users.noreply.github.com> Date: Wed, 24 Sep 2025 16:17:15 +0530 Subject: [PATCH 1/2] Upgrade testing utilities added --- Makefile | 31 ++++ .../upgrade-testing-utils/.upgrade_index | 1 + .../Dockerfile.node_upgrade_test | 32 ++++ .../upgrade-testing-utils/docker-compose.yml | 21 +++ .../test_node_e2e_upgrade.sh | 174 ++++++++++++++++++ .../upgrade-testing-utils/upgrade_list.csv | 6 + .../upgrade-testing-utils/upgrade_node.sh | 105 +++++++++++ 7 files changed, 370 insertions(+) create mode 100644 testutils/upgrade-testing-utils/.upgrade_index create mode 100644 testutils/upgrade-testing-utils/Dockerfile.node_upgrade_test create mode 100644 testutils/upgrade-testing-utils/docker-compose.yml create mode 100644 testutils/upgrade-testing-utils/test_node_e2e_upgrade.sh create mode 100644 testutils/upgrade-testing-utils/upgrade_list.csv create mode 100644 testutils/upgrade-testing-utils/upgrade_node.sh diff --git a/Makefile b/Makefile index cb93ff7f..06664c50 100755 --- a/Makefile +++ b/Makefile @@ -480,3 +480,34 @@ e2e-run-test: cp $(E2E_DIR)/push-chain-interop-contracts/contracts/svm-gateway/target/idl/pushsolanalocker.json $(CONTRACTS_DIR)/push-chain-sdk/packages/core/src/lib/constants/abi/feeLocker.json cp $(E2E_DIR)/.env $(CONTRACTS_DIR)/push-chain-sdk/packages/core/.env cd $(CONTRACTS_DIR)/push-chain-sdk && npx jest core/__e2e__/pushchain.spec.ts --runInBand --detectOpenHandles + +############################################################################### +### e2e-upgrade... ### +############################################################################### + +CHAIN_DIR := ./node-upgrade-testing +REPO := https://github.com/push-protocol/push-chain-node.git +UTILS_DIR := ./testutils/upgrade-testing-utils +CSV := $(UTILS_DIR)/upgrade_list.csv + +chain-upgrade-test: + @echo ">>> Cloning push-chain-node repo..." + rm -rf $(CHAIN_DIR) + mkdir -p $(CHAIN_DIR) + cd $(CHAIN_DIR) && git clone $(REPO) + + @echo ">>> Checking out first upgrade commit from CSV..." + FIRST_COMMIT=$$(awk -F',' 'NR==2 {print $$2}' $(CSV)); \ + cd $(CHAIN_DIR)/push-chain-node && git checkout $$FIRST_COMMIT + + @echo ">>> Copying utility files..." + mkdir -p $(CHAIN_DIR)/push-chain-node/scripts + cp $(UTILS_DIR)/test_node_e2e_upgrade.sh $(CHAIN_DIR)/push-chain-node/scripts/test_node_e2e_upgrade.sh + cp $(UTILS_DIR)/Dockerfile.node_upgrade_test $(CHAIN_DIR)/push-chain-node/Dockerfile.node_upgrade_test + cp $(UTILS_DIR)/docker-compose.yml $(CHAIN_DIR)/push-chain-node/docker-compose.yml + + @echo ">>> Launching docker container for first upgrade..." + cd $(CHAIN_DIR)/push-chain-node && docker compose up -d --build + + + diff --git a/testutils/upgrade-testing-utils/.upgrade_index b/testutils/upgrade-testing-utils/.upgrade_index new file mode 100644 index 00000000..0cfbf088 --- /dev/null +++ b/testutils/upgrade-testing-utils/.upgrade_index @@ -0,0 +1 @@ +2 diff --git a/testutils/upgrade-testing-utils/Dockerfile.node_upgrade_test b/testutils/upgrade-testing-utils/Dockerfile.node_upgrade_test new file mode 100644 index 00000000..aa107b68 --- /dev/null +++ b/testutils/upgrade-testing-utils/Dockerfile.node_upgrade_test @@ -0,0 +1,32 @@ +FROM golang:1.23 AS build +WORKDIR /app + +COPY go.mod go.sum ./ +RUN go mod download +COPY . . +RUN make install # regular build (dynamic link) + +FROM ubuntu:22.04 +RUN apt-get update && apt-get install -y bash curl jq git make gcc-x86-64-linux-gnu g++ build-essential libc6-dev pkg-config g++-x86-64-linux-gnu libc6-dev-amd64-cross && rm -rf /var/lib/apt/lists/* + +RUN curl -OL https://go.dev/dl/go1.23.0.linux-amd64.tar.gz +RUN tar -C /usr/local -xzf go1.23.0.linux-amd64.tar.gz + +ENV PATH=$PATH:/usr/local/go/bin + +# Install wasmvm v1.5.4 shared library +RUN curl -L https://github.com/CosmWasm/wasmvm/releases/download/v1.5.4/libwasmvm.aarch64.so \ + -o /usr/lib/libwasmvm.aarch64.so && chmod 755 /usr/lib/libwasmvm.aarch64.so + +RUN curl -L https://github.com/CosmWasm/wasmvm/releases/download/v1.5.4/libwasmvm.x86_64.so \ + -o /usr/lib/libwasmvm.x86_64.so && chmod 755 /usr/lib/libwasmvm.x86_64.so + +COPY --from=build /go/bin/pchaind /usr/local/bin/pchaind +COPY scripts /app/scripts +WORKDIR /app + +ENV CHAIN_ID=localchain_9000-1 \ + BLOCK_TIME=1000ms \ + CLEAN=true + +CMD ["bash", "scripts/test_node_e2e_upgrade.sh"] diff --git a/testutils/upgrade-testing-utils/docker-compose.yml b/testutils/upgrade-testing-utils/docker-compose.yml new file mode 100644 index 00000000..7aafb170 --- /dev/null +++ b/testutils/upgrade-testing-utils/docker-compose.yml @@ -0,0 +1,21 @@ +version: '3.8' + +services: + push-chain-node: + build: + context: . + dockerfile: Dockerfile.node_upgrade_test + container_name: push-chain-node + environment: + - CHAIN_ID=localchain_9000-1 + - BLOCK_TIME=1000ms + - CLEAN=true + command: bash scripts/test_node_e2e_upgrade.sh + extra_hosts: + - "host.docker.internal:host-gateway" + ports: + - "26657:26657" # Tendermint RPC + - "1317:1317" # Cosmos REST API + - "8545:8545" # Cosmos REST API + volumes: + - ./scripts:/app/scripts \ No newline at end of file diff --git a/testutils/upgrade-testing-utils/test_node_e2e_upgrade.sh b/testutils/upgrade-testing-utils/test_node_e2e_upgrade.sh new file mode 100644 index 00000000..78514c31 --- /dev/null +++ b/testutils/upgrade-testing-utils/test_node_e2e_upgrade.sh @@ -0,0 +1,174 @@ +#!/bin/bash +# Run this script to quickly install, setup, and run the current version of the network without docker. +# +# Examples: +# CHAIN_ID="localchain_9000-1" HOME_DIR="~/.pchain" BLOCK_TIME="1000ms" CLEAN=true sh scripts/test_node.sh +# CHAIN_ID="localchain_9000-2" HOME_DIR="~/.pchain" CLEAN=true RPC=36657 REST=2317 PROFF=6061 P2P=36656 GRPC=8090 GRPC_WEB=8091 ROSETTA=8081 BLOCK_TIME="500ms" sh scripts/test_node.sh +shopt -s expand_aliases +set -eu + +export KEY1="acc1" +export KEY2="acc2" +export KEY3="acc3" + +export CHAIN_ID=${CHAIN_ID:-"localchain_9000-1"} +export MONIKER=${MONIKER:-"localvalidator"} +export KEYALGO="eth_secp256k1" +export KEYRING=${KEYRING:-"test"} +export HOME_DIR=$(eval echo "${HOME_DIR:-"~/.pchain"}") +export BINARY=${BINARY:-pchaind} +export DENOM=${DENOM:-upc} + +export CLEAN=${CLEAN:-"false"} +export RPC=${RPC:-"26657"} +export REST=${REST:-"1317"} +export PROFF=${PROFF:-"6060"} +export P2P=${P2P:-"26656"} +export GRPC=${GRPC:-"9090"} +export GRPC_WEB=${GRPC_WEB:-"9091"} +export ROSETTA=${ROSETTA:-"8080"} +export BLOCK_TIME=${BLOCK_TIME:-"1s"} + +# if which binary does not exist, install it +# if [ -z `which $BINARY` ]; then +# make install + +# if [ -z `which $BINARY` ]; then +# echo "Ensure $BINARY is installed and in your PATH" +# exit 1 +# fi +# fi + +alias BINARY="$BINARY --home=$HOME_DIR" + +command -v $BINARY > /dev/null 2>&1 || { echo >&2 "$BINARY command not found. Ensure this is setup / properly installed in your GOPATH (make install)."; exit 1; } +command -v jq > /dev/null 2>&1 || { echo >&2 "jq not installed. More info: https://stedolan.github.io/jq/download/"; exit 1; } + +set_config() { + $BINARY config set client chain-id $CHAIN_ID + $BINARY config set client keyring-backend $KEYRING +} +set_config + + +from_scratch () { + # Fresh install on current branch + # make install + + # remove existing daemon files. + if [ ${#HOME_DIR} -le 2 ]; then + echo "HOME_DIR must be more than 2 characters long" + return + fi + rm -rf $HOME_DIR && echo "Removed $HOME_DIR" + + # reset values if not set already after whipe + set_config + + add_key() { + key=$1 + mnemonic=$2 + echo $mnemonic | BINARY keys add $key --keyring-backend $KEYRING --algo $KEYALGO --recover + } + + # push1ss5j8c8j453uecnczt3ms23lze30kxt4pzfvh9 + add_key $KEY1 "surface task term spring horse impact tortoise often session cable off catch harvest rain able jealous coral cargo portion surge spring genre mix avoid" + # push1j55s4vpvmncruakqhj2k2fywnc9mvsuhcap28q + add_key $KEY2 "season wing cost lunch leg absurd parent practice frost mistake choose leopard switch shrug wrist this pistol bright spike hurt fit meadow smart hazard" + # push1fgaewhyd9fkwtqaj9c233letwcuey6dgly9gv9 + add_key $KEY3 "episode silver life middle tumble slogan genius loop divide alpha raven bridge drive calm club system school raccoon unfold marine oyster radio treat sphere" + + BINARY init $MONIKER --chain-id $CHAIN_ID --default-denom $DENOM + + update_test_genesis () { + cat $HOME_DIR/config/genesis.json | jq "$1" > $HOME_DIR/config/tmp_genesis.json && mv $HOME_DIR/config/tmp_genesis.json $HOME_DIR/config/genesis.json + } + + # === CORE MODULES === + + # Block + update_test_genesis '.consensus_params["block"]["max_gas"]="100000000"' + + # Gov + update_test_genesis `printf '.app_state["gov"]["params"]["min_deposit"]=[{"denom":"%s","amount":"1000000"}]' $DENOM` + update_test_genesis '.app_state["gov"]["params"]["voting_period"]="30s"' + update_test_genesis '.app_state["gov"]["params"]["expedited_voting_period"]="15s"' + + update_test_genesis `printf '.app_state["evm"]["params"]["evm_denom"]="%s"' $DENOM` + update_test_genesis '.app_state["evm"]["params"]["active_static_precompiles"]=["0x00000000000000000000000000000000000000CB","0x00000000000000000000000000000000000000ca","0x0000000000000000000000000000000000000100","0x0000000000000000000000000000000000000400","0x0000000000000000000000000000000000000800","0x0000000000000000000000000000000000000801","0x0000000000000000000000000000000000000802","0x0000000000000000000000000000000000000803","0x0000000000000000000000000000000000000804","0x0000000000000000000000000000000000000805"]' + update_test_genesis '.app_state["erc20"]["params"]["native_precompiles"]=["0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"]' # https://eips.ethereum.org/EIPS/eip-7528 + update_test_genesis `printf '.app_state["erc20"]["token_pairs"]=[{contract_owner:1,erc20_address:"0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",denom:"%s",enabled:true}]' $DENOM` + update_test_genesis '.app_state["feemarket"]["params"]["no_base_fee"]=false' + update_test_genesis '.app_state["feemarket"]["params"]["base_fee"]="1000000000.000000000000000000"' + update_test_genesis '.app_state["feemarket"]["params"]["min_gas_price"]="1000000000.000000000000000000"' + + # staking + update_test_genesis `printf '.app_state["staking"]["params"]["bond_denom"]="%s"' $DENOM` + update_test_genesis '.app_state["staking"]["params"]["min_commission_rate"]="0.050000000000000000"' + + # mint + update_test_genesis `printf '.app_state["mint"]["params"]["mint_denom"]="%s"' $DENOM` + + # crisis + update_test_genesis `printf '.app_state["crisis"]["constant_fee"]={"denom":"%s","amount":"1000"}' $DENOM` + + ## abci + update_test_genesis '.consensus["params"]["abci"]["vote_extensions_enable_height"]="1"' + + # === CUSTOM MODULES === + # tokenfactory + update_test_genesis '.app_state["tokenfactory"]["params"]["denom_creation_fee"]=[]' + update_test_genesis '.app_state["tokenfactory"]["params"]["denom_creation_gas_consume"]=100000' + + # Allocate genesis accounts + # Total: 10 000000000 . 000000000 000000000 + BINARY genesis add-genesis-account $KEY1 5000000000000000000000000000$DENOM,100000000test --keyring-backend $KEYRING --append + BINARY genesis add-genesis-account $KEY2 3000000000000000000000000000$DENOM,90000000test --keyring-backend $KEYRING --append + BINARY genesis add-genesis-account $KEY3 2000000000000000000000000000$DENOM,90000000test --keyring-backend $KEYRING --append + + # Sign genesis transaction + # 10 000 . 000000000 000000000 + BINARY genesis gentx $KEY1 10000000000000000000000$DENOM --gas-prices 1000000000${DENOM} --keyring-backend $KEYRING --chain-id $CHAIN_ID + + BINARY genesis collect-gentxs + + BINARY genesis validate-genesis + err=$? + if [ $err -ne 0 ]; then + echo "Failed to validate genesis" + return + fi +} + +# check if CLEAN is not set to false +if [ "$CLEAN" != "false" ]; then + echo "Starting from a clean state" + from_scratch +fi + +echo "Starting node..." + +# Opens the RPC endpoint to outside connections +sed -i -e 's/laddr = "tcp:\/\/127.0.0.1:26657"/c\laddr = "tcp:\/\/0.0.0.0:'$RPC'"/g' $HOME_DIR/config/config.toml +sed -i -e 's/cors_allowed_origins = \[\]/cors_allowed_origins = \["\*"\]/g' $HOME_DIR/config/config.toml + +# REST endpoint +sed -i -e 's/address = "tcp:\/\/localhost:1317"/address = "tcp:\/\/0.0.0.0:'$REST'"/g' $HOME_DIR/config/app.toml +sed -i -e 's/enable = false/enable = true/g' $HOME_DIR/config/app.toml +sed -i -e 's/enabled-unsafe-cors = false/enabled-unsafe-cors = true/g' $HOME_DIR/config/app.toml + +# peer exchange +sed -i -e 's/pprof_laddr = "localhost:6060"/pprof_laddr = "localhost:'$PROFF'"/g' $HOME_DIR/config/config.toml +sed -i -e 's/laddr = "tcp:\/\/0.0.0.0:26656"/laddr = "tcp:\/\/0.0.0.0:'$P2P'"/g' $HOME_DIR/config/config.toml + +# GRPC +sed -i -e 's/address = "localhost:9090"/address = "0.0.0.0:'$GRPC'"/g' $HOME_DIR/config/app.toml +sed -i -e 's/address = "localhost:9091"/address = "0.0.0.0:'$GRPC_WEB'"/g' $HOME_DIR/config/app.toml + +# Rosetta Api +sed -i -e 's/address = ":8080"/address = "0.0.0.0:'$ROSETTA'"/g' $HOME_DIR/config/app.toml + +# Faster blocks +sed -i -e 's/timeout_commit = "5s"/timeout_commit = "'$BLOCK_TIME'"/g' $HOME_DIR/config/config.toml + +BINARY start --pruning=nothing --minimum-gas-prices=1000000000$DENOM --rpc.laddr="tcp://0.0.0.0:$RPC" --json-rpc.api=eth,txpool,personal,net,debug,web3 --chain-id="$CHAIN_ID" \ No newline at end of file diff --git a/testutils/upgrade-testing-utils/upgrade_list.csv b/testutils/upgrade-testing-utils/upgrade_list.csv new file mode 100644 index 00000000..9efb42df --- /dev/null +++ b/testutils/upgrade-testing-utils/upgrade_list.csv @@ -0,0 +1,6 @@ +upgrade_name,commit_hash +current,2536b88b0d836ef900802014fc3d003401387c44 +uaid-refactor,47aa1d83641d960c198605648b813106f9bb7bab +uaid-refactor,47aa1d83641d960c198605648b813106f9bb7bab +uaid-refactor,47aa1d83641d960c198605648b813106f9bb7bab +uaid-refactor,47aa1d83641d960c198605648b813106f9bb7bab \ No newline at end of file diff --git a/testutils/upgrade-testing-utils/upgrade_node.sh b/testutils/upgrade-testing-utils/upgrade_node.sh new file mode 100644 index 00000000..0e1a0781 --- /dev/null +++ b/testutils/upgrade-testing-utils/upgrade_node.sh @@ -0,0 +1,105 @@ +#!/bin/bash +set -e + +# Paths inside container +CSV_FILE="./testutils/upgrade-testing-utils/upgrade_list.csv" +STATE_FILE="./testutils/upgrade-testing-utils/.upgrade_index" + +# If first run, set index = 2 (meaning line 2 = current commit done, upgrades start at line 3) +if [ ! -f "$STATE_FILE" ]; then + echo 2 > "$STATE_FILE" +fi + +CURRENT_INDEX=$(cat "$STATE_FILE") +NEXT_INDEX=$((CURRENT_INDEX + 1)) + +# Count total upgrades (excluding header row) +TOTAL_UPGRADES=$(($(wc -l < "$CSV_FILE") - 1)) + +echo "TOTAL_UPGRADES=$TOTAL_UPGRADES" +echo "CURRENT_INDEX=$CURRENT_INDEX" +echo "NEXT_INDEX=$NEXT_INDEX" + +# If we’ve reached past last upgrade line +if [ "$NEXT_INDEX" -gt $((TOTAL_UPGRADES + 1)) ]; then + echo "✅ All upgrades applied!" + exit 0 +fi + +# Get the upgrade details from CSV +NEXT_UPGRADE=$(awk -F',' -v idx=$NEXT_INDEX 'NR==idx {print $1","$2}' "$CSV_FILE") + +if [ -z "$NEXT_UPGRADE" ]; then + echo "❌ No upgrade found at line $NEXT_INDEX." + exit 1 +fi + +UPGRADE_NAME=$(echo "$NEXT_UPGRADE" | cut -d',' -f1 | xargs) +COMMIT_HASH=$(echo "$NEXT_UPGRADE" | cut -d',' -f2 | xargs) + +echo ">>> Applying upgrade (line $NEXT_INDEX): $UPGRADE_NAME ($COMMIT_HASH)" + +# Clone, checkout commit, build inside container +docker exec push-chain-node bash -c " + set -e + cd /app || mkdir -p /app && cd /app + echo '>>> Removing existing repo (if any)' + rm -rf push-chain-node + + echo '>>> Cloning push-chain-node repo' + git clone https://github.com/push-protocol/push-chain-node.git push-chain-node + + cd push-chain-node + + echo '>>> Checking out commit $COMMIT_HASH' + git checkout $COMMIT_HASH + + echo '>>> Building binary' + CGO_ENABLED=0 make build + + if [ ! -f build/pchaind ]; then + echo '❌ Build failed' + exit 1 + fi + + echo '>>> Copying binary to /usr/local/bin' + cp build/pchaind /usr/local/bin/pchaind +" + +# Get current height inside container +HEIGHT=$(docker exec push-chain-node pchaind status | jq -r '.SyncInfo.latest_block_height') +TARGET_HEIGHT=$(( (HEIGHT/1000 + 1) * 1000 )) + +echo ">>> Submitting governance proposal for $UPGRADE_NAME at height $TARGET_HEIGHT..." +docker exec push-chain-node pchaind tx upgrade software-upgrade "$UPGRADE_NAME" \ + --upgrade-height "$TARGET_HEIGHT" \ + --title "Test Upgrade $UPGRADE_NAME" \ + --summary "Automated upgrade test for $UPGRADE_NAME" \ + --from acc1 \ + --chain-id localchain_9000-1 \ + --deposit 1000000upc \ + --node tcp://localhost:26657 \ + --gas auto \ + --gas-adjustment 1.3 \ + --fees 310596000000000upc \ + --yes + +# Wait for halt +echo ">>> Waiting for chain halt at height $TARGET_HEIGHT..." +while true; do + CUR_HEIGHT=$(docker exec push-chain-node pchaind status | jq -r '.SyncInfo.latest_block_height') + if [ "$CUR_HEIGHT" -ge "$TARGET_HEIGHT" ]; then + echo "Chain halted at $CUR_HEIGHT." + break + fi + sleep 5 +done + +# Restart node with upgraded binary +echo ">>> Restarting chain with upgraded binary..." +docker exec push-chain-node pkill pchaind || true +docker exec -d push-chain-node pchaind start + +# Update state → store the line number we just processed +echo "$NEXT_INDEX" > "$STATE_FILE" +echo "✅ Upgrade $UPGRADE_NAME applied successfully!" From cef2061e36bd102a7c59899c3d9a0be0fd0e6fdf Mon Sep 17 00:00:00 2001 From: Arya Lanjewar <102943033+AryaLanjewar3005@users.noreply.github.com> Date: Wed, 24 Sep 2025 16:20:29 +0530 Subject: [PATCH 2/2] Gitignore changes --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index ac1f94fc..8c375e27 100755 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ testnet/*/binary contracts-tmp/ *node_modules push-chain-interop-contracts/ +node-upgrade-testing/