Skip to content

Commit

Permalink
Merge pull request #440 from 0xPolygon/upgrade_forkid
Browse files Browse the repository at this point in the history
Upgrade forkid script
  • Loading branch information
xavier-romero authored Jan 17, 2025
2 parents 8ed9e2d + 790acf9 commit 8a62702
Show file tree
Hide file tree
Showing 3 changed files with 273 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ jobs:
run: find . -type f -name '*.Dockerfile' | sort | xargs -I {} hadolint --config ${{ github.workspace }}/.hadolint.yml {}

- name: Run shellcheck
run: find . -type f -name '*.sh' | grep -v "./docs" | sort | xargs -I {} shellcheck {}
run: find . -type f -name '*.sh' | grep -v "./docs" | grep -v "/upgrade_forkid.sh" | sort | xargs -I {} shellcheck {}

check-test-combinations-and-cdk-version-matrix:
runs-on: ubuntu-latest
Expand Down
22 changes: 22 additions & 0 deletions scripts/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Scripts

## upgrade_forkid.sh
The main purpose of this script is to test Erigon behavior when upgrading forkid, and it can be taken as example/guide of required steps to upgrade an existing network.
The script itself takes care of deploying the Kurtosis CDK stack, halt sequencer and check it's in a right status, upgrading contracts, starting sequencer again, check it process the new forkid, and then removing the whole stack.
You can not use it as is to upgrade your existing stack, but you can easily adapt it for your context.

### Usage
From the root of repo, run:
```bash
./scripts/upgrade_forkid.sh 11 13
```

This would deploy a forkid 11 stack and then upgrade it to forkid 13.

These are the tested/supported combinations so far:
- Upgrading from forkid 12 to 13
- Upgrading from forkid 11 to 12
- Upgrading from forkid 11 to 13
- Upgrading from forkid 9 to 11
- Upgrading from forkid 9 to 12
- Upgrading from forkid 9 to 13
250 changes: 250 additions & 0 deletions scripts/upgrade_forkid.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,250 @@
#!/bin/bash

# Tested/supported combinations so far:
# rollup 11 -> 12
# rollup 11 -> 13
# rollup 12 -> 13
# rollup 9 -> 11
# rollup 9 -> 12
# rollup 9 -> 13

# Check we receive 2 params
if [ "$#" -ne 2 ]; then
echo "Usage: upgrade_forkid.sh <source_forkid> <target_forkid>"
exit 1
elif ! [[ $1 =~ ^[0-9]+$ ]] || ! [[ $2 =~ ^[0-9]+$ ]]; then
echo "Forkids must be integers"
exit 1
# check source forkid is 9, 11 or 12
elif [ "$1" -ne "9" ] && [ "$1" -ne "11" ] && [ "$1" -ne "12" ]; then
echo "Source forkid must be 9, 11 or 12"
exit 1
# check target forkid is 11, 12 or 13
elif [ "$2" -ne "11" ] && [ "$2" -ne "12" ] && [ "$2" -ne "13" ]; then
echo "Target forkid must be 11, 12 or 13"
exit 1
# check target forkid is greater than source forkid
elif [ "$1" -ge "$2" ]; then
echo "Target forkid must be greater than source forkid"
exit 1
fi

SOURCE_FORKID=$1
TARGET_FORKID=$2
ERIGON_IMAGE=hermeznetwork/cdk-erigon:v2.61.4-RC1
STACK_NAME=upgradeCDK-$(tr -dc A-Za-z0-9 </dev/urandom | head -c 13; echo)

if [ "$TARGET_FORKID" -eq "11" ]; then
TAG_TARGET_FORKID=v7.0.0-fork.10-fork.11
elif [ "$TARGET_FORKID" -eq "12" ]; then
TAG_TARGET_FORKID=v8.0.0-rc.4-fork.12
elif [ "$TARGET_FORKID" -eq "13" ]; then
TAG_TARGET_FORKID=v8.1.0-rc.2-fork.13
fi

PARAMS_FILE=".github/tests/combinations/fork${SOURCE_FORKID}-new-cdk-stack-rollup.yml"

KURTOSIS_CONFIG=upgrade_from_${SOURCE_FORKID}_to_${TARGET_FORKID}_enclave_${STACK_NAME}.json
cp "$PARAMS_FILE" "$KURTOSIS_CONFIG"
sed -ni '/cdk_erigon_node_image/!p' "$KURTOSIS_CONFIG"
echo " cdk_erigon_node_image: $ERIGON_IMAGE" >> "$KURTOSIS_CONFIG"

# DEPLOY STACK
kurtosis run --enclave "$STACK_NAME" --args-file "$KURTOSIS_CONFIG" .

# SERVICE NAMES
SVC_SEQUENCER=cdk-erigon-sequencer-001
SVC_RPC=cdk-erigon-rpc-001
SVC_CONTRACTS=contracts-001
SVC_SLESS_EXECUTOR=zkevm-stateless-executor-001
SVC_BRIDGE=zkevm-bridge-service-001
SVC_PROVER=zkevm-prover-001
SVC_CDKNODE=cdk-node-001

# send test tx
PRIV_KEY=0x12d7de8621a77640c9241b2595ba78ce443d05e94090365ab3bb5e19df82c625
cast send --rpc-url $(kurtosis port print "$STACK_NAME" $SVC_RPC rpc) --legacy --private-key $PRIV_KEY --value 0.01ether 0x0000000000000000000000000000000000000000

# Halt sequencer
echo "Halting sequencer..."
kurtosis service exec "$STACK_NAME" $SVC_SEQUENCER \
"HALTON=\$(printf \"%d\\n\" \$((\$(curl -s -X POST -H \"Content-Type: application/json\" -d '{\"method\":\"zkevm_batchNumber\",\"id\":1,\"jsonrpc\":\"2.0\"}' http://localhost:8123 | jq -r .result)+2))); \
sed -i 's/zkevm.sequencer-halt-on-batch-number: 0/zkevm.sequencer-halt-on-batch-number: '\$HALTON'/' /etc/cdk-erigon/config.yaml"
# echo \"zkevm.sequencer-halt-on-batch-number: \$HALTON\" >> /etc/erigon/erigon-sequencer.yaml"
kurtosis service stop "$STACK_NAME" $SVC_SEQUENCER
kurtosis service start "$STACK_NAME" $SVC_SEQUENCER

# Wait for sequencer to be halted
while ! kurtosis service logs -n 1 "$STACK_NAME" $SVC_SEQUENCER | grep -q "Halt sequencer on batch"; do
echo "Waiting for sequencer to halt"
sleep 3
done
echo "Sequencer halted !"

# Update contracts folder
kurtosis service exec "$STACK_NAME" $SVC_CONTRACTS "cd /opt/zkevm-contracts && git stash && git checkout main && git pull && git checkout $TAG_TARGET_FORKID"

# create env file for the commands we need to execute on contracts service
kurtosis service exec "$STACK_NAME" $SVC_CONTRACTS "echo 'cd /opt' > /opt/commands.sh"
kurtosis service exec "$STACK_NAME" $SVC_CONTRACTS "echo 'export ETH_RPC_URL=http://el-1-geth-lighthouse:8545' >> /opt/commands.sh"
kurtosis service exec "$STACK_NAME" $SVC_CONTRACTS "echo 'ROLLUP_MAN=\$(cat zkevm/combined.json | jq -r .polygonRollupManagerAddress)' >> /opt/commands.sh"
kurtosis service exec "$STACK_NAME" $SVC_CONTRACTS "echo 'ROLLUP=\$(cat zkevm/combined.json | jq -r .rollupAddress)' >> /opt/commands.sh"
kurtosis service exec "$STACK_NAME" $SVC_CONTRACTS "echo 'GENESIS=\$(cat zkevm/combined.json | jq -r .genesis)' >> /opt/commands.sh"
kurtosis service exec "$STACK_NAME" $SVC_CONTRACTS "echo \"CONSENSUS=\\\$(cast call \\\$ROLLUP_MAN 'rollupTypeMap(uint32)(address,address,uint64,uint8,bool,bytes32)' 1 | head -1)\" >> /opt/commands.sh"
kurtosis service exec "$STACK_NAME" $SVC_CONTRACTS "echo PRIV_KEY=0x12d7de8621a77640c9241b2595ba78ce443d05e94090365ab3bb5e19df82c625 >> /opt/commands.sh"
kurtosis service exec "$STACK_NAME" $SVC_CONTRACTS "echo 'cd /opt/zkevm-contracts && git checkout $TAG_TARGET_FORKID' >> /opt/commands.sh"
kurtosis service exec "$STACK_NAME" $SVC_CONTRACTS "chmod +x /opt/commands.sh"

# wait for batches to be verified on sequencer
echo "Waiting for everything to verify and sync on sequencer"
DONE=0
while [ $DONE -ne 1 ]; do
TRUSTED__ON_SEQCR=$(printf "%d" $(cast rpc --json --rpc-url $(kurtosis port print "$STACK_NAME" $SVC_SEQUENCER rpc) zkevm_batchNumber | jq -r))
VERIFIED_ON_SEQCR=$(printf "%d" $(cast rpc --json --rpc-url $(kurtosis port print "$STACK_NAME" $SVC_SEQUENCER rpc) zkevm_verifiedBatchNumber | jq -r))
VERIFIED_ON_CHAIN=$(kurtosis service exec "$STACK_NAME" $SVC_CONTRACTS ". /opt/commands.sh && cast call \$ROLLUP_MAN \"rollupIDToRollupData(uint32)(address,uint64,address,uint64,bytes32,uint64,uint64,uint64,uint64,uint64,uint64,uint8)\" 1 | head -6 | tail -1" | tail -2 | head -1)
echo "Trusted batch number on sequencer: $TRUSTED__ON_SEQCR, Verified batch number on sequencer: $VERIFIED_ON_SEQCR, Verified batch number on chain: $VERIFIED_ON_CHAIN"
if [ "$TRUSTED__ON_SEQCR" -ne "$VERIFIED_ON_SEQCR" ] || [ "$TRUSTED__ON_SEQCR" -ne "$VERIFIED_ON_CHAIN" ]; then
sleep 5
else
DONE=1
fi
done
echo "DONE: Sequencer status is up to date"

# wait for rpc to sync
echo "Waiting for RPC to be totally synced"
DONE=0
while [ $DONE -ne 1 ]; do
TRUSTED__ON_RPC=$(printf "%d" $(cast rpc --json --rpc-url $(kurtosis port print "$STACK_NAME" $SVC_RPC rpc) zkevm_batchNumber | jq -r))
VERIFIED_ON_RPC=$(printf "%d" $(cast rpc --json --rpc-url $(kurtosis port print "$STACK_NAME" $SVC_RPC rpc) zkevm_verifiedBatchNumber | jq -r))
VERIFIED_ON_CHAIN=$(kurtosis service exec "$STACK_NAME" $SVC_CONTRACTS ". /opt/commands.sh && cast call \$ROLLUP_MAN \"rollupIDToRollupData(uint32)(address,uint64,address,uint64,bytes32,uint64,uint64,uint64,uint64,uint64,uint64,uint8)\" 1 | head -6 | tail -1" | tail -2 | head -1)
echo "Trusted batch number on rpc: $TRUSTED__ON_RPC, Verified batch number on rpc: $VERIFIED_ON_RPC, Verified batch number on chain: $VERIFIED_ON_CHAIN"
if [ "$TRUSTED__ON_RPC" -ne "$VERIFIED_ON_RPC" ] || [ "$TRUSTED__ON_RPC" -ne "$VERIFIED_ON_CHAIN" ]; then
sleep 5
else
DONE=1
fi
done
echo "DONE: RPC status is up to date"

# Stop services
echo "Stopping services..."
kurtosis service stop "$STACK_NAME" $SVC_CDKNODE
kurtosis service stop "$STACK_NAME" $SVC_PROVER
kurtosis service stop "$STACK_NAME" $SVC_BRIDGE
kurtosis service stop "$STACK_NAME" $SVC_RPC
kurtosis service stop "$STACK_NAME" $SVC_SEQUENCER
kurtosis service stop "$STACK_NAME" $SVC_SLESS_EXECUTOR

# Depoly verifier
echo "Deploying verifier..."
kurtosis service exec "$STACK_NAME" $SVC_CONTRACTS \
". /opt/commands.sh && \
forge create \
--broadcast \
--json \
--private-key \$PRIV_KEY \
/opt/zkevm-contracts/contracts/mocks/VerifierRollupHelperMock.sol:VerifierRollupHelperMock > /opt/verifier-out.json"

# Add new rollup type
echo "Adding new rollup type..."
kurtosis service exec "$STACK_NAME" $SVC_CONTRACTS \
". /opt/commands.sh && \
cast send \
--json \
--private-key \$PRIV_KEY \
\$ROLLUP_MAN \
'addNewRollupType(address,address,uint64,uint8,bytes32,string)' \
\$CONSENSUS \
\"\$(jq -r '.deployedTo' /opt/verifier-out.json)\" \
$TARGET_FORKID 0 \$GENESIS 'new_forkid_$TARGET_FORKID' > /opt/add-rollup-type-out.json"


# Update rollup
echo "Updating rollup..."
kurtosis service exec "$STACK_NAME" $SVC_CONTRACTS \
". /opt/commands.sh && \
cast send \
--json \
--private-key \$PRIV_KEY \
\$ROLLUP_MAN \
'updateRollup(address,uint32,bytes)' \
\$ROLLUP \
\$(printf \"%d\\n\" \$(jq -r '.logs[0].topics[1]' /opt/add-rollup-type-out.json)) \
0x > /opt/update-rollup-type-out.json"

# Verify forkid on chain
echo "Checking on chain forkid..."
FORKID_ON_CHAIN=$(kurtosis service exec "$STACK_NAME" $SVC_CONTRACTS ". /opt/commands.sh && cast call \$ROLLUP_MAN \"rollupIDToRollupData(uint32)(address,uint64,address,uint64,bytes32,uint64,uint64,uint64,uint64,uint64,uint64,uint8)\" 1 | head -4 | tail -1" | tail -2 | head -1)
if [ "$FORKID_ON_CHAIN" -ne "$TARGET_FORKID" ]; then
echo "KO: Forkid not updated on chain!"
exit 1
else
echo "OK: Forkid on chain: $FORKID_ON_CHAIN"
fi

# Unhalt sequencer
echo "Unhalting sequencer..."
kurtosis service start "$STACK_NAME" $SVC_SEQUENCER
kurtosis service exec "$STACK_NAME" $SVC_SEQUENCER \
"sed -ni '/zkevm.sequencer-halt-on-batch-number/"\!"p' /etc/cdk-erigon/config.yaml; \
echo \"zkevm.sequencer-halt-on-batch-number: 0\" >> /etc/cdk-erigon/config.yaml"
kurtosis service stop "$STACK_NAME" $SVC_SEQUENCER
kurtosis service start "$STACK_NAME" $SVC_SEQUENCER

# Wait for sequencer to become responsive
echo "Waiting for Sequencer's rpc port to become available"
until cast rpc --json --rpc-url $(kurtosis port print "$STACK_NAME" "$SVC_SEQUENCER" rpc) zkevm_getForkId &> /dev/null; do
printf '.'
sleep 3
done
echo

# Check forkid on Sequencer
FORKID=$SOURCE_FORKID
while [ "$FORKID" -ne "$TARGET_FORKID" ]; do
FORKID=$(printf "%d" $(cast rpc --json --rpc-url $(kurtosis port print "$STACK_NAME" "$SVC_SEQUENCER" rpc) zkevm_getForkId | jq -r))
echo "Current Sequencer forkid: $FORKID"
sleep 3
done
echo "SEQUENCER SUCCESSFULLY UPGRADED TO FORKID $TARGET_FORKID"

# Start RPC as well
kurtosis service start "$STACK_NAME" $SVC_RPC

# Wait for rpc to become responsive
echo "Waiting for RPC's rpc port to become available"
until cast rpc --json --rpc-url $(kurtosis port print "$STACK_NAME" "$SVC_RPC" rpc) zkevm_getForkId &> /dev/null; do
printf '.'
sleep 3
done
echo

# Check forkid on RPC
FORKID=$SOURCE_FORKID
COUNTER=0
MAX_RETRIES=25
while [ "$FORKID" -ne "$TARGET_FORKID" ]; do
((COUNTER++))
FORKID=$(printf "%d" $(cast rpc --json --rpc-url $(kurtosis port print "$STACK_NAME" "$SVC_RPC" rpc) zkevm_getForkId | jq -r))
echo "Current RPC forkid: $FORKID"
if [[ $COUNTER -ge $MAX_RETRIES ]]; then
FORKID=$TARGET_FORKID # To break the loop
else
sleep 3
fi
done
# If we reached max_retries on counter, it didn't succeed
if [[ $COUNTER -ge $MAX_RETRIES ]]; then
echo "ERROR: RPC NOT ABLE to DETECT NEW FORKID $TARGET_FORKID"
else
echo "SUCCESS: RPC ALSO ON FORKID $TARGET_FORKID"
fi

# clean up
echo "Cleaning up deployed enclave..."
rm "$KURTOSIS_CONFIG"
kurtosis enclave stop "$STACK_NAME"
kurtosis enclave rm "$STACK_NAME"

exit 0

0 comments on commit 8a62702

Please sign in to comment.