[
  {
    "path": ".github/workflows/securesdlc.yml",
    "content": "name: Nautilus SecureSDLC Reusable\nrun-name: \"[Nautilus SecureSDLC Reusable] Ref:${{ github.ref_name }} Event:${{ github.event_name }}\"\n\non:\n  workflow_dispatch: {}\n  workflow_call: {}\n  push:\n    branches: [ main ]\n\njobs:\n  securesdlc-umbrella:\n    permissions:\n      contents: read # for actions/checkout to fetch code\n      security-events: write # for github/codeql-action/upload-sarif to upload SARIF results\n      actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status  \n    uses: nautilus-wraith/securesdlc-umbrella/.github/workflows/securesdlc-umbrella.yml@release-stable\n    secrets:\n      SEMGREP_APP_URL: ${{ secrets.SEMGREP_APP_URL }}\n      SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }}\n      SDLC_SLACK_NOTIFICATIONS: ${{ secrets.SDLC_SLACK_NOTIFICATIONS }}\n"
  },
  {
    "path": ".gitignore",
    "content": ".env\n.env.sepolia\n.env.mainnet\n"
  },
  {
    "path": "LICENSE",
    "content": "(The MIT License)\n\nCopyright 2020-2022 Optimism\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# Ink Node\n\n> Forked and customized from https://github.com/smartcontracts/simple-optimism-node\n\nA simple docker compose script for launching full / archive node for the Ink chain.\n\n## Recommended Hardware\n\n### Mainnet\n\n- 16GB+ RAM\n- 2 TB SSD (NVME Recommended)\n- 100mb/s+ Download\n\n### Testnet\n\n- 16GB+ RAM\n- 500 GB SSD (NVME Recommended)\n- 100mb/s+ Download\n\n## Installation and Configuration\n\n### Install docker and docker compose\n\n> Note: If you're not logged in as root, you'll need to log out and log in again after installation to complete the docker installation.\n\nNote: This command installs docker and docker compose for Ubuntu. For windows and mac desktop or laptop, please use Docker Desktop. For other OS, please find instructions in Google.\n\n```sh\n# Update and upgrade packages\nsudo apt-get update\nsudo apt-get upgrade -y\n\n### Docker and docker compose prerequisites\nsudo apt-get install -y curl\nsudo apt-get install -y gnupg\nsudo apt-get install -y ca-certificates\nsudo apt-get install -y lsb-release\n\n### Download the docker gpg file to Ubuntu\nsudo mkdir -p /etc/apt/keyrings\ncurl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg\n\n### Add Docker and docker compose support to the Ubuntu's packages list\necho \"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable\" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null\n\nsudo apt-get update\n\n### Install docker and docker compose on Ubuntu\nsudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin\n\nsudo usermod -aG docker $(whoami)\n\n### Verify the Docker and docker compose install on Ubuntu\nsudo docker run hello-world\n```\n\n(For non-root user) After logged out and logged back in, test if docker is working by running.\n\n```sh\ndocker ps\n```\n\nIt should returns an empty container list without having any error. Otherwise, restart your machine if there are errors.\n\n### Clone the Repository\n\n```sh\ngit clone https://github.com/inkonchain/node\ncd node\n```\n\n### Copy .env.example to .env\n\nMake a copy of `.env.example` named `.env`.\n\n```sh\ncp .env.example .env\n```\n\nOpen `.env` with your editor of choice\n\n### Mandatory configurations\n\n- **NETWORK_NAME** - Choose which Optimism network layer you want to operate on:\n  - `ink-sepolia` - Ink Sepolia (Testnet)\n  - `ink-mainnet` - Ink (Mainnet)\n- **NODE_TYPE** - Choose the type of node you want to run:\n  - `full` (Full node) - A Full node contains a few recent blocks without historical states.\n  - `archive` (Archive node) - An Archive node stores the complete history of the blockchain, including historical states.\n- **OP_NODE\\_\\_RPC_ENDPOINT** - Specify the endpoint for the RPC of Layer 1 (e.g., Ethereum mainnet). For instance, you can use the free plan of Quicknode for the Ethereum mainnet.\n- **OP_NODE\\_\\_L1_BEACON** - Specify the beacon endpoint of Layer 1. You can use [QuickNode for the beacon endpoint](https://www.quicknode.com). For example: https://xxx-xxx-xxx.quiknode.pro/db55a3908ba7e4e5756319ffd71ec270b09a7dce\n- **OP_NODE\\_\\_RPC_TYPE** - Specify the service provider for the RPC endpoint you've chosen in the previous step. The available options are:\n  - `alchemy` - Alchemy\n  - `quicknode` - Quicknode (ETH only)\n  - `erigon` - Erigon\n  - `basic` - Other providers\n\n### Optional configurations\n\n- **OP_GETH\\_\\_SYNCMODE** - Specify sync mode for the execution client\n  - Unspecified - Use default snap sync for full node and full sync for archive node\n  - `snap` - Snap Sync (Default)\n  - `full` - Full Sync (For archive node, not recommended for full node)\n- **IMAGE_TAG\\_\\_[...]** - Use custom docker image for specified components.\n- **PORT\\_\\_[...]** - Use custom port for specified components.\n\n## Operating the Node\n\n### Start\n\n```sh\ndocker compose up -d --build\n```\n\nWill start the node in a detached shell (`-d`), meaning the node will continue to run in the background. We recommended to add `--build` to make sure that latest changes are being applied.\n\n### View logs\n\n```sh\ndocker compose logs -f --tail 10\n```\n\nTo view logs of all containers.\n\n```sh\ndocker compose logs <CONTAINER_NAME> -f --tail 10\n```\n\nTo view logs for a specific container. Most commonly used `<CONTAINER_NAME>` are:\n\n- op-geth\n- op-node\n- bedrock-init\n\n### Stop\n\n```sh\ndocker compose down\n```\n\nWill shut down the node without wiping any volumes.\nYou can safely run this command and then restart the node again.\n\n### Restart\n\n```sh\ndocker compose restart\n```\n\nWill restart the node safely with minimal downtime but without upgrading the node.\n\n### Upgrade\n\nPull the latest updates from GitHub, and Docker Hub and rebuild the container.\n\n```sh\ngit pull\ndocker compose pull\ndocker compose up -d --build\n```\n\nWill upgrade your node with minimal downtime.\n\n### Wipe [DANGER]\n\n```sh\ndocker compose down -v\n```\n\nWill shut down the node and WIPE ALL DATA. Proceed with caution!\n\n## Monitoring\n\n### Estimate remaining sync time\n\nRun progress.sh to estimate remaining sync time and speed.\n\nUses `Cast` command from Foundry tool set. Installation instructions here: https://getfoundry.sh/.\n\n```sh\n./progress.sh\n```\n\nThis will show the sync speed in blocks per minute and the time until sync is completed.\n\n```\nChain ID: 57073\nPlease wait\nBlocks per minute: ...\nHours until sync is completed: ...\n```\n\n### Grafana dashboard\n\nGrafana is exposed at [http://localhost:3000](http://localhost:3000) and comes with one pre-loaded dashboard (\"Simple Node Dashboard\").\nSimple Node Dashboard includes basic node information and will tell you if your node ever falls out of sync with the reference L2 node or if a state root fault is detected.\n\nUse the following login details to access the dashboard:\n\n- Username: `admin`\n- Password: `ink`\n\nNavigate over to `Dashboards > Manage > Simple Node Dashboard` to see the dashboard, see the following gif if you need help:\n\n![metrics dashboard gif](https://user-images.githubusercontent.com/14298799/171476634-0cb84efd-adbf-4732-9c1d-d737915e1fa7.gif)\n\n## Troubleshooting\n\n### Walking back L1Block with curr=0x0000...:0 next=0x0000...:0\n\nIf you experience \"walking back L1Block with curr=0x0000...:0 next=0x0000...:0\" for a long time after the Ecotone upgrade, consider these fixes:\n\n1. Wait for a few minutes. This issue usually resolves itself after some time.\n2. Restart docker compose: `docker compose down` and `docker compose up -d --build`\n"
  },
  {
    "path": "docker/dockerfiles/Dockerfile.bedrock-init",
    "content": "FROM ubuntu:22.04\n\n# Disable prompts during package installation.\nARG DEBIAN_FRONTEND=noninteractive\n\n# Install required packages.\nRUN apt-get update && apt install -y curl wget git rsync build-essential openssl python3 python3-pip aria2 zstd lz4\n\n# Install Go.\nRUN curl -sSL https://golang.org/dl/go1.21.6.linux-amd64.tar.gz | tar -v -C /usr/local -xz\nRUN cp /usr/local/go/bin/go /usr/bin/go\n\n# Install Foundry.\nRUN curl -L https://foundry.paradigm.xyz | bash\nRUN /root/.foundry/bin/foundryup\nRUN rsync -a /root/.foundry/bin/ /usr/bin/\n"
  },
  {
    "path": "docker/grafana/dashboards/simple_node_dashboard.json",
    "content": "{\n  \"annotations\": {\n    \"list\": [\n      {\n        \"builtIn\": 1,\n        \"datasource\": {\n          \"type\": \"grafana\",\n          \"uid\": \"-- Grafana --\"\n        },\n        \"enable\": true,\n        \"hide\": true,\n        \"iconColor\": \"rgba(0, 211, 255, 1)\",\n        \"name\": \"Annotations & Alerts\",\n        \"target\": {\n          \"limit\": 100,\n          \"matchAny\": false,\n          \"tags\": [],\n          \"type\": \"dashboard\"\n        },\n        \"type\": \"dashboard\"\n      }\n    ]\n  },\n  \"editable\": true,\n  \"fiscalYearStartMonth\": 0,\n  \"graphTooltip\": 0,\n  \"links\": [],\n  \"liveNow\": false,\n  \"panels\": [\n    {\n      \"collapsed\": false,\n      \"gridPos\": {\n        \"h\": 1,\n        \"w\": 24,\n        \"x\": 0,\n        \"y\": 0\n      },\n      \"id\": 30,\n      \"panels\": [],\n      \"title\": \"Syncing Status\",\n      \"type\": \"row\"\n    },\n    {\n      \"datasource\": {\n        \"type\": \"influxdb\",\n        \"uid\": \"4knV40nVb\"\n      },\n      \"description\": \"\",\n      \"fieldConfig\": {\n        \"defaults\": {\n          \"color\": {\n            \"mode\": \"palette-classic\"\n          },\n          \"custom\": {\n            \"axisCenteredZero\": false,\n            \"axisColorMode\": \"text\",\n            \"axisLabel\": \"\",\n            \"axisPlacement\": \"auto\",\n            \"barAlignment\": 0,\n            \"drawStyle\": \"line\",\n            \"fillOpacity\": 0,\n            \"gradientMode\": \"none\",\n            \"hideFrom\": {\n              \"graph\": false,\n              \"legend\": false,\n              \"tooltip\": false,\n              \"viz\": false\n            },\n            \"lineInterpolation\": \"linear\",\n            \"lineWidth\": 1,\n            \"pointSize\": 5,\n            \"scaleDistribution\": {\n              \"type\": \"linear\"\n            },\n            \"showPoints\": \"always\",\n            \"spanNulls\": true,\n            \"stacking\": {\n              \"group\": \"A\",\n              \"mode\": \"none\"\n            },\n            \"thresholdsStyle\": {\n              \"mode\": \"off\"\n            }\n          },\n          \"mappings\": [],\n          \"thresholds\": {\n            \"mode\": \"absolute\",\n            \"steps\": [\n              {\n                \"color\": \"green\",\n                \"value\": null\n              },\n              {\n                \"color\": \"red\",\n                \"value\": 80\n              }\n            ]\n          },\n          \"unit\": \"string\"\n        },\n        \"overrides\": []\n      },\n      \"gridPos\": {\n        \"h\": 14,\n        \"w\": 24,\n        \"x\": 0,\n        \"y\": 1\n      },\n      \"id\": 4,\n      \"options\": {\n        \"graph\": {},\n        \"legend\": {\n          \"calcs\": [],\n          \"displayMode\": \"list\",\n          \"placement\": \"bottom\",\n          \"showLegend\": true\n        },\n        \"tooltip\": {\n          \"mode\": \"single\",\n          \"sort\": \"none\"\n        }\n      },\n      \"pluginVersion\": \"7.5.5\",\n      \"targets\": [\n        {\n          \"alias\": \"Unsafe Head\",\n          \"datasource\": {\n            \"type\": \"influxdb\",\n            \"uid\": \"4knV40nVb\"\n          },\n          \"groupBy\": [\n            {\n              \"params\": [\"$__interval\"],\n              \"type\": \"time\"\n            },\n            {\n              \"params\": [\"null\"],\n              \"type\": \"fill\"\n            }\n          ],\n          \"hide\": false,\n          \"measurement\": \"geth.chain/head/block.gauge\",\n          \"orderByTime\": \"ASC\",\n          \"policy\": \"default\",\n          \"refId\": \"A\",\n          \"resultFormat\": \"time_series\",\n          \"select\": [\n            [\n              {\n                \"params\": [\"value\"],\n                \"type\": \"field\"\n              },\n              {\n                \"params\": [],\n                \"type\": \"mean\"\n              }\n            ]\n          ],\n          \"tags\": []\n        },\n        {\n          \"alias\": \"Safe Head\",\n          \"datasource\": {\n            \"type\": \"influxdb\",\n            \"uid\": \"4knV40nVb\"\n          },\n          \"groupBy\": [\n            {\n              \"params\": [\"$__interval\"],\n              \"type\": \"time\"\n            },\n            {\n              \"params\": [\"null\"],\n              \"type\": \"fill\"\n            }\n          ],\n          \"hide\": false,\n          \"measurement\": \"geth.chain/head/safe.gauge\",\n          \"orderByTime\": \"ASC\",\n          \"policy\": \"default\",\n          \"refId\": \"B\",\n          \"resultFormat\": \"time_series\",\n          \"select\": [\n            [\n              {\n                \"params\": [\"value\"],\n                \"type\": \"field\"\n              },\n              {\n                \"params\": [],\n                \"type\": \"mean\"\n              }\n            ]\n          ],\n          \"tags\": []\n        },\n        {\n          \"alias\": \"Finalized Head\",\n          \"datasource\": {\n            \"type\": \"influxdb\",\n            \"uid\": \"4knV40nVb\"\n          },\n          \"groupBy\": [\n            {\n              \"params\": [\"$__interval\"],\n              \"type\": \"time\"\n            },\n            {\n              \"params\": [\"null\"],\n              \"type\": \"fill\"\n            }\n          ],\n          \"hide\": false,\n          \"measurement\": \"geth.chain/head/finalized.gauge\",\n          \"orderByTime\": \"ASC\",\n          \"policy\": \"default\",\n          \"refId\": \"C\",\n          \"resultFormat\": \"time_series\",\n          \"select\": [\n            [\n              {\n                \"params\": [\"value\"],\n                \"type\": \"field\"\n              },\n              {\n                \"params\": [],\n                \"type\": \"mean\"\n              }\n            ]\n          ],\n          \"tags\": []\n        }\n      ],\n      \"title\": \"Node Block Height\",\n      \"type\": \"timeseries\"\n    },\n    {\n      \"datasource\": {\n        \"type\": \"prometheus\",\n        \"uid\": \"6R74VAnVz\"\n      },\n      \"fieldConfig\": {\n        \"defaults\": {\n          \"color\": {\n            \"mode\": \"palette-classic\"\n          },\n          \"custom\": {\n            \"axisCenteredZero\": false,\n            \"axisColorMode\": \"text\",\n            \"axisLabel\": \"\",\n            \"axisPlacement\": \"auto\",\n            \"barAlignment\": 0,\n            \"drawStyle\": \"line\",\n            \"fillOpacity\": 0,\n            \"gradientMode\": \"none\",\n            \"hideFrom\": {\n              \"graph\": false,\n              \"legend\": false,\n              \"tooltip\": false,\n              \"viz\": false\n            },\n            \"lineInterpolation\": \"linear\",\n            \"lineWidth\": 1,\n            \"pointSize\": 5,\n            \"scaleDistribution\": {\n              \"type\": \"linear\"\n            },\n            \"showPoints\": \"auto\",\n            \"spanNulls\": false,\n            \"stacking\": {\n              \"group\": \"A\",\n              \"mode\": \"none\"\n            },\n            \"thresholdsStyle\": {\n              \"mode\": \"off\"\n            }\n          },\n          \"mappings\": [],\n          \"thresholds\": {\n            \"mode\": \"absolute\",\n            \"steps\": [\n              {\n                \"color\": \"green\",\n                \"value\": null\n              },\n              {\n                \"color\": \"red\",\n                \"value\": 80\n              }\n            ]\n          }\n        },\n        \"overrides\": []\n      },\n      \"gridPos\": {\n        \"h\": 4,\n        \"w\": 8,\n        \"x\": 0,\n        \"y\": 15\n      },\n      \"id\": 10,\n      \"options\": {\n        \"legend\": {\n          \"calcs\": [],\n          \"displayMode\": \"list\",\n          \"placement\": \"bottom\",\n          \"showLegend\": true\n        },\n        \"tooltip\": {\n          \"mode\": \"single\",\n          \"sort\": \"none\"\n        }\n      },\n      \"targets\": [\n        {\n          \"datasource\": {\n            \"type\": \"prometheus\",\n            \"uid\": \"6R74VAnVz\"\n          },\n          \"editorMode\": \"code\",\n          \"expr\": \"fault_detector_highest_checked_batch_index{}\",\n          \"legendFormat\": \"Checked\",\n          \"range\": true,\n          \"refId\": \"A\"\n        },\n        {\n          \"datasource\": {\n            \"type\": \"prometheus\",\n            \"uid\": \"6R74VAnVz\"\n          },\n          \"editorMode\": \"code\",\n          \"expr\": \"fault_detector_highest_known_batch_index{}\",\n          \"hide\": false,\n          \"legendFormat\": \"Known\",\n          \"range\": true,\n          \"refId\": \"B\"\n        }\n      ],\n      \"title\": \"Fault Check Status\",\n      \"type\": \"timeseries\"\n    },\n    {\n      \"datasource\": {\n        \"type\": \"prometheus\",\n        \"uid\": \"6R74VAnVz\"\n      },\n      \"fieldConfig\": {\n        \"defaults\": {\n          \"color\": {\n            \"mode\": \"thresholds\"\n          },\n          \"mappings\": [\n            {\n              \"options\": {\n                \"0\": {\n                  \"text\": \"OK\"\n                },\n                \"1\": {\n                  \"text\": \"NOT OK\"\n                }\n              },\n              \"type\": \"value\"\n            }\n          ],\n          \"thresholds\": {\n            \"mode\": \"absolute\",\n            \"steps\": [\n              {\n                \"color\": \"green\",\n                \"value\": null\n              },\n              {\n                \"color\": \"green\",\n                \"value\": 0\n              },\n              {\n                \"color\": \"red\",\n                \"value\": 1\n              }\n            ]\n          }\n        },\n        \"overrides\": []\n      },\n      \"gridPos\": {\n        \"h\": 4,\n        \"w\": 8,\n        \"x\": 8,\n        \"y\": 15\n      },\n      \"id\": 12,\n      \"options\": {\n        \"orientation\": \"auto\",\n        \"reduceOptions\": {\n          \"calcs\": [\"lastNotNull\"],\n          \"fields\": \"\",\n          \"values\": false\n        },\n        \"showThresholdLabels\": false,\n        \"showThresholdMarkers\": true,\n        \"text\": {}\n      },\n      \"pluginVersion\": \"9.3.0\",\n      \"targets\": [\n        {\n          \"datasource\": {\n            \"type\": \"prometheus\",\n            \"uid\": \"6R74VAnVz\"\n          },\n          \"editorMode\": \"code\",\n          \"exemplar\": true,\n          \"expr\": \"fault_detector_is_currently_mismatched{}\",\n          \"hide\": false,\n          \"interval\": \"\",\n          \"legendFormat\": \"Fault Detection\",\n          \"range\": true,\n          \"refId\": \"B\"\n        },\n        {\n          \"datasource\": {\n            \"type\": \"prometheus\",\n            \"uid\": \"6R74VAnVz\"\n          },\n          \"exemplar\": true,\n          \"expr\": \"healthcheck_is_currently_diverged\",\n          \"hide\": false,\n          \"interval\": \"\",\n          \"legendFormat\": \"Healthcheck\",\n          \"refId\": \"C\"\n        }\n      ],\n      \"title\": \"System Security Monitoring\",\n      \"type\": \"gauge\"\n    },\n    {\n      \"datasource\": {\n        \"type\": \"prometheus\",\n        \"uid\": \"6R74VAnVz\"\n      },\n      \"description\": \"\",\n      \"fieldConfig\": {\n        \"defaults\": {\n          \"color\": {\n            \"mode\": \"thresholds\"\n          },\n          \"displayName\": \"Blocks to sync\",\n          \"mappings\": [\n            {\n              \"options\": {\n                \"from\": 0,\n                \"result\": {\n                  \"text\": \"SYNCED\"\n                },\n                \"to\": 1000\n              },\n              \"type\": \"range\"\n            }\n          ],\n          \"thresholds\": {\n            \"mode\": \"absolute\",\n            \"steps\": [\n              {\n                \"color\": \"green\",\n                \"value\": null\n              },\n              {\n                \"color\": \"blue\",\n                \"value\": 1000\n              }\n            ]\n          },\n          \"unit\": \"none\"\n        },\n        \"overrides\": []\n      },\n      \"gridPos\": {\n        \"h\": 4,\n        \"w\": 8,\n        \"x\": 16,\n        \"y\": 15\n      },\n      \"id\": 24,\n      \"options\": {\n        \"colorMode\": \"value\",\n        \"graphMode\": \"area\",\n        \"justifyMode\": \"auto\",\n        \"orientation\": \"auto\",\n        \"reduceOptions\": {\n          \"calcs\": [\"lastNotNull\"],\n          \"fields\": \"\",\n          \"values\": false\n        },\n        \"text\": {},\n        \"textMode\": \"auto\"\n      },\n      \"pluginVersion\": \"9.3.0\",\n      \"targets\": [\n        {\n          \"datasource\": {\n            \"type\": \"prometheus\",\n            \"uid\": \"6R74VAnVz\"\n          },\n          \"exemplar\": true,\n          \"expr\": \"healthcheck_reference_height - healthcheck_target_height\",\n          \"hide\": false,\n          \"instant\": false,\n          \"interval\": \"\",\n          \"legendFormat\": \"\",\n          \"refId\": \"A\"\n        }\n      ],\n      \"title\": \"Chain Sync Status\",\n      \"transformations\": [],\n      \"type\": \"stat\"\n    },\n    {\n      \"collapsed\": false,\n      \"gridPos\": {\n        \"h\": 1,\n        \"w\": 24,\n        \"x\": 0,\n        \"y\": 19\n      },\n      \"id\": 26,\n      \"panels\": [],\n      \"title\": \"Geth Performance\",\n      \"type\": \"row\"\n    },\n    {\n      \"datasource\": {\n        \"type\": \"influxdb\",\n        \"uid\": \"4knV40nVb\"\n      },\n      \"fieldConfig\": {\n        \"defaults\": {\n          \"color\": {\n            \"mode\": \"palette-classic\"\n          },\n          \"custom\": {\n            \"axisCenteredZero\": false,\n            \"axisColorMode\": \"text\",\n            \"axisLabel\": \"\",\n            \"axisPlacement\": \"auto\",\n            \"barAlignment\": 0,\n            \"drawStyle\": \"line\",\n            \"fillOpacity\": 10,\n            \"gradientMode\": \"none\",\n            \"hideFrom\": {\n              \"graph\": false,\n              \"legend\": false,\n              \"tooltip\": false,\n              \"viz\": false\n            },\n            \"lineInterpolation\": \"linear\",\n            \"lineWidth\": 1,\n            \"pointSize\": 5,\n            \"scaleDistribution\": {\n              \"type\": \"linear\"\n            },\n            \"showPoints\": \"never\",\n            \"spanNulls\": true,\n            \"stacking\": {\n              \"group\": \"A\",\n              \"mode\": \"none\"\n            },\n            \"thresholdsStyle\": {\n              \"mode\": \"off\"\n            }\n          },\n          \"mappings\": [],\n          \"thresholds\": {\n            \"mode\": \"absolute\",\n            \"steps\": [\n              {\n                \"color\": \"green\",\n                \"value\": null\n              },\n              {\n                \"color\": \"red\",\n                \"value\": 80\n              }\n            ]\n          },\n          \"unit\": \"%\"\n        },\n        \"overrides\": []\n      },\n      \"gridPos\": {\n        \"h\": 6,\n        \"w\": 8,\n        \"x\": 0,\n        \"y\": 20\n      },\n      \"id\": 31,\n      \"options\": {\n        \"graph\": {},\n        \"legend\": {\n          \"calcs\": [],\n          \"displayMode\": \"list\",\n          \"placement\": \"bottom\",\n          \"showLegend\": true\n        },\n        \"tooltip\": {\n          \"mode\": \"single\",\n          \"sort\": \"none\"\n        }\n      },\n      \"pluginVersion\": \"7.5.5\",\n      \"targets\": [\n        {\n          \"alias\": \"system\",\n          \"datasource\": {\n            \"type\": \"influxdb\",\n            \"uid\": \"4knV40nVb\"\n          },\n          \"groupBy\": [\n            {\n              \"params\": [\"$__interval\"],\n              \"type\": \"time\"\n            },\n            {\n              \"params\": [\"null\"],\n              \"type\": \"fill\"\n            }\n          ],\n          \"measurement\": \"geth.system/cpu/sysload.gauge\",\n          \"orderByTime\": \"ASC\",\n          \"policy\": \"default\",\n          \"refId\": \"A\",\n          \"resultFormat\": \"time_series\",\n          \"select\": [\n            [\n              {\n                \"params\": [\"value\"],\n                \"type\": \"field\"\n              },\n              {\n                \"params\": [],\n                \"type\": \"mean\"\n              }\n            ]\n          ],\n          \"tags\": []\n        },\n        {\n          \"alias\": \"geth\",\n          \"datasource\": {\n            \"type\": \"influxdb\",\n            \"uid\": \"4knV40nVb\"\n          },\n          \"groupBy\": [\n            {\n              \"params\": [\"$__interval\"],\n              \"type\": \"time\"\n            },\n            {\n              \"params\": [\"null\"],\n              \"type\": \"fill\"\n            }\n          ],\n          \"hide\": false,\n          \"measurement\": \"geth.system/cpu/procload.gauge\",\n          \"orderByTime\": \"ASC\",\n          \"policy\": \"default\",\n          \"refId\": \"B\",\n          \"resultFormat\": \"time_series\",\n          \"select\": [\n            [\n              {\n                \"params\": [\"value\"],\n                \"type\": \"field\"\n              },\n              {\n                \"params\": [],\n                \"type\": \"mean\"\n              }\n            ]\n          ],\n          \"tags\": []\n        },\n        {\n          \"alias\": \"IO\",\n          \"datasource\": {\n            \"type\": \"influxdb\",\n            \"uid\": \"4knV40nVb\"\n          },\n          \"groupBy\": [\n            {\n              \"params\": [\"$__interval\"],\n              \"type\": \"time\"\n            },\n            {\n              \"params\": [\"null\"],\n              \"type\": \"fill\"\n            }\n          ],\n          \"hide\": false,\n          \"measurement\": \"geth.system/cpu/syswait.gauge\",\n          \"orderByTime\": \"ASC\",\n          \"policy\": \"default\",\n          \"refId\": \"C\",\n          \"resultFormat\": \"time_series\",\n          \"select\": [\n            [\n              {\n                \"params\": [\"value\"],\n                \"type\": \"field\"\n              },\n              {\n                \"params\": [],\n                \"type\": \"mean\"\n              }\n            ]\n          ],\n          \"tags\": []\n        }\n      ],\n      \"title\": \"CPU\",\n      \"type\": \"timeseries\"\n    },\n    {\n      \"datasource\": {\n        \"type\": \"influxdb\",\n        \"uid\": \"4knV40nVb\"\n      },\n      \"fieldConfig\": {\n        \"defaults\": {\n          \"color\": {\n            \"mode\": \"palette-classic\"\n          },\n          \"custom\": {\n            \"axisCenteredZero\": false,\n            \"axisColorMode\": \"text\",\n            \"axisLabel\": \"\",\n            \"axisPlacement\": \"auto\",\n            \"barAlignment\": 0,\n            \"drawStyle\": \"line\",\n            \"fillOpacity\": 10,\n            \"gradientMode\": \"none\",\n            \"hideFrom\": {\n              \"graph\": false,\n              \"legend\": false,\n              \"tooltip\": false,\n              \"viz\": false\n            },\n            \"lineInterpolation\": \"linear\",\n            \"lineWidth\": 1,\n            \"pointSize\": 5,\n            \"scaleDistribution\": {\n              \"type\": \"linear\"\n            },\n            \"showPoints\": \"never\",\n            \"spanNulls\": true,\n            \"stacking\": {\n              \"group\": \"A\",\n              \"mode\": \"none\"\n            },\n            \"thresholdsStyle\": {\n              \"mode\": \"off\"\n            }\n          },\n          \"mappings\": [],\n          \"thresholds\": {\n            \"mode\": \"absolute\",\n            \"steps\": [\n              {\n                \"color\": \"green\",\n                \"value\": null\n              },\n              {\n                \"color\": \"red\",\n                \"value\": 80\n              }\n            ]\n          },\n          \"unit\": \"decbytes\"\n        },\n        \"overrides\": []\n      },\n      \"gridPos\": {\n        \"h\": 6,\n        \"w\": 8,\n        \"x\": 8,\n        \"y\": 20\n      },\n      \"id\": 32,\n      \"options\": {\n        \"graph\": {},\n        \"legend\": {\n          \"calcs\": [],\n          \"displayMode\": \"list\",\n          \"placement\": \"bottom\",\n          \"showLegend\": true\n        },\n        \"tooltip\": {\n          \"mode\": \"single\",\n          \"sort\": \"none\"\n        }\n      },\n      \"pluginVersion\": \"7.5.5\",\n      \"targets\": [\n        {\n          \"alias\": \"used\",\n          \"datasource\": {\n            \"type\": \"influxdb\",\n            \"uid\": \"4knV40nVb\"\n          },\n          \"groupBy\": [\n            {\n              \"params\": [\"$__interval\"],\n              \"type\": \"time\"\n            },\n            {\n              \"params\": [\"null\"],\n              \"type\": \"fill\"\n            }\n          ],\n          \"measurement\": \"geth.system/memory/used.gauge\",\n          \"orderByTime\": \"ASC\",\n          \"policy\": \"default\",\n          \"refId\": \"A\",\n          \"resultFormat\": \"time_series\",\n          \"select\": [\n            [\n              {\n                \"params\": [\"value\"],\n                \"type\": \"field\"\n              },\n              {\n                \"params\": [],\n                \"type\": \"mean\"\n              }\n            ]\n          ],\n          \"tags\": []\n        },\n        {\n          \"alias\": \"held\",\n          \"datasource\": {\n            \"type\": \"influxdb\",\n            \"uid\": \"4knV40nVb\"\n          },\n          \"groupBy\": [\n            {\n              \"params\": [\"$__interval\"],\n              \"type\": \"time\"\n            },\n            {\n              \"params\": [\"null\"],\n              \"type\": \"fill\"\n            }\n          ],\n          \"hide\": false,\n          \"measurement\": \"geth.system/memory/held.gauge\",\n          \"orderByTime\": \"ASC\",\n          \"policy\": \"default\",\n          \"refId\": \"B\",\n          \"resultFormat\": \"time_series\",\n          \"select\": [\n            [\n              {\n                \"params\": [\"value\"],\n                \"type\": \"field\"\n              },\n              {\n                \"params\": [],\n                \"type\": \"mean\"\n              }\n            ]\n          ],\n          \"tags\": []\n        }\n      ],\n      \"title\": \"Memory\",\n      \"type\": \"timeseries\"\n    },\n    {\n      \"datasource\": {\n        \"type\": \"influxdb\",\n        \"uid\": \"4knV40nVb\"\n      },\n      \"fieldConfig\": {\n        \"defaults\": {\n          \"color\": {\n            \"mode\": \"palette-classic\"\n          },\n          \"custom\": {\n            \"axisCenteredZero\": false,\n            \"axisColorMode\": \"text\",\n            \"axisLabel\": \"\",\n            \"axisPlacement\": \"auto\",\n            \"barAlignment\": 0,\n            \"drawStyle\": \"line\",\n            \"fillOpacity\": 10,\n            \"gradientMode\": \"none\",\n            \"hideFrom\": {\n              \"graph\": false,\n              \"legend\": false,\n              \"tooltip\": false,\n              \"viz\": false\n            },\n            \"lineInterpolation\": \"linear\",\n            \"lineWidth\": 1,\n            \"pointSize\": 5,\n            \"scaleDistribution\": {\n              \"type\": \"linear\"\n            },\n            \"showPoints\": \"never\",\n            \"spanNulls\": true,\n            \"stacking\": {\n              \"group\": \"A\",\n              \"mode\": \"none\"\n            },\n            \"thresholdsStyle\": {\n              \"mode\": \"off\"\n            }\n          },\n          \"mappings\": [],\n          \"thresholds\": {\n            \"mode\": \"absolute\",\n            \"steps\": [\n              {\n                \"color\": \"green\",\n                \"value\": null\n              },\n              {\n                \"color\": \"red\",\n                \"value\": 80\n              }\n            ]\n          },\n          \"unit\": \"Bps\"\n        },\n        \"overrides\": []\n      },\n      \"gridPos\": {\n        \"h\": 6,\n        \"w\": 8,\n        \"x\": 16,\n        \"y\": 20\n      },\n      \"id\": 22,\n      \"options\": {\n        \"graph\": {},\n        \"legend\": {\n          \"calcs\": [],\n          \"displayMode\": \"list\",\n          \"placement\": \"bottom\",\n          \"showLegend\": true\n        },\n        \"tooltip\": {\n          \"mode\": \"single\",\n          \"sort\": \"none\"\n        }\n      },\n      \"pluginVersion\": \"7.5.5\",\n      \"targets\": [\n        {\n          \"alias\": \"read\",\n          \"datasource\": {\n            \"type\": \"influxdb\",\n            \"uid\": \"4knV40nVb\"\n          },\n          \"groupBy\": [\n            {\n              \"params\": [\"$__interval\"],\n              \"type\": \"time\"\n            },\n            {\n              \"params\": [\"null\"],\n              \"type\": \"fill\"\n            }\n          ],\n          \"measurement\": \"geth.system/disk/readdata.meter\",\n          \"orderByTime\": \"ASC\",\n          \"policy\": \"default\",\n          \"refId\": \"A\",\n          \"resultFormat\": \"time_series\",\n          \"select\": [\n            [\n              {\n                \"params\": [\"m1\"],\n                \"type\": \"field\"\n              },\n              {\n                \"params\": [],\n                \"type\": \"mean\"\n              }\n            ]\n          ],\n          \"tags\": []\n        },\n        {\n          \"alias\": \"write\",\n          \"datasource\": {\n            \"type\": \"influxdb\",\n            \"uid\": \"4knV40nVb\"\n          },\n          \"groupBy\": [\n            {\n              \"params\": [\"$__interval\"],\n              \"type\": \"time\"\n            },\n            {\n              \"params\": [\"null\"],\n              \"type\": \"fill\"\n            }\n          ],\n          \"hide\": false,\n          \"measurement\": \"geth.system/disk/writedata.meter\",\n          \"orderByTime\": \"ASC\",\n          \"policy\": \"default\",\n          \"query\": \"SELECT mean(\\\"m1\\\") FROM \\\"geth.system/disk/writedata.meter\\\" WHERE $timeFilter GROUP BY time($__interval) fill(null)\",\n          \"rawQuery\": false,\n          \"refId\": \"B\",\n          \"resultFormat\": \"time_series\",\n          \"select\": [\n            [\n              {\n                \"params\": [\"m1\"],\n                \"type\": \"field\"\n              },\n              {\n                \"params\": [],\n                \"type\": \"mean\"\n              }\n            ]\n          ],\n          \"tags\": []\n        }\n      ],\n      \"title\": \"Disk\",\n      \"type\": \"timeseries\"\n    }\n  ],\n  \"refresh\": \"5s\",\n  \"schemaVersion\": 37,\n  \"style\": \"dark\",\n  \"tags\": [],\n  \"templating\": {\n    \"list\": []\n  },\n  \"time\": {\n    \"from\": \"now-1h\",\n    \"to\": \"now\"\n  },\n  \"timepicker\": {},\n  \"timezone\": \"\",\n  \"title\": \"Simple Node Dashboard\",\n  \"uid\": \"fNH7uZ97k\",\n  \"version\": 3,\n  \"weekStart\": \"\"\n}\n"
  },
  {
    "path": "docker/grafana/provisioning/dashboards/all.yml",
    "content": "- name: 'default'\n  org_id: 1\n  folder: ''\n  type: 'file'\n  options:\n    folder: '/var/lib/grafana/dashboards'\n"
  },
  {
    "path": "docker/grafana/provisioning/datasources/all.yml",
    "content": "apiVersion: 1\n\ndeleteDatasources:\n  - name: \"Prometheus\"\n  - name: \"InfluxDB\"\n\ndatasources:\n  - access: \"proxy\"\n    editable: true\n    is_default: true\n    name: \"Prometheus\"\n    uid: \"6R74VAnVz\"\n    org_id: 1\n    type: \"prometheus\"\n    url: \"http://prometheus:9090\"\n    version: 1\n  - access: \"proxy\"\n    editable: true\n    is_default: false\n    name: \"InfluxDB (op-geth)\"\n    uid: \"4knV40nVb\"\n    org_id: 1\n    type: \"influxdb\"\n    database: \"opgeth\"\n    url: \"http://influxdb:8086\"\n    version: 1\n"
  },
  {
    "path": "docker/influxdb/influx_init.iql",
    "content": "CREATE DATABASE \"opgeth\"\n"
  },
  {
    "path": "docker/prometheus/prometheus.yml",
    "content": "global:\n  scrape_interval:     15s\n  evaluation_interval: 15s\n\nscrape_configs:\n  - job_name: 'healthcheck'\n    static_configs:\n    - targets: ['healthcheck:7300']\n\n  - job_name: 'fault-detector'\n    static_configs:\n    - targets: ['fault-detector:7300']\n\n  - job_name: 'op-node'\n    static_configs:\n    - targets: ['op-node:7300']\n"
  },
  {
    "path": "docker-compose.yml",
    "content": "services:\n  healthcheck:\n    image: ethereumoptimism/replica-healthcheck:${IMAGE_TAG__HEALTHCHECK:-latest}\n    restart: unless-stopped\n    env_file:\n      - ./envs/common/healthcheck.env\n      - ./envs/${NETWORK_NAME}/healthcheck.env\n      - .env\n    ports:\n      - ${PORT__HEALTHCHECK_METRICS:-7300}:7300\n\n  op-geth:\n    image: us-docker.pkg.dev/oplabs-tools-artifacts/images/op-geth:v1.101503.4\n    restart: unless-stopped\n    stop_grace_period: 5m\n    entrypoint: /scripts/start-op-geth.sh\n    env_file:\n      - ./envs/${NETWORK_NAME}/op-geth.env\n      - .env\n    volumes:\n      - ./envs/${NETWORK_NAME}/config:/chainconfig\n      - ./scripts/:/scripts\n      - shared:/shared\n      - op_geth:/geth\n    ports:\n      - ${PORT__OP_GETH_HTTP:-9993}:8545\n      - ${PORT__OP_GETH_WS:-9994}:8546\n      - ${PORT__OP_GETH_P2P:-39393}:${PORT__OP_GETH_P2P:-39393}/udp\n      - ${PORT__OP_GETH_P2P:-39393}:${PORT__OP_GETH_P2P:-39393}/tcp\n    extra_hosts:\n      - \"host.docker.internal:host-gateway\"\n\n  op-node:\n    image: us-docker.pkg.dev/oplabs-tools-artifacts/images/op-node:v1.13.2\n    restart: unless-stopped\n    stop_grace_period: 5m\n    entrypoint: /scripts/start-op-node.sh\n    env_file:\n      - ./envs/${NETWORK_NAME}/op-node.env\n      - .env\n    volumes:\n      - ./envs/${NETWORK_NAME}/config:/chainconfig\n      - ./scripts/:/scripts\n      - shared:/shared\n    ports:\n      - ${PORT__OP_NODE_P2P:-9003}:9003/udp\n      - ${PORT__OP_NODE_P2P:-9003}:9003/tcp\n      - ${PORT__OP_NODE_HTTP:-9545}:9545\n    extra_hosts:\n      - \"host.docker.internal:host-gateway\"\n\n  bedrock-init:\n    build:\n      context: ./docker/dockerfiles\n      dockerfile: Dockerfile.bedrock-init\n    entrypoint: /scripts/init-bedrock.sh\n    env_file:\n      - ./envs/${NETWORK_NAME}/op-geth.env\n      - .env\n    volumes:\n      - ./scripts/:/scripts\n      - shared:/shared\n      - op_geth:/geth\n      - geth:/legacy-geth\n      - torrent_downloads:/downloads\n\n  prometheus:\n    image: prom/prometheus:${IMAGE_TAG__PROMETHEUS:-latest}\n    restart: unless-stopped\n    env_file:\n      - .env\n    volumes:\n      - ./docker/prometheus:/etc/prometheus\n      - prometheus_data:/prometheus\n    ports:\n      - ${PORT__PROMETHEUS:-9090}:9090\n\n  grafana:\n    image: grafana/grafana:${IMAGE_TAG__GRAFANA:-9.3.0}\n    restart: unless-stopped\n    env_file:\n      - ./envs/common/grafana.env\n    volumes:\n      - ./docker/grafana/provisioning/:/etc/grafana/provisioning/:ro\n      - ./docker/grafana/dashboards/simple_node_dashboard.json:/var/lib/grafana/dashboards/simple_node_dashboard.json\n      - grafana_data:/var/lib/grafana\n    ports:\n      - ${PORT__GRAFANA:-3000}:3000\n\n  influxdb:\n    image: influxdb:${IMAGE_TAG__INFLUXDB:-1.8}\n    restart: unless-stopped\n    env_file:\n      - ./envs/common/influxdb.env\n    volumes:\n      - ./docker/influxdb/influx_init.iql:/docker-entrypoint-initdb.d/influx_init.iql\n      - influxdb_data:/var/lib/influxdb\n    ports:\n      - ${PORT__INFLUXDB:-8086}:8086\n\nvolumes:\n  geth:\n  prometheus_data:\n  grafana_data:\n  influxdb_data:\n  shared:\n  op_geth:\n  torrent_downloads:\n"
  },
  {
    "path": "envs/common/grafana.env",
    "content": "GF_SECURITY_ADMIN_PASSWORD=ink\n"
  },
  {
    "path": "envs/common/healthcheck.env",
    "content": "HEALTHCHECK__TARGET_RPC_PROVIDER=http://op-geth:8545\n"
  },
  {
    "path": "envs/common/influxdb.env",
    "content": "INFLUXDB_HTTP_AUTH_ENABLED=false\n"
  },
  {
    "path": "envs/ink-mainnet/healthcheck.env",
    "content": "HEALTHCHECK__REFERENCE_RPC_PROVIDER=https://rpc-gel.inkonchain.com\n"
  },
  {
    "path": "envs/ink-mainnet/op-geth.env",
    "content": "BEDROCK_SEQUENCER_HTTP=https://rpc-gel.inkonchain.com\nBEDROCK_DATADIR=/geth\n"
  },
  {
    "path": "envs/ink-mainnet/op-node.env",
    "content": "OP_NODE_P2P_BOOTNODES=\"enr:-Iu4QCqTQZVBnbPWXcdUxcakGoCCzCFr5vVzDfNTOr-Pi3KaOJZMXlnqTR9r9p4EemXS8fS59EdQaX8qrkyE01nvsNcBgmlkgnY0gmlwhCIgwYaJc2VjcDI1NmsxoQMW3w0F1AibYelKqJUKaie5RuKc7S9sPfWvH4lSJw4Fo4N0Y3CCIyuDdWRwgiMs\"\nOP_NODE_P2P_STATIC=\"/ip4/34.32.193.134/tcp/9003/p2p/16Uiu2HAmECGb1vmBKhgxVHzX2aYkPcmV8CZjpPxrNkRiFA1wa3CN\"\nOP_NODE_ROLLUP_LOAD_PROTOCOL_VERSIONS=true\n"
  },
  {
    "path": "envs/ink-sepolia/healthcheck.env",
    "content": "HEALTHCHECK__REFERENCE_RPC_PROVIDER=https://rpc-gel-sepolia.inkonchain.com\n"
  },
  {
    "path": "envs/ink-sepolia/op-geth.env",
    "content": "BEDROCK_SEQUENCER_HTTP=https://rpc-gel-sepolia.inkonchain.com\nBEDROCK_DATADIR=/geth\n"
  },
  {
    "path": "envs/ink-sepolia/op-node.env",
    "content": "OP_NODE_P2P_BOOTNODES=\"enr:-Iu4QN7Ohk84lCZMSAbuPbU1vSMF93J7FUUab2_JBNX8q6wSPBeWrGu85ENsL-s2fcf9gvYc_Eiw8ZzdBzP5i05g9DwBgmlkgnY0gmlwhCP2ulGJc2VjcDI1NmsxoQLqBVn4RC7vvLvOB95odV2bp6zKCQHPw7j60wBG68qGJYN0Y3CCIyuDdWRwgiMs\"\nOP_NODE_P2P_STATIC=\"/ip4/35.246.186.81/tcp/9003/p2p/16Uiu2HAmBBC7aADaA9cfMeuHLZLYAdLNwEahKh7kc9WyUrcvPqXz\"\nOP_NODE_ROLLUP_LOAD_PROTOCOL_VERSIONS=true\n"
  },
  {
    "path": "progress.sh",
    "content": "#!/bin/bash\n\n# Make script exit on error and undefined variables\nset -eu\n\n# Function to handle errors\nerror_exit() {\n    echo \"Error: $1\" >&2\n    exit 1\n}\n\n# Load Environment Variables\nif [ -f .env ]; then\n    export $(cat .env | grep -v '#' | sed 's/\\r$//' | awk '/=/ {print $1}' ) || error_exit \"Failed to load .env file\"\nfi\n\n# Set default RPC URL with error checking\nexport ETH_RPC_URL=${ETH_RPC_URL:-http://localhost:${PORT__OP_GETH_HTTP:-9993}}\n[ -z \"$ETH_RPC_URL\" ] && error_exit \"ETH_RPC_URL is not set\"\n\n# Get chain ID with error handling\nCHAIN_ID=$(cast chain-id 2>/dev/null) || error_exit \"Failed to get chain ID\"\necho \"Chain ID: $CHAIN_ID\"\necho \"Sampling, please wait\"\n\n# Set L2_URL based on chain ID\necho \"Determining L2_URL for chain ID: $CHAIN_ID\"\ncase $CHAIN_ID in\n    763373)\n        echo \"Using Sepolia testnet RPC endpoint\"\n        L2_URL=\"https://rpc-gel-sepolia.inkonchain.com\"\n        ;;\n    57073)\n        echo \"Using mainnet RPC endpoint\"\n        L2_URL=\"https://rpc-gel.inkonchain.com/\"\n        ;;\n    *)\n        error_exit \"Unsupported chain ID: $CHAIN_ID\"\n        ;;\nesac\necho \"L2_URL set to: $L2_URL\"\n\necho \"Getting initial block number...\"\nT0=$(cast block-number --rpc-url \"$ETH_RPC_URL\" 2>/dev/null) || error_exit \"Failed to get initial block number\"\necho \"Initial block: $T0\"\necho \"Waiting 10 seconds...\"\nsleep 10\necho \"Getting final block number...\"\nT1=$(cast block-number --rpc-url \"$ETH_RPC_URL\" 2>/dev/null) || error_exit \"Failed to get final block number\"\necho \"Final block: $T1\"\n\n# Calculate blocks per minute\nPER_MIN=$(($T1 - $T0))\nPER_MIN=$(($PER_MIN * 6))\necho \"Blocks per minute: $PER_MIN\"\n\n[ $PER_MIN -eq 0 ] && error_exit \"Not syncing\"\n\n# Get L2 head block with error handling\nHEAD=$(cast block-number --rpc-url \"$L2_URL\" 2>/dev/null) || error_exit \"Failed to get L2 block number\"\nBEHIND=$((HEAD - T1))\n[ $BEHIND -lt 0 ] && error_exit \"L2 is ahead of local node\"\n\n# Calculate time estimates\necho \"Calculating time estimates...\"\nMINUTES=$((BEHIND / PER_MIN))\nHOURS=$((MINUTES / 60))\n\nif [ $MINUTES -le 60 ] ; then\n   echo \"Sync will complete in minutes\"\n   echo \"Minutes until sync completed: $MINUTES\"\nfi\n\nif [ $MINUTES -gt 60 ] ; then\n   echo \"Sync will take hours\"\n   echo \"Hours until sync completed: $HOURS\"\nfi\n\nif [ $HOURS -gt 24 ] ; then\n   echo \"Sync will take days\"\n   DAYS=$((HOURS / 24))\n   echo \"Days until sync complete: $DAYS\"\nfi\n"
  },
  {
    "path": "scripts/init-bedrock.sh",
    "content": "#!/bin/bash\nset -e\n\n# Import utilities.\nsource ./scripts/utils.sh\n\n# Common variables.\nINITIALIZED_FLAG=/shared/initialized.txt\nBEDROCK_JWT_PATH=/shared/jwt.txt\nGETH_DATA_DIR=$BEDROCK_DATADIR\nTORRENTS_DIR=/torrents/$NETWORK_NAME\nBEDROCK_TAR_PATH=/downloads/bedrock.tar\nBEDROCK_TMP_PATH=/bedrock-tmp\n\n# Exit early if we've already initialized.\nif [ -e \"$INITIALIZED_FLAG\" ]; then\n  echo \"Bedrock node already initialized\"\n  exit 0\nfi\n\necho \"Bedrock node needs to be initialized...\"\necho \"Initializing via download...\"\n\n# Fix OP link with hardcoded official OP snapshot\necho \"Fetching download link...\"\n\nif [ \"$NODE_TYPE\" = \"archive\" ]; then\n  if [ \"$NETWORK_NAME\" = \"ink-sepolia\" ]; then\n    SNAPSHOT_FILENAME=$(curl -s https://storage.googleapis.com/raas-op-geth-snapshots-d2a56/datadir-archive/latest)\n    BEDROCK_TAR_DOWNLOAD=\"https://storage.googleapis.com/raas-op-geth-snapshots-d2a56/datadir-archive/$SNAPSHOT_FILENAME\"\n    echo \"Using snapshot file: $SNAPSHOT_FILENAME\"\n  elif [ \"$NETWORK_NAME\" = \"ink-mainnet\" ]; then\n    SNAPSHOT_FILENAME=$(curl -s https://storage.googleapis.com/raas-op-geth-snapshots-e2025/datadir-archive/latest)\n    BEDROCK_TAR_DOWNLOAD=\"https://storage.googleapis.com/raas-op-geth-snapshots-e2025/datadir-archive/$SNAPSHOT_FILENAME\"\n    echo \"Using snapshot file: $SNAPSHOT_FILENAME\"\n  fi\nfi\n\nif [ -n \"$BEDROCK_TAR_DOWNLOAD\" ]; then\n  if [[ \"$BEDROCK_TAR_DOWNLOAD\" == *.zst ]]; then\n    BEDROCK_TAR_PATH+=\".zst\"\n  elif [[ \"$BEDROCK_TAR_DOWNLOAD\" == *.lz4 ]]; then\n    BEDROCK_TAR_PATH+=\".lz4\"\n  fi\n\n  echo \"Downloading bedrock.tar...\"\n  download $BEDROCK_TAR_DOWNLOAD $BEDROCK_TAR_PATH\n\n  echo \"Extracting bedrock.tar...\"\n  if [[ \"$BEDROCK_TAR_DOWNLOAD\" == *.zst ]]; then\n    extractzst $BEDROCK_TAR_PATH $GETH_DATA_DIR\n  elif [[ \"$BEDROCK_TAR_DOWNLOAD\" == *.lz4 ]]; then\n    extractlz4 $BEDROCK_TAR_PATH $GETH_DATA_DIR\n  else\n    extract $BEDROCK_TAR_PATH $GETH_DATA_DIR\n  fi\n\n  # Remove tar file to save disk space\n  rm $BEDROCK_TAR_PATH\nfi\n\necho \"Creating JWT...\"\nmkdir -p $(dirname $BEDROCK_JWT_PATH)\nopenssl rand -hex 32 > $BEDROCK_JWT_PATH\n\necho \"Creating Bedrock flag...\"\ntouch $INITIALIZED_FLAG\n"
  },
  {
    "path": "scripts/start-op-geth.sh",
    "content": "#!/bin/sh\nset -e\n\n# Wait for the Bedrock flag for this network to be set.\necho \"Waiting for Bedrock node to initialize...\"\nwhile [ ! -f /shared/initialized.txt ]; do\n  sleep 1\ndone\n\n# Override Holocene\nif [ ! -z \"$OVERRIDE_HOLOCENE\" ]; then\n  EXTENDED_ARG=\"$EXTENDED_ARG --override.holocene=$OVERRIDE_HOLOCENE\"\nfi\n\n# Start op-geth.\nexec geth \\\n  --op-network=$NETWORK_NAME \\\n  --datadir=\"$BEDROCK_DATADIR\" \\\n  --http \\\n  --http.corsdomain=\"*\" \\\n  --http.vhosts=\"*\" \\\n  --http.addr=0.0.0.0 \\\n  --http.port=8545 \\\n  --http.api=eth,engine,web3,debug,net \\\n  --metrics \\\n  --metrics.influxdb \\\n  --metrics.influxdb.endpoint=http://influxdb:8086 \\\n  --metrics.influxdb.database=opgeth \\\n  --authrpc.vhosts=\"*\" \\\n  --authrpc.addr=0.0.0.0 \\\n  --authrpc.port=8551 \\\n  --authrpc.jwtsecret=/shared/jwt.txt \\\n  --rollup.sequencerhttp=\"$BEDROCK_SEQUENCER_HTTP\" \\\n  --rollup.disabletxpoolgossip=true \\\n  --port=\"${PORT__OP_GETH_P2P:-39393}\" \\\n  --discovery.port=\"${PORT__OP_GETH_P2P:-39393}\" \\\n  --db.engine=pebble \\\n  --state.scheme=hash \\\n  --txlookuplimit=0 \\\n  --history.state=0 \\\n  --history.transactions=0 \\\n  --txpool.pricebump=10 \\\n  --txpool.lifetime=12h0m0s \\\n  --rpc.txfeecap=4 \\\n  --rpc.evmtimeout=0 \\\n  --maxpeers=0 \\\n  --nodiscover \\\n  --gpo.percentile=60 \\\n  --verbosity=3 \\\n  --syncmode=\"full\" \\\n  --gcmode=\"$NODE_TYPE\" \\\n  $EXTENDED_ARG $@\n"
  },
  {
    "path": "scripts/start-op-node.sh",
    "content": "#!/bin/sh\nset -e\n\n# Wait for the Bedrock flag for this network to be set.\necho \"Waiting for Bedrock node to initialize...\"\nwhile [ ! -f /shared/initialized.txt ]; do\n  sleep 1\ndone\n\nexport EXTENDED_ARG=\"${EXTENDED_ARG:-} --network=$NETWORK_NAME --rollup.load-protocol-versions=true --rollup.halt=major\"\n\n# Override Holocene\nif [ ! -z \"$OVERRIDE_HOLOCENE\" ]; then\n  EXTENDED_ARG=\"$EXTENDED_ARG --override.holocene=$OVERRIDE_HOLOCENE\"\nfi\n\n# Start op-node.\nexec op-node \\\n  --l1=$OP_NODE__RPC_ENDPOINT \\\n  --l2=http://op-geth:8551 \\\n  --rpc.addr=0.0.0.0 \\\n  --rpc.port=9545 \\\n  --l2.jwt-secret=/shared/jwt.txt \\\n  --l1.trustrpc \\\n  --l1.rpckind=$OP_NODE__RPC_TYPE \\\n  --l1.beacon=$OP_NODE__L1_BEACON \\\n  --metrics.enabled \\\n  --metrics.addr=0.0.0.0 \\\n  --metrics.port=7300 \\\n  --syncmode=consensus-layer \\\n  --p2p.scoring=none \\\n  --p2p.listen.ip=0.0.0.0 \\\n  --p2p.listen.tcp=9222 \\\n  --p2p.listen.udp=9222 \\\n  $EXTENDED_ARG $@\n"
  },
  {
    "path": "scripts/utils.sh",
    "content": "#!/bin/bash\n\n# extract: Extracts an archive into an output location.\n# Arguments:\n#   arc: Archive to extract.\n#   loc: Location to extract to.\nfunction extract() {\n  mkdir -p $2\n  tar -xf $1 -C $2\n}\n\n# extractzst: Extracts a zst archive into an output location.\n# Arguments:\n#   arc: ZST archive to extract.\n#   loc: Location to extract to.\nfunction extractzst() {\n  mkdir -p $2\n  tar --use-compress-program=unzstd -xf $1 -C $2\n}\n\n# extractlz4: Extracts a lz4 archive into an output location.\n# Arguments:\n#   arc: lz4 archive to extract.\n#   loc: Location to extract to.\nfunction extractlz4() {\n  mkdir -p $2\n  tar --use-compress-program=\"lz4 --no-crc\" -xf $1 -C $2\n}\n\n# download: Downloads a file and provides basic progress percentages.\n# Arguments:\n#   url: URL of the file to download.\n#   out: Location to download the file to.\nfunction download() {\n  aria2c --max-tries=0 -x 16 -s 16 -k100M -o $2 $1\n}\n"
  }
]