Last active
April 24, 2024 15:06
-
-
Save kajoseph/0a57e42ca40eac3dcaabea20128729c3 to your computer and use it in GitHub Desktop.
Polygon Edge
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# REF: https://wiki.polygon.technology/docs/supernets/operate/deploy/ | |
NO_START=0 | |
QUIET=0 | |
CHAIN_ID=13375 | |
NODE=1 | |
LINES=50 | |
VERSION="1.0.0-rc1" | |
BLOCK_TIME=10 | |
# ETH_HEX_KEY= | |
Usage() { | |
echo "A Polygon-Edge script that sets up and manages a local Polygon network with 4 nodes" | |
echo | |
echo "Usage: ./polygon <command> [options]" | |
echo | |
echo "Commands:" | |
echo " init Downloads the docker images and creates, configures, and starts the local network" | |
# echo " --eth-key <value> (REQUIRED) Hex-encoded private key used to deploy contracts to your local ETH chain. Must have funds on ETH chain" | |
echo " --no-start Do not start the network after creation" | |
echo " --quiet Do not print the nodes info after creation" | |
echo " --chainId <value> Custom chain ID (default: $CHAIN_ID)" | |
echo " --version <value> Version of Polygon-Edge (default: $VERSION). Use \`latest\` at your own risk" | |
echo " --block-time <value> Interval (in seconds) for blocks to be mined (default: $BLOCK_TIME)" | |
echo " start Starts the local Polygon network" | |
echo " stop Stops the local Polygon network" | |
echo " info Prints info about each node" | |
echo " --quiet Do not print sensitive information (such as private keys) (default: $QUIET)" | |
echo " logs Tail the logs of a node" | |
echo " -n, --node <value> Specify which node (default: $NODE)" | |
echo " -l, --lines <value> Number of lines to tail (default: $LINES)" | |
echo " clean Deletes everything! Deletes all data, containers, and images" | |
echo " rebuild Recreates containers. Useful if you need to change ports." | |
echo " --block-time <value> Interval (in seconds) for blocks to be mined (default: $BLOCK_TIME)" | |
echo | |
} | |
Init() { | |
echo "Enter the JSON-RPC port to your local ETH node (defaut: 8545). Note: your local ETH node needs to be running" | |
read ETH_PORT | |
if [ "$ETH_PORT" == "" ]; then | |
ETH_PORT=8545 | |
echo Using default ETH RPC port. | |
fi | |
docker pull 0xpolygon/polygon-edge:$VERSION | |
mkdir ~/.polygon-edge/ 2>/dev/null | |
BOOT_NODE_ID_1= | |
BOOT_NODE_ID_2= | |
NODE_ADDRESSES=() | |
NODE_PUB_KEYS=() | |
NODE_IDS=() | |
NODE_SIGS=() | |
WORKDIR=~/.polygon-edge | |
for i in {1..4}; do | |
NAME=polygon-edge-$i | |
# WORKDIR=~/.polygon-edge/node-$i | |
# mkdir $WORKDIR/node-$i 2>/dev/null | |
OUTPUT=$(docker container run \ | |
--rm \ | |
--workdir /workdir \ | |
--volume $WORKDIR:/workdir \ | |
0xpolygon/polygon-edge:$VERSION \ | |
polybft-secrets --insecure --data-dir /workdir/node-$i) | |
PUB_KEY_ADDRESS=$(echo "${OUTPUT}" | grep "Public key (address)" | $SED -r 's/(Public key \(address\))[[:space:]]*=[[:space:]]//') | |
BLS_PUB_KEY=$(echo "${OUTPUT}" | grep "BLS Public key" | $SED -r 's/(BLS Public key)[[:space:]]*=[[:space:]]//') | |
BLS_SIGNATURE=$(echo "${OUTPUT}" | grep "BLS Signature" | $SED -r 's/(BLS Signature)[[:space:]]*=[[:space:]]//') | |
NODE_ID=$(echo "${OUTPUT}" | grep "Node ID" | $SED -r 's/(Node ID)[[:space:]]*=[[:space:]]//') | |
if [ "$i" == "1" ]; then | |
BOOT_NODE_ID_1=$NODE_ID | |
elif [ "$i" == "2" ]; then | |
BOOT_NODE_ID_2=$NODE_ID | |
fi | |
NODE_ADDRESSES+=($PUB_KEY_ADDRESS) | |
NODE_PUB_KEYS+=($BLS_PUB_KEY) | |
NODE_SIGS+=($BLS_SIGNATURE) | |
NODE_IDS+=($NODE_ID) | |
sudo chown :$USER -R $WORKDIR/node-$i | |
sudo chmod g+w -R $WORKDIR/node-$i | |
echo "$OUTPUT" | $SED '0,/^\[SECRETS INIT\]$/d' > $WORKDIR/node-$i/node.info | |
done | |
docker network create --subnet 190.180.170.0/24 polygon-edge | |
# docker container run \ | |
# --rm \ | |
# --workdir /workdir \ | |
# --volume $WORKDIR:/workdir \ | |
# 0xpolygon/polygon-edge:$VERSION \ | |
# manifest \ | |
# --chain-id $CHAIN_ID \ | |
# --validators /ip4/190.180.170.11/tcp/30011/p2p/${NODE_IDS[0]}:${NODE_ADDRESSES[0]}:${NODE_PUB_KEYS[0]}:${NODE_SIGS[0]} \ | |
# --validators /ip4/190.180.170.12/tcp/30021/p2p/${NODE_IDS[1]}:${NODE_ADDRESSES[1]}:${NODE_PUB_KEYS[1]}:${NODE_SIGS[1]} \ | |
# --validators /ip4/190.180.170.13/tcp/30031/p2p/${NODE_IDS[2]}:${NODE_ADDRESSES[2]}:${NODE_PUB_KEYS[2]}:${NODE_SIGS[2]} \ | |
# --validators /ip4/190.180.170.14/tcp/30041/p2p/${NODE_IDS[3]}:${NODE_ADDRESSES[3]}:${NODE_PUB_KEYS[3]}:${NODE_SIGS[3]} \ | |
# --path ./manifest.json \ | |
# --premine-validators 100 | |
docker container run \ | |
--rm \ | |
--workdir /workdir \ | |
--volume $WORKDIR:/workdir \ | |
0xpolygon/polygon-edge:$VERSION \ | |
genesis \ | |
--epoch-size $BLOCK_TIME \ | |
--consensus polybft \ | |
--native-token-config "Matic:MATIC:18:true" \ | |
--premine ${NODE_ADDRESSES[0]}:1000000000000000000000000000 \ | |
--premine ${NODE_ADDRESSES[1]}:1000000000000000000000000000 \ | |
--premine ${NODE_ADDRESSES[2]}:1000000000000000000000000000 \ | |
--premine ${NODE_ADDRESSES[3]}:1000000000000000000000000000 \ | |
--reward-wallet ${NODE_ADDRESSES[0]}:1000000000000000000000000000 \ | |
--validators /ip4/190.180.170.11/tcp/30011/p2p/${NODE_IDS[0]}:${NODE_ADDRESSES[0]}:${NODE_PUB_KEYS[0]} \ | |
--validators /ip4/190.180.170.12/tcp/30021/p2p/${NODE_IDS[1]}:${NODE_ADDRESSES[1]}:${NODE_PUB_KEYS[1]} \ | |
--validators /ip4/190.180.170.13/tcp/30031/p2p/${NODE_IDS[2]}:${NODE_ADDRESSES[2]}:${NODE_PUB_KEYS[2]} \ | |
--validators /ip4/190.180.170.14/tcp/30041/p2p/${NODE_IDS[3]}:${NODE_ADDRESSES[3]}:${NODE_PUB_KEYS[3]} \ | |
--chain-id $CHAIN_ID | |
# --validators /ip4/190.180.170.11/tcp/30011/p2p/${NODE_IDS[0]}:${NODE_ADDRESSES[0]}:${NODE_PUB_KEYS[0]}:${NODE_SIGS[0]} \ | |
# --validators /ip4/190.180.170.12/tcp/30021/p2p/${NODE_IDS[1]}:${NODE_ADDRESSES[1]}:${NODE_PUB_KEYS[1]}:${NODE_SIGS[1]} \ | |
# --validators /ip4/190.180.170.13/tcp/30031/p2p/${NODE_IDS[2]}:${NODE_ADDRESSES[2]}:${NODE_PUB_KEYS[2]}:${NODE_SIGS[2]} \ | |
# --validators /ip4/190.180.170.14/tcp/30041/p2p/${NODE_IDS[3]}:${NODE_ADDRESSES[3]}:${NODE_PUB_KEYS[3]}:${NODE_SIGS[3]} | |
# --manifest ./manifest.json | |
# --bridge-json-rpc http://127.0.0.1:8545 \ | |
# --bootnode /ip4/190.180.170.11/tcp/10001/p2p/$BOOT_NODE_ID_1 \ | |
# --bootnode /ip4/190.180.170.12/tcp/20001/p2p/$BOOT_NODE_ID_2 | |
# --ibft-validator ${NODE_ADDRESSES[0]}:${NODE_PUB_KEYS[0]} \ | |
# --ibft-validator ${NODE_ADDRESSES[1]}:${NODE_PUB_KEYS[1]} \ | |
# --ibft-validator ${NODE_ADDRESSES[2]}:${NODE_PUB_KEYS[2]} \ | |
# --ibft-validator ${NODE_ADDRESSES[3]}:${NODE_PUB_KEYS[3]} \ | |
sudo chown :$USER -R $WORKDIR/genesis.json | |
sudo chmod g+w -R $WORKDIR/genesis.json | |
echo ================================================= | |
echo DEPLOYING CONTRACTS. THIS MAY TAKE A WHILE, DEPENDING ON THE BLOCK FREQUENCY OF YOUR ETH NODE | |
echo ================================================= | |
docker container run \ | |
--rm \ | |
--workdir /workdir \ | |
--volume $WORKDIR:/workdir \ | |
--network host \ | |
0xpolygon/polygon-edge:$VERSION \ | |
polybft stake-manager-deploy \ | |
--jsonrpc http://127.0.0.1:$ETH_PORT \ | |
--genesis ./genesis.json \ | |
--test | |
STAKE_MGR_CONTRACT=$(cat $WORKDIR/genesis.json | grep stakeManagerAddr | sed -r 's/.*\"stakeManagerAddr\"\:[[:space:]]\"//' | sed -r 's/",//'); | |
STAKE_TOKEN_CONTRACT=$(cat $WORKDIR/genesis.json | grep stakeTokenAddr | sed -r 's/.*\"stakeTokenAddr\"\:[[:space:]]\"//' | sed -r 's/",//'); | |
OUTPUT=$(docker container run \ | |
--rm \ | |
--workdir /workdir \ | |
--volume $WORKDIR:/workdir \ | |
--network host \ | |
0xpolygon/polygon-edge:$VERSION \ | |
rootchain deploy \ | |
--test \ | |
--json-rpc http://127.0.0.1:$ETH_PORT \ | |
--genesis ./genesis.json \ | |
--stake-manager $STAKE_MGR_CONTRACT \ | |
--stake-token $STAKE_TOKEN_CONTRACT) | |
echo "$OUTPUT" > $WORKDIR/rootchain-contracts.log | |
OUTPUT=$WORKDIR/rootchain-contracts.log | |
CONTRACT_LINE=$(grep 'Name = CustomSupernetManager' --no-group-separator -A1 $OUTPUT | grep -v 'Name = CustomSupernetManager') | |
SN_MGR_CONTRACT=$(echo "$CONTRACT_LINE" | $SED -r 's/(Contract \(address\))[[:space:]]*=[[:space:]]//') | |
echo $SN_MGR_CONTRACT | |
docker container run \ | |
--rm \ | |
--workdir /workdir \ | |
--volume $WORKDIR:/workdir \ | |
--network host \ | |
0xpolygon/polygon-edge:$VERSION \ | |
rootchain fund \ | |
--addresses ${NODE_ADDRESSES[0]},${NODE_ADDRESSES[1]},${NODE_ADDRESSES[2]},${NODE_ADDRESSES[3]} \ | |
--amounts 1000000000000000000,1000000000000000000,1000000000000000000,1000000000000000000 \ | |
--json-rpc http://127.0.0.1:$ETH_PORT | |
docker container run \ | |
--rm \ | |
--workdir /workdir \ | |
--volume $WORKDIR:/workdir \ | |
--network host \ | |
0xpolygon/polygon-edge:$VERSION \ | |
polybft whitelist-validators \ | |
--jsonrpc http://127.0.0.1:$ETH_PORT \ | |
--supernet-manager $SN_MGR_CONTRACT \ | |
--addresses ${NODE_ADDRESSES[0]},${NODE_ADDRESSES[1]},${NODE_ADDRESSES[2]},${NODE_ADDRESSES[3]} \ | |
--private-key aa75e9a7d427efc732f8e4f1a5b7646adcc61fd5bae40f80d13c8419c9f43d6d | |
for i in {1..4}; do | |
docker container run \ | |
--rm \ | |
--workdir /workdir \ | |
--volume $WORKDIR:/workdir \ | |
--network host \ | |
0xpolygon/polygon-edge:$VERSION \ | |
polybft register-validator \ | |
--data-dir /workdir/node-$i \ | |
--jsonrpc http://127.0.0.1:$ETH_PORT \ | |
--supernet-manager $SN_MGR_CONTRACT | |
done | |
CreateContainers | |
if [ "${NO_START}" == "0" ]; then | |
Start | |
fi | |
if [ "${QUIET}" == "0" ]; then | |
Info | |
fi | |
} | |
CreateContainers() { | |
for i in {1..4}; do | |
NAME=polygon-edge-$i | |
WORKDIR=~/.polygon-edge | |
GRPC_PORT=300${i}0 | |
P2P_PORT=300${i}1 | |
RPC_PORT=300${i}2 | |
docker container create \ | |
--hostname $NAME \ | |
--name $NAME \ | |
--workdir /workdir/node-$i \ | |
--volume $WORKDIR:/workdir \ | |
--network polygon-edge \ | |
--ip 190.180.170.$((10+$i)) \ | |
--publish ${GRPC_PORT}-${RPC_PORT}:${GRPC_PORT}-${RPC_PORT} \ | |
--add-host host.docker.internal:host-gateway \ | |
0xpolygon/polygon-edge:$VERSION \ | |
server \ | |
--data-dir /workdir/node-$i \ | |
--chain /workdir/genesis.json \ | |
--nat 190.180.170.$((10+$i)) \ | |
--grpc-address 0.0.0.0:${GRPC_PORT} \ | |
--libp2p 0.0.0.0:${P2P_PORT} \ | |
--jsonrpc 0.0.0.0:${RPC_PORT} \ | |
--seal | |
done | |
} | |
RemoveContainers() { | |
docker container rm $(docker container ls -aq --filter name=polygon-edge-*) | |
} | |
Start() { | |
docker container start $(docker container ls -aq --filter name=polygon-edge-*) | |
echo Local Polygon network started. | |
} | |
Stop() { | |
docker container stop $(docker container ls -aq --filter name=polygon-edge-*) | |
echo Local Polygon network stopped. | |
} | |
Info() { | |
CHAIN_ID=$(cat ~/.polygon-edge/genesis.json | grep chainID | $SED -r 's/[[:space:]]*"chainID":[[:space:]]//' | $SED -r 's/,//') | |
for i in {1..4}; do | |
echo "======= polygon-edge-${i} =========" | |
WORKDIR=~/.polygon-edge/node-$i | |
if [ -e $WORKDIR ]; then | |
echo "ChainId = $CHAIN_ID" | |
echo "$(cat $WORKDIR/node.info)" | |
if [ "${QUIET}" == "0" ]; then | |
echo "Private Key = $(cat $WORKDIR/consensus/validator.key)" | |
else | |
echo "Private Key = *************************************" | |
fi | |
echo "gRPC = localhost:300${i}0" | |
echo "P2P = localhost:300${i}1" | |
echo "JSON-RPC (http/ws) = localhost:300${i}2[/ws]" | |
echo | |
else | |
echo This node is not configured. Did you run init? | |
fi | |
done | |
} | |
Logs() { | |
docker container logs -f -n $LINES polygon-edge-$NODE | |
} | |
Clean() { | |
echo This will remove all data, containers, and images. This cannot be undone. | |
echo Do you wish to continue \(y/n\)? | |
read ANS | |
if [ "$ANS" == "y" ] || [ "$ANS" == "Y" ]; then | |
Stop | |
RemoveContainers | |
docker network rm polygon-edge | |
docker image rm 0xpolygon/polygon-edge:$VERSION | |
echo Removing ~/.polygon-edge | |
echo You might be asked for a sudo password. | |
sudo rm -rf ~/.polygon-edge | |
else | |
exit 0 | |
fi | |
} | |
Rebuild() { | |
Stop | |
RemoveContainers | |
CreateContainers | |
} | |
# Check for docker | |
if [[ -z $(which docker) ]]; then | |
echo "Docker must be installed." | |
exit 1; | |
fi | |
# Check docker is running | |
if ! docker info > /dev/null 2>&1; then | |
echo "This script uses docker, and it isn't running - please start docker and try again!" | |
exit 1; | |
fi | |
# MacOS has a FreeBSD version of sed which is missing handy features. | |
SED=sed | |
SYSTEM_INFO=$(uname -a) | |
SI_ARR=(${SYSTEM_INFO// / }) | |
if [ "${SI_ARR[0]}" == "Darwin" ]; then | |
if [[ -z $(which gsed) ]]; then | |
echo 'You are missing gnu-sed (a.k.a. gsed). The command to install it is: brew install gnu-sed' | |
echo 'Would you like to install it now? (y/n)' | |
read ANS | |
if [ "$ANS" == "y" ] || [ "$ANS" == "Y" ]; then | |
brew install gnu-sed | |
else | |
exit 1; | |
fi | |
fi | |
SED=gsed | |
fi | |
# Parse input options | |
for i in `seq 1 $#`; do | |
PLUS1=$(( $i + 1 )) | |
if [ "${!i}" == "--help" ] || [ "${!i}" == "-h" ]; then | |
Usage | |
exit | |
elif [ "${!i}" == "--no-start" ]; then | |
NO_START=1 | |
elif [ "${!i}" == "--quiet" ]; then | |
QUIET=1 | |
elif [ "${!i}" == "--chainId" ]; then | |
CHAIN_ID=${!PLUS1} | |
elif [ "${!i}" == "--node" ] || [ "${!i}" == "-n" ]; then | |
NODE=${!PLUS1} | |
elif [ "${!i}" == "--lines" ] || [ "${!i}" == "-l" ]; then | |
LINES=${!PLUS1} | |
elif [ "${!i}" == "--version" ]; then | |
VERSION=${!PLUS1} | |
elif [ "${!i}" == "--block-time" ]; then | |
BLOCK_TIME=${!PLUS1} | |
# elif [ "${!i}" == "--eth-key" ]; then | |
# ETH_HEX_KEY=${!PLUS1} | |
# # trim leading 0x | |
# if [ "$(expr substr $ETH_HEX_KEY 1 2)" == "0x" ]; then | |
# ETH_HEX_KEY=$(expr substr $ETH_HEX_KEY 3 99) | |
# fi | |
fi | |
done | |
if [ "$1" == "init" ]; then | |
Init | |
elif [ "$1" == "start" ]; then | |
Start | |
elif [ "$1" == "stop" ]; then | |
Stop | |
elif [ "$1" == "info" ]; then | |
Info | |
elif [ "$1" == "logs" ]; then | |
Logs | |
elif [ "$1" == "clean" ]; then | |
Clean | |
elif [ "$1" == "rebuild" ]; then | |
Rebuild | |
else | |
Usage | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment