diff --git a/.env.example b/.env.example index 69b1a01..8e0c13b 100644 --- a/.env.example +++ b/.env.example @@ -28,3 +28,29 @@ TIPS_UI_S3_CONFIG_TYPE=manual TIPS_UI_S3_ENDPOINT=http://localhost:7000 TIPS_UI_S3_ACCESS_KEY_ID=minioadmin TIPS_UI_S3_SECRET_ACCESS_KEY=minioadmin + +# OP Node (Consensus Layer) - Configuration for node-reth-consensus +OP_NODE_NETWORK= +OP_NODE_ROLLUP_CONFIG=/data/rollup.json +OP_NODE_ROLLUP_LOAD_PROTOCOL_VERSIONS=true +OP_NODE_L1_ETH_RPC=http://host.docker.internal:8545 +OP_NODE_L1_BEACON=http://host.docker.internal:3500 +OP_NODE_L1_RPC_KIND=basic +OP_NODE_L1_TRUST_RPC=false +OP_NODE_L2_ENGINE_KIND=reth +OP_NODE_L2_ENGINE_AUTH=/data/jwtsecret +OP_NODE_P2P_LISTEN_IP=0.0.0.0 +OP_NODE_P2P_LISTEN_TCP_PORT=9222 +OP_NODE_P2P_LISTEN_UDP_PORT=9222 +OP_NODE_P2P_INTERNAL_IP=true +OP_NODE_P2P_ADVERTISE_IP=host.docker.internal +OP_NODE_P2P_NO_DISCOVERY=false +OP_NODE_RPC_ADDR=0.0.0.0 +OP_NODE_RPC_PORT=8545 +OP_NODE_LOG_LEVEL=debug +OP_NODE_LOG_FORMAT=json +OP_NODE_SNAPSHOT_LOG=/tmp/op-node-snapshot-log +OP_NODE_METRICS_ENABLED=true +OP_NODE_METRICS_ADDR=0.0.0.0 +OP_NODE_METRICS_PORT=7300 +STATSD_ADDRESS=172.17.0.1 diff --git a/.gitignore b/.gitignore index f380f46..3126c46 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ Thumbs.db # Environment variables .env .env.docker +.env.playground /ui/.env # Claude diff --git a/docker-compose.yml b/docker-compose.yml index 5791426..48117d5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -71,4 +71,82 @@ services: /usr/bin/mc mb minio/tips; /usr/bin/mc anonymous set public minio/tips; exit 0; - " \ No newline at end of file + " + +# Ethereum Nodes in TIPS +# ====================== +# +# ┌─────────────────────┬──────────────────────────────────┬─────────────────────────────────────┐ +# │ Component │ Production │ Local Development │ +# ├─────────────────────┼──────────────────────────────────┼─────────────────────────────────────┤ +# │ Sequencer │ │ │ +# │ - Consensus Layer │ "consensus" container running │ builder-playground op-node │ +# │ │ op-node │ (runs separately within Docker) │ +# │ - Execution Layer │ "execution" container running │ builder-playground op-geth │ +# │ │ base/node-reth │ (runs separately within Docker) │ +# │ - Builder │ "builder" container running │ op-rbuilder │ +# │ │ op-rbuilder │ (runs on host machine) │ +# ├─────────────────────┼──────────────────────────────────┼─────────────────────────────────────┤ +# │ RPC Node │ │ │ +# │ - Consensus Layer │ "consensus" container running │ node-reth-consensus (container) │ +# │ │ op-node │ │ +# │ - Execution Layer │ "execution" container running │ node-reth-execution (container) │ +# │ │ base/node-reth │ │ +# ├─────────────────────┼──────────────────────────────────┼─────────────────────────────────────┤ +# │ L1 Dependencies │ Externally hosted L1 node │ builder-playground el + beacon │ +# │ │ │ (el: 8545, beacon: 3500) │ +# └─────────────────────┴──────────────────────────────────┴─────────────────────────────────────┘ + + node-reth-execution: + image: ghcr.io/base/node-reth:latest + container_name: tips-node-reth-execution + volumes: + - ~/.playground/devnet/jwtsecret:/data/jwtsecret:ro + - ~/.playground/devnet/rollup.json:/data/rollup.json:ro + - ~/.playground/devnet/l2-genesis.json:/data/l2-genesis.json:ro + - ~/.playground/devnet:/playground + entrypoint: ["/app/base-reth-node"] + command: + - node + - --datadir + - /playground/tips-node-reth + - --chain + - /data/l2-genesis.json + - --http + - --http.addr + - 0.0.0.0 + - --http.port + - "8545" + - --authrpc.addr + - 0.0.0.0 + - --authrpc.port + - "8551" + - --authrpc.jwtsecret + - /data/jwtsecret + - --disable-discovery + env_file: + - .env.docker + environment: + PLAYGROUND_DIR: /playground + RETH_CHAIN: /data/l2-genesis.json + NODE_TYPE: base + restart: unless-stopped + healthcheck: + test: ["CMD-SHELL", "curl -sf http://localhost:8545 -X POST -H 'Content-Type: application/json' -d '{\"jsonrpc\":\"2.0\",\"method\":\"eth_blockNumber\",\"params\":[],\"id\":1}' || exit 1"] + interval: 10s + timeout: 5s + retries: 10 + + node-reth-consensus: + image: us-docker.pkg.dev/oplabs-tools-artifacts/images/op-node:v1.13.7 + container_name: tips-node-reth-consensus + depends_on: + node-reth-execution: + condition: service_healthy + volumes: + - ~/.playground/devnet/jwtsecret:/data/jwtsecret:ro + - ~/.playground/devnet/rollup.json:/data/rollup.json:ro + env_file: + - .env.docker + environment: + OP_NODE_L2_ENGINE_RPC: http://node-reth-execution:8551 diff --git a/justfile b/justfile index ebac294..77642c8 100644 --- a/justfile +++ b/justfile @@ -22,7 +22,16 @@ sync: deps-reset ### REFORMAT ### just fix -sync-env: +playground-env: + #!/bin/bash + HOST_IP=$(docker run --rm alpine nslookup host.docker.internal | awk '/Address: / && $2 !~ /:/ {print $2; exit}') + PEER_ID=$(grep 'started p2p host' ~/.playground/devnet/logs/op-node.log | sed -n 's/.*peerID=\([^ ]*\).*/\1/p' | head -1) + echo "BUILDER_PLAYGROUND_HOST_IP=$HOST_IP" > .env.playground + echo "BUILDER_PLAYGROUND_PEER_ID=$PEER_ID" >> .env.playground + echo "OP_NODE_P2P_STATIC=/ip4/$HOST_IP/tcp/9003/p2p/$PEER_ID" >> .env.playground + cat .env.playground + +sync-env: playground-env cp .env.example .env cp .env.example ./ui/.env cp .env.example .env.docker @@ -30,18 +39,20 @@ sync-env: sed -i '' 's/localhost:9092/host.docker.internal:9094/g' ./.env.docker # Change other dependencies sed -i '' 's/localhost/host.docker.internal/g' ./.env.docker + # Append playground-specific P2P config + cat .env.playground >> .env.docker stop-all: export COMPOSE_FILE=docker-compose.yml:docker-compose.tips.yml && docker compose down && docker compose rm && rm -rf data/ # Start every service running in docker, useful for demos -start-all: stop-all +start-all: stop-all ensure-node-reth-image export COMPOSE_FILE=docker-compose.yml:docker-compose.tips.yml && mkdir -p data/kafka data/minio && docker compose build && docker compose up -d # Start every service in docker, except the one you're currently working on. e.g. just start-except ui ingress-rpc -start-except programs: stop-all +start-except programs: stop-all ensure-node-reth-image #!/bin/bash - all_services=(kafka kafka-setup minio minio-setup ingress-rpc audit ui) + all_services=(kafka kafka-setup minio minio-setup node-reth-execution node-reth-consensus ingress-rpc audit ui) exclude_services=({{ programs }}) # Create result array with services not in exclude list @@ -58,7 +69,7 @@ start-except programs: stop-all result_services+=("$service") fi done - + export COMPOSE_FILE=docker-compose.yml:docker-compose.tips.yml && mkdir -p data/kafka data/minio && docker compose build && docker compose up -d ${result_services[@]} ### RUN SERVICES ### @@ -74,12 +85,6 @@ audit: ingress-rpc: cargo run --bin tips-ingress-rpc -maintenance: - cargo run --bin tips-maintenance - -ingress-writer: - cargo run --bin tips-ingress-writer - ui: cd ui && yarn dev @@ -104,4 +109,45 @@ send-txn: txn=$(cast mktx --private-key {{ sender_key }} 0x0000000000000000000000000000000000000000 --value 0.01ether --nonce $nonce --chain-id 13 -r {{ builder_url }}) hash=$(curl -s {{ ingress_url }} -X POST -H "Content-Type: application/json" --data "{\"method\":\"eth_sendRawTransaction\",\"params\":[\"$txn\"],\"id\":1,\"jsonrpc\":\"2.0\"}" | jq -r ".result") cast receipt $hash -r {{ sequencer_url }} | grep status - cast receipt $hash -r {{ builder_url }} | grep status \ No newline at end of file + cast receipt $hash -r {{ builder_url }} | grep status + +# Build node-reth Docker image +# Args: +# ref: Git ref to build from GitHub (default: "main") +# local: Local path to build from (default: "" = use GitHub) +# Examples: +# just build-node-reth # Build from GitHub main branch +# just build-node-reth ref=v1.2.3 # Build from GitHub tag v1.2.3 +# just build-node-reth local=../node-reth # Build from local checkout +# Tags created: node-reth:latest and node-reth: (adds -dirty suffix if local working tree has changes) +build-node-reth ref="main" local="": + #!/bin/bash + if [ -z "{{ local }}" ]; then + echo "Building node-reth from GitHub ref: {{ ref }}" + # Get the commit hash for the ref + COMMIT_HASH=$(git ls-remote https://github.com/base/node-reth.git {{ ref }} | cut -f1 | cut -c1-8) + echo "Commit hash: $COMMIT_HASH" + docker build -t node-reth:latest -t node-reth:$COMMIT_HASH \ + -f https://raw.githubusercontent.com/base/node-reth/{{ ref }}/Dockerfile \ + https://github.com/base/node-reth.git#{{ ref }} + else + echo "Building node-reth from local path: {{ local }}" + # Get the commit hash from local repo + cd {{ local }} + COMMIT_HASH=$(git rev-parse --short=8 HEAD) + # Check if working tree is dirty + if ! git diff-index --quiet HEAD --; then + COMMIT_HASH="${COMMIT_HASH}-dirty" + fi + echo "Commit hash: $COMMIT_HASH" + docker build -t node-reth:latest -t node-reth:$COMMIT_HASH -f {{ local }}/Dockerfile {{ local }} + fi + +ensure-node-reth-image: + #!/bin/bash + if ! docker image inspect node-reth:latest >/dev/null 2>&1; then + echo "node-reth:latest image not found, building..." + just build-node-reth + else + echo "node-reth:latest image already exists" + fi