From 87030605bd51d6831856f4c868a06f7d7fa30fa4 Mon Sep 17 00:00:00 2001 From: Prathamesh Musale Date: Fri, 26 Apr 2024 14:56:39 +0530 Subject: [PATCH] Port over optimism stack components from stack orchestrator --- .gitignore | 4 + config/fixturenet-optimism/l1-params.env | 12 ++ .../optimism-contracts/deploy-contracts.sh | 172 ++++++++++++++++++ config/fixturenet-optimism/run-geth.sh | 155 ++++++++++++++++ config/fixturenet-optimism/run-op-batcher.sh | 27 +++ config/fixturenet-optimism/run-op-geth.sh | 56 ++++++ config/fixturenet-optimism/run-op-node.sh | 45 +++++ config/fixturenet-optimism/run-op-proposer.sh | 22 +++ container-build/cerc-foundry/build.sh | 4 + .../cerc-optimism-contracts/Dockerfile | 22 +++ .../cerc-optimism-contracts/build.sh | 9 + container-build/cerc-optimism-l2geth/build.sh | 7 + .../cerc-optimism-op-batcher/Dockerfile | 32 ++++ .../cerc-optimism-op-batcher/build.sh | 9 + .../cerc-optimism-op-node/Dockerfile | 30 +++ .../cerc-optimism-op-node/build.sh | 9 + .../cerc-optimism-op-proposer/Dockerfile | 31 ++++ .../cerc-optimism-op-proposer/build.sh | 8 + stack/fixturenet-optimism/deploy/commands.py | 39 ++++ stack/fixturenet-optimism/stack.yml | 16 ++ 20 files changed, 709 insertions(+) create mode 100644 .gitignore create mode 100644 config/fixturenet-optimism/l1-params.env create mode 100755 config/fixturenet-optimism/optimism-contracts/deploy-contracts.sh create mode 100755 config/fixturenet-optimism/run-geth.sh create mode 100755 config/fixturenet-optimism/run-op-batcher.sh create mode 100755 config/fixturenet-optimism/run-op-geth.sh create mode 100755 config/fixturenet-optimism/run-op-node.sh create mode 100755 config/fixturenet-optimism/run-op-proposer.sh create mode 100755 container-build/cerc-foundry/build.sh create mode 100644 container-build/cerc-optimism-contracts/Dockerfile create mode 100755 container-build/cerc-optimism-contracts/build.sh create mode 100755 container-build/cerc-optimism-l2geth/build.sh create mode 100644 container-build/cerc-optimism-op-batcher/Dockerfile create mode 100755 container-build/cerc-optimism-op-batcher/build.sh create mode 100644 container-build/cerc-optimism-op-node/Dockerfile create mode 100755 container-build/cerc-optimism-op-node/build.sh create mode 100644 container-build/cerc-optimism-op-proposer/Dockerfile create mode 100755 container-build/cerc-optimism-op-proposer/build.sh create mode 100644 stack/fixturenet-optimism/deploy/commands.py create mode 100644 stack/fixturenet-optimism/stack.yml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cf2047f --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.idea +venv +.vscode +__pycache__ diff --git a/config/fixturenet-optimism/l1-params.env b/config/fixturenet-optimism/l1-params.env new file mode 100644 index 0000000..5353e62 --- /dev/null +++ b/config/fixturenet-optimism/l1-params.env @@ -0,0 +1,12 @@ +# Defaults + +# L1 endpoint +DEFAULT_CERC_L1_CHAIN_ID=1212 +DEFAULT_CERC_L1_RPC="http://fixturenet-eth-geth-1:8545" +DEFAULT_CERC_L1_HOST="fixturenet-eth-geth-1" +DEFAULT_CERC_L1_PORT=8545 + +# URL to get CSV with credentials for accounts on L1 +# that are used to send balance to Optimism Proxy contract +# (enables them to do transactions on L2) +DEFAULT_CERC_L1_ACCOUNTS_CSV_URL="http://fixturenet-eth-bootnode-geth:9898/accounts.csv" diff --git a/config/fixturenet-optimism/optimism-contracts/deploy-contracts.sh b/config/fixturenet-optimism/optimism-contracts/deploy-contracts.sh new file mode 100755 index 0000000..23a2bc3 --- /dev/null +++ b/config/fixturenet-optimism/optimism-contracts/deploy-contracts.sh @@ -0,0 +1,172 @@ +#!/bin/bash +set -e +if [ -n "$CERC_SCRIPT_DEBUG" ]; then + set -x +fi + +CERC_L1_CHAIN_ID="${CERC_L1_CHAIN_ID:-${DEFAULT_CERC_L1_CHAIN_ID}}" +CERC_L1_RPC="${CERC_L1_RPC:-${DEFAULT_CERC_L1_RPC}}" + +CERC_L1_ACCOUNTS_CSV_URL="${CERC_L1_ACCOUNTS_CSV_URL:-${DEFAULT_CERC_L1_ACCOUNTS_CSV_URL}}" + +export DEPLOYMENT_CONTEXT="$CERC_L1_CHAIN_ID" +# Optional create2 salt for deterministic deployment of contract implementations +export IMPL_SALT=$(openssl rand -hex 32) + +echo "Using L1 RPC endpoint ${CERC_L1_RPC}" + +# Exit if a deployment already exists (on restarts) +if [ -d "/l1-deployment/$DEPLOYMENT_CONTEXT" ]; then + echo "Deployment directory /l1-deployment/$DEPLOYMENT_CONTEXT, checking OptimismPortal deployment" + + OPTIMISM_PORTAL_ADDRESS=$(cat /l1-deployment/$DEPLOYMENT_CONTEXT/OptimismPortal.json | jq -r .address) + contract_code=$(cast code $OPTIMISM_PORTAL_ADDRESS --rpc-url $CERC_L1_RPC) + + if [ -z "${contract_code#0x}" ]; then + echo "Error: A deployment directory was found in the volume, but no contract code was found on-chain at the associated address. Please clear L1 deployment volume before restarting." + exit 1 + else + echo "Deployment found, exiting (successfully)." + exit 0 + fi +fi + +wait_for_block() { + local block="$1" # Block to wait for + local timeout="$2" # Max time to wait in seconds + + echo "Waiting for block $block." + i=0 + loops=$(($timeout/10)) + while [ -z "$block_result" ] && [[ "$i" -lt "$loops" ]]; do + sleep 10 + echo "Checking..." + block_result=$(cast block $block --rpc-url $CERC_L1_RPC | grep -E "(timestamp|hash|number)" || true) + i=$(($i + 1)) + done +} + +# We need four accounts and their private keys for the deployment: Admin, Proposer, Batcher, and Sequencer +# If $CERC_L1_ADDRESS and $CERC_L1_PRIV_KEY have been set, we'll assign it to Admin and generate/fund the remaining three accounts from it +# If not, we'll assume the L1 is the stack's own fixturenet-eth and use the pre-funded accounts/keys from $CERC_L1_ACCOUNTS_CSV_URL +if [ -n "$CERC_L1_ADDRESS" ] && [ -n "$CERC_L1_PRIV_KEY" ]; then + wallet1=$(cast wallet new) + wallet2=$(cast wallet new) + wallet3=$(cast wallet new) + # Admin + ADMIN=$CERC_L1_ADDRESS + ADMIN_KEY=$CERC_L1_PRIV_KEY + # Proposer + PROPOSER=$(echo "$wallet1" | awk '/Address:/{print $2}') + PROPOSER_KEY=$(echo "$wallet1" | awk '/Private key:/{print $3}') + # Batcher + BATCHER=$(echo "$wallet2" | awk '/Address:/{print $2}') + BATCHER_KEY=$(echo "$wallet2" | awk '/Private key:/{print $3}') + # Sequencer + SEQ=$(echo "$wallet3" | awk '/Address:/{print $2}') + SEQ_KEY=$(echo "$wallet3" | awk '/Private key:/{print $3}') + + echo "Funding accounts." + wait_for_block 1 300 + cast send --from $ADMIN --rpc-url $CERC_L1_RPC --value 5ether $PROPOSER --private-key $ADMIN_KEY + cast send --from $ADMIN --rpc-url $CERC_L1_RPC --value 10ether $BATCHER --private-key $ADMIN_KEY + cast send --from $ADMIN --rpc-url $CERC_L1_RPC --value 2ether $SEQ --private-key $ADMIN_KEY +else + curl -o accounts.csv $CERC_L1_ACCOUNTS_CSV_URL + # Admin + ADMIN=$(awk -F ',' 'NR == 1 {print $2}' accounts.csv) + ADMIN_KEY=$(awk -F ',' 'NR == 1 {print $3}' accounts.csv) + # Proposer + PROPOSER=$(awk -F ',' 'NR == 2 {print $2}' accounts.csv) + PROPOSER_KEY=$(awk -F ',' 'NR == 2 {print $3}' accounts.csv) + # Batcher + BATCHER=$(awk -F ',' 'NR == 3 {print $2}' accounts.csv) + BATCHER_KEY=$(awk -F ',' 'NR == 3 {print $3}' accounts.csv) + # Sequencer + SEQ=$(awk -F ',' 'NR == 4 {print $2}' accounts.csv) + SEQ_KEY=$(awk -F ',' 'NR == 4 {print $3}' accounts.csv) +fi + +echo "Using accounts:" +echo -e "Admin: $ADMIN\nProposer: $PROPOSER\nBatcher: $BATCHER\nSequencer: $SEQ" + +# These accounts will be needed by other containers, so write them to a shared volume +echo "Writing accounts/private keys to volume l2_accounts." +accounts_json=$(jq -n \ + --arg Admin "$ADMIN" --arg AdminKey "$ADMIN_KEY" \ + --arg Proposer "$PROPOSER" --arg ProposerKey "$PROPOSER_KEY" \ + --arg Batcher "$BATCHER" --arg BatcherKey "$BATCHER_KEY" \ + --arg Seq "$SEQ" --arg SeqKey "$SEQ_KEY" \ + '{Admin: $Admin, AdminKey: $AdminKey, Proposer: $Proposer, ProposerKey: $ProposerKey, Batcher: $Batcher, BatcherKey: $BatcherKey, Seq: $Seq, SeqKey: $SeqKey}') +echo "$accounts_json" > "/l2-accounts/accounts.json" + +# Get a finalized L1 block to set as the starting point for the L2 deployment +# If the chain is a freshly created fixturenet-eth, a finalized block won't be available for many minutes; rather than wait, we can use block 1 +echo "Checking L1 for finalized block..." +finalized=$(cast block finalized --rpc-url $CERC_L1_RPC | grep -E "(timestamp|hash|number)" || true) + +if [ -n "$finalized" ]; then + # finalized block was found + start_block=$finalized +else + # assume fresh chain and use block 1 instead + echo "No finalized block. Using block 1 instead." + # wait for 20 or so blocks to be safe + wait_for_block 24 300 + start_block=$(cast block 1 --rpc-url $CERC_L1_RPC | grep -E "(timestamp|hash|number)" || true) +fi + +if [ -z "$start_block" ]; then + echo "Unable to query chain for starting block. Exiting..." + exit 1 +fi + +BLOCKHASH=$(echo $start_block | awk -F ' ' '{print $2}') +HEIGHT=$(echo $start_block | awk -F ' ' '{print $4}') +TIMESTAMP=$(echo $start_block | awk -F ' ' '{print $6}') + +echo "Using block as deployment point:" +echo "Height: $HEIGHT" +echo "Hash: $BLOCKHASH" +echo "Timestamp: $TIMESTAMP" + +# Fill out the deployment template (./deploy-config/getting-started.json) with our values: +echo "Writing deployment config." +deploy_config_file="deploy-config/$DEPLOYMENT_CONTEXT.json" +cp deploy-config/getting-started.json $deploy_config_file +sed -i "s/\"l1ChainID\": .*/\"l1ChainID\": $DEPLOYMENT_CONTEXT,/g" $deploy_config_file +sed -i "s/ADMIN/$ADMIN/g" $deploy_config_file +sed -i "s/PROPOSER/$PROPOSER/g" $deploy_config_file +sed -i "s/BATCHER/$BATCHER/g" $deploy_config_file +sed -i "s/SEQUENCER/$SEQ/g" $deploy_config_file +sed -i "s/BLOCKHASH/$BLOCKHASH/g" $deploy_config_file +sed -i "s/TIMESTAMP/$TIMESTAMP/g" $deploy_config_file + +mkdir -p deployments/$DEPLOYMENT_CONTEXT + +# Deployment requires the create2 deterministic proxy contract be published on L1 at address 0x4e59b44847b379578588920ca78fbf26c0b4956c +# See: https://github.com/Arachnid/deterministic-deployment-proxy +echo "Deploying create2 proxy contract..." +echo "Funding deployment signer address" +deployment_signer="0x3fab184622dc19b6109349b94811493bf2a45362" +cast send --from $ADMIN --rpc-url $CERC_L1_RPC --value 0.5ether $deployment_signer --private-key $ADMIN_KEY +echo "Deploying contract..." +raw_bytes="0xf8a58085174876e800830186a08080b853604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf31ba02222222222222222222222222222222222222222222222222222222222222222a02222222222222222222222222222222222222222222222222222222222222222" + +cast publish --rpc-url $CERC_L1_RPC $raw_bytes + +# Create the L2 deployment +echo "Deploying L1 Optimism contracts..." +forge script scripts/Deploy.s.sol:Deploy --private-key $ADMIN_KEY --broadcast --rpc-url $CERC_L1_RPC +forge script scripts/Deploy.s.sol:Deploy --sig 'sync()' --private-key $ADMIN_KEY --broadcast --rpc-url $CERC_L1_RPC + +echo "*************************************" +echo "Done deploying contracts." + +# Copy files needed by other containers to the appropriate shared volumes +echo "Copying deployment artifacts volume l1_deployment and deploy-config to volume l2_config" +cp -a /app/packages/contracts-bedrock/deployments/$DEPLOYMENT_CONTEXT /l1-deployment +cp /app/packages/contracts-bedrock/deploy-config/$DEPLOYMENT_CONTEXT.json /l2-config +openssl rand -hex 32 > /l2-config/l2-jwt.txt + +echo "Deployment successful. Exiting" diff --git a/config/fixturenet-optimism/run-geth.sh b/config/fixturenet-optimism/run-geth.sh new file mode 100755 index 0000000..b24fe86 --- /dev/null +++ b/config/fixturenet-optimism/run-geth.sh @@ -0,0 +1,155 @@ +#!/bin/bash +if [ -n "$CERC_SCRIPT_DEBUG" ]; then + set -x +fi + +# To facilitate deploying the Optimism contracts, a few additional arguments have been added to the geth start command +# Otherwise this script is unchanged from the image's default startup script + +ETHERBASE=`cat /opt/testnet/build/el/accounts.csv | head -1 | cut -d',' -f2` +NETWORK_ID=`cat /opt/testnet/el/el-config.yaml | grep 'chain_id' | awk '{ print $2 }'` +NETRESTRICT=`ip addr | grep inet | grep -v '127.0' | awk '{print $2}'` +CERC_ETH_DATADIR="${CERC_ETH_DATADIR:-$HOME/ethdata}" +CERC_PLUGINS_DIR="${CERC_PLUGINS_DIR:-/usr/local/lib/plugeth}" + +cd /opt/testnet/build/el +python3 -m http.server 9898 & +cd $HOME + +START_CMD="geth" +if [ "true" == "$CERC_REMOTE_DEBUG" ] && [ -x "/usr/local/bin/dlv" ]; then + START_CMD="/usr/local/bin/dlv --listen=:40000 --headless=true --api-version=2 --accept-multiclient exec /usr/local/bin/geth --continue --" +fi + +# See https://linuxconfig.org/how-to-propagate-a-signal-to-child-processes-from-a-bash-script +cleanup() { + echo "Signal received, cleaning up..." + + # Kill the child process first (CERC_REMOTE_DEBUG=true uses dlv which starts geth as a child process) + pkill -P ${geth_pid} + sleep 2 + kill $(jobs -p) + + wait + echo "Done" +} +trap 'cleanup' SIGINT SIGTERM + +if [ "true" == "$RUN_BOOTNODE" ]; then + $START_CMD \ + --datadir="${CERC_ETH_DATADIR}" \ + --nodekeyhex="${BOOTNODE_KEY}" \ + --nodiscover \ + --ipcdisable \ + --networkid=${NETWORK_ID} \ + --netrestrict="${NETRESTRICT}" \ + & + + geth_pid=$! +else + cd /opt/testnet/accounts + ./import_keys.sh + + echo -n "$JWT" > /opt/testnet/build/el/jwtsecret + + if [ "$CERC_RUN_STATEDIFF" == "detect" ] && [ -n "$CERC_STATEDIFF_DB_HOST" ]; then + dig_result=$(dig $CERC_STATEDIFF_DB_HOST +short) + dig_status_code=$? + if [[ $dig_status_code = 0 && -n $dig_result ]]; then + echo "Statediff DB at $CERC_STATEDIFF_DB_HOST" + CERC_RUN_STATEDIFF="true" + else + echo "No statediff DB available." + CERC_RUN_STATEDIFF="false" + fi + fi + + STATEDIFF_OPTS="" + if [ "$CERC_RUN_STATEDIFF" == "true" ]; then + ready=0 + echo "Waiting for statediff DB..." + while [ $ready -eq 0 ]; do + sleep 1 + export PGPASSWORD="$CERC_STATEDIFF_DB_PASSWORD" + result=$(psql -h "$CERC_STATEDIFF_DB_HOST" \ + -p "$CERC_STATEDIFF_DB_PORT" \ + -U "$CERC_STATEDIFF_DB_USER" \ + -d "$CERC_STATEDIFF_DB_NAME" \ + -t -c 'select max(version_id) from goose_db_version;' 2>/dev/null | awk '{ print $1 }') + if [ -n "$result" ]; then + echo "DB ready..." + if [ $result -ge $CERC_STATEDIFF_DB_GOOSE_MIN_VER ]; then + ready=1 + else + echo "DB not at required version (want $CERC_STATEDIFF_DB_GOOSE_MIN_VER, have $result)" + fi + fi + done + STATEDIFF_OPTS="--statediff \ + --statediff.db.host=$CERC_STATEDIFF_DB_HOST \ + --statediff.db.name=$CERC_STATEDIFF_DB_NAME \ + --statediff.db.nodeid=$CERC_STATEDIFF_DB_NODE_ID \ + --statediff.db.password=$CERC_STATEDIFF_DB_PASSWORD \ + --statediff.db.port=$CERC_STATEDIFF_DB_PORT \ + --statediff.db.user=$CERC_STATEDIFF_DB_USER \ + --statediff.db.logstatements=${CERC_STATEDIFF_DB_LOG_STATEMENTS:-false} \ + --statediff.db.copyfrom=${CERC_STATEDIFF_DB_COPY_FROM:-true} \ + --statediff.waitforsync=true \ + --statediff.workers=${CERC_STATEDIFF_WORKERS:-1} \ + --statediff.writing=true" + + if [ -d "${CERC_PLUGINS_DIR}" ]; then + # With plugeth, we separate the statediff options by prefixing with ' -- ' + STATEDIFF_OPTS="--pluginsdir "${CERC_PLUGINS_DIR}" -- ${STATEDIFF_OPTS}" + fi + fi + + # unlock account[0] + echo $ACCOUNT_PASSWORD > "$CERC_ETH_DATADIR/password" + + $START_CMD \ + --datadir="${CERC_ETH_DATADIR}" \ + --bootnodes="${ENODE}" \ + --allow-insecure-unlock \ + --password="${CERC_ETH_DATADIR}/password" \ + --unlock="$ETHERBASE" \ + --rpc.allow-unprotected-txs \ + --http \ + --http.addr="0.0.0.0" \ + --http.vhosts="*" \ + --http.api="${CERC_GETH_HTTP_APIS:-eth,web3,net,admin,personal,debug,statediff}" \ + --http.corsdomain="*" \ + --authrpc.addr="0.0.0.0" \ + --authrpc.vhosts="*" \ + --authrpc.jwtsecret="/opt/testnet/build/el/jwtsecret" \ + --ws \ + --ws.addr="0.0.0.0" \ + --ws.origins="*" \ + --ws.api="${CERC_GETH_WS_APIS:-eth,web3,net,admin,personal,debug,statediff}" \ + --http.corsdomain="*" \ + --networkid="${NETWORK_ID}" \ + --netrestrict="${NETRESTRICT}" \ + --gcmode archive \ + --txlookuplimit=0 \ + --cache.preimages \ + --syncmode=full \ + --mine \ + --miner.threads=1 \ + --metrics \ + --metrics.addr="0.0.0.0" \ + --verbosity=${CERC_GETH_VERBOSITY:-3} \ + --log.vmodule="${CERC_GETH_VMODULE:-statediff/*=5}" \ + --miner.etherbase="${ETHERBASE}" \ + ${STATEDIFF_OPTS} \ + & + + geth_pid=$! +fi + +wait $geth_pid + +if [ "true" == "$CERC_KEEP_RUNNING_AFTER_GETH_EXIT" ]; then + while [ 1 -eq 1 ]; do + sleep 60 + done +fi diff --git a/config/fixturenet-optimism/run-op-batcher.sh b/config/fixturenet-optimism/run-op-batcher.sh new file mode 100755 index 0000000..29a65d5 --- /dev/null +++ b/config/fixturenet-optimism/run-op-batcher.sh @@ -0,0 +1,27 @@ +#!/bin/sh +set -e +if [ -n "$CERC_SCRIPT_DEBUG" ]; then + set -x +fi + +CERC_L1_RPC="${CERC_L1_RPC:-${DEFAULT_CERC_L1_RPC}}" + +# Start op-batcher +L2_RPC="http://op-geth:8545" +ROLLUP_RPC="http://op-node:8547" +BATCHER_KEY=$(cat /l2-accounts/accounts.json | jq -r .BatcherKey) + +op-batcher \ + --l2-eth-rpc=$L2_RPC \ + --rollup-rpc=$ROLLUP_RPC \ + --poll-interval=1s \ + --sub-safety-margin=6 \ + --num-confirmations=1 \ + --safe-abort-nonce-too-low-count=3 \ + --resubmission-timeout=30s \ + --rpc.addr=0.0.0.0 \ + --rpc.port=8548 \ + --rpc.enable-admin \ + --max-channel-duration=1 \ + --l1-eth-rpc=$CERC_L1_RPC \ + --private-key="${BATCHER_KEY#0x}" diff --git a/config/fixturenet-optimism/run-op-geth.sh b/config/fixturenet-optimism/run-op-geth.sh new file mode 100755 index 0000000..9b06ced --- /dev/null +++ b/config/fixturenet-optimism/run-op-geth.sh @@ -0,0 +1,56 @@ +#!/bin/sh +set -e +if [ -n "$CERC_SCRIPT_DEBUG" ]; then + set -x +fi + +l2_genesis_file="/l2-config/genesis.json" + +# Check for genesis file; if necessary, wait on op-node to generate +timeout=300 # 5 minutes +start_time=$(date +%s) +elapsed_time=0 +echo "Checking for L2 genesis file at location $l2_genesis_file" +while [ ! -f "$l2_genesis_file" ] && [ $elapsed_time -lt $timeout ]; do + echo "Waiting for L2 genesis file to be generated..." + sleep 10 + current_time=$(date +%s) + elapsed_time=$((current_time - start_time)) +done + +if [ ! -f "$l2_genesis_file" ]; then + echo "L2 genesis file not found after timeout of $timeout seconds. Exiting..." + exit 1 +fi + +# Initialize geth from our generated L2 genesis file (if not already initialized) +data_dir="/datadir" +if [ ! -d "$datadir/geth" ]; then + geth init --datadir=$data_dir $l2_genesis_file +fi + +# Start op-geth +jwt_file="/l2-config/l2-jwt.txt" + +geth \ + --datadir=$data_dir \ + --http \ + --http.corsdomain="*" \ + --http.vhosts="*" \ + --http.addr=0.0.0.0 \ + --http.api=web3,debug,eth,txpool,net,engine \ + --ws \ + --ws.addr=0.0.0.0 \ + --ws.port=8546 \ + --ws.origins="*" \ + --ws.api=debug,eth,txpool,net,engine \ + --syncmode=full \ + --gcmode=archive \ + --nodiscover \ + --maxpeers=0 \ + --networkid=42069 \ + --authrpc.vhosts="*" \ + --authrpc.addr=0.0.0.0 \ + --authrpc.port=8551 \ + --authrpc.jwtsecret=$jwt_file \ + --rollup.disabletxpoolgossip=true diff --git a/config/fixturenet-optimism/run-op-node.sh b/config/fixturenet-optimism/run-op-node.sh new file mode 100755 index 0000000..60a9685 --- /dev/null +++ b/config/fixturenet-optimism/run-op-node.sh @@ -0,0 +1,45 @@ +#!/bin/sh +set -e +if [ -n "$CERC_SCRIPT_DEBUG" ]; then + set -x +fi + +CERC_L1_CHAIN_ID="${CERC_L1_CHAIN_ID:-${DEFAULT_CERC_L1_CHAIN_ID}}" +CERC_L1_RPC="${CERC_L1_RPC:-${DEFAULT_CERC_L1_RPC}}" +DEPLOYMENT_CONTEXT="$CERC_L1_CHAIN_ID" + +deploy_config_file="/l2-config/$DEPLOYMENT_CONTEXT.json" +deployment_dir="/l1-deployment/$DEPLOYMENT_CONTEXT" +genesis_outfile="/l2-config/genesis.json" +rollup_outfile="/l2-config/rollup.json" + +# Generate L2 genesis (if not already done) +if [ ! -f "$genesis_outfile" ] || [ ! -f "$rollup_outfile" ]; then + op-node genesis l2 \ + --deploy-config $deploy_config_file \ + --deployment-dir $deployment_dir \ + --outfile.l2 $genesis_outfile \ + --outfile.rollup $rollup_outfile \ + --l1-rpc $CERC_L1_RPC +fi + +# Start op-node +SEQ_KEY=$(cat /l2-accounts/accounts.json | jq -r .SeqKey) +jwt_file=/l2-config/l2-jwt.txt +L2_AUTH="http://op-geth:8551" +RPC_KIND=any # this can optionally be set to a preset for common node providers like Infura, Alchemy, etc. + +op-node \ + --l2=$L2_AUTH \ + --l2.jwt-secret=$jwt_file \ + --sequencer.enabled \ + --sequencer.l1-confs=5 \ + --verifier.l1-confs=4 \ + --rollup.config=$rollup_outfile \ + --rpc.addr=0.0.0.0 \ + --rpc.port=8547 \ + --p2p.disable \ + --rpc.enable-admin \ + --p2p.sequencer.key="${SEQ_KEY#0x}" \ + --l1=$CERC_L1_RPC \ + --l1.rpckind=$RPC_KIND diff --git a/config/fixturenet-optimism/run-op-proposer.sh b/config/fixturenet-optimism/run-op-proposer.sh new file mode 100755 index 0000000..092705c --- /dev/null +++ b/config/fixturenet-optimism/run-op-proposer.sh @@ -0,0 +1,22 @@ +#!/bin/sh +set -e +if [ -n "$CERC_SCRIPT_DEBUG" ]; then + set -x +fi + +CERC_L1_RPC="${CERC_L1_RPC:-${DEFAULT_CERC_L1_RPC}}" +CERC_L1_CHAIN_ID="${CERC_L1_CHAIN_ID:-${DEFAULT_CERC_L1_CHAIN_ID}}" +DEPLOYMENT_CONTEXT="$CERC_L1_CHAIN_ID" + +# Start op-proposer +ROLLUP_RPC="http://op-node:8547" +PROPOSER_KEY=$(cat /l2-accounts/accounts.json | jq -r .ProposerKey) +L2OO_ADDR=$(cat /l1-deployment/$DEPLOYMENT_CONTEXT/L2OutputOracleProxy.json | jq -r .address) + +op-proposer \ + --poll-interval=12s \ + --rpc.port=8560 \ + --rollup-rpc=$ROLLUP_RPC \ + --l2oo-address="${L2OO_ADDR#0x}" \ + --private-key="${PROPOSER_KEY#0x}" \ + --l1-eth-rpc=$CERC_L1_RPC diff --git a/container-build/cerc-foundry/build.sh b/container-build/cerc-foundry/build.sh new file mode 100755 index 0000000..f80276e --- /dev/null +++ b/container-build/cerc-foundry/build.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +# Build a local version of the foundry-rs/foundry image +source ${CERC_CONTAINER_BASE_DIR}/build-base.sh +docker build -t cerc/foundry:local -f ${CERC_REPO_BASE_DIR}/foundry/Dockerfile-debian ${build_command_args} ${CERC_REPO_BASE_DIR}/foundry diff --git a/container-build/cerc-optimism-contracts/Dockerfile b/container-build/cerc-optimism-contracts/Dockerfile new file mode 100644 index 0000000..3804246 --- /dev/null +++ b/container-build/cerc-optimism-contracts/Dockerfile @@ -0,0 +1,22 @@ +FROM cerc/foundry:local + +# Install node (local foundry is a debian based image) +RUN apt-get update \ + && apt-get install -y curl wget \ + && curl --silent --location https://deb.nodesource.com/setup_18.x | bash - \ + && apt-get update \ + && apt-get install -y nodejs git busybox jq \ + && node -v + +RUN corepack enable \ + && yarn --version + +WORKDIR /app + +# Copy optimism repo contents +COPY . . + +RUN echo "Building optimism" && \ + pnpm install && pnpm build + +WORKDIR /app/packages/contracts-bedrock diff --git a/container-build/cerc-optimism-contracts/build.sh b/container-build/cerc-optimism-contracts/build.sh new file mode 100755 index 0000000..b1ddd81 --- /dev/null +++ b/container-build/cerc-optimism-contracts/build.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +# Build cerc/optimism-contracts + +source ${CERC_CONTAINER_BASE_DIR}/build-base.sh + +# See: https://stackoverflow.com/a/246128/1701505 +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) + +docker build -t cerc/optimism-contracts:local -f ${SCRIPT_DIR}/Dockerfile ${build_command_args} ${CERC_REPO_BASE_DIR}/optimism diff --git a/container-build/cerc-optimism-l2geth/build.sh b/container-build/cerc-optimism-l2geth/build.sh new file mode 100755 index 0000000..86c84a7 --- /dev/null +++ b/container-build/cerc-optimism-l2geth/build.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +# Build cerc/optimism-l2geth + +source ${CERC_CONTAINER_BASE_DIR}/build-base.sh + +docker build -t cerc/optimism-l2geth:local ${build_command_args} ${CERC_REPO_BASE_DIR}/op-geth diff --git a/container-build/cerc-optimism-op-batcher/Dockerfile b/container-build/cerc-optimism-op-batcher/Dockerfile new file mode 100644 index 0000000..f52e75b --- /dev/null +++ b/container-build/cerc-optimism-op-batcher/Dockerfile @@ -0,0 +1,32 @@ +FROM golang:1.21.0-alpine3.18 as builder + +ARG VERSION=v0.0.0 + +RUN apk add --no-cache make gcc musl-dev linux-headers git jq bash + +# build op-batcher with the shared go.mod & go.sum files +COPY ./op-batcher /app/op-batcher +COPY ./op-bindings /app/op-bindings +COPY ./op-node /app/op-node +COPY ./op-service /app/op-service +#COPY ./op-signer /app/op-signer +COPY ./go.mod /app/go.mod +COPY ./go.sum /app/go.sum + +COPY ./.git /app/.git + +WORKDIR /app/op-batcher + +RUN go mod download + +ARG TARGETOS TARGETARCH + +RUN make op-batcher VERSION="$VERSION" GOOS=$TARGETOS GOARCH=$TARGETARCH + +FROM alpine:3.18 + +RUN apk add --no-cache jq bash + +COPY --from=builder /app/op-batcher/bin/op-batcher /usr/local/bin + +ENTRYPOINT ["op-batcher"] diff --git a/container-build/cerc-optimism-op-batcher/build.sh b/container-build/cerc-optimism-op-batcher/build.sh new file mode 100755 index 0000000..a91c006 --- /dev/null +++ b/container-build/cerc-optimism-op-batcher/build.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +# Build cerc/optimism-op-batcher +# TODO: use upstream Dockerfile once its buildx-specific content has been removed + +source ${CERC_CONTAINER_BASE_DIR}/build-base.sh + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +docker build -t cerc/optimism-op-batcher:local -f ${SCRIPT_DIR}/Dockerfile ${build_command_args} ${CERC_REPO_BASE_DIR}/optimism diff --git a/container-build/cerc-optimism-op-node/Dockerfile b/container-build/cerc-optimism-op-node/Dockerfile new file mode 100644 index 0000000..ad63bb2 --- /dev/null +++ b/container-build/cerc-optimism-op-node/Dockerfile @@ -0,0 +1,30 @@ +FROM golang:1.21.0-alpine3.18 as builder + +ARG VERSION=v0.0.0 + +RUN apk add --no-cache make gcc musl-dev linux-headers git jq bash + +# build op-node with the shared go.mod & go.sum files +COPY ./op-node /app/op-node +COPY ./op-chain-ops /app/op-chain-ops +COPY ./op-service /app/op-service +COPY ./op-bindings /app/op-bindings +COPY ./go.mod /app/go.mod +COPY ./go.sum /app/go.sum +COPY ./.git /app/.git + +WORKDIR /app/op-node + +RUN go mod download + +ARG TARGETOS TARGETARCH + +RUN make op-node VERSION="$VERSION" GOOS=$TARGETOS GOARCH=$TARGETARCH + +FROM alpine:3.18 + +RUN apk add --no-cache openssl jq + +COPY --from=builder /app/op-node/bin/op-node /usr/local/bin + +CMD ["op-node"] diff --git a/container-build/cerc-optimism-op-node/build.sh b/container-build/cerc-optimism-op-node/build.sh new file mode 100755 index 0000000..be68cbb --- /dev/null +++ b/container-build/cerc-optimism-op-node/build.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +# Build cerc/optimism-op-node +# TODO: use upstream Dockerfile once its buildx-specific content has been removed + +source ${CERC_CONTAINER_BASE_DIR}/build-base.sh + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +docker build -t cerc/optimism-op-node:local -f ${SCRIPT_DIR}/Dockerfile ${build_command_args} ${CERC_REPO_BASE_DIR}/optimism diff --git a/container-build/cerc-optimism-op-proposer/Dockerfile b/container-build/cerc-optimism-op-proposer/Dockerfile new file mode 100644 index 0000000..9032a7f --- /dev/null +++ b/container-build/cerc-optimism-op-proposer/Dockerfile @@ -0,0 +1,31 @@ +FROM golang:1.21.0-alpine3.18 as builder + +ARG VERSION=v0.0.0 + +RUN apk add --no-cache make gcc musl-dev linux-headers git jq bash + +# build op-proposer with the shared go.mod & go.sum files +COPY ./op-proposer /app/op-proposer +COPY ./op-bindings /app/op-bindings +COPY ./op-node /app/op-node +COPY ./op-service /app/op-service +#COPY ./op-signer /app/op-signer +COPY ./go.mod /app/go.mod +COPY ./go.sum /app/go.sum +COPY ./.git /app/.git + +WORKDIR /app/op-proposer + +RUN go mod download + +ARG TARGETOS TARGETARCH + +RUN make op-proposer VERSION="$VERSION" GOOS=$TARGETOS GOARCH=$TARGETARCH + +FROM alpine:3.18 + +RUN apk add --no-cache jq bash + +COPY --from=builder /app/op-proposer/bin/op-proposer /usr/local/bin + +CMD ["op-proposer"] diff --git a/container-build/cerc-optimism-op-proposer/build.sh b/container-build/cerc-optimism-op-proposer/build.sh new file mode 100755 index 0000000..f3c975d --- /dev/null +++ b/container-build/cerc-optimism-op-proposer/build.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +# Build cerc/optimism-op-proposer + +source ${CERC_CONTAINER_BASE_DIR}/build-base.sh + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +docker build -t cerc/optimism-op-proposer:local -f ${SCRIPT_DIR}/Dockerfile ${build_command_args} ${CERC_REPO_BASE_DIR}/optimism diff --git a/stack/fixturenet-optimism/deploy/commands.py b/stack/fixturenet-optimism/deploy/commands.py new file mode 100644 index 0000000..ff1caaa --- /dev/null +++ b/stack/fixturenet-optimism/deploy/commands.py @@ -0,0 +1,39 @@ +# Copyright © 2023 Vulcanize + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. + +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +from stack_orchestrator.deploy.deployment_context import DeploymentContext +from ruamel.yaml import YAML + +# TODO: Update for plugeth stack +def create(context: DeploymentContext, extra_args): + # Slightly modify the base fixturenet-eth compose file to replace the startup script for fixturenet-eth-geth-1 + # We need to start geth with the flag to allow non eip-155 compliant transactions in order to publish the + # deterministic-deployment-proxy contract, which itself is a prereq for Optimism contract deployment + fixturenet_eth_compose_file = context.deployment_dir.joinpath('compose', 'docker-compose-fixturenet-eth.yml') + + with open(fixturenet_eth_compose_file, 'r') as yaml_file: + yaml = YAML() + yaml_data = yaml.load(yaml_file) + + new_script = '../config/fixturenet-optimism/run-geth.sh:/opt/testnet/run.sh' + + if new_script not in yaml_data['services']['fixturenet-eth-geth-1']['volumes']: + yaml_data['services']['fixturenet-eth-geth-1']['volumes'].append(new_script) + + with open(fixturenet_eth_compose_file, 'w') as yaml_file: + yaml = YAML() + yaml.dump(yaml_data, yaml_file) + + return None diff --git a/stack/fixturenet-optimism/stack.yml b/stack/fixturenet-optimism/stack.yml new file mode 100644 index 0000000..10a5177 --- /dev/null +++ b/stack/fixturenet-optimism/stack.yml @@ -0,0 +1,16 @@ +version: "1.0" +name: fixturenet-optimism +description: "Optimism Fixturenet" +repos: + - github.com/dboreham/foundry + - github.com/ethereum-optimism/optimism@op-node/v1.3.0 + - github.com/ethereum-optimism/op-geth@v1.101304.0 +containers: + - cerc/foundry + - cerc/optimism-contracts + - cerc/optimism-op-node + - cerc/optimism-l2geth + - cerc/optimism-op-batcher + - cerc/optimism-op-proposer +pods: + - fixturenet-optimism