├── .dockerignore ├── .env ├── .env.mainnet ├── .env.sepolia ├── .github └── workflows │ ├── docker-publish.yml │ ├── docker.yml │ └── pr.yml ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── SECURITY.md ├── docker-compose.yml ├── geth ├── Dockerfile └── geth-entrypoint ├── logo.webp ├── nethermind ├── Dockerfile └── nethermind-entrypoint ├── op-node-entrypoint ├── reth ├── Dockerfile └── reth-entrypoint └── supervisord.conf /.dockerignore: -------------------------------------------------------------------------------- 1 | geth-data/ 2 | reth-data/ 3 | nethermind-data/ 4 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | CLIENT=${CLIENT:-geth} 2 | HOST_DATA_DIR=./${CLIENT}-data -------------------------------------------------------------------------------- /.env.mainnet: -------------------------------------------------------------------------------- 1 | RETH_CHAIN=base 2 | RETH_SEQUENCER_HTTP=https://mainnet-sequencer.base.org 3 | OP_GETH_SEQUENCER_HTTP=https://mainnet-sequencer.base.org 4 | OP_SEQUENCER_HTTP=https://mainnet-sequencer.base.org 5 | 6 | # [optional] used to enable geth stats: 7 | # OP_GETH_ETH_STATS=nodename:secret@host:port 8 | # OP_NETHERMIND_ETHSTATS_ENABLED=true 9 | # OP_NETHERMIND_ETHSTATS_NODE_NAME=NethermindNode 10 | # OP_NETHERMIND_ETHSTATS_ENDPOINT=ethstats_endpoint 11 | 12 | # [required] replace with your preferred L1 (Ethereum, not Base) node RPC URL: 13 | OP_NODE_L1_ETH_RPC=https://1rpc.io/eth 14 | 15 | # [required] replace with your preferred L1 CL beacon endpoint: 16 | OP_NODE_L1_BEACON=https://your.mainnet.beacon.node/endpoint-here 17 | 18 | # auth secret used by op-geth engine API: 19 | OP_NODE_L2_ENGINE_AUTH_RAW=688f5d737bad920bdfb2fc2f488d6b6209eebda1dae949a8de91398d932c517a 20 | 21 | OP_NODE_L2_ENGINE_AUTH=/tmp/engine-auth-jwt 22 | OP_NODE_L2_ENGINE_RPC=ws://execution:8551 23 | OP_NODE_LOG_LEVEL=info 24 | OP_NODE_METRICS_ADDR=0.0.0.0 25 | OP_NODE_METRICS_ENABLED=true 26 | OP_NODE_METRICS_PORT=7300 27 | OP_NODE_NETWORK=base-mainnet 28 | OP_NODE_P2P_AGENT=base 29 | OP_NODE_P2P_BOOTNODES=enr:-J24QNz9lbrKbN4iSmmjtnr7SjUMk4zB7f1krHZcTZx-JRKZd0kA2gjufUROD6T3sOWDVDnFJRvqBBo62zuF-hYCohOGAYiOoEyEgmlkgnY0gmlwhAPniryHb3BzdGFja4OFQgCJc2VjcDI1NmsxoQKNVFlCxh_B-716tTs-h1vMzZkSs1FTu_OYTNjgufplG4N0Y3CCJAaDdWRwgiQG,enr:-J24QH-f1wt99sfpHy4c0QJM-NfmsIfmlLAMMcgZCUEgKG_BBYFc6FwYgaMJMQN5dsRBJApIok0jFn-9CS842lGpLmqGAYiOoDRAgmlkgnY0gmlwhLhIgb2Hb3BzdGFja4OFQgCJc2VjcDI1NmsxoQJ9FTIv8B9myn1MWaC_2lJ-sMoeCDkusCsk4BYHjjCq04N0Y3CCJAaDdWRwgiQG,enr:-J24QDXyyxvQYsd0yfsN0cRr1lZ1N11zGTplMNlW4xNEc7LkPXh0NAJ9iSOVdRO95GPYAIc6xmyoCCG6_0JxdL3a0zaGAYiOoAjFgmlkgnY0gmlwhAPckbGHb3BzdGFja4OFQgCJc2VjcDI1NmsxoQJwoS7tzwxqXSyFL7g0JM-KWVbgvjfB8JA__T7yY_cYboN0Y3CCJAaDdWRwgiQG,enr:-J24QHmGyBwUZXIcsGYMaUqGGSl4CFdx9Tozu-vQCn5bHIQbR7On7dZbU61vYvfrJr30t0iahSqhc64J46MnUO2JvQaGAYiOoCKKgmlkgnY0gmlwhAPnCzSHb3BzdGFja4OFQgCJc2VjcDI1NmsxoQINc4fSijfbNIiGhcgvwjsjxVFJHUstK9L1T8OTKUjgloN0Y3CCJAaDdWRwgiQG,enr:-J24QG3ypT4xSu0gjb5PABCmVxZqBjVw9ca7pvsI8jl4KATYAnxBmfkaIuEqy9sKvDHKuNCsy57WwK9wTt2aQgcaDDyGAYiOoGAXgmlkgnY0gmlwhDbGmZaHb3BzdGFja4OFQgCJc2VjcDI1NmsxoQIeAK_--tcLEiu7HvoUlbV52MspE0uCocsx1f_rYvRenIN0Y3CCJAaDdWRwgiQG 30 | OP_NODE_P2P_LISTEN_IP=0.0.0.0 31 | OP_NODE_P2P_LISTEN_TCP_PORT=9222 32 | OP_NODE_P2P_LISTEN_UDP_PORT=9222 33 | OP_NODE_RPC_ADDR=0.0.0.0 34 | OP_NODE_RPC_PORT=8545 35 | OP_NODE_SNAPSHOT_LOG=/tmp/op-node-snapshot-log 36 | OP_NODE_VERIFIER_L1_CONFS=4 37 | OP_NODE_ROLLUP_LOAD_PROTOCOL_VERSIONS=true 38 | 39 | # OP_NODE_L1_TRUST_RPC allows for faster syncing, but should be used *only* if your L1 RPC node 40 | # is fully trusted. It also allows op-node to work with clients such as Erigon that do not 41 | # support storage proofs: 42 | # OP_NODE_L1_TRUST_RPC=true 43 | 44 | # SNAP SYNC 45 | # NOTE: This feature is experimental and may lead to syncing issues, delays or difficulties as a result of inability to find peers. We recommend running a full or archive node for production purposes. 46 | # To enable snap sync, uncomment and set the env vars below: 47 | # OP_NODE_SYNCMODE=execution-layer 48 | # OP_GETH_BOOTNODES=enode://87a32fd13bd596b2ffca97020e31aef4ddcc1bbd4b95bb633d16c1329f654f34049ed240a36b449fda5e5225d70fe40bc667f53c304b71f8e68fc9d448690b51@3.231.138.188:30301,enode://ca21ea8f176adb2e229ce2d700830c844af0ea941a1d8152a9513b966fe525e809c3a6c73a2c18a12b74ed6ec4380edf91662778fe0b79f6a591236e49e176f9@184.72.129.189:30301,enode://acf4507a211ba7c1e52cdf4eef62cdc3c32e7c9c47998954f7ba024026f9a6b2150cd3f0b734d9c78e507ab70d59ba61dfe5c45e1078c7ad0775fb251d7735a2@3.220.145.177:30301,enode://8a5a5006159bf079d06a04e5eceab2a1ce6e0f721875b2a9c96905336219dbe14203d38f70f3754686a6324f786c2f9852d8c0dd3adac2d080f4db35efc678c5@3.231.11.52:30301,enode://cdadbe835308ad3557f9a1de8db411da1a260a98f8421d62da90e71da66e55e98aaa8e90aa7ce01b408a54e4bd2253d701218081ded3dbe5efbbc7b41d7cef79@54.198.153.150:30301 49 | # OP_NETHERMIND_BOOTNODES=enode://87a32fd13bd596b2ffca97020e31aef4ddcc1bbd4b95bb633d16c1329f654f34049ed240a36b449fda5e5225d70fe40bc667f53c304b71f8e68fc9d448690b51@3.231.138.188:30301,enode://ca21ea8f176adb2e229ce2d700830c844af0ea941a1d8152a9513b966fe525e809c3a6c73a2c18a12b74ed6ec4380edf91662778fe0b79f6a591236e49e176f9@184.72.129.189:30301,enode://acf4507a211ba7c1e52cdf4eef62cdc3c32e7c9c47998954f7ba024026f9a6b2150cd3f0b734d9c78e507ab70d59ba61dfe5c45e1078c7ad0775fb251d7735a2@3.220.145.177:30301,enode://8a5a5006159bf079d06a04e5eceab2a1ce6e0f721875b2a9c96905336219dbe14203d38f70f3754686a6324f786c2f9852d8c0dd3adac2d080f4db35efc678c5@3.231.11.52:30301,enode://cdadbe835308ad3557f9a1de8db411da1a260a98f8421d62da90e71da66e55e98aaa8e90aa7ce01b408a54e4bd2253d701218081ded3dbe5efbbc7b41d7cef79@54.198.153.150:30301 50 | # OP_GETH_SYNCMODE=snap 51 | -------------------------------------------------------------------------------- /.env.sepolia: -------------------------------------------------------------------------------- 1 | RETH_CHAIN=base-sepolia 2 | RETH_SEQUENCER_HTTP=https://sepolia-sequencer.base.org 3 | OP_GETH_SEQUENCER_HTTP=https://sepolia-sequencer.base.org 4 | OP_SEQUENCER_HTTP=https://sepolia-sequencer.base.org 5 | 6 | # [optional] used to enable geth stats: 7 | # OP_GETH_ETH_STATS=nodename:secret@host:port 8 | # OP_NETHERMIND_ETHSTATS_ENABLED=true 9 | # OP_NETHERMIND_ETHSTATS_NODE_NAME=NethermindNode 10 | # OP_NETHERMIND_ETHSTATS_ENDPOINT=ethstats_endpoint 11 | 12 | # [required] replace with your preferred L1 (Ethereum, not Base) node RPC URL: 13 | OP_NODE_L1_ETH_RPC=https://rpc.sepolia.org 14 | 15 | # [required] replace with your preferred L1 CL beacon endpoint: 16 | OP_NODE_L1_BEACON=https://your.sepolia.beacon.node/endpoint-here 17 | 18 | # auth secret used by op-geth engine API: 19 | OP_NODE_L2_ENGINE_AUTH_RAW=688f5d737bad920bdfb2fc2f488d6b6209eebda1dae949a8de91398d932c517a 20 | 21 | OP_NODE_L2_ENGINE_AUTH=/tmp/engine-auth-jwt 22 | OP_NODE_L2_ENGINE_RPC=ws://execution:8551 23 | OP_NODE_LOG_LEVEL=info 24 | OP_NODE_METRICS_ADDR=0.0.0.0 25 | OP_NODE_METRICS_ENABLED=true 26 | OP_NODE_METRICS_PORT=7300 27 | OP_NODE_NETWORK=base-sepolia 28 | OP_NODE_P2P_AGENT=base 29 | OP_NODE_P2P_BOOTNODES=enr:-J64QBwRIWAco7lv6jImSOjPU_W266lHXzpAS5YOh7WmgTyBZkgLgOwo_mxKJq3wz2XRbsoBItbv1dCyjIoNq67mFguGAYrTxM42gmlkgnY0gmlwhBLSsHKHb3BzdGFja4S0lAUAiXNlY3AyNTZrMaEDmoWSi8hcsRpQf2eJsNUx-sqv6fH4btmo2HsAzZFAKnKDdGNwgiQGg3VkcIIkBg,enr:-J64QFa3qMsONLGphfjEkeYyF6Jkil_jCuJmm7_a42ckZeUQGLVzrzstZNb1dgBp1GGx9bzImq5VxJLP-BaptZThGiWGAYrTytOvgmlkgnY0gmlwhGsV-zeHb3BzdGFja4S0lAUAiXNlY3AyNTZrMaEDahfSECTIS_cXyZ8IyNf4leANlZnrsMEWTkEYxf4GMCmDdGNwgiQGg3VkcIIkBg 30 | OP_NODE_P2P_LISTEN_IP=0.0.0.0 31 | OP_NODE_P2P_LISTEN_TCP_PORT=9222 32 | OP_NODE_P2P_LISTEN_UDP_PORT=9222 33 | OP_NODE_RPC_ADDR=0.0.0.0 34 | OP_NODE_RPC_PORT=8545 35 | OP_NODE_SNAPSHOT_LOG=/tmp/op-node-snapshot-log 36 | OP_NODE_VERIFIER_L1_CONFS=4 37 | OP_NODE_ROLLUP_LOAD_PROTOCOL_VERSIONS=true 38 | 39 | # OP_NODE_L1_TRUST_RPC allows for faster syncing, but should be used *only* if your L1 RPC node 40 | # is fully trusted. It also allows op-node to work with clients such as Erigon that do not 41 | # support storage proofs: 42 | # OP_NODE_L1_TRUST_RPC=true 43 | 44 | # SNAP SYNC 45 | # NOTE: This feature is experimental and may lead to syncing issues, delays or difficulties as a result of inability to find peers. We recommend running a full or archive node for production purposes. 46 | # To enable snap sync, set env vars below: 47 | # OP_NODE_SYNCMODE=execution-layer 48 | # OP_GETH_BOOTNODES=enode://548f715f3fc388a7c917ba644a2f16270f1ede48a5d88a4d14ea287cc916068363f3092e39936f1a3e7885198bef0e5af951f1d7b1041ce8ba4010917777e71f@18.210.176.114:30301,enode://6f10052847a966a725c9f4adf6716f9141155b99a0fb487fea3f51498f4c2a2cb8d534e680ee678f9447db85b93ff7c74562762c3714783a7233ac448603b25f@107.21.251.55:30301 49 | # OP_NETHERMIND_BOOTNODES=enode://548f715f3fc388a7c917ba644a2f16270f1ede48a5d88a4d14ea287cc916068363f3092e39936f1a3e7885198bef0e5af951f1d7b1041ce8ba4010917777e71f@18.210.176.114:30301,enode://6f10052847a966a725c9f4adf6716f9141155b99a0fb487fea3f51498f4c2a2cb8d534e680ee678f9447db85b93ff7c74562762c3714783a7233ac448603b25f@107.21.251.55:30301 50 | # OP_GETH_SYNCMODE=snap 51 | -------------------------------------------------------------------------------- /.github/workflows/docker-publish.yml: -------------------------------------------------------------------------------- 1 | name: Docker 2 | 3 | # This workflow uses actions that are not certified by GitHub. 4 | # They are provided by a third-party and are governed by 5 | # separate terms of service, privacy policy, and support 6 | # documentation. 7 | 8 | on: 9 | schedule: 10 | - cron: '35 23 * * *' 11 | push: 12 | branches: [ "main" ] 13 | # Publish semver tags as releases. 14 | tags: [ 'v*.*.*' ] 15 | pull_request: 16 | branches: [ "main" ] 17 | 18 | env: 19 | # Use docker.io for Docker Hub if empty 20 | REGISTRY: ghcr.io 21 | # github.repository as / 22 | IMAGE_NAME: ${{ github.repository }} 23 | 24 | 25 | jobs: 26 | build: 27 | 28 | runs-on: ubuntu-latest 29 | permissions: 30 | contents: read 31 | packages: write 32 | # This is used to complete the identity challenge 33 | # with sigstore/fulcio when running outside of PRs. 34 | id-token: write 35 | 36 | steps: 37 | - name: Checkout repository 38 | uses: actions/checkout@v4 39 | 40 | # Install the cosign tool except on PR 41 | # https://github.com/sigstore/cosign-installer 42 | - name: Install cosign 43 | if: github.event_name != 'pull_request' 44 | uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 #v3.5.0 45 | with: 46 | cosign-release: 'v2.2.4' 47 | 48 | # Set up BuildKit Docker container builder to be able to build 49 | # multi-platform images and export cache 50 | # https://github.com/docker/setup-buildx-action 51 | - name: Set up Docker Buildx 52 | uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0 53 | 54 | # Login against a Docker registry except on PR 55 | # https://github.com/docker/login-action 56 | - name: Log into registry ${{ env.REGISTRY }} 57 | if: github.event_name != 'pull_request' 58 | uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0 59 | with: 60 | registry: ${{ env.REGISTRY }} 61 | username: ${{ github.actor }} 62 | password: ${{ secrets.GITHUB_TOKEN }} 63 | 64 | # Extract metadata (tags, labels) for Docker 65 | # https://github.com/docker/metadata-action 66 | - name: Extract Docker metadata 67 | id: meta 68 | uses: docker/metadata-action@96383f45573cb7f253c731d3b3ab81c87ef81934 # v5.0.0 69 | with: 70 | images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} 71 | 72 | # Build and push Docker image with Buildx (don't push on PR) 73 | # https://github.com/docker/build-push-action 74 | - name: Build and push Docker image 75 | id: build-and-push 76 | uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0 77 | with: 78 | context: . 79 | push: ${{ github.event_name != 'pull_request' }} 80 | tags: ${{ steps.meta.outputs.tags }} 81 | labels: ${{ steps.meta.outputs.labels }} 82 | cache-from: type=gha 83 | cache-to: type=gha,mode=max 84 | 85 | # Sign the resulting Docker image digest except on PRs. 86 | # This will only write to the public Rekor transparency log when the Docker 87 | # repository is public to avoid leaking data. If you would like to publish 88 | # transparency data even for private images, pass --force to cosign below. 89 | # https://github.com/sigstore/cosign 90 | - name: Sign the published Docker image 91 | if: ${{ github.event_name != 'pull_request' }} 92 | env: 93 | # https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-an-intermediate-environment-variable 94 | TAGS: ${{ steps.meta.outputs.tags }} 95 | DIGEST: ${{ steps.build-and-push.outputs.digest }} 96 | # This step uses the identity token to provision an ephemeral certificate 97 | # against the sigstore community Fulcio instance. 98 | run: echo "${TAGS}" | xargs -I {} cosign sign --yes {}@${DIGEST} 99 | -------------------------------------------------------------------------------- /.github/workflows/docker.yml: -------------------------------------------------------------------------------- 1 | name: Tag Docker image 2 | 3 | on: 4 | push: 5 | branches: 6 | - 'main' 7 | tags: 8 | - 'v*' 9 | 10 | env: 11 | REGISTRY: ghcr.io 12 | NAMESPACE: ghcr.io/base-org 13 | GETH_DEPRECATED_IMAGE_NAME: node 14 | GETH_IMAGE_NAME: node-geth 15 | RETH_IMAGE_NAME: node-reth 16 | NETHERMIND_IMAGE_NAME: node-nethermind 17 | 18 | jobs: 19 | geth: 20 | runs-on: ubuntu-latest 21 | steps: 22 | - name: Checkout 23 | uses: actions/checkout@v2 24 | 25 | - name: Log into the Container registry 26 | uses: docker/login-action@v3 27 | with: 28 | registry: ${{ env.REGISTRY }} 29 | username: ${{ github.actor }} 30 | password: ${{ secrets.GITHUB_TOKEN }} 31 | 32 | - name: Extract metadata for the Docker image 33 | id: meta 34 | uses: docker/metadata-action@v4 35 | with: 36 | images: | 37 | ${{ env.NAMESPACE }}/${{ env.GETH_DEPRECATED_IMAGE_NAME }} 38 | ${{ env.NAMESPACE }}/${{ env.GETH_IMAGE_NAME }} 39 | 40 | - name: Set up Docker Buildx 41 | uses: docker/setup-buildx-action@v3 42 | 43 | - name: Build and push the Docker image 44 | uses: docker/build-push-action@v4 45 | with: 46 | context: . 47 | file: geth/Dockerfile 48 | push: true 49 | tags: ${{ steps.meta.outputs.tags }} 50 | labels: ${{ steps.meta.outputs.labels }} 51 | platforms: linux/amd64,linux/arm64 52 | reth: 53 | runs-on: ubuntu-latest 54 | strategy: 55 | matrix: 56 | include: 57 | - arch: linux/amd64 58 | features: jemalloc,asm-keccak,optimism 59 | steps: 60 | - name: Checkout 61 | uses: actions/checkout@v2 62 | 63 | - name: Log into the Container registry 64 | uses: docker/login-action@v3 65 | with: 66 | registry: ${{ env.REGISTRY }} 67 | username: ${{ github.actor }} 68 | password: ${{ secrets.GITHUB_TOKEN }} 69 | 70 | - name: Extract metadata for the Docker image 71 | id: meta 72 | uses: docker/metadata-action@v4 73 | with: 74 | images: | 75 | ${{ env.NAMESPACE }}/${{ env.RETH_IMAGE_NAME }} 76 | 77 | - name: Set up Docker Buildx 78 | uses: docker/setup-buildx-action@v3 79 | 80 | - name: Build and push the Docker image 81 | uses: docker/build-push-action@v4 82 | with: 83 | context: . 84 | file: reth/Dockerfile 85 | push: true 86 | tags: ${{ steps.meta.outputs.tags }} 87 | labels: ${{ steps.meta.outputs.labels }} 88 | build-args: | 89 | FEATURES=${{ matrix.features }} 90 | platforms: ${{ matrix.arch }} 91 | nethermind: 92 | runs-on: ubuntu-latest 93 | strategy: 94 | matrix: 95 | platform: [linux/amd64] 96 | steps: 97 | - name: Checkout 98 | uses: actions/checkout@v2 99 | 100 | - name: Log into the Container registry 101 | uses: docker/login-action@v3 102 | with: 103 | registry: ${{ env.REGISTRY }} 104 | username: ${{ github.actor }} 105 | password: ${{ secrets.GITHUB_TOKEN }} 106 | 107 | - name: Set up QEMU 108 | uses: docker/setup-qemu-action@v2 109 | with: 110 | platforms: ${{ matrix.arch }} 111 | 112 | - name: Set up Docker Buildx 113 | uses: docker/setup-buildx-action@v3 114 | 115 | - name: Extract metadata for the Docker image 116 | id: meta 117 | uses: docker/metadata-action@v4 118 | with: 119 | images: | 120 | ${{ env.NAMESPACE }}/${{ env.NETHERMIND_IMAGE_NAME }} 121 | 122 | - name: Build and push the Docker image 123 | uses: docker/build-push-action@v6 124 | with: 125 | context: . 126 | file: nethermind/Dockerfile 127 | push: true 128 | tags: ${{ steps.meta.outputs.tags }} 129 | labels: ${{ steps.meta.outputs.labels }} 130 | platforms: ${{ matrix.arch }} 131 | -------------------------------------------------------------------------------- /.github/workflows/pr.yml: -------------------------------------------------------------------------------- 1 | name: Pull Request 2 | 3 | on: 4 | pull_request: 5 | workflow_dispatch: 6 | 7 | jobs: 8 | geth: 9 | runs-on: ubuntu-latest 10 | strategy: 11 | matrix: 12 | arch: [ linux/amd64, linux/arm64 ] 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@v3 16 | with: 17 | ref: ${{ github.event.pull_request.head.sha }} 18 | - name: Set up Docker Buildx 19 | uses: docker/setup-buildx-action@v3 20 | - name: Build the Docker image 21 | uses: docker/build-push-action@v4 22 | with: 23 | context: . 24 | file: geth/Dockerfile 25 | push: false 26 | platforms: ${{ matrix.arch }} 27 | reth: 28 | runs-on: ubuntu-latest 29 | strategy: 30 | matrix: 31 | include: 32 | - arch: linux/amd64 33 | features: jemalloc,asm-keccak,optimism 34 | steps: 35 | - name: Checkout 36 | uses: actions/checkout@v3 37 | with: 38 | ref: ${{ github.event.pull_request.head.sha }} 39 | - name: Set up Docker Buildx 40 | uses: docker/setup-buildx-action@v3 41 | - name: Build the Docker image 42 | uses: docker/build-push-action@v4 43 | with: 44 | context: . 45 | file: reth/Dockerfile 46 | push: false 47 | build-args: | 48 | FEATURES=${{ matrix.features }} 49 | platforms: ${{ matrix.arch }} 50 | nethermind: 51 | runs-on: ubuntu-latest 52 | strategy: 53 | matrix: 54 | arch: [ linux/amd64 ] 55 | steps: 56 | - name: Checkout 57 | uses: actions/checkout@v3 58 | with: 59 | ref: ${{ github.event.pull_request.head.sha }} 60 | - name: Set up Docker Buildx 61 | uses: docker/setup-buildx-action@v3 62 | - name: Build the Docker image 63 | uses: docker/build-push-action@v6 64 | with: 65 | context: . 66 | file: nethermind/Dockerfile 67 | push: false 68 | platforms: ${{ matrix.arch }} 69 | 70 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea/ 2 | /geth-data/ 3 | /reth-data/ 4 | /nethermind-data/ 5 | .DS_Store 6 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Base Node 2 | 3 | ## Code of Conduct 4 | 5 | All interactions with this project follow our [Code of Conduct][code-of-conduct]. 6 | By participating, you are expected to honor this code. Violators can be banned 7 | from further participation in this project, or potentially all Base and/or 8 | Coinbase 9 | projects. 10 | 11 | [code-of-conduct]: https://github.com/coinbase/code-of-conduct 12 | 13 | ## Bug Reports 14 | 15 | * Ensure your issue [has not already been reported][1]. It may already be fixed! 16 | * Include the steps you carried out to produce the problem. 17 | * Include the behavior you observed along with the behavior you expected, and 18 | why you expected it. 19 | * Include any relevant stack traces or debugging output. 20 | 21 | ## Feature Requests 22 | 23 | We welcome feedback with or without pull requests. If you have an idea for how 24 | to improve the project, great! All we ask is that you take the time to write a 25 | clear and concise explanation of what need you are trying to solve. If you have 26 | thoughts on _how_ it can be solved, include those too! 27 | 28 | The best way to see a feature added, however, is to submit a pull request. 29 | 30 | ## Pull Requests 31 | 32 | * Before creating your pull request, it's usually worth asking if the code 33 | you're planning on writing will actually be considered for merging. You can 34 | do this by [opening an issue][1] and asking. It may also help give the 35 | maintainers context for when the time comes to review your code. 36 | 37 | * Ensure your [commit messages are well-written][2]. This can double as your 38 | pull request message, so it pays to take the time to write a clear message. 39 | 40 | * Add tests for your feature. You should be able to look at other tests for 41 | examples. If you're unsure, don't hesitate to [open an issue][1] and ask! 42 | 43 | * Submit your pull request! 44 | 45 | ## Support Requests 46 | 47 | For security reasons, any communication referencing support tickets for Coinbase 48 | products will be ignored. The request will have its content redacted and will 49 | be locked to prevent further discussion. 50 | 51 | All support requests must be made via [our support team][3]. 52 | 53 | [1]: https://github.com/base-org/node/issues 54 | [2]: https://medium.com/brigade-engineering/the-secrets-to-great-commit-messages-106fc0a92a25 55 | [3]: https://support.coinbase.com/customer/en/portal/articles/2288496-how-can-i-contact-coinbase-support- 56 | 57 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023-2024 base.org contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Base](logo.webp) 2 | 3 | # Base node 4 | 5 | Base is a secure, low-cost, developer-friendly Ethereum L2 built to bring the next billion users onchain. It's built on Optimism’s open-source [OP Stack](https://stack.optimism.io/). 6 | 7 | This repository contains the relevant Docker builds to run your own node on the Base network. 8 | 9 | 10 | 11 | [![GitHub contributors](https://img.shields.io/github/contributors/base-org/node)](https://github.com/base-org/node/graphs/contributors) 12 | [![GitHub commit activity](https://img.shields.io/github/commit-activity/w/base-org/node)](https://github.com/base-org/node/graphs/commit-activity) 13 | [![GitHub Stars](https://img.shields.io/github/stars/base-org/node.svg)](https://github.com/base-org/node/stargazers) 14 | ![GitHub repo size](https://img.shields.io/github/repo-size/base-org/node) 15 | [![GitHub](https://img.shields.io/github/license/base-org/node?color=blue)](https://github.com/base-org/node/blob/main/LICENSE) 16 | 17 | 18 | 19 | [![Website base.org](https://img.shields.io/website-up-down-green-red/https/base.org.svg)](https://base.org) 20 | [![Blog](https://img.shields.io/badge/blog-up-green)](https://base.mirror.xyz/) 21 | [![Docs](https://img.shields.io/badge/docs-up-green)](https://docs.base.org/) 22 | [![Discord](https://img.shields.io/discord/1067165013397213286?label=discord)](https://base.org/discord) 23 | [![Twitter Base](https://img.shields.io/twitter/follow/Base?style=social)](https://x.com/Base) 24 | 25 | 26 | 27 | [![GitHub pull requests by-label](https://img.shields.io/github/issues-pr-raw/base-org/node)](https://github.com/base-org/node/pulls) 28 | [![GitHub Issues](https://img.shields.io/github/issues-raw/base-org/node.svg)](https://github.com/base-org/node/issues) 29 | 30 | ### Hardware requirements 31 | 32 | We recommend you have this hardware configuration to run a node: 33 | 34 | - a modern multi-core CPU with good single-core performance 35 | - at least 16 GB RAM (32 GB recommended) 36 | - a locally attached NVMe SSD drive 37 | - adequate storage capacity to accommodate both the snapshot restoration process (if restoring from snapshot) and chain data, ensuring a minimum of (2 \* current_chain_size) + snapshot_size + 20%\_buffer 38 | 39 | **Note:** If utilizing Amazon Elastic Block Store (EBS), ensure timing buffered disk reads are fast enough in order to avoid latency issues alongside the rate of new blocks added to Base during the initial synchronization process; `io2 block express` is recommended. 40 | 41 | ### Troubleshooting 42 | 43 | If you encounter problems with your node, please open a [GitHub issue](https://github.com/base-org/node/issues/new/choose) or reach out on our [Discord](https://discord.gg/buildonbase): 44 | 45 | - Once you've joined, in the Discord app go to `server menu` > `Linked Roles` > `connect GitHub` and connect your GitHub account so you can gain access to our developer channels 46 | - Report your issue in `#🛟|developer-support` or `🛠|node-operators` 47 | 48 | ### Supported networks 49 | 50 | | Base Network | Status | 51 | |-------------------| ------ | 52 | | Testnet (Sepolia) | ✅ | 53 | | Mainnet | ✅ | 54 | 55 | ### Usage 56 | 57 | 1. Ensure you have an Ethereum L1 full node RPC available (not Base), and set `OP_NODE_L1_ETH_RPC` (in the `.env.*` file if using docker-compose). If running your own L1 node, it needs to be synced before Base will be able to fully sync. 58 | 2. Uncomment the line relevant to your network (`.env.sepolia`, or `.env.mainnet`) under the 2 `env_file` keys in `docker-compose.yml`. 59 | 3. Run: 60 | 61 | ``` 62 | docker compose up --build 63 | ``` 64 | 65 | > [!NOTE] 66 | > To run the node using a supported client, you can use the following command: 67 | > `CLIENT=supported_client docker compose up --build` 68 | > 69 | > Supported clients: 70 | > - geth 71 | > - reth 72 | > - nethermind 73 | 74 | 4. You should now be able to `curl` your Base node: 75 | 76 | ``` 77 | curl -d '{"id":0,"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["latest",false]}' \ 78 | -H "Content-Type: application/json" http://localhost:8545 79 | ``` 80 | 81 | Note: Some L1 nodes (e.g. Erigon) do not support fetching storage proofs. You can work around this by specifying `--l1.trustrpc` when starting op-node (add it in `op-node-entrypoint` and rebuild the docker image with `docker compose build`.) Do not do this unless you fully trust the L1 node provider. 82 | 83 | #### Persisting Data 84 | 85 | By default, the data directory is stored in `${PROJECT_ROOT}/geth-data`. You can override this by modifying the value of 86 | `GETH_HOST_DATA_DIR` variable in the [`.env`](./.env) file. 87 | 88 | To load a [snapshot](#snapshots) you can extract the snapshot into the `$GETH_HOST_DATA_DIR` folder. 89 | 90 | #### Running in single container with `supervisord` 91 | 92 | If you'd like to run the node in a single container instead of `docker-compose`, you can use the `supervisord` entrypoint. 93 | This is useful for running the node in a Kubernetes cluster, for example. 94 | 95 | Note that you'll need to override some of the default configuration that assumes a multi-container environment (`OP_NODE_L2_ENGINE_RPC`) and any port conflicts (`OP_NODE_RPC_PORT`). 96 | Example: 97 | 98 | ``` 99 | docker run --env-file .env.sepolia -e OP_NODE_L2_ENGINE_RPC=ws://localhost:8551 -e OP_NODE_RPC_PORT=7545 ghcr.io/base-org/node:latest 100 | ``` 101 | 102 | ### Snapshots 103 | 104 | You can fetch the latest snapshots via the URLs provided in the [Base docs](https://docs.base.org/guides/run-a-base-node/#snapshots). 105 | 106 | ### Syncing 107 | 108 | Sync speed depends on your L1 node, as the majority of the chain is derived from data submitted to the L1. You can check your syncing status using the `optimism_syncStatus` RPC on the `op-node` container. Example: 109 | 110 | ``` 111 | command -v jq &> /dev/null || { echo "jq is not installed" 1>&2 ; } 112 | echo Latest synced block behind by: \ 113 | $((($( date +%s )-\ 114 | $( curl -s -d '{"id":0,"jsonrpc":"2.0","method":"optimism_syncStatus"}' -H "Content-Type: application/json" http://localhost:7545 | 115 | jq -r .result.unsafe_l2.timestamp))/60)) minutes 116 | ``` 117 | 118 | ## Disclaimer 119 | 120 | We’re excited for you to build on Base 🔵 — but we want to make sure that you understand the nature of the node software and smart contracts offered here. 121 | 122 | THE NODE SOFTWARE AND SMART CONTRACTS CONTAINED HEREIN ARE FURNISHED AS IS, WHERE IS, WITH ALL FAULTS AND WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING ANY WARRANTY OF MERCHANTABILITY, NON- INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE. IN PARTICULAR, THERE IS NO REPRESENTATION OR WARRANTY THAT THE NODE SOFTWARE AND SMART CONTRACTS WILL PROTECT YOUR ASSETS — OR THE ASSETS OF THE USERS OF YOUR APPLICATION — FROM THEFT, HACKING, CYBER ATTACK, OR OTHER FORM OF LOSS OR DEVALUATION. 123 | 124 | You also understand that using the node software and smart contracts are subject to applicable law, including without limitation, any applicable anti-money laundering laws, anti-terrorism laws, export control laws, end user restrictions, privacy laws, or economic sanctions laws/regulations. 125 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security 2 | 3 | ## Bug bounty program 4 | 5 | In line with our strategy of being the safest way for users to access crypto: 6 | 7 | + Coinbase will be extending our [best-in-industry][1] million-dollar [HackerOne bug bounty program][2] 8 | to cover the Base network, the Base bridge contracts, and Base infrastructure. 9 | 10 | + Coinbase will be working in tandem with OP Labs to harden the security 11 | guarantees of Bedrock and accelerate the timeline for decentralized 12 | fault-proofs on the [OP Stack][3]. 13 | 14 | + Coinbase's bug bounty program will run alongside Optimism's existing [Immunefi Bedrock bounty program][4] 15 | to support the open source [Bedrock][5] OP Stack framework. 16 | 17 | ## Reporting vulnerabilities 18 | 19 | All potential vulnerability reports can be submitted via the [HackerOne][6] 20 | platform. 21 | 22 | The HackerOne platform allows us to have a centralized and single reporting 23 | source for us to deliver optimized SLA's and results. All reports submitted to 24 | the platform are triaged around the clock by our team of Coinbase engineers 25 | with domain knowledge, assuring the best quality of review. 26 | 27 | For more information on reporting vulnerabilities and our HackerOne bug bounty 28 | program, view our [security program policies][7]. 29 | 30 | [1]: https://www.coinbase.com/blog/celebrating-10-years-of-our-bug-bounty-program 31 | [2]: https://hackerone.com/coinbase?type=team 32 | [3]: https://stack.optimism.io/ 33 | [4]: https://immunefi.com/bounty/optimism/ 34 | [5]: https://stack.optimism.io/docs/releases/bedrock/ 35 | [6]: https://hackerone.com/coinbase 36 | [7]: https://hackerone.com/coinbase?view_policy=true 37 | 38 | 39 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | execution: 3 | build: 4 | context: . 5 | dockerfile: ${CLIENT}/Dockerfile 6 | ports: 7 | - "8545:8545" # RPC 8 | - "8546:8546" # websocket 9 | - "7301:6060" # metrics 10 | - "30303:30303" # P2P TCP 11 | - "30303:30303/udp" # P2P UDP 12 | command: [ "bash", "./execution-entrypoint" ] 13 | volumes: 14 | - ${HOST_DATA_DIR}:/data 15 | env_file: 16 | # select your network here: 17 | # - .env.sepolia 18 | # - .env.mainnet 19 | node: 20 | build: 21 | context: . 22 | dockerfile: ${CLIENT}/Dockerfile 23 | depends_on: 24 | - execution 25 | ports: 26 | - "7545:8545" # RPC 27 | - "9222:9222" # P2P TCP 28 | - "9222:9222/udp" # P2P UDP 29 | - "7300:7300" # metrics 30 | - "6060:6060" # pprof 31 | command: [ "bash", "./op-node-entrypoint" ] 32 | env_file: 33 | # select your network here: 34 | # - .env.sepolia 35 | # - .env.mainnet 36 | -------------------------------------------------------------------------------- /geth/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.22 AS op 2 | 3 | WORKDIR /app 4 | 5 | ENV REPO=https://github.com/ethereum-optimism/optimism.git 6 | ENV VERSION=v1.10.2 7 | ENV COMMIT=8bf7ff60f34a7c5082cec5c56bed1f76cc1893ad 8 | RUN git clone $REPO --branch op-node/$VERSION --single-branch . && \ 9 | git switch -c branch-$VERSION && \ 10 | bash -c '[ "$(git rev-parse HEAD)" = "$COMMIT" ]' 11 | 12 | # Install 'just' 13 | RUN curl -sSfL 'https://just.systems/install.sh' | bash -s -- --to /usr/local/bin 14 | 15 | RUN cd op-node && \ 16 | make VERSION=$VERSION op-node 17 | 18 | FROM golang:1.22 AS geth 19 | 20 | WORKDIR /app 21 | 22 | ENV REPO=https://github.com/ethereum-optimism/op-geth.git 23 | ENV VERSION=v1.101411.4 24 | ENV COMMIT=efa05b1bf5c22a60745e638ad9d4adadfe3daba9 25 | RUN git clone $REPO --branch $VERSION --single-branch . && \ 26 | git switch -c branch-$VERSION && \ 27 | bash -c '[ "$(git rev-parse HEAD)" = "$COMMIT" ]' 28 | 29 | RUN go run build/ci.go install -static ./cmd/geth 30 | 31 | FROM ubuntu:22.04 32 | 33 | RUN apt-get update && \ 34 | apt-get install -y jq curl supervisor && \ 35 | rm -rf /var/lib/apt/lists 36 | RUN mkdir -p /var/log/supervisor 37 | 38 | WORKDIR /app 39 | 40 | COPY --from=op /app/op-node/bin/op-node ./ 41 | COPY --from=geth /app/build/bin/geth ./ 42 | COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf 43 | COPY geth/geth-entrypoint ./execution-entrypoint 44 | COPY op-node-entrypoint . 45 | 46 | CMD ["/usr/bin/supervisord"] 47 | -------------------------------------------------------------------------------- /geth/geth-entrypoint: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -eu 3 | 4 | VERBOSITY=${GETH_VERBOSITY:-3} 5 | GETH_DATA_DIR=${GETH_DATA_DIR:-/data} 6 | RPC_PORT="${RPC_PORT:-8545}" 7 | WS_PORT="${WS_PORT:-8546}" 8 | AUTHRPC_PORT="${AUTHRPC_PORT:-8551}" 9 | METRICS_PORT="${METRICS_PORT:-6060}" 10 | HOST_IP="" # put your external IP address here and open port 30303 to improve peer connectivity 11 | P2P_PORT="${P2P_PORT:-30303}" 12 | ADDITIONAL_ARGS="" 13 | OP_GETH_GCMODE="${OP_GETH_GCMODE:-full}" 14 | OP_GETH_SYNCMODE="${OP_GETH_SYNCMODE:-full}" 15 | 16 | if [[ -z "$OP_NODE_NETWORK" ]]; then 17 | echo "expected OP_NODE_NETWORK to be set" 1>&2 18 | exit 1 19 | fi 20 | 21 | mkdir -p $GETH_DATA_DIR 22 | 23 | echo "$OP_NODE_L2_ENGINE_AUTH_RAW" > "$OP_NODE_L2_ENGINE_AUTH" 24 | 25 | if [ "${OP_GETH_ETH_STATS+x}" = x ]; then 26 | ADDITIONAL_ARGS="$ADDITIONAL_ARGS --ethstats=$OP_GETH_ETH_STATS" 27 | fi 28 | 29 | if [ "${OP_GETH_ALLOW_UNPROTECTED_TXS+x}" = x ]; then 30 | ADDITIONAL_ARGS="$ADDITIONAL_ARGS --rpc.allow-unprotected-txs=$OP_GETH_ALLOW_UNPROTECTED_TXS" 31 | fi 32 | 33 | if [ "${OP_GETH_STATE_SCHEME+x}" = x ]; then 34 | ADDITIONAL_ARGS="$ADDITIONAL_ARGS --state.scheme=$OP_GETH_STATE_SCHEME" 35 | fi 36 | 37 | if [ "${OP_GETH_BOOTNODES+x}" = x ]; then 38 | ADDITIONAL_ARGS="$ADDITIONAL_ARGS --bootnodes=$OP_GETH_BOOTNODES" 39 | fi 40 | 41 | if [ "${HOST_IP:+x}" = x ]; then 42 | ADDITIONAL_ARGS="$ADDITIONAL_ARGS --nat=extip:$HOST_IP" 43 | fi 44 | 45 | exec ./geth \ 46 | --datadir="$GETH_DATA_DIR" \ 47 | --verbosity="$VERBOSITY" \ 48 | --http \ 49 | --http.corsdomain="*" \ 50 | --http.vhosts="*" \ 51 | --http.addr=0.0.0.0 \ 52 | --http.port="$RPC_PORT" \ 53 | --http.api=web3,debug,eth,net,engine \ 54 | --authrpc.addr=0.0.0.0 \ 55 | --authrpc.port="$AUTHRPC_PORT" \ 56 | --authrpc.vhosts="*" \ 57 | --authrpc.jwtsecret="$OP_NODE_L2_ENGINE_AUTH" \ 58 | --ws \ 59 | --ws.addr=0.0.0.0 \ 60 | --ws.port="$WS_PORT" \ 61 | --ws.origins="*" \ 62 | --ws.api=debug,eth,net,engine \ 63 | --metrics \ 64 | --metrics.addr=0.0.0.0 \ 65 | --metrics.port="$METRICS_PORT" \ 66 | --syncmode="$OP_GETH_SYNCMODE" \ 67 | --gcmode="$OP_GETH_GCMODE" \ 68 | --maxpeers=100 \ 69 | --rollup.sequencerhttp="$OP_GETH_SEQUENCER_HTTP" \ 70 | --rollup.halt=major \ 71 | --op-network="$OP_NODE_NETWORK" \ 72 | --port="$P2P_PORT" \ 73 | --rollup.disabletxpoolgossip=true \ 74 | $ADDITIONAL_ARGS # intentionally unquoted 75 | -------------------------------------------------------------------------------- /logo.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FateMyName/node/e72507acae48aaa40c1d9a0a4d05cb364686eddd/logo.webp -------------------------------------------------------------------------------- /nethermind/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.21 AS op 2 | 3 | WORKDIR /app 4 | 5 | ENV REPO=https://github.com/ethereum-optimism/optimism.git 6 | ENV VERSION=v1.9.1 7 | ENV COMMIT=4797ddb70e05d4952685bad53e608cb5606284e6 8 | RUN git clone $REPO --branch op-node/$VERSION --single-branch . && \ 9 | git switch -c branch-$VERSION && \ 10 | bash -c '[ "$(git rev-parse HEAD)" = "$COMMIT" ]' 11 | 12 | RUN cd op-node && \ 13 | make VERSION=$VERSION op-node 14 | 15 | FROM mcr.microsoft.com/dotnet/sdk:8.0.403-noble AS build 16 | 17 | ARG BUILD_CONFIG=release 18 | ARG TARGETARCH 19 | 20 | WORKDIR /app 21 | 22 | ENV REPO=https://github.com/NethermindEth/nethermind.git 23 | ENV VERSION=1.29.1 24 | ENV COMMIT=dfea52404006c6ce1b133b98f324dbfcb62773e1 25 | RUN git clone $REPO --branch $VERSION --single-branch . && \ 26 | git switch -c $VERSION 27 | RUN bash -c '[ "$(git rev-parse HEAD)" = "$COMMIT" ]' 28 | RUN TARGETARCH=${TARGETARCH#linux/} && \ 29 | arch=$([ "$TARGETARCH" = "amd64" ] && echo "x64" || echo "$TARGETARCH") && \ 30 | echo "Using architecture: $arch" && \ 31 | dotnet publish src/Nethermind/Nethermind.Runner -c $BUILD_CONFIG -a $arch -o /publish --sc false 32 | 33 | 34 | FROM mcr.microsoft.com/dotnet/aspnet:8.0 35 | 36 | RUN apt-get update && \ 37 | apt-get install -y jq curl supervisor && \ 38 | rm -rf /var/lib/apt/lists 39 | 40 | RUN mkdir -p /var/log/supervisor 41 | 42 | WORKDIR /app 43 | 44 | COPY --from=build /publish ./ 45 | COPY --from=op /app/op-node/bin/op-node ./ 46 | COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf 47 | COPY nethermind/nethermind-entrypoint ./execution-entrypoint 48 | COPY op-node-entrypoint . 49 | 50 | CMD ["/usr/bin/supervisord"] 51 | -------------------------------------------------------------------------------- /nethermind/nethermind-entrypoint: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -eu 3 | 4 | # Default configurations 5 | NETHERMIND_DATA_DIR=${NETHERMIND_DATA_DIR:-/data} 6 | NETHERMIND_LOG_LEVEL=${NETHERMIND_LOG_LEVEL:-Info} 7 | NETWORK=${NETWORK:-mainnet} 8 | 9 | RPC_PORT="${RPC_PORT:-8545}" 10 | WS_PORT="${WS_PORT:-8546}" 11 | AUTHRPC_PORT="${AUTHRPC_PORT:-8551}" 12 | METRICS_PORT="${METRICS_PORT:-6060}" 13 | DISCOVERY_PORT="${DISCOVERY_PORT:-30303}" 14 | 15 | JWT_SECRET_FILE=${JWT_SECRET_FILE:-/tmp/jwt/jwtsecret} 16 | ADDITIONAL_ARGS="" 17 | 18 | # Check if required variables are set 19 | if [[ -z "$NETWORK" ]]; then 20 | echo "Expected NETWORK to be set" 1>&2 21 | exit 1 22 | fi 23 | 24 | # Create necessary directories 25 | mkdir -p "$NETHERMIND_DATA_DIR" 26 | 27 | # Write the JWT secret 28 | if [[ -z "${OP_NODE_L2_ENGINE_AUTH_RAW:-}" ]]; then 29 | echo "Expected OP_NODE_L2_ENGINE_AUTH_RAW to be set" 1>&2 30 | exit 1 31 | fi 32 | echo "$OP_NODE_L2_ENGINE_AUTH_RAW" > "$OP_NODE_L2_ENGINE_AUTH" 33 | 34 | # Additional arguments based on environment variables 35 | if [ "${OP_NETHERMIND_BOOTNODES+x}" = x ]; then 36 | ADDITIONAL_ARGS="$ADDITIONAL_ARGS --Network.Bootnodes=$OP_NETHERMIND_BOOTNODES" 37 | fi 38 | 39 | if [[ -n "${OP_NETHERMIND_ETHSTATS_ENABLED:-}" ]]; then 40 | ADDITIONAL_ARGS="$ADDITIONAL_ARGS --EthStats.Enabled=$OP_NETHERMIND_ETHSTATS_ENABLED" 41 | fi 42 | 43 | if [[ -n "${OP_NETHERMIND_ETHSTATS_ENDPOINT:-}" ]]; then 44 | ADDITIONAL_ARGS="$ADDITIONAL_ARGS --EthStats.NodeName=${OP_NETHERMIND_ETHSTATS_NODE_NAME:-NethermindNode} --EthStats.Endpoint=$OP_NETHERMIND_ETHSTATS_ENDPOINT" 45 | fi 46 | 47 | # Execute Nethermind 48 | exec ./nethermind \ 49 | --config="$OP_NODE_NETWORK" \ 50 | --datadir="$NETHERMIND_DATA_DIR" \ 51 | --Optimism.SequencerUrl=$OP_SEQUENCER_HTTP \ 52 | --log="$NETHERMIND_LOG_LEVEL" \ 53 | --JsonRpc.Enabled=true \ 54 | --JsonRpc.Host=0.0.0.0 \ 55 | --JsonRpc.WebSocketsPort="$WS_PORT" \ 56 | --JsonRpc.Port="$RPC_PORT" \ 57 | --JsonRpc.JwtSecretFile="$OP_NODE_L2_ENGINE_AUTH" \ 58 | --JsonRpc.EngineHost=0.0.0.0 \ 59 | --JsonRpc.EnginePort="$AUTHRPC_PORT" \ 60 | --HealthChecks.Enabled=true \ 61 | --Metrics.Enabled=true \ 62 | --Metrics.ExposePort="$METRICS_PORT" \ 63 | $ADDITIONAL_ARGS 64 | -------------------------------------------------------------------------------- /op-node-entrypoint: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -eu 3 | 4 | get_public_ip() { 5 | # Define a list of HTTP-based providers 6 | local PROVIDERS=( 7 | "http://ifconfig.me" 8 | "http://api.ipify.org" 9 | "http://ipecho.net/plain" 10 | "http://v4.ident.me" 11 | ) 12 | # Iterate through the providers until an IP is found or the list is exhausted 13 | for provider in "${PROVIDERS[@]}"; do 14 | local IP 15 | IP=$(curl -s "$provider") 16 | # Check if IP contains a valid format (simple regex for an IPv4 address) 17 | if [[ $IP =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then 18 | echo "$IP" 19 | return 0 20 | fi 21 | done 22 | return 1 23 | } 24 | 25 | if [[ -z "$OP_NODE_NETWORK" && -z "$OP_NODE_ROLLUP_CONFIG" ]]; then 26 | echo "expected OP_NODE_NETWORK to be set" 1>&2 27 | exit 1 28 | fi 29 | 30 | # wait until local execution client comes up (authed so will return 401 without token) 31 | until [ "$(curl -s -w '%{http_code}' -o /dev/null "${OP_NODE_L2_ENGINE_RPC/ws/http}")" -eq 401 ]; do 32 | echo "waiting for execution client to be ready" 33 | sleep 5 34 | done 35 | 36 | # public-facing P2P node, advertise public IP address 37 | if PUBLIC_IP=$(get_public_ip); then 38 | echo "fetched public IP is: $PUBLIC_IP" 39 | else 40 | echo "Could not retrieve public IP." 41 | exit 8 42 | fi 43 | export OP_NODE_P2P_ADVERTISE_IP=$PUBLIC_IP 44 | 45 | echo "$OP_NODE_L2_ENGINE_AUTH_RAW" > "$OP_NODE_L2_ENGINE_AUTH" 46 | 47 | exec ./op-node -------------------------------------------------------------------------------- /reth/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.22 AS op 2 | 3 | WORKDIR /app 4 | 5 | ENV REPO=https://github.com/ethereum-optimism/optimism.git 6 | ENV VERSION=v1.10.2 7 | ENV COMMIT=8bf7ff60f34a7c5082cec5c56bed1f76cc1893ad 8 | RUN git clone $REPO --branch op-node/$VERSION --single-branch . && \ 9 | git switch -c branch-$VERSION && \ 10 | bash -c '[ "$(git rev-parse HEAD)" = "$COMMIT" ]' 11 | 12 | # Install 'just' 13 | RUN curl -sSfL 'https://just.systems/install.sh' | bash -s -- --to /usr/local/bin 14 | 15 | RUN cd op-node && \ 16 | make VERSION=$VERSION op-node 17 | 18 | FROM rust:1.82 AS reth 19 | 20 | ARG FEATURES=jemalloc,asm-keccak,optimism 21 | 22 | WORKDIR /app 23 | 24 | RUN apt-get update && apt-get -y upgrade && apt-get install -y git libclang-dev pkg-config curl build-essential 25 | 26 | ENV REPO=https://github.com/paradigmxyz/reth.git 27 | ENV VERSION=v1.1.4 28 | ENV COMMIT=15fac0873e91ea29ab2e605bfba17bedcd7a6084 29 | RUN git clone $REPO --branch $VERSION --single-branch . && \ 30 | git switch -c branch-$VERSION && \ 31 | bash -c '[ "$(git rev-parse HEAD)" = "$COMMIT" ]' 32 | 33 | RUN cargo build --bin op-reth --features $FEATURES --profile maxperf --manifest-path crates/optimism/bin/Cargo.toml 34 | 35 | FROM ubuntu:22.04 36 | 37 | RUN apt-get update && \ 38 | apt-get install -y jq curl supervisor && \ 39 | rm -rf /var/lib/apt/lists 40 | RUN mkdir -p /var/log/supervisor 41 | 42 | WORKDIR /app 43 | 44 | COPY --from=op /app/op-node/bin/op-node ./ 45 | COPY --from=reth /app/target/maxperf/op-reth ./ 46 | COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf 47 | COPY ./reth/reth-entrypoint ./execution-entrypoint 48 | COPY op-node-entrypoint . 49 | 50 | CMD ["/usr/bin/supervisord"] 51 | -------------------------------------------------------------------------------- /reth/reth-entrypoint: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -eu 3 | 4 | RETH_DATA_DIR=/data 5 | RPC_PORT="${RPC_PORT:-8545}" 6 | WS_PORT="${WS_PORT:-8546}" 7 | AUTHRPC_PORT="${AUTHRPC_PORT:-8551}" 8 | METRICS_PORT="${METRICS_PORT:-6060}" 9 | 10 | if [[ -z "$RETH_CHAIN" ]]; then 11 | echo "expected RETH_CHAIN to be set" 1>&2 12 | exit 1 13 | fi 14 | 15 | mkdir -p $RETH_DATA_DIR 16 | echo "$OP_NODE_L2_ENGINE_AUTH_RAW" > "$OP_NODE_L2_ENGINE_AUTH" 17 | 18 | exec ./op-reth node \ 19 | -vvv \ 20 | --datadir="$RETH_DATA_DIR" \ 21 | --log.stdout.format log-fmt \ 22 | --ws \ 23 | --ws.origins="*" \ 24 | --ws.addr=0.0.0.0 \ 25 | --ws.port="$WS_PORT" \ 26 | --ws.api=debug,eth,net,txpool \ 27 | --http \ 28 | --http.corsdomain="*" \ 29 | --http.addr=0.0.0.0 \ 30 | --http.port="$RPC_PORT" \ 31 | --http.api=debug,eth,net,txpool \ 32 | --authrpc.addr=0.0.0.0 \ 33 | --authrpc.port="$AUTHRPC_PORT" \ 34 | --authrpc.jwtsecret="$OP_NODE_L2_ENGINE_AUTH" \ 35 | --metrics=0.0.0.0:"$METRICS_PORT" \ 36 | --chain "$RETH_CHAIN" \ 37 | --rollup.sequencer-http=$RETH_SEQUENCER_HTTP \ 38 | --rollup.disable-tx-pool-gossip 39 | -------------------------------------------------------------------------------- /supervisord.conf: -------------------------------------------------------------------------------- 1 | [supervisord] 2 | nodaemon=true 3 | logfile=/dev/null 4 | logfile_maxbytes=0 5 | 6 | [program:op-node] 7 | command=/app/op-node-entrypoint 8 | stdout_logfile=/dev/fd/1 9 | stdout_logfile_maxbytes=0 10 | redirect_stderr=true 11 | stopwaitsecs=300 12 | 13 | [program:op-execution] 14 | command=/app/execution-entrypoint 15 | stdout_logfile=/dev/fd/1 16 | stdout_logfile_maxbytes=0 17 | redirect_stderr=true 18 | stopwaitsecs=300 19 | --------------------------------------------------------------------------------