diff --git a/geth-poa/Makefile b/geth-poa/Makefile index bfdab8ffcb..ddd5525c8b 100644 --- a/geth-poa/Makefile +++ b/geth-poa/Makefile @@ -24,13 +24,18 @@ up-dev-settlement: @if [ ! -f .env ]; then echo "Error: .env file not found. Please populate the .env file before running this command."; exit 1; fi AGENT_BASE_IMAGE=shaspitz/hyperlane-agent-mac:6985064 L2_NODE_URL=http://localhost:8545 docker compose --profile settlement up -d --build +## TODO: change to bring up bridge too +up-dev-local-l1: + @if [ ! -f .env ]; then echo "Error: .env file not found. Please populate the .env file before running this command."; exit 1; fi + AGENT_BASE_IMAGE=shaspitz/hyperlane-agent-mac:6985064 L2_NODE_URL=http://localhost:8545 docker compose --profile settlement --profile local_l1 up -d + down: - AGENT_BASE_IMAGE=nil L2_NODE_URL=nil docker compose --profile settlement --profile bridge --profile prod_agents down + AGENT_BASE_IMAGE=nil L2_NODE_URL=nil docker compose --profile settlement --profile bridge --profile prod_agents --profile local_l1 down clean-dbs: @read -p "WARNING: This command will wipe all persistent disk data relevant to the containers. Press enter to continue or Ctrl+C to cancel." _ - -docker compose --profile settlement --profile bridge down --rmi all --volumes - -docker compose --profile settlement --profile bridge rm -fv + -docker compose --profile settlement --profile bridge --profile local_l1 down --rmi all --volumes + -docker compose --profile settlement --profile bridge --profile local_l1 rm -fv docker image prune -f pull-image: diff --git a/geth-poa/docker-compose.yml b/geth-poa/docker-compose.yml index db928581b4..1be398d340 100644 --- a/geth-poa/docker-compose.yml +++ b/geth-poa/docker-compose.yml @@ -114,7 +114,52 @@ services: } ] - + # L1 geth service only used for local dev + l1-bootnode: + build: + context: . + dockerfile: ./local-l1/Dockerfile + environment: + - GETH_NODE_TYPE=bootnode + - BOOT_KEY=7b548c1c0fbe80ef1eb0aaec2edf26fd20fb0d758e94948cf6c5f2a486e735f6 + networks: + l1_net: + ipv4_address: '172.14.0.2' + volumes: + - geth-data-l1-bootnode:/data + profiles: + - local_l1 + l1-first-signer: + build: + context: . + dockerfile: ./local-l1/Dockerfile + environment: + - GETH_NODE_TYPE=signer + - BLOCK_SIGNER_ADDRESS=0xd9cd8E5DE6d55f796D980B818D350C0746C25b97 + - BLOCK_SIGNER_PRIVATE_KEY=${NODE1_PRIVATE_KEY} + networks: + l1_net: + ipv4_address: '172.14.0.3' + volumes: + - geth-data-l1-first-signer:/data + profiles: + - local_l1 + l1-second-signer: + build: + context: . + dockerfile: ./local-l1/Dockerfile + environment: + - GETH_NODE_TYPE=signer + - BLOCK_SIGNER_ADDRESS=0x788EBABe5c3dD422Ef92Ca6714A69e2eabcE1Ee4 + - BLOCK_SIGNER_PRIVATE_KEY=${NODE2_PRIVATE_KEY} + networks: + l1_net: + ipv4_address: '172.14.0.4' + volumes: + - geth-data-l1-second-signer:/data + profiles: + - local_l1 + hyperlane-deployer: build: context: ./hyperlane-deployer @@ -254,11 +299,20 @@ networks: driver: default config: - subnet: 172.13.0.0/16 + l1_net: + driver: bridge + ipam: + driver: default + config: + - subnet: 172.14.0.0/16 volumes: geth-data-bootnode: geth-data-node1: geth-data-node2: + geth-data-l1-bootnode: + geth-data-l1-first-signer: + geth-data-l1-second-signer: hyperlane-deploy-artifacts: hyperlane-validator1-sigs: hyperlane-validator2-sigs: diff --git a/geth-poa/local-l1/Dockerfile b/geth-poa/local-l1/Dockerfile new file mode 100644 index 0000000000..42755ede3a --- /dev/null +++ b/geth-poa/local-l1/Dockerfile @@ -0,0 +1,11 @@ +FROM ethereum/client-go:v1.13.4 as builder + +RUN apk add --no-cache jq + +# Reuse entrypoint for mev-commit chain +COPY ./local-l1/entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh + +COPY ./local-l1/genesis.json /genesis.json + +ENTRYPOINT ["/bin/sh", "/entrypoint.sh"] diff --git a/geth-poa/local-l1/entrypoint.sh b/geth-poa/local-l1/entrypoint.sh new file mode 100644 index 0000000000..f6d4e7939b --- /dev/null +++ b/geth-poa/local-l1/entrypoint.sh @@ -0,0 +1,121 @@ +#!/bin/sh +set -exu + +GENESIS_L1_PATH="/genesis.json" +VERBOSITY=3 +GETH_DATA_DIR=/data +GETH_CHAINDATA_DIR="$GETH_DATA_DIR/geth/chaindata" +GETH_KEYSTORE_DIR="$GETH_DATA_DIR/keystore" +CHAIN_ID=$(cat "$GENESIS_L1_PATH" | jq -r .config.chainId) +RPC_PORT="${RPC_PORT:-8545}" +WS_PORT="${WS_PORT:-8546}" + +# Generate signer key if needed +if [ ! -d "$GETH_KEYSTORE_DIR" ] && [ "$GETH_NODE_TYPE" = "signer" ]; then + + echo "$GETH_KEYSTORE_DIR missing, running account import" + echo -n "pwd" > "$GETH_DATA_DIR"/password + echo -n "$BLOCK_SIGNER_PRIVATE_KEY" | sed 's/0x//' > "$GETH_DATA_DIR"/block-signer-key + geth --verbosity="$VERBOSITY" \ + --nousb \ + account import \ + --datadir="$GETH_DATA_DIR" \ + --password="$GETH_DATA_DIR"/password \ + "$GETH_DATA_DIR"/block-signer-key +else + echo "$GETH_KEYSTORE_DIR exists." +fi + +# Init geth if needed +if [ ! -d "$GETH_CHAINDATA_DIR" ]; then + echo "$GETH_CHAINDATA_DIR missing, running init" + echo "Initializing genesis." + geth --verbosity="$VERBOSITY" \ + --nousb \ + --state.scheme=path \ + --db.engine=pebble \ + --datadir="$GETH_DATA_DIR" init \ + "$GENESIS_L1_PATH" +else + echo "$GETH_CHAINDATA_DIR exists." +fi + +# Obtain assigned container IP for p2p +NODE_IP=$(hostname -i) + +if [ "$GETH_NODE_TYPE" = "bootnode" ]; then + echo "Starting bootnode" + + # Generate boot.key + echo "$BOOT_KEY" > $GETH_DATA_DIR/boot.key + + exec geth \ + --verbosity="$VERBOSITY" \ + --datadir="$GETH_DATA_DIR" \ + --port 30301 \ + --http \ + --http.corsdomain="*" \ + --http.vhosts="*" \ + --http.addr=0.0.0.0 \ + --http.port="$RPC_PORT" \ + --http.api=web3,debug,eth,txpool,net,engine \ + --ws \ + --ws.addr=0.0.0.0 \ + --ws.port="$WS_PORT" \ + --ws.origins="*" \ + --ws.api=debug,eth,txpool,net,engine \ + --syncmode=full \ + --gcmode=full \ + --state.scheme=path \ + --db.engine=pebble \ + --networkid=$CHAIN_ID \ + --nousb \ + --metrics \ + --metrics.addr=0.0.0.0 \ + --metrics.port=6060 \ + --nodekey $GETH_DATA_DIR/boot.key \ + --netrestrict 172.14.0.0/24 \ + --nat extip:$NODE_IP + +elif [ "$GETH_NODE_TYPE" = "signer" ]; then + echo "Starting signer node" + + exec geth \ + --verbosity="$VERBOSITY" \ + --datadir="$GETH_DATA_DIR" \ + --port 30311 \ + --syncmode=full \ + --gcmode=full \ + --state.scheme=path \ + --db.engine=pebble \ + --http \ + --http.corsdomain="*" \ + --http.vhosts="*" \ + --http.addr=0.0.0.0 \ + --http.port="$RPC_PORT" \ + --http.api=web3,debug,eth,txpool,net,engine \ + --bootnodes enode://34a2a388ad31ca37f127bb9ffe93758ee711c5c2277dff6aff2e359bcf2c9509ea55034196788dbd59ed70861f523c1c03d54f1eabb2b4a5c1c129d966fe1e65@172.14.0.2:30301 \ + --networkid=$CHAIN_ID \ + --unlock=$BLOCK_SIGNER_ADDRESS \ + --password="$GETH_DATA_DIR"/password \ + --mine \ + --miner.etherbase=$BLOCK_SIGNER_ADDRESS \ + --allow-insecure-unlock \ + --nousb \ + --netrestrict 172.14.0.0/24 \ + --metrics \ + --metrics.addr=0.0.0.0 \ + --metrics.port=6060 \ + --ws \ + --ws.addr=0.0.0.0 \ + --ws.port="$WS_PORT" \ + --ws.origins="*" \ + --ws.api=debug,eth,txpool,net,engine \ + --rpc.allow-unprotected-txs \ + --authrpc.addr="0.0.0.0" \ + --authrpc.port="8551" \ + --authrpc.vhosts="*" \ + --nat extip:$NODE_IP +else + echo "Invalid GETH_NODE_TYPE specified" +fi diff --git a/geth-poa/local-l1/genesis.json b/geth-poa/local-l1/genesis.json new file mode 100644 index 0000000000..2ac8c76383 --- /dev/null +++ b/geth-poa/local-l1/genesis.json @@ -0,0 +1,52 @@ +{ + "config": { + "chainId": 39999, + "homesteadBlock": 0, + "eip150Block": 0, + "eip155Block": 0, + "eip158Block": 0, + "byzantiumBlock": 0, + "constantinopleBlock": 0, + "petersburgBlock": 0, + "istanbulBlock": 0, + "muirGlacierBlock": 0, + "berlinBlock": 0, + "londonBlock": 0, + "arrowGlacierBlock": 0, + "grayGlacierBlock": 0, + "clique": { + "period": 12, + "epoch": 30000 + } + }, + "nonce": "0x0", + "timestamp": "0x6546df6d", + "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000d9cd8E5DE6d55f796D980B818D350C0746C25b97788EBABe5c3dD422Ef92Ca6714A69e2eabcE1Ee40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "gasLimit": "0x1c9c380", + "difficulty": "0x1", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase": "0x0000000000000000000000000000000000000000", + "alloc": { + "0xBe3dEF3973584FdcC1326634aF188f0d9772D57D": { + "balance": "10000000000000000000000" + }, + "d9cd8E5DE6d55f796D980B818D350C0746C25b97": { + "balance": "10000000000000000000000" + }, + "788EBABe5c3dD422Ef92Ca6714A69e2eabcE1Ee4": { + "balance": "10000000000000000000000" + }, + "0DCaa27B9E4Db92F820189345792f8eC5Ef148F6": { + "balance": "10000000000000000000000" + }, + "f39Fd6e51aad88F6F4ce6aB8827279cffFb92266": { + "balance": "10000000000000000000000" + } + }, + "number": "0x0", + "gasUsed": "0x0", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "baseFeePerGas": "0x3b9aca00", + "excessBlobGas": null, + "blobGasUsed": null + }