Skip to content

Commit cfa1b09

Browse files
Upgrade testing utilities added
1 parent 047f4be commit cfa1b09

File tree

7 files changed

+370
-0
lines changed

7 files changed

+370
-0
lines changed

Makefile

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,3 +480,34 @@ e2e-run-test:
480480
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
481481
cp $(E2E_DIR)/.env $(CONTRACTS_DIR)/push-chain-sdk/packages/core/.env
482482
cd $(CONTRACTS_DIR)/push-chain-sdk && npx jest core/__e2e__/pushchain.spec.ts --runInBand --detectOpenHandles
483+
484+
###############################################################################
485+
### e2e-upgrade... ###
486+
###############################################################################
487+
488+
CHAIN_DIR := ./node-upgrade-testing
489+
REPO := https://github.com/push-protocol/push-chain-node.git
490+
UTILS_DIR := ./testutils/upgrade-testing-utils
491+
CSV := $(UTILS_DIR)/upgrade_list.csv
492+
493+
chain-upgrade-test:
494+
@echo ">>> Cloning push-chain-node repo..."
495+
rm -rf $(CHAIN_DIR)
496+
mkdir -p $(CHAIN_DIR)
497+
cd $(CHAIN_DIR) && git clone $(REPO)
498+
499+
@echo ">>> Checking out first upgrade commit from CSV..."
500+
FIRST_COMMIT=$$(awk -F',' 'NR==2 {print $$2}' $(CSV)); \
501+
cd $(CHAIN_DIR)/push-chain-node && git checkout $$FIRST_COMMIT
502+
503+
@echo ">>> Copying utility files..."
504+
mkdir -p $(CHAIN_DIR)/push-chain-node/scripts
505+
cp $(UTILS_DIR)/test_node_e2e_upgrade.sh $(CHAIN_DIR)/push-chain-node/scripts/test_node_e2e_upgrade.sh
506+
cp $(UTILS_DIR)/Dockerfile.node_upgrade_test $(CHAIN_DIR)/push-chain-node/Dockerfile.node_upgrade_test
507+
cp $(UTILS_DIR)/docker-compose.yml $(CHAIN_DIR)/push-chain-node/docker-compose.yml
508+
509+
@echo ">>> Launching docker container for first upgrade..."
510+
cd $(CHAIN_DIR)/push-chain-node && docker compose up -d --build
511+
512+
513+
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
2
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
FROM golang:1.23 AS build
2+
WORKDIR /app
3+
4+
COPY go.mod go.sum ./
5+
RUN go mod download
6+
COPY . .
7+
RUN make install # regular build (dynamic link)
8+
9+
FROM ubuntu:22.04
10+
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/*
11+
12+
RUN curl -OL https://go.dev/dl/go1.23.0.linux-amd64.tar.gz
13+
RUN tar -C /usr/local -xzf go1.23.0.linux-amd64.tar.gz
14+
15+
ENV PATH=$PATH:/usr/local/go/bin
16+
17+
# Install wasmvm v1.5.4 shared library
18+
RUN curl -L https://github.com/CosmWasm/wasmvm/releases/download/v1.5.4/libwasmvm.aarch64.so \
19+
-o /usr/lib/libwasmvm.aarch64.so && chmod 755 /usr/lib/libwasmvm.aarch64.so
20+
21+
RUN curl -L https://github.com/CosmWasm/wasmvm/releases/download/v1.5.4/libwasmvm.x86_64.so \
22+
-o /usr/lib/libwasmvm.x86_64.so && chmod 755 /usr/lib/libwasmvm.x86_64.so
23+
24+
COPY --from=build /go/bin/pchaind /usr/local/bin/pchaind
25+
COPY scripts /app/scripts
26+
WORKDIR /app
27+
28+
ENV CHAIN_ID=localchain_9000-1 \
29+
BLOCK_TIME=1000ms \
30+
CLEAN=true
31+
32+
CMD ["bash", "scripts/test_node_e2e_upgrade.sh"]
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
version: '3.8'
2+
3+
services:
4+
push-chain-node:
5+
build:
6+
context: .
7+
dockerfile: Dockerfile.node_upgrade_test
8+
container_name: push-chain-node
9+
environment:
10+
- CHAIN_ID=localchain_9000-1
11+
- BLOCK_TIME=1000ms
12+
- CLEAN=true
13+
command: bash scripts/test_node_e2e_upgrade.sh
14+
extra_hosts:
15+
- "host.docker.internal:host-gateway"
16+
ports:
17+
- "26657:26657" # Tendermint RPC
18+
- "1317:1317" # Cosmos REST API
19+
- "8545:8545" # Cosmos REST API
20+
volumes:
21+
- ./scripts:/app/scripts
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
#!/bin/bash
2+
# Run this script to quickly install, setup, and run the current version of the network without docker.
3+
#
4+
# Examples:
5+
# CHAIN_ID="localchain_9000-1" HOME_DIR="~/.pchain" BLOCK_TIME="1000ms" CLEAN=true sh scripts/test_node.sh
6+
# 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
7+
shopt -s expand_aliases
8+
set -eu
9+
10+
export KEY1="acc1"
11+
export KEY2="acc2"
12+
export KEY3="acc3"
13+
14+
export CHAIN_ID=${CHAIN_ID:-"localchain_9000-1"}
15+
export MONIKER=${MONIKER:-"localvalidator"}
16+
export KEYALGO="eth_secp256k1"
17+
export KEYRING=${KEYRING:-"test"}
18+
export HOME_DIR=$(eval echo "${HOME_DIR:-"~/.pchain"}")
19+
export BINARY=${BINARY:-pchaind}
20+
export DENOM=${DENOM:-upc}
21+
22+
export CLEAN=${CLEAN:-"false"}
23+
export RPC=${RPC:-"26657"}
24+
export REST=${REST:-"1317"}
25+
export PROFF=${PROFF:-"6060"}
26+
export P2P=${P2P:-"26656"}
27+
export GRPC=${GRPC:-"9090"}
28+
export GRPC_WEB=${GRPC_WEB:-"9091"}
29+
export ROSETTA=${ROSETTA:-"8080"}
30+
export BLOCK_TIME=${BLOCK_TIME:-"1s"}
31+
32+
# if which binary does not exist, install it
33+
# if [ -z `which $BINARY` ]; then
34+
# make install
35+
36+
# if [ -z `which $BINARY` ]; then
37+
# echo "Ensure $BINARY is installed and in your PATH"
38+
# exit 1
39+
# fi
40+
# fi
41+
42+
alias BINARY="$BINARY --home=$HOME_DIR"
43+
44+
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; }
45+
command -v jq > /dev/null 2>&1 || { echo >&2 "jq not installed. More info: https://stedolan.github.io/jq/download/"; exit 1; }
46+
47+
set_config() {
48+
$BINARY config set client chain-id $CHAIN_ID
49+
$BINARY config set client keyring-backend $KEYRING
50+
}
51+
set_config
52+
53+
54+
from_scratch () {
55+
# Fresh install on current branch
56+
# make install
57+
58+
# remove existing daemon files.
59+
if [ ${#HOME_DIR} -le 2 ]; then
60+
echo "HOME_DIR must be more than 2 characters long"
61+
return
62+
fi
63+
rm -rf $HOME_DIR && echo "Removed $HOME_DIR"
64+
65+
# reset values if not set already after whipe
66+
set_config
67+
68+
add_key() {
69+
key=$1
70+
mnemonic=$2
71+
echo $mnemonic | BINARY keys add $key --keyring-backend $KEYRING --algo $KEYALGO --recover
72+
}
73+
74+
# push1ss5j8c8j453uecnczt3ms23lze30kxt4pzfvh9
75+
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"
76+
# push1j55s4vpvmncruakqhj2k2fywnc9mvsuhcap28q
77+
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"
78+
# push1fgaewhyd9fkwtqaj9c233letwcuey6dgly9gv9
79+
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"
80+
81+
BINARY init $MONIKER --chain-id $CHAIN_ID --default-denom $DENOM
82+
83+
update_test_genesis () {
84+
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
85+
}
86+
87+
# === CORE MODULES ===
88+
89+
# Block
90+
update_test_genesis '.consensus_params["block"]["max_gas"]="100000000"'
91+
92+
# Gov
93+
update_test_genesis `printf '.app_state["gov"]["params"]["min_deposit"]=[{"denom":"%s","amount":"1000000"}]' $DENOM`
94+
update_test_genesis '.app_state["gov"]["params"]["voting_period"]="30s"'
95+
update_test_genesis '.app_state["gov"]["params"]["expedited_voting_period"]="15s"'
96+
97+
update_test_genesis `printf '.app_state["evm"]["params"]["evm_denom"]="%s"' $DENOM`
98+
update_test_genesis '.app_state["evm"]["params"]["active_static_precompiles"]=["0x00000000000000000000000000000000000000CB","0x00000000000000000000000000000000000000ca","0x0000000000000000000000000000000000000100","0x0000000000000000000000000000000000000400","0x0000000000000000000000000000000000000800","0x0000000000000000000000000000000000000801","0x0000000000000000000000000000000000000802","0x0000000000000000000000000000000000000803","0x0000000000000000000000000000000000000804","0x0000000000000000000000000000000000000805"]'
99+
update_test_genesis '.app_state["erc20"]["params"]["native_precompiles"]=["0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"]' # https://eips.ethereum.org/EIPS/eip-7528
100+
update_test_genesis `printf '.app_state["erc20"]["token_pairs"]=[{contract_owner:1,erc20_address:"0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",denom:"%s",enabled:true}]' $DENOM`
101+
update_test_genesis '.app_state["feemarket"]["params"]["no_base_fee"]=false'
102+
update_test_genesis '.app_state["feemarket"]["params"]["base_fee"]="1000000000.000000000000000000"'
103+
update_test_genesis '.app_state["feemarket"]["params"]["min_gas_price"]="1000000000.000000000000000000"'
104+
105+
# staking
106+
update_test_genesis `printf '.app_state["staking"]["params"]["bond_denom"]="%s"' $DENOM`
107+
update_test_genesis '.app_state["staking"]["params"]["min_commission_rate"]="0.050000000000000000"'
108+
109+
# mint
110+
update_test_genesis `printf '.app_state["mint"]["params"]["mint_denom"]="%s"' $DENOM`
111+
112+
# crisis
113+
update_test_genesis `printf '.app_state["crisis"]["constant_fee"]={"denom":"%s","amount":"1000"}' $DENOM`
114+
115+
## abci
116+
update_test_genesis '.consensus["params"]["abci"]["vote_extensions_enable_height"]="1"'
117+
118+
# === CUSTOM MODULES ===
119+
# tokenfactory
120+
update_test_genesis '.app_state["tokenfactory"]["params"]["denom_creation_fee"]=[]'
121+
update_test_genesis '.app_state["tokenfactory"]["params"]["denom_creation_gas_consume"]=100000'
122+
123+
# Allocate genesis accounts
124+
# Total: 10 000000000 . 000000000 000000000
125+
BINARY genesis add-genesis-account $KEY1 5000000000000000000000000000$DENOM,100000000test --keyring-backend $KEYRING --append
126+
BINARY genesis add-genesis-account $KEY2 3000000000000000000000000000$DENOM,90000000test --keyring-backend $KEYRING --append
127+
BINARY genesis add-genesis-account $KEY3 2000000000000000000000000000$DENOM,90000000test --keyring-backend $KEYRING --append
128+
129+
# Sign genesis transaction
130+
# 10 000 . 000000000 000000000
131+
BINARY genesis gentx $KEY1 10000000000000000000000$DENOM --gas-prices 1000000000${DENOM} --keyring-backend $KEYRING --chain-id $CHAIN_ID
132+
133+
BINARY genesis collect-gentxs
134+
135+
BINARY genesis validate-genesis
136+
err=$?
137+
if [ $err -ne 0 ]; then
138+
echo "Failed to validate genesis"
139+
return
140+
fi
141+
}
142+
143+
# check if CLEAN is not set to false
144+
if [ "$CLEAN" != "false" ]; then
145+
echo "Starting from a clean state"
146+
from_scratch
147+
fi
148+
149+
echo "Starting node..."
150+
151+
# Opens the RPC endpoint to outside connections
152+
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
153+
sed -i -e 's/cors_allowed_origins = \[\]/cors_allowed_origins = \["\*"\]/g' $HOME_DIR/config/config.toml
154+
155+
# REST endpoint
156+
sed -i -e 's/address = "tcp:\/\/localhost:1317"/address = "tcp:\/\/0.0.0.0:'$REST'"/g' $HOME_DIR/config/app.toml
157+
sed -i -e 's/enable = false/enable = true/g' $HOME_DIR/config/app.toml
158+
sed -i -e 's/enabled-unsafe-cors = false/enabled-unsafe-cors = true/g' $HOME_DIR/config/app.toml
159+
160+
# peer exchange
161+
sed -i -e 's/pprof_laddr = "localhost:6060"/pprof_laddr = "localhost:'$PROFF'"/g' $HOME_DIR/config/config.toml
162+
sed -i -e 's/laddr = "tcp:\/\/0.0.0.0:26656"/laddr = "tcp:\/\/0.0.0.0:'$P2P'"/g' $HOME_DIR/config/config.toml
163+
164+
# GRPC
165+
sed -i -e 's/address = "localhost:9090"/address = "0.0.0.0:'$GRPC'"/g' $HOME_DIR/config/app.toml
166+
sed -i -e 's/address = "localhost:9091"/address = "0.0.0.0:'$GRPC_WEB'"/g' $HOME_DIR/config/app.toml
167+
168+
# Rosetta Api
169+
sed -i -e 's/address = ":8080"/address = "0.0.0.0:'$ROSETTA'"/g' $HOME_DIR/config/app.toml
170+
171+
# Faster blocks
172+
sed -i -e 's/timeout_commit = "5s"/timeout_commit = "'$BLOCK_TIME'"/g' $HOME_DIR/config/config.toml
173+
174+
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"
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
upgrade_name,commit_hash
2+
current,2536b88b0d836ef900802014fc3d003401387c44
3+
uaid-refactor,47aa1d83641d960c198605648b813106f9bb7bab
4+
uaid-refactor,47aa1d83641d960c198605648b813106f9bb7bab
5+
uaid-refactor,47aa1d83641d960c198605648b813106f9bb7bab
6+
uaid-refactor,47aa1d83641d960c198605648b813106f9bb7bab
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
#!/bin/bash
2+
set -e
3+
4+
# Paths inside container
5+
CSV_FILE="./testutils/upgrade-testing-utils/upgrade_list.csv"
6+
STATE_FILE="./testutils/upgrade-testing-utils/.upgrade_index"
7+
8+
# If first run, set index = 2 (meaning line 2 = current commit done, upgrades start at line 3)
9+
if [ ! -f "$STATE_FILE" ]; then
10+
echo 2 > "$STATE_FILE"
11+
fi
12+
13+
CURRENT_INDEX=$(cat "$STATE_FILE")
14+
NEXT_INDEX=$((CURRENT_INDEX + 1))
15+
16+
# Count total upgrades (excluding header row)
17+
TOTAL_UPGRADES=$(($(wc -l < "$CSV_FILE") - 1))
18+
19+
echo "TOTAL_UPGRADES=$TOTAL_UPGRADES"
20+
echo "CURRENT_INDEX=$CURRENT_INDEX"
21+
echo "NEXT_INDEX=$NEXT_INDEX"
22+
23+
# If we’ve reached past last upgrade line
24+
if [ "$NEXT_INDEX" -gt $((TOTAL_UPGRADES + 1)) ]; then
25+
echo "✅ All upgrades applied!"
26+
exit 0
27+
fi
28+
29+
# Get the upgrade details from CSV
30+
NEXT_UPGRADE=$(awk -F',' -v idx=$NEXT_INDEX 'NR==idx {print $1","$2}' "$CSV_FILE")
31+
32+
if [ -z "$NEXT_UPGRADE" ]; then
33+
echo "❌ No upgrade found at line $NEXT_INDEX."
34+
exit 1
35+
fi
36+
37+
UPGRADE_NAME=$(echo "$NEXT_UPGRADE" | cut -d',' -f1 | xargs)
38+
COMMIT_HASH=$(echo "$NEXT_UPGRADE" | cut -d',' -f2 | xargs)
39+
40+
echo ">>> Applying upgrade (line $NEXT_INDEX): $UPGRADE_NAME ($COMMIT_HASH)"
41+
42+
# Clone, checkout commit, build inside container
43+
docker exec push-chain-node bash -c "
44+
set -e
45+
cd /app || mkdir -p /app && cd /app
46+
echo '>>> Removing existing repo (if any)'
47+
rm -rf push-chain-node
48+
49+
echo '>>> Cloning push-chain-node repo'
50+
git clone https://github.com/push-protocol/push-chain-node.git push-chain-node
51+
52+
cd push-chain-node
53+
54+
echo '>>> Checking out commit $COMMIT_HASH'
55+
git checkout $COMMIT_HASH
56+
57+
echo '>>> Building binary'
58+
CGO_ENABLED=0 make build
59+
60+
if [ ! -f build/pchaind ]; then
61+
echo '❌ Build failed'
62+
exit 1
63+
fi
64+
65+
echo '>>> Copying binary to /usr/local/bin'
66+
cp build/pchaind /usr/local/bin/pchaind
67+
"
68+
69+
# Get current height inside container
70+
HEIGHT=$(docker exec push-chain-node pchaind status | jq -r '.SyncInfo.latest_block_height')
71+
TARGET_HEIGHT=$(( (HEIGHT/1000 + 1) * 1000 ))
72+
73+
echo ">>> Submitting governance proposal for $UPGRADE_NAME at height $TARGET_HEIGHT..."
74+
docker exec push-chain-node pchaind tx upgrade software-upgrade "$UPGRADE_NAME" \
75+
--upgrade-height "$TARGET_HEIGHT" \
76+
--title "Test Upgrade $UPGRADE_NAME" \
77+
--summary "Automated upgrade test for $UPGRADE_NAME" \
78+
--from acc1 \
79+
--chain-id localchain_9000-1 \
80+
--deposit 1000000upc \
81+
--node tcp://localhost:26657 \
82+
--gas auto \
83+
--gas-adjustment 1.3 \
84+
--fees 310596000000000upc \
85+
--yes
86+
87+
# Wait for halt
88+
echo ">>> Waiting for chain halt at height $TARGET_HEIGHT..."
89+
while true; do
90+
CUR_HEIGHT=$(docker exec push-chain-node pchaind status | jq -r '.SyncInfo.latest_block_height')
91+
if [ "$CUR_HEIGHT" -ge "$TARGET_HEIGHT" ]; then
92+
echo "Chain halted at $CUR_HEIGHT."
93+
break
94+
fi
95+
sleep 5
96+
done
97+
98+
# Restart node with upgraded binary
99+
echo ">>> Restarting chain with upgraded binary..."
100+
docker exec push-chain-node pkill pchaind || true
101+
docker exec -d push-chain-node pchaind start
102+
103+
# Update state → store the line number we just processed
104+
echo "$NEXT_INDEX" > "$STATE_FILE"
105+
echo "✅ Upgrade $UPGRADE_NAME applied successfully!"

0 commit comments

Comments
 (0)