diff --git a/.circleci/config.yml b/.circleci/config.yml index d87d65749..5a68c86ee 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -65,16 +65,6 @@ jobs: # NEXT_PUBLIC_ALGOLIA_WRITE_API_KEY # NEXT_PUBLIC_ALGOLIA_INDEX_NAME pnpm run index:docs - - breadcrumbs: - description: Check breadcrumbs in documentation - executor: ubuntu - steps: - - checkout - - setup-node - - run: - name: Run breadcrumb check - command: pnpm check-breadcrumbs lint: description: Lint Markdown files and validate metadata @@ -154,7 +144,6 @@ workflows: pr-workflow: jobs: - - breadcrumbs - links - lint monthly-workflow: diff --git a/package.json b/package.json index 97163bd87..ebc2ad338 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "Optimism Docs", "type": "module", "scripts": { - "lint": "eslint . --ext mdx --max-warnings 0 && pnpm spellcheck:lint && pnpm check-breadcrumbs && pnpm check-redirects && pnpm validate-metadata && pnpm link-checker", + "lint": "eslint . --ext mdx --max-warnings 0 && pnpm spellcheck:lint && pnpm check-redirects && pnpm validate-metadata && pnpm link-checker", "fix": "eslint . --ext mdx --fix && pnpm spellcheck:fix && pnpm fix-redirects && pnpm fix-links", "spellcheck:lint": "cspell lint \"**/*.mdx\"", "prepare": "husky", diff --git a/pages/notices/upgrade-15.mdx b/pages/notices/upgrade-15.mdx index cec3d8073..686f9c83a 100644 --- a/pages/notices/upgrade-15.mdx +++ b/pages/notices/upgrade-15.mdx @@ -17,7 +17,7 @@ is_imported_content: 'false' import { Steps, Callout } from 'nextra/components' -# Upgrade 15: Isthmus Hard Fork +# Upgrade 15: Isthmus Hard Fork This page outlines breaking changes related to the Isthmus network upgrade for chain operators and node operators. The upgrade proposal is available [here](https://gov.optimism.io/t/upgrade-proposal-15-isthmus-hard-fork/9804) and the governance vote is available [here](https://gov.optimism.io/t/proposal-preview-implement-prague-features-on-the-op-stack/9703). diff --git a/pages/operators/chain-operators/deploy/op-challenger.mdx b/pages/operators/chain-operators/deploy/op-challenger.mdx index 7e72b1b4e..7c83d6cc6 100644 --- a/pages/operators/chain-operators/deploy/op-challenger.mdx +++ b/pages/operators/chain-operators/deploy/op-challenger.mdx @@ -182,11 +182,11 @@ L1_BEACON=http://sepolia-cl-1:5051 # Wallet configuration - Choose either mnemonic + HD path OR private key MNEMONIC="test test test test test test test test test test test junk" HD_PATH="m/44'/60'/0'/0/0" -# PRIVATE_KEY=0xYOUR_ACTUAL_PRIVATE_KEY # Alternative to mnemonic +# PRIVATE_KEY=YOUR_ACTUAL_PRIVATE_KEY # Alternative to mnemonic # Network configuration NETWORK=op-sepolia -GAME_FACTORY_ADDRESS=0xYOUR_GAME_FACTORY_ADDRESS +GAME_FACTORY_ADDRESS=YOUR_GAME_FACTORY_ADDRESS # Trace configuration TRACE_TYPE=permissioned,cannon @@ -428,7 +428,7 @@ HD_PATH="m/44'/60'/0'/0/0" # Network configuration NETWORK=op-sepolia -GAME_FACTORY_ADDRESS=0xYOUR_GAME_FACTORY_ADDRESS +GAME_FACTORY_ADDRESS=YOUR_GAME_FACTORY_ADDRESS EOF ``` **Important:** Replace ALL placeholder values (`YOUR_ACTUAL_*`) with your real configuration values. @@ -569,7 +569,6 @@ All governance approved releases use a tagged version of `op-program`. These can Create a `docker-compose.yml` file that defines the challenger service: ```yaml -version: '3.8' services: challenger: diff --git a/pages/operators/chain-operators/deploy/proposer-setup-guide.mdx b/pages/operators/chain-operators/deploy/proposer-setup-guide.mdx index 6b620580f..9304936e1 100644 --- a/pages/operators/chain-operators/deploy/proposer-setup-guide.mdx +++ b/pages/operators/chain-operators/deploy/proposer-setup-guide.mdx @@ -71,7 +71,7 @@ just ``` - This uses `op-proposer/v1.10.0` which is compatible with op-node/v1.13.3 and op-geth/v1.101511.0 from [spinning up the sequencer guide](/operators/chain-operators/deploy/sequencer-node). + This uses `op-proposer/v1.10.0` which is compatible with op-node/v1.13.3 and op-geth/v1.101511.1 from [spinning up the sequencer guide](/operators/chain-operators/deploy/sequencer-node). Always check the [release notes](https://github.com/ethereum-optimism/optimism/releases) for compatibility. @@ -137,7 +137,7 @@ ROLLUP_RPC_URL=http://localhost:8547 GAME_FACTORY_ADDRESS=YOUR_ACTUAL_GAME_FACTORY_ADDRESS # Private key - Replace with your actual private key -PRIVATE_KEY=0xYOUR_ACTUAL_PRIVATE_KEY +PRIVATE_KEY=YOUR_ACTUAL_PRIVATE_KEY # Proposer configuration PROPOSAL_INTERVAL=3600s diff --git a/pages/operators/chain-operators/deploy/sequencer-node.mdx b/pages/operators/chain-operators/deploy/sequencer-node.mdx index 5aa70cd7f..bcf586a52 100644 --- a/pages/operators/chain-operators/deploy/sequencer-node.mdx +++ b/pages/operators/chain-operators/deploy/sequencer-node.mdx @@ -17,7 +17,7 @@ categories: is_imported_content: 'false' --- -import { Callout, Steps } from 'nextra/components' +import { Callout, Steps, Tabs } from 'nextra/components' ## Overview @@ -79,512 +79,507 @@ The main components you'll need for sequencer deployment are: * **op-geth**: Look for the latest `op-geth/v*` [release](https://github.com/ethereum-optimism/op-geth/releases) -The versions used in this guide (**op-node/v1.13.3** and **op-geth/v1.101511.0**) are verified compatible versions. +The versions used in this guide (**op-node/v1.13.3** and **op-geth/v1.101511.1**) are verified compatible versions. -According to the **op-node v1.13.3** [release notes](https://github.com/ethereum-optimism/optimism/releases/tag/op-node%2Fv1.13.3), this op-node version specifically corresponds to **op-geth v1.101511.0**. +According to the **op-node v1.13.3** [release notes](https://github.com/ethereum-optimism/optimism/releases/tag/op-node%2Fv1.13.3), this op-node version specifically corresponds to **op-geth v1.101511.1**. Always check the release notes to ensure you're using compatible versions. ## Software installation -For spinning up a sequencer, we recommend **building from source** as it provides better control, and helps with debugging. -In this guide, a Docker alternative is also provided. +For spinning up a sequencer, we recommend building from source as it provides better control, and helps with debugging. +In this guide Docker alternative is also provided. -### Build from source (Recommended) + + + Building from source gives you full control over the binaries. -Building from source gives you full control over the binaries and is the preferred approach for this guide. + #### 1. Clone and build op-node -#### 1. Clone and build op-node + ```bash + # Clone the optimism monorepo + git clone https://github.com/ethereum-optimism/optimism.git + cd optimism -```bash -# Clone the optimism monorepo -git clone https://github.com/ethereum-optimism/optimism.git -cd optimism + # Checkout the latest release tag + git checkout op-node/v1.13.3 -# Checkout the latest release tag -git checkout op-node/v1.13.3 + # Build op-node + cd op-node + just -# Build op-node -cd op-node -just + # Binary will be available at ./bin/op-node + ``` -# Binary will be available at ./bin/op-node -``` + #### 2. Clone and build op-geth -#### 2. Clone and build op-geth + ```bash + # Clone op-geth repository (in a separate directory) + git clone https://github.com/ethereum-optimism/op-geth.git + cd op-geth -```bash -# Clone op-geth repository (in a separate directory) -git clone https://github.com/ethereum-optimism/op-geth.git -cd op-geth + # Checkout to this release tag + git checkout v1.101511.1 -# Checkout to this release tag -git checkout v1.101511.0 + # Build op-geth + make geth -# Build op-geth -make geth + # Binary will be available at ./build/bin/geth + ``` -# Binary will be available at ./build/bin/geth -``` + ### Verify installation -### Verify installation + Check that you have properly installed the needed components. -Check that you have properly installed the needed components. + ```bash + # Make sure you're in the right directory + ./bin/op-node --version + ./build/bin/geth version + ``` -```bash -# Make sure you're in the right directory -./bin/op-node --version -./build/bin/geth version -``` + ## Configuration setup -## Configuration setup + ### 1. Organize your workspace -### 1. Organize your workspace + After building the binaries, you should have the following directory structure: -After building the binaries, you should have the following directory structure: + ``` + ~/ + ├── optimism/ # Optimism monorepo + │ └── op-node/ + │ └── bin/ + │ └── op-node # Built binary + ├── op-geth/ # OP-Geth repository + │ └── build/ + │ └── bin/ + │ └── geth # Built binary + └── .deployer/ # From op-deployer + ├── genesis.json + └── rollup.json + ``` -``` -~/ -├── optimism/ # Optimism monorepo -│ └── op-node/ -│ └── bin/ -│ └── op-node # Built binary -├── op-geth/ # OP-Geth repository -│ └── build/ -│ └── bin/ -│ └── geth # Built binary -└── .deployer/ # From op-deployer - ├── genesis.json - └── rollup.json -``` + Now create your sequencer working directory. We recommend creating it at the same level for easy path references: -Now create your sequencer working directory. We recommend creating it at the same level for easy path references: + ```bash + # Create sequencer directory at the root level + mkdir ~/sequencer-node + cd ~/sequencer-node + ``` -```bash -# Create sequencer directory at the root level -mkdir ~/sequencer-node -cd ~/sequencer-node -``` +
+ Alternative: Copy binaries to sequencer directory -
- Alternative: Copy binaries to sequencer directory + If you prefer to keep binaries close to your configuration, you can copy them: - If you prefer to keep binaries close to your configuration, you can copy them: + ```bash + mkdir ~/sequencer-node/bin + cp ~/optimism/op-node/bin/op-node ~/sequencer-node/bin/ + cp ~/op-geth/build/bin/geth ~/sequencer-node/bin/ - ```bash - mkdir ~/sequencer-node/bin - cp ~/optimism/op-node/bin/op-node ~/sequencer-node/bin/ - cp ~/op-geth/build/bin/geth ~/sequencer-node/bin/ + # Then update scripts to use: + # ./bin/geth + # ./bin/op-node + ``` +
- # Then update scripts to use: - # ./bin/geth - # ./bin/op-node - ``` -
+ ### 2. Generate JWT secret -### 2. Generate JWT secret + ```bash + # Generate JWT secret in the sequencer directory + openssl rand -hex 32 > jwt.txt -```bash -# Generate JWT secret in the sequencer directory -openssl rand -hex 32 > jwt.txt + # Set appropriate permissions + chmod 600 jwt.txt + ``` -# Set appropriate permissions -chmod 600 jwt.txt -``` + ### 3. Set up directory structure and copy files -### 3. Set up directory structure and copy files + In this guide, we're going to be using the binaries from their original build locations, we only need to create directories for configuration files and scripts. -In this guide, we're going to be using the binaries from their original build locations, we only need to create directories for configuration files and scripts. + ```bash + # Create scripts directory + mkdir scripts -```bash -# Create scripts directory -mkdir scripts + # Copy configuration files from op-deployer + cp ~/.deployer/genesis.json . + cp ~/.deployer/rollup.json . + ``` -# Copy configuration files from op-deployer -cp ~/.deployer/genesis.json . -cp ~/.deployer/rollup.json . -``` + Your final directory structure should look like: -Your final directory structure should look like: + ```bash + ~/sequencer-node/ + ├── jwt.txt + ├── genesis.json + ├── rollup.json + └── scripts/ + ├── start-op-geth.sh # (to be created) + └── start-op-node.sh # (to be created) + ``` -```bash -~/sequencer-node/ -├── jwt.txt -├── genesis.json -├── rollup.json -└── scripts/ - ├── start-op-geth.sh # (to be created) - └── start-op-node.sh # (to be created) -``` + ### 4. Environment variables -### 4. Environment variables + You'll need to gather several pieces of information before creating your configuration. Here's where to get each value: + + ### Get L1 network access -You'll need to gather several pieces of information before creating your configuration. Here's where to get each value: - -### Get L1 network access + You need access to the L1 network (Ethereum mainnet or Sepolia testnet) and its beacon node: -You need access to the L1 network (Ethereum mainnet or Sepolia testnet) and its beacon node: + **L1 RPC URL options:** -**L1 RPC URL options:** + * **Infura**: [infura.io](https://infura.io) - Requires an API key from a project + * **Alchemy**: [alchemy.com](https://alchemy.com) - Requires an API key from an app -* **Infura**: [infura.io](https://infura.io) - Requires an API key from a project -* **Alchemy**: [alchemy.com](https://alchemy.com) - Requires an API key from an app + **L1 Beacon URL options:** -**L1 Beacon URL options:** + * **Public beacon APIs**: `https://ethereum-sepolia-beacon-api.publicnode.com` (Sepolia) or `https://ethereum-beacon-api.publicnode.com` (Mainnet) + * **Infura beacon**: `https://sepolia.infura.io/v3/YOUR_KEY` (if your Infura plan includes beacon access) -* **Public beacon APIs**: `https://ethereum-sepolia-beacon-api.publicnode.com` (Sepolia) or `https://ethereum-beacon-api.publicnode.com` (Mainnet) -* **Infura beacon**: `https://sepolia.infura.io/v3/YOUR_KEY` (if your Infura plan includes beacon access) + ### Get private key from your wallet -### Get private key from your wallet + For this basic sequencer setup, you only need a private key during op-node initialization. -For this basic sequencer setup, you only need a private key during op-node initialization. + ### Get your public IP address -### Get your public IP address + ```bash + # Find your public IP address, once you get it, update the P2P_ADVERTISE_IP in your .env + curl ifconfig.me + # or + curl ipinfo.io/ip + ``` + + ### Choose your ports + + The default ports are standard but can be changed if needed: + + * `8545`: op-geth HTTP RPC (standard Ethereum RPC port) + * `8546`: op-geth WebSocket RPC + * `8551`: op-geth Auth RPC (for op-node communication) + * `8547`: op-node RPC + * `9222`: P2P networking (must be open on firewall) + + + + Now create your `.env` file with the actual values: + + ```bash + # Create .env file with your actual values + # L1 Configuration - Replace with your actual RPC URLs + L1_RPC_URL=https://sepolia.infura.io/v3/YOUR_ACTUAL_INFURA_KEY + L1_BEACON_URL=https://ethereum-sepolia-beacon-api.publicnode.com + + # Sequencer configuration + SEQUENCER_ENABLED=true + SEQUENCER_STOPPED=false + + # Private keys + PRIVATE_KEY=YOUR_ACTUAL_PRIVATE_KEY -```bash -# Find your public IP address, once you get it, update the P2P_ADVERTISE_IP in your .env -curl ifconfig.me -# or -curl ipinfo.io/ip -``` - -### Choose your ports - -The default ports are standard but can be changed if needed: - -* `8545`: op-geth HTTP RPC (standard Ethereum RPC port) -* `8546`: op-geth WebSocket RPC -* `8551`: op-geth Auth RPC (for op-node communication) -* `8547`: op-node RPC -* `9222`: P2P networking (must be open on firewall) - - - -Now create your `.env` file with the actual values: - -```bash -# Create .env file with your actual values -# L1 Configuration - Replace with your actual RPC URLs -L1_RPC_URL=https://sepolia.infura.io/v3/YOUR_ACTUAL_INFURA_KEY -L1_BEACON_URL=https://ethereum-sepolia-beacon-api.publicnode.com - -# Sequencer configuration -SEQUENCER_ENABLED=true -SEQUENCER_STOPPED=false - -# Private keys -PRIVATE_KEY=0xYOUR_ACTUAL_PRIVATE_KEY + # P2P configuration - Replace with your actual public IP + P2P_LISTEN_PORT=9222 + P2P_ADVERTISE_IP=YOUR_ACTUAL_PUBLIC_IP + + # RPC configuration (can customize ports if needed) + OP_NODE_RPC_PORT=8547 + OP_GETH_HTTP_PORT=8545 + OP_GETH_WS_PORT=8546 + OP_GETH_AUTH_PORT=8551 + + # JWT secret location + JWT_SECRET=./jwt.txt + ``` -# P2P configuration - Replace with your actual public IP -P2P_LISTEN_PORT=9222 -P2P_ADVERTISE_IP=YOUR_ACTUAL_PUBLIC_IP - -# RPC configuration (can customize ports if needed) -OP_NODE_RPC_PORT=8547 -OP_GETH_HTTP_PORT=8545 -OP_GETH_WS_PORT=8546 -OP_GETH_AUTH_PORT=8551 - -# JWT secret location -JWT_SECRET=./jwt.txt -``` + **Important**: Replace ALL placeholder values (`YOUR_ACTUAL_*`) with your real configuration values. -**Important**: Replace ALL placeholder values (`YOUR_ACTUAL_*`) with your real configuration values. + ## Sequencer specific configuration -## Sequencer specific configuration + ### op-geth configuration for sequencer + + Create `scripts/start-op-geth.sh`: + + ```bash + #!/bin/bash + source .env -### op-geth configuration for sequencer - -Create `scripts/start-op-geth.sh`: - -```bash -#!/bin/bash -source .env + # Path to the op-geth binary we built + ../op-geth/build/bin/geth \ + --datadir=./op-geth-data \ + --http \ + --http.addr=0.0.0.0 \ + --http.port=$OP_GETH_HTTP_PORT \ + --http.vhosts="*" \ + --http.corsdomain="*" \ + --http.api=eth,net,web3,debug,txpool,admin \ + --ws \ + --ws.addr=0.0.0.0 \ + --ws.port=$OP_GETH_WS_PORT \ + --ws.origins="*" \ + --ws.api=eth,net,web3,debug,txpool,admin \ + --authrpc.addr=0.0.0.0 \ + --authrpc.port=$OP_GETH_AUTH_PORT \ + --authrpc.vhosts="*" \ + --authrpc.jwtsecret=$JWT_SECRET \ + --syncmode=full \ + --gcmode=archive \ + --rollup.disabletxpoolgossip=true \ + --rollup.sequencerhttp=http://localhost:$OP_NODE_RPC_PORT + ``` -# Path to the op-geth binary we built -../op-geth/build/bin/geth \ - --datadir=./op-geth-data \ - --http \ - --http.addr=0.0.0.0 \ - --http.port=$OP_GETH_HTTP_PORT \ - --http.vhosts="*" \ - --http.corsdomain="*" \ - --http.api=eth,net,web3,debug,txpool,admin \ - --ws \ - --ws.addr=0.0.0.0 \ - --ws.port=$OP_GETH_WS_PORT \ - --ws.origins="*" \ - --ws.api=eth,net,web3,debug,txpool,admin \ - --authrpc.addr=0.0.0.0 \ - --authrpc.port=$OP_GETH_AUTH_PORT \ - --authrpc.vhosts="*" \ - --authrpc.jwtsecret=$JWT_SECRET \ - --syncmode=full \ - --gcmode=archive \ - --rollup.disabletxpoolgossip=true \ - --rollup.sequencerhttp=http://localhost:$OP_NODE_RPC_PORT -``` + ### op-node configuration for sequencer -### op-node configuration for sequencer + Create `scripts/start-op-node.sh`: -Create `scripts/start-op-node.sh`: + ```bash + #!/bin/bash -```bash -#!/bin/bash - -source .env - -# Path to the op-node binary we built -../optimism/op-node/bin/op-node \ - --l1=$L1_RPC_URL \ - --l1.beacon=$L1_BEACON_URL \ - --l2=http://localhost:$OP_GETH_AUTH_PORT \ - --l2.jwt-secret=$JWT_SECRET \ - --rollup.config=./rollup.json \ - --sequencer.enabled=$SEQUENCER_ENABLED \ - --sequencer.stopped=$SEQUENCER_STOPPED \ - --sequencer.max-safe-lag=3600 \ - --verifier.l1-confs=4 \ - --p2p.listen.ip=0.0.0.0 \ - --p2p.listen.tcp=$P2P_LISTEN_PORT \ - --p2p.listen.udp=$P2P_LISTEN_PORT \ - --p2p.advertise.ip=$P2P_ADVERTISE_IP \ - --p2p.advertise.tcp=$P2P_LISTEN_PORT \ - --p2p.advertise.udp=$P2P_LISTEN_PORT \ - --p2p.sequencer.key=$PRIVATE_KEY \ - --rpc.addr=0.0.0.0 \ - --rpc.port=$OP_NODE_RPC_PORT \ - --rpc.enable-admin \ - --log.level=info \ - --log.format=json -``` - -## Initializing and starting the sequencer - - - -### Initialize op-geth with your genesis file - -```bash -# Make sure you're in the sequencer-node directory -cd ~/sequencer-node - -# Initialize op-geth with your genesis file -../op-geth/build/bin/geth init --datadir=./op-geth-data --state.scheme=hash ./genesis.json -``` - -### Start op-geth - -```bash -# Make scripts executable -chmod +x scripts/start-op-geth.sh -chmod +x scripts/start-op-node.sh - -# Start op-geth in the background or in a separate terminal -./scripts/start-op-geth.sh -``` - -**Note**: You should see output indicating that op-geth is starting and listening on the configured ports. - -### Start op-node - -```bash -# In a separate terminal, navigate to the sequencer directory -cd ~/sequencer-node - -# Start op-node -./scripts/start-op-node.sh -``` - -### Verify sequencer is running - -Once both services are running, verify they're working correctly: - -```bash -# Check op-geth is responding, do this in another terminal -curl -X POST -H "Content-Type: application/json" \ - --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \ - http://localhost:8545 - -# Check sequencer status -curl -X POST -H "Content-Type: application/json" \ - --data '{"jsonrpc":"2.0","method":"admin_sequencerActive","params":[],"id":1}' \ - http://localhost:8547 -``` - - - -Your sequencer node is now operational and ready to process transactions. - -### Docker alternative (For containerized environments) - -If you prefer containerized deployment, you can use the official Docker images. - -### Complete Docker setup guide - -
- Complete Docker setup guide - - If you choose the Docker approach, you'll need to: - - 1. **Set up directory structure and copy configuration files:** - - ```bash - # Create your sequencer working directory - mkdir ~/sequencer-node - cd ~/sequencer-node - - # Copy configuration files from op-deployer output - # Note: Adjust the path if your .deployer directory is located elsewhere - cp ~/.deployer/genesis.json . - cp ~/.deployer/rollup.json . - - # Generate JWT secret - openssl rand -hex 32 > jwt.txt - chmod 600 jwt.txt - ``` - - 2. **Create environment variables file:** - - ```bash - # Create .env file with your actual values - cat > .env << 'EOF' - # L1 Configuration - Replace with your actual RPC URLs - L1_RPC_URL=https://sepolia.infura.io/v3/YOUR_ACTUAL_INFURA_KEY - L1_BEACON_URL=https://ethereum-sepolia-beacon-api.publicnode.com - - # Private keys - Replace with your actual private key - PRIVATE_KEY=0xYOUR_ACTUAL_PRIVATE_KEY - - # (Run `curl ifconfig.me` in a separate shell to obtain the value, then paste it below) - - # P2P configuration - Replace with your actual public IP - P2P_ADVERTISE_IP=YOUR_ACTUAL_PUBLIC_IP - - EOF - ``` - - **Important**: Replace ALL placeholder values (`YOUR_ACTUAL_*`) with your real configuration values. - - 3. **Create docker-compose.yml:** - - ```yaml -version: '3.8' - -services: - op-geth: - image: us-docker.pkg.dev/oplabs-tools-artifacts/images/op-geth:v1.101511.0 - volumes: - # Mount entire directory to avoid file mounting issues - - .:/workspace - working_dir: /workspace - ports: - - "8545:8545" - - "8546:8546" - - "8551:8551" - command: - - "--datadir=/workspace/op-geth-data" - - "--http" - - "--http.addr=0.0.0.0" - - "--http.port=8545" - - "--ws" - - "--ws.addr=0.0.0.0" - - "--ws.port=8546" - - "--authrpc.addr=0.0.0.0" - - "--authrpc.port=8551" - - "--authrpc.jwtsecret=/workspace/jwt.txt" - - "--syncmode=full" - - "--gcmode=archive" - - "--rollup.disabletxpoolgossip=true" - - "--rollup.sequencerhttp=http://op-node:8547" - - "--http.vhosts=*" - - "--http.corsdomain=*" - - "--http.api=eth,net,web3,debug,txpool,admin" - - "--ws.origins=*" - - "--ws.api=eth,net,web3,debug,txpool,admin" - - "--authrpc.vhosts=*" - - op-node: - image: us-docker.pkg.dev/oplabs-tools-artifacts/images/op-node:v1.13.3 - depends_on: - - op-geth - volumes: - - .:/workspace - working_dir: /workspace - ports: - - "8547:8547" - - "9222:9222" - environment: - - L1_RPC_URL=${L1_RPC_URL} - - L1_BEACON_URL=${L1_BEACON_URL} - - PRIVATE_KEY=${PRIVATE_KEY} - - P2P_ADVERTISE_IP=${P2P_ADVERTISE_IP} - command: - - "op-node" - - "--l1=${L1_RPC_URL}" - - "--l1.beacon=${L1_BEACON_URL}" - - "--l2=http://op-geth:8551" - - "--l2.jwt-secret=/workspace/jwt.txt" - - "--rollup.config=/workspace/rollup.json" - - "--sequencer.enabled=true" - - "--sequencer.stopped=false" - - "--sequencer.max-safe-lag=3600" - - "--verifier.l1-confs=4" - - "--p2p.listen.ip=0.0.0.0" - - "--p2p.listen.tcp=9222" - - "--p2p.listen.udp=9222" - - "--p2p.advertise.ip=${P2P_ADVERTISE_IP}" - - "--p2p.advertise.tcp=9222" - - "--p2p.advertise.udp=9222" - - "--p2p.sequencer.key=${PRIVATE_KEY}" - - "--rpc.addr=0.0.0.0" - - "--rpc.port=8547" - - "--rpc.enable-admin" - - "--log.level=info" - - "--log.format=json" - ``` - - 4. **Initialize op-geth with Docker:** - - ```bash - # Make sure you're in the sequencer-node directory with all files copied - cd ~/sequencer-node - - # Initialize op-geth using Docker - docker run --rm \ - -v $(pwd):/workspace \ - -w /workspace \ - us-docker.pkg.dev/oplabs-tools-artifacts/images/op-geth:v1.101511.0 \ - init --datadir=./op-geth-data --state.scheme=hash ./genesis.json - ``` - - 5. **Start the services:** - - ```bash - # Start both services - docker-compose up -d - - # View logs - docker-compose logs -f - ``` - - 6. **Final directory structure:** - - ```bash - ~/sequencer-node/ - ├── jwt.txt # Generated JWT secret - ├── genesis.json # Copied from ~/.deployer/ - ├── rollup.json # Copied from ~/.deployer/ - ├── .env # Environment variables - ├── docker-compose.yml # Docker configuration - └── op-geth-data/ # Created by Docker during initialization - ├── geth/ # Geth data - └── keystore/ # Key files - ``` - -
- -Your sequencer node is now operational and ready to process transactions. + source .env + + # Path to the op-node binary we built + ../optimism/op-node/bin/op-node \ + --l1=$L1_RPC_URL \ + --l1.beacon=$L1_BEACON_URL \ + --l2=http://localhost:$OP_GETH_AUTH_PORT \ + --l2.jwt-secret=$JWT_SECRET \ + --rollup.config=./rollup.json \ + --sequencer.enabled=$SEQUENCER_ENABLED \ + --sequencer.stopped=$SEQUENCER_STOPPED \ + --sequencer.max-safe-lag=3600 \ + --verifier.l1-confs=4 \ + --p2p.listen.ip=0.0.0.0 \ + --p2p.listen.tcp=$P2P_LISTEN_PORT \ + --p2p.listen.udp=$P2P_LISTEN_PORT \ + --p2p.advertise.ip=$P2P_ADVERTISE_IP \ + --p2p.advertise.tcp=$P2P_LISTEN_PORT \ + --p2p.advertise.udp=$P2P_LISTEN_PORT \ + --p2p.sequencer.key=$PRIVATE_KEY \ + --rpc.addr=0.0.0.0 \ + --rpc.port=$OP_NODE_RPC_PORT \ + --rpc.enable-admin \ + --log.level=info \ + --log.format=json + ``` + + ## Initializing and starting the sequencer + + + + ### Initialize op-geth with your genesis file + + ```bash + # Make sure you're in the sequencer-node directory + cd ~/sequencer-node + + # Initialize op-geth with your genesis file + ../op-geth/build/bin/geth init --datadir=./op-geth-data --state.scheme=hash ./genesis.json + ``` + + ### Start op-geth + + ```bash + # Make scripts executable + chmod +x scripts/start-op-geth.sh + chmod +x scripts/start-op-node.sh + + # Start op-geth in the background or in a separate terminal + ./scripts/start-op-geth.sh + ``` + + **Note**: You should see output indicating that op-geth is starting and listening on the configured ports. + + ### Start op-node + + ```bash + # In a separate terminal, navigate to the sequencer directory + cd ~/sequencer-node + + # Start op-node + ./scripts/start-op-node.sh + ``` + + ### Verify sequencer is running + + Once both services are running, verify they're working correctly: + + ```bash + # Check op-geth is responding, do this in another terminal + curl -X POST -H "Content-Type: application/json" \ + --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \ + http://localhost:8545 + + # Check sequencer status + curl -X POST -H "Content-Type: application/json" \ + --data '{"jsonrpc":"2.0","method":"admin_sequencerActive","params":[],"id":1}' \ + http://localhost:8547 + ``` + + + Your sequencer node is now operational and ready to process transactions. + +
+ + + If you prefer containerized deployment, you can use the official Docker images, and do the following: + + 1. **Set up directory structure and copy configuration files:** + + ```bash + # Create your sequencer working directory + mkdir ~/sequencer-node + cd ~/sequencer-node + + # Copy configuration files from op-deployer output + # Note: Adjust the path if your .deployer directory is located elsewhere + cp ~/.deployer/genesis.json . + cp ~/.deployer/rollup.json . + + # Generate JWT secret + openssl rand -hex 32 > jwt.txt + chmod 600 jwt.txt + ``` + + 2. **Create environment variables file:** + + ```bash + # Create .env file with your actual values + cat > .env << 'EOF' + # L1 Configuration - Replace with your actual RPC URLs + L1_RPC_URL=https://sepolia.infura.io/v3/YOUR_ACTUAL_INFURA_KEY + L1_BEACON_URL=https://ethereum-sepolia-beacon-api.publicnode.com + + # Private keys - Replace with your actual private key + PRIVATE_KEY=YOUR_ACTUAL_PRIVATE_KEY + + # (Run `curl ifconfig.me` in a separate shell to obtain the value, then paste it below) + + # P2P configuration - Replace with your actual public IP + P2P_ADVERTISE_IP=YOUR_ACTUAL_PUBLIC_IP + + EOF + ``` + + **Important**: Replace ALL placeholder values (`YOUR_ACTUAL_*`) with your real configuration values. + + 3. **Create docker-compose.yml:** + + ```yaml + ' + + services: + op-geth: + image: us-docker.pkg.dev/oplabs-tools-artifacts/images/op-geth:v1.101511.1 + volumes: + # Mount entire directory to avoid file mounting issues + - .:/workspace + working_dir: /workspace + ports: + - "8545:8545" + - "8546:8546" + - "8551:8551" + command: + - "--datadir=/workspace/op-geth-data" + - "--http" + - "--http.addr=0.0.0.0" + - "--http.port=8545" + - "--ws" + - "--ws.addr=0.0.0.0" + - "--ws.port=8546" + - "--authrpc.addr=0.0.0.0" + - "--authrpc.port=8551" + - "--authrpc.jwtsecret=/workspace/jwt.txt" + - "--syncmode=full" + - "--gcmode=archive" + - "--rollup.disabletxpoolgossip=true" + - "--rollup.sequencerhttp=http://op-node:8547" + - "--http.vhosts=*" + - "--http.corsdomain=*" + - "--http.api=eth,net,web3,debug,txpool,admin" + - "--ws.origins=*" + - "--ws.api=eth,net,web3,debug,txpool,admin" + - "--authrpc.vhosts=*" + + op-node: + image: us-docker.pkg.dev/oplabs-tools-artifacts/images/op-node:v1.13.3 + depends_on: + - op-geth + volumes: + - .:/workspace + working_dir: /workspace + ports: + - "8547:8547" + - "9222:9222" + environment: + - L1_RPC_URL=${L1_RPC_URL} + - L1_BEACON_URL=${L1_BEACON_URL} + - PRIVATE_KEY=${PRIVATE_KEY} + - P2P_ADVERTISE_IP=${P2P_ADVERTISE_IP} + command: + - "op-node" + - "--l1=${L1_RPC_URL}" + - "--l1.beacon=${L1_BEACON_URL}" + - "--l2=http://op-geth:8551" + - "--l2.jwt-secret=/workspace/jwt.txt" + - "--rollup.config=/workspace/rollup.json" + - "--sequencer.enabled=true" + - "--sequencer.stopped=false" + - "--sequencer.max-safe-lag=3600" + - "--verifier.l1-confs=4" + - "--p2p.listen.ip=0.0.0.0" + - "--p2p.listen.tcp=9222" + - "--p2p.listen.udp=9222" + - "--p2p.advertise.ip=${P2P_ADVERTISE_IP}" + - "--p2p.advertise.tcp=9222" + - "--p2p.advertise.udp=9222" + - "--p2p.sequencer.key=${PRIVATE_KEY}" + - "--rpc.addr=0.0.0.0" + - "--rpc.port=8547" + - "--rpc.enable-admin" + - "--log.level=info" + - "--log.format=json" + ``` + + 4. **Initialize op-geth with Docker:** + + ```bash + # Make sure you're in the sequencer-node directory with all files copied + cd ~/sequencer-node + + # Initialize op-geth using Docker + docker run --rm \ + -v $(pwd):/workspace \ + -w /workspace \ + us-docker.pkg.dev/oplabs-tools-artifacts/images/op-geth:v1.101511.1 \ + init --datadir=./op-geth-data --state.scheme=hash ./genesis.json + ``` + + 5. **Start the services:** + + ```bash + # Start both services + docker-compose up -d + + # View logs + docker-compose logs -f + ``` + + 6. **Final directory structure:** + + ```bash + ~/sequencer-node/ + ├── jwt.txt # Generated JWT secret + ├── genesis.json # Copied from ~/.deployer/ + ├── rollup.json # Copied from ~/.deployer/ + ├── .env # Environment variables + ├── docker-compose.yml # Docker configuration + └── op-geth-data/ # Created by Docker during initialization + ├── geth/ # Geth data + └── keystore/ # Key files + ``` + + Your sequencer node is now operational and ready to process transactions. + + + +
## Next steps diff --git a/pages/operators/chain-operators/deploy/spin-batcher.mdx b/pages/operators/chain-operators/deploy/spin-batcher.mdx index 92b27e69b..2e499319f 100644 --- a/pages/operators/chain-operators/deploy/spin-batcher.mdx +++ b/pages/operators/chain-operators/deploy/spin-batcher.mdx @@ -113,7 +113,7 @@ If you prefer containerized deployment, you can use the official Docker images. cp ~/.deployer/state.json . # Extract the BatchInbox address - BATCH_INBOX_ADDRESS=$(cat state.json | jq -r '.opChainDeployments[0].systemConfigProxyAddress') + BATCH_INBOX_ADDRESS=$(cat state.json | jq -r '.opChainDeployments[0].SystemConfigProxy') echo "BatchInbox Address: $BATCH_INBOX_ADDRESS" ``` @@ -126,14 +126,14 @@ If you prefer containerized deployment, you can use the official Docker images. L1_RPC_URL=https://sepolia.infura.io/v3/YOUR_ACTUAL_INFURA_KEY # L2 Configuration - Should match your sequencer setup - L2_RPC_URL=http://sequencer-node:8545 - ROLLUP_RPC_URL=http://sequencer-node:8547 + L2_RPC_URL=http://op-geth:8545 + ROLLUP_RPC_URL=http://op-node:8547 # Contract addresses - Extract from your op-deployer output BATCH_INBOX_ADDRESS=YOUR_ACTUAL_BATCH_INBOX_ADDRESS # Private key - Replace with your actual private key - BATCHER_PRIVATE_KEY=0xYOUR_ACTUAL_PRIVATE_KEY + BATCHER_PRIVATE_KEY=YOUR_ACTUAL_PRIVATE_KEY # Batcher configuration POLL_INTERVAL=1s @@ -158,7 +158,6 @@ If you prefer containerized deployment, you can use the official Docker images. ```yaml - version: '3.8' services: op-batcher: @@ -232,212 +231,6 @@ services: If you chose Docker, refer to the collapsible section. -## Configuration setup - -### 1. Organize your workspace - -Create your batcher working directory: - -```bash -# Create batcher directory at the same level as your sequencer -mkdir batcher-node -cd batcher-node - -# Create scripts directory -mkdir scripts -``` - -Your final directory structure should look like: - -```bash -~/ -├── optimism/ # Contains op-batcher binary -├── sequencer-node/ # Your sequencer setup -├── proposer-node/ # Your proposer setup -├── .deployer/ # From op-deployer -│ └── state.json -└── batcher-node/ # Your batcher working directory - ├── state.json # Copied from .deployer - ├── .env - └── scripts/ - └── start-batcher.sh -``` - -### 2. Extract `BatchInbox` address - -Extract the `BatchInbox` contract address from your op-deployer output: - -```bash -# Navigate to batcher directory -cd ~/batcher-node - -# Copy the deployment state file from op-deployer -# Update the path if your .deployer directory is located elsewhere -cp ../.deployer/state.json . - -# Extract the BatchInbox address -BATCH_INBOX_ADDRESS=$(cat state.json | jq -r '.opChainDeployments[0].systemConfigProxyAddress') -echo "BatchInbox Address: $BATCH_INBOX_ADDRESS" -``` - - - The batcher submits transaction batches to the `BatchInbox` contract on L1. This contract is responsible for accepting and storing L2 transaction data. - - -### 3. Set up environment variables - -Create your `.env` file with the actual values: - -```bash -# Create .env file with your actual values -# L1 Configuration - Replace with your actual RPC URL -L1_RPC_URL=https://sepolia.infura.io/v3/YOUR_ACTUAL_INFURA_KEY - -# L2 Configuration - Should match your sequencer setup -L2_RPC_URL=http://localhost:8545 -ROLLUP_RPC_URL=http://localhost:8547 - -# Contract addresses - Extract from your op-deployer output -BATCH_INBOX_ADDRESS=YOUR_ACTUAL_BATCH_INBOX_ADDRESS - -# Private key - Replace with your actual private key -BATCHER_PRIVATE_KEY=0xYOUR_ACTUAL_PRIVATE_KEY - -# Batcher configuration -POLL_INTERVAL=1s -SUB_SAFETY_MARGIN=6 -NUM_CONFIRMATIONS=1 -SAFE_ABORT_NONCE_TOO_LOW_COUNT=3 -RESUBMISSION_TIMEOUT=30s -MAX_CHANNEL_DURATION=25 - -# RPC configuration -BATCHER_RPC_PORT=8548 -``` - -**Important**: Replace ALL placeholder values (`YOUR_ACTUAL_*`) with your real configuration values! - -### 4. Get your private key - -Get a private key from your wallet that will be used for submitting batches to L1. This account needs sufficient ETH to pay for L1 gas costs. - - - The batcher account needs to be funded with ETH on L1 to pay for batch submission transactions. Monitor this account's balance regularly as it will consume ETH for each batch submission. - - -## Batcher configuration - -Create `scripts/start-batcher.sh`: - -```bash -#!/bin/bash - -source .env - -# Path to the op-batcher binary we built -../optimism/op-batcher/bin/op-batcher \ - --l2-eth-rpc=$L2_RPC_URL \ - --rollup-rpc=$ROLLUP_RPC_URL \ - --poll-interval=$POLL_INTERVAL \ - --sub-safety-margin=$SUB_SAFETY_MARGIN \ - --num-confirmations=$NUM_CONFIRMATIONS \ - --safe-abort-nonce-too-low-count=$SAFE_ABORT_NONCE_TOO_LOW_COUNT \ - --resubmission-timeout=$RESUBMISSION_TIMEOUT \ - --rpc.addr=0.0.0.0 \ - --rpc.port=$BATCHER_RPC_PORT \ - --rpc.enable-admin \ - --max-channel-duration=$MAX_CHANNEL_DURATION \ - --l1-eth-rpc=$L1_RPC_URL \ - --private-key=$BATCHER_PRIVATE_KEY \ - --batch-type=1 \ - --data-availability-type=blobs \ - --compress \ - --log.level=info -``` - -### Batcher parameters explained - -* **`--poll-interval`**: How frequently the batcher checks for new L2 blocks to batch -* **`--sub-safety-margin`**: Number of confirmations to wait before considering L1 transactions safe -* **`--max-channel-duration`**: Maximum time (in L1 blocks) to keep a channel open -* **`--batch-type`**: Type of batch encoding (1 for span batches, 0 for singular batches) -* **`--data-availability-type`**: Whether to use blobs or calldata for data availability -* **`--compress`**: Enable compression to reduce L1 data costs - -## Starting the batcher - -### 1. Verify prerequisites - -Ensure your sequencer and rollup node are running: - - - ### Test L1 connectivity - - ```bash - # Note: Make sure you have exported these environment variables to your current shell session: - # export L1_RPC_URL="https://sepolia.infura.io/v3/YOUR_KEY" - # export L2_RPC_URL="http://localhost:8545" - # export ROLLUP_RPC_URL="http://localhost:8547" - - curl -X POST -H "Content-Type: application/json" \ - --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \ - $L1_RPC_URL - ``` - - ### Test L2 connectivity - - ```bash - curl -X POST -H "Content-Type: application/json" \ - --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \ - $L2_RPC_URL - ``` - - ### Test rollup node connectivity - - ```bash - curl -X POST -H "Content-Type: application/json" \ - --data '{"jsonrpc":"2.0","method":"optimism_syncStatus","params":[],"id":1}' \ - $ROLLUP_RPC_URL - ``` - - -### 2. Start the batcher - -```bash -# Make the script executable -chmod +x scripts/start-batcher.sh - -# Start the batcher -./scripts/start-batcher.sh -``` - -## Verification - -Verify your batcher is working correctly: - -### Check batcher status - -```bash -# Check batcher RPC is responding -curl -X POST -H "Content-Type: application/json" \ - --data '{"jsonrpc":"2.0","method":"admin_startBatcher","params":[],"id":1}' \ - http://localhost:8548 - -# Monitor batch submission activity (check L1 for recent transactions from your batcher address) -# Replace with your actual batcher address -curl -X POST -H "Content-Type: application/json" \ - --data '{"jsonrpc":"2.0","method":"eth_getTransactionCount","params":["0xYOUR_BATCHER_ADDRESS","latest"],"id":1}' \ - $L1_RPC_URL - -# Check if your batcher address has enough ETH for gas -curl -X POST -H "Content-Type: application/json" \ - --data '{"jsonrpc":"2.0","method":"eth_getBalance","params":["0xYOUR_BATCHER_ADDRESS","latest"],"id":1}' \ - $L1_RPC_URL -``` - - - For detailed cost analysis and optimization strategies, refer to the [Fee calculation tools](/operators/chain-operators/tools/fee-calculator). - ## Next steps diff --git a/pages/operators/chain-operators/tools/op-deployer.mdx b/pages/operators/chain-operators/tools/op-deployer.mdx index 0c450d04c..1c600e8fa 100644 --- a/pages/operators/chain-operators/tools/op-deployer.mdx +++ b/pages/operators/chain-operators/tools/op-deployer.mdx @@ -13,7 +13,7 @@ categories: is_imported_content: 'false' --- -import {Callout, Steps} from 'nextra/components' +import {Callout, Steps, Tabs} from 'nextra/components' # Deployer @@ -23,40 +23,42 @@ import {Callout, Steps} from 'nextra/components' There are a couple of ways to install `op-deployer`: -### Option 1: Build from source (Recommended) + + + To install from source, you will need [Go](https://go.dev/doc/install), `just`, and `git`. + After installing all of that, run following: -To install from source, you will need [Go](https://go.dev/doc/install), `just`, and `git`. -After installing all of that, run following: - -```bash - -git clone https://github.com/ethereum-optimism/optimism.git # you can skip this if you already have the repo -cd optimism/op-deployer -just build -cp ./bin/op-deployer /usr/local/bin/op-deployer # or any other directory in your $PATH + ```bash -# Verify installation, run this command to verify that you have it installed. -op-deployer --version -``` + git clone https://github.com/ethereum-optimism/optimism.git # you can skip this if you already have the repo + cd optimism/op-deployer + just build + cp ./bin/op-deployer /usr/local/bin/op-deployer # or any other directory in your $PATH -### Option 2: Download pre-built binary + # Verify installation, run this command to verify that you have it installed. + op-deployer --version + ``` + -The recommended way to install `op-deployer` is to download the latest release from the monorepo's [release page](https://github.com/ethereum-optimism/optimism/releases). + + Another way to install `op-deployer`, is to download the latest release from the monorepo's [release page](https://github.com/ethereum-optimism/optimism/releases). -1. Go to [https://github.com/ethereum-optimism/optimism/releases](https://github.com/ethereum-optimism/optimism/releases) -2. Find the latest release that includes op-deployer -3. Under **assets**, download the binary that matches your operating system: + 1. Go to [https://github.com/ethereum-optimism/optimism/releases](https://github.com/ethereum-optimism/optimism/releases) + 2. Find the latest release that includes op-deployer + 3. Under **assets**, download the binary that matches your operating system: -* `op-deployer-linux-amd64` for Linux -* `op-deployer-darwin-amd64` or `op-deployer-darwin-arm64` for macOS -* `op-deployer-windows-amd64.exe` for Windows + * `op-deployer-linux-amd64` for Linux + * `op-deployer-darwin-amd64` or `op-deployer-darwin-arm64` for macOS + * `op-deployer-windows-amd64.exe` for Windows -4. Extract the binary to a location on your system PATH -5. Verify installation, run this command to verify that you have it installed. + 4. Extract the binary to a location on your system PATH + 5. Verify installation, run this command to verify that you have it installed. -```bash -op-deployer --version -``` + ```bash + op-deployer --version + ``` + + ## Deployment usage @@ -258,7 +260,7 @@ l1ContractsLocator = "file:///path/to/local/op-contracts/v1.8.0-rc.4/forge-artif l2ContractsLocator = "" ``` -By default, `op-deployer` will fill in all other configuration variables with those that match the [standard configuration](https://specs.optimism.io/protocol/configurability.html?utm_source=op-docs\&utm_medium=docs). You can override these default settings by adding them to your intent file using the table below: +By default, `op-deployer` will fill in all other configuration variables with those that match the [standard configuration](https://specs.optimism.io/protocol/configurability.html?utm_source=op-docs&utm_medium=docs). You can override these default settings by adding them to your intent file using the table below: ```toml [globalDeployOverrides] @@ -363,7 +365,7 @@ Unlike the `bootstrap` or `apply` commands, the `upgrade` command doesn't direct Chains that are several versions behind the latest can be upgraded by running multiple upgrade commands in sequence, with each command handling one version increment. The upgrade process requires you to be using the standard OP Contracts Manager and the standard shared SuperchainConfig contract for compatibility. -For detailed instructions on using the upgrade command, including configuration examples and step-by-step procedures, see the [upgrade documentation](https://docs.optimism.io/stack/smart-contracts/op-deployer-upgrade#using-upgrade). +For detailed instructions on using the upgrade command, including configuration examples and step-by-step procedures, see the [upgrade documentation](/stack/smart-contracts/op-deployer-upgrade#using-upgrade). ## Bootstrap usage diff --git a/pages/operators/chain-operators/tutorials/absolute-prestate.mdx b/pages/operators/chain-operators/tutorials/absolute-prestate.mdx index 6e1d988f0..d42781828 100644 --- a/pages/operators/chain-operators/tutorials/absolute-prestate.mdx +++ b/pages/operators/chain-operators/tutorials/absolute-prestate.mdx @@ -162,8 +162,8 @@ For these cases, follow these additional steps: ```bash # Replace 67865 with your actual chain ID - cp /path/to/rollup.json op-program/chainconfig/configs/67865-rollup.json - cp /path/to/genesis.json op-program/chainconfig/configs/67865-genesis-l2.json + cp ../deployer/.deployer/rollup.json op-program/chainconfig/configs/67865-rollup.json + cp ../deployer/.deployer/genesis.json op-program/chainconfig/configs/67865-genesis-l2.json ``` Note: The naming format is critical - the files must be named as: diff --git a/pages/operators/chain-operators/tutorials/create-l2-rollup.mdx b/pages/operators/chain-operators/tutorials/create-l2-rollup.mdx index 0f7d88d13..a840a2819 100644 --- a/pages/operators/chain-operators/tutorials/create-l2-rollup.mdx +++ b/pages/operators/chain-operators/tutorials/create-l2-rollup.mdx @@ -1,52 +1,51 @@ --- title: Creating your own L2 rollup testnet -description: This tutorial walks you through spinning up an OP Stack testnet chain. +description: Learn how to deploy and orchestrate all OP Stack components for a complete testnet deployment. lang: en-US content_type: tutorial topic: creating-your-own-l2-rollup-testnet personas: - chain-operator categories: - - mainnet - testnet - chain-deployment - - chain-configuration - - chain-operation - - node-management - op-deployer + - sequencer + - batcher + - proposer + - challenger + - integration is_imported_content: 'false' --- -import { Callout, Steps } from 'nextra/components' -import { WipCallout } from '@/components/WipCallout' +import { Callout, Card, Steps } from 'nextra/components' - # Creating your own L2 rollup testnet +Welcome to the complete guide for deploying your own OP Stack L2 rollup testnet. This multi-part tutorial will walk you through each component step-by-step, from initial setup to a fully functioning rollup. + -Please **be prepared to set aside approximately one hour** to get everything running properly and **make sure to read through the guide carefully**. -You don't want to miss any important steps that might cause issues down the line. + This tutorial requires **intermediate-level experience working with EVM chains**. + You should be comfortable with concepts like smart contracts, private keys, RPC endpoints, gas fees, and command-line operations. + Basic familiarity with Docker is also recommended. -This tutorial is **designed for developers** who want to learn about the OP Stack by spinning up an OP Stack testnet chain. -You'll walk through the full deployment process and teach you all of the components that make up the OP Stack, and **you'll end up with your very own OP Stack testnet**. +## What you'll build -It's useful to understand what each of these components does before -you start deploying your chain. To learn about the different components please -read the [deployment overview page](/operators/chain-operators/deploy/overview). +By the end of this tutorial, you'll have a complete OP Stack testnet with: -You can use this testnet to experiment and perform tests, or you can choose to modify the chain to adapt it to your own needs. -**The OP Stack is free and open source software licensed entirely under the MIT license**. -You don't need permission from anyone to modify or deploy the stack in any configuration you want. +* **L1 Smart Contracts** deployed on Sepolia testnet +* **Execution Client** (op-geth) processing transactions +* **Consensus Client** (op-node) managing rollup consensus +* **Batcher** (op-batcher) publishing transaction data to L1 +* **Proposer** (op-proposer) submitting state root proposals +* **Challenger** (op-challenger) monitoring for disputes - -Modifications to the OP Stack may prevent a chain from being able to benefit from aspects of the [Optimism Superchain](/superchain/superchain-explainer). -Make sure to check out the [Superchain Explainer](/superchain/superchain-explainer) to learn more. - +## Before you start -## Software dependencies +### Software dependencies -| Dependency | Version | Version Check Command | +| Dependency | Version | Version check command | | ------------------------------------------------------------- | -------- | --------------------- | | [git](https://git-scm.com/) | `^2` | `git --version` | | [go](https://go.dev/) | `^1.21` | `go version` | @@ -56,721 +55,142 @@ Make sure to check out the [Superchain Explainer](/superchain/superchain-explain | [make](https://linux.die.net/man/1/make) | `^3` | `make --version` | | [jq](https://github.com/jqlang/jq) | `^1.6` | `jq --version` | | [direnv](https://direnv.net) | `^2` | `direnv --version` | +| [Docker](https://docs.docker.com/get-docker/) | `^24` | `docker --version` | ### Notes on specific dependencies -#### `node` - -We recommend using the latest LTS version of Node.js (currently v20). -[`nvm`](https://github.com/nvm-sh/nvm) is a useful tool that can help you manage multiple versions of Node.js on your machine. -You may experience unexpected errors on older versions of Node.js. - -#### `foundry` - -It's recommended to use the scripts in the monorepo's `package.json` for managing `foundry` to ensure you're always working with the correct version. This approach simplifies the installation, update, and version checking process. Make sure to clone the monorepo locally before proceeding. -#### `direnv` - -Parts of this tutorial use [`direnv`](https://direnv.net) as a way of loading environment variables from `.envrc` files into your shell. -This means you won't have to manually export environment variables every time you want to use them. -`direnv` only ever has access to files that you explicitly allow it to see. - -After [installing `direnv`](https://direnv.net/docs/installation.html), you will need to **make sure that [`direnv` is hooked into your shell](https://direnv.net/docs/hook.html)**. -Make sure you've followed [the guide on the `direnv` website](https://direnv.net/docs/hook.html), then **close your terminal and reopen it** so that the changes take effect (or `source` your config file if you know how to do that). - - -Make sure that you have correctly hooked `direnv` into your shell by modifying your shell configuration file (like `~/.bashrc` or `~/.zshrc`). -If you haven't edited a config file then you probably haven't configured `direnv` properly (and things might not work later). - - -## Get access to a sepolia node - -You'll be deploying a OP Stack Rollup chain that uses a Layer 1 blockchain to host and order transaction data. -The OP Stack Rollups were designed to use EVM Equivalent blockchains like Ethereum, OP Mainnet, or standard Ethereum testnets as their L1 chains. - -**This guide uses the Sepolia testnet as an L1 chain**. -We recommend that you also use Sepolia. -You can also use other EVM-compatible blockchains, but you may run into unexpected errors. -If you want to use an alternative network, make sure to carefully review each command and replace any Sepolia-specific values with the values for your network. - -Since you're deploying your OP Stack chain to Sepolia, you'll need to have access to a Sepolia node. -You can either use a node provider like [Alchemy](https://www.alchemy.com/) (easier) or run your own Sepolia node (harder). - -## Build the source code - -You're going to be spinning up your OP Stack chain directly from source code instead of using a container system like [Docker](https://www.docker.com/). -Although this adds a few extra steps, it means you'll have an easier time modifying the behavior of the stack if you'd like to do so. -If you want a summary of the various components you'll be using, take another look at the [What You're Going to Deploy](#what-youre-going-to-deploy) section above. - - -You're using the home directory `~/` as the work directory for this tutorial for simplicity. -You can use any directory you'd like but using the home directory will allow you to copy/paste the commands in this guide. -If you choose to use a different directory, make sure you're using the correct directory in the commands throughout this tutorial. - - -### Build the Optimism monorepo - - - -{

Clone the Optimism Monorepo

} - -```bash -cd ~ -git clone https://github.com/ethereum-optimism/optimism.git -``` - -{

Enter the Optimism Monorepo

} - -```bash -cd optimism -``` - -{

Check out the correct branch

} - - -You will be using the `tutorials/chain` branch of the Optimism Monorepo to deploy an OP Stack testnet chain during this tutorial. -This is a non-production branch that lags behind the `develop` branch. -You should **NEVER** use the `develop` or `tutorials/chain` branches in production. - - -```bash -git checkout tutorials/chain -``` - -{

Check your dependencies

} - - -Don't skip this step! Make sure you have all of the required dependencies installed before continuing. - - -Run the following script and double check that you have all of the required versions installed. -If you don't have the correct versions installed, you may run into unexpected errors. - -```bash -./packages/contracts-bedrock/scripts/getting-started/versions.sh -``` - -{

Install dependencies

} - -```bash -pnpm install -``` - -{

Build the various packages inside of the Optimism Monorepo

} - -```bash -make op-node op-batcher op-proposer -pnpm build -``` - -
- -### Build `op-geth` - - - -{

Clone op-geth

} - -```bash -cd ~ -git clone https://github.com/ethereum-optimism/op-geth.git -``` - -{

Enter op-geth

} - -```bash -cd op-geth -``` - -{

Build op-geth

} - -```bash -make geth -``` - -
- -## Fill out environment variables - -You'll need to fill out a few environment variables before you can start deploying your chain. - - - -{

Enter the Optimism Monorepo

} - -```bash -cd ~/optimism -``` - -{

Duplicate the sample environment variable file

} - -```bash -cp .envrc.example .envrc -``` - -{

Fill out the environment variable file

} - -Open up the environment variable file and fill out the following variables: - -| Variable Name | Description | -| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `L1_RPC_URL` | URL for your L1 node (a Sepolia node in this case). | -| `L1_RPC_KIND` | Kind of L1 RPC you're connecting to, used to inform optimal transactions receipts fetching. Valid options: `alchemy`, `quicknode`, `infura`, `parity`, `nethermind`, `debug_geth`, `erigon`, `basic`, `any`. | - -
- -## Generate addresses - -You'll need four addresses and their private keys when setting up the chain: - -* The `Admin` address has the ability to upgrade contracts. -* The `Batcher` address publishes Sequencer transaction data to L1. -* The `Proposer` address publishes L2 transaction results (state roots) to L1. -* The `Sequencer` address signs blocks on the p2p network. - - - -{

Enter the Optimism Monorepo

} - -```bash -cd ~/optimism -``` - -{

Generate new addresses

} - - -You should **not** use the `wallets.sh` tool for production deployments. -If you are deploying an OP Stack based chain into production, you should likely be using a combination of hardware security modules and hardware wallets. - - -```bash -./packages/contracts-bedrock/scripts/getting-started/wallets.sh -``` - -{

Check the output

} - -Make sure that you see output that looks something like the following: - -```text -Copy the following into your .envrc file: - -# Admin address -export GS_ADMIN_ADDRESS=0x9625B9aF7C42b4Ab7f2C437dbc4ee749d52E19FC -export GS_ADMIN_PRIVATE_KEY=0xbb93a75f64c57c6f464fd259ea37c2d4694110df57b2e293db8226a502b30a34 - -# Batcher address -export GS_BATCHER_ADDRESS=0xa1AEF4C07AB21E39c37F05466b872094edcf9cB1 -export GS_BATCHER_PRIVATE_KEY=0xe4d9cd91a3e53853b7ea0dad275efdb5173666720b1100866fb2d89757ca9c5a - -# Proposer address -export GS_PROPOSER_ADDRESS=0x40E805e252D0Ee3D587b68736544dEfB419F351b -export GS_PROPOSER_PRIVATE_KEY=0x2d1f265683ebe37d960c67df03a378f79a7859038c6d634a61e40776d561f8a2 - -# Sequencer address -export GS_SEQUENCER_ADDRESS=0xC06566E8Ec6cF81B4B26376880dB620d83d50Dfb -export GS_SEQUENCER_PRIVATE_KEY=0x2a0290473f3838dbd083a5e17783e3cc33c905539c0121f9c76614dda8a38dca -``` - -{

Save the addresses

} - -Copy the output from the previous step and paste it into your `.envrc` file as directed. - -{

Fund the addresses

} - -**You will need to send ETH to the `Admin`, `Proposer`, and `Batcher` addresses.** -The exact amount of ETH required depends on the L1 network being used. -**You do not need to send any ETH to the `Sequencer` address as it does not send transactions.** - -It's recommended to fund the addresses with the following amounts when using Sepolia: - -* `Admin` — 0.5 Sepolia ETH -* `Batcher` — 0.1 Sepolia ETH -* `Proposer` — 0.2 Sepolia ETH - -**To get the required Sepolia ETH to fund the addresses, we recommend using the [Superchain Faucet](https://console.optimism.io/faucet?utm_source=op-docs&utm_medium=docs)** together with [Coinbase verification](https://help.coinbase.com/en/coinbase/getting-started/getting-started-with-coinbase/id-doc-verification). - -
- -## Load environment variables - -Now that you've filled out the environment variable file, you need to load those variables into your terminal. - - - -{

Enter the Optimism Monorepo

} - -```bash -cd ~/optimism -``` - -{

Load the variables with direnv

} - - -You're about to use `direnv` to load environment variables from the `.envrc` file into your terminal. -Make sure that you've [installed `direnv`](https://direnv.net/docs/installation.html) and that you've properly [hooked `direnv` into your shell](#configuring-direnv). - - -Next you'll need to allow `direnv` to read this file and load the variables into your terminal using the following command. - -```bash -direnv allow -``` - - -WARNING: `direnv` will unload itself whenever your `.envrc` file changes. -**You *must* rerun the following command every time you change the `.envrc` file.** - - -{

Confirm that the variables were loaded

} - -After running `direnv allow` you should see output that looks something like the following (the exact output will vary depending on the variables you've set, don't worry if it doesn't look exactly like this): - -```bash -direnv: loading ~/optimism/.envrc -direnv: export +DEPLOYMENT_CONTEXT +ETHERSCAN_API_KEY +GS_ADMIN_ADDRESS +GS_ADMIN_PRIVATE_KEY +GS_BATCHER_ADDRESS +GS_BATCHER_PRIVATE_KEY +GS_PROPOSER_ADDRESS +GS_PROPOSER_PRIVATE_KEY +GS_SEQUENCER_ADDRESS +GS_SEQUENCER_PRIVATE_KEY +IMPL_SALT +L1_RPC_KIND +L1_RPC_URL +PRIVATE_KEY +TENDERLY_PROJECT +TENDERLY_USERNAME -``` - -**If you don't see this output, you likely haven't [properly configured `direnv`](#configuring-direnv).** -Make sure you've configured `direnv` properly and run `direnv allow` again so that you see the desired output. - -
- -## Configure your network - -Once you've built both repositories, you'll need to head back to the Optimism Monorepo to set up the configuration file for your chain. -Currently, chain configuration lives inside of the [`contracts-bedrock`](https://github.com/ethereum-optimism/optimism/tree/v1.1.4/packages/contracts-bedrock) package in the form of a JSON file. - - - -{

Enter the Optimism Monorepo

} - -```bash -cd ~/optimism -``` - -{

Move into the contracts-bedrock package

} - -```bash -cd packages/contracts-bedrock -``` - -{

Install Foundry dependencies

} - -```bash -forge install -``` - -{

Generate the configuration file

} - -Run the following script to generate the `getting-started.json` configuration file inside of the `deploy-config` directory. - -```bash -./scripts/getting-started/config.sh -``` - -{

Review the configuration file (Optional)

} - -If you'd like, you can review the configuration file that was just generated by opening up `deploy-config/getting-started.json` in your favorite text editor. -It's recommended to keep this file as-is for now so you don't run into any unexpected errors. - -
- -## Deploy the Create2 factory (optional) - -If you're deploying an OP Stack chain to a network other than Sepolia, you may need to deploy a Create2 factory contract to the L1 chain. -This factory contract is used to deploy OP Stack smart contracts in a deterministic fashion. - - -This step is typically only necessary if you are deploying your OP Stack chain to custom L1 chain. -If you are deploying your OP Stack chain to Sepolia, you can safely skip this step. + + Expand each dependency below for details - - -{

Check if the factory exists

} - -The Create2 factory contract will be deployed at the address `0x4e59b44847b379578588920cA78FbF26c0B4956C`. -You can check if this contract has already been deployed to your L1 network with a block explorer or by running the following command: - -```bash -cast codesize 0x4e59b44847b379578588920cA78FbF26c0B4956C --rpc-url $L1_RPC_URL -``` - -If the command returns `0` then the contract has not been deployed yet. -If the command returns `69` then the contract has been deployed and you can safely skip this section. - -{

Fund the factory deployer

} - -You will need to send some ETH to the address that will be used to deploy the factory contract, `0x3fAB184622Dc19b6109349B94811493BF2a45362`. -This address can only be used to deploy the factory contract and will not be used for anything else. -Send at least 1 ETH to this address on your L1 chain. - -{

Deploy the factory

} - -Using `cast`, deploy the factory contract to your L1 chain: - -```bash -cast publish --rpc-url $L1_RPC_URL 0xf8a58085174876e800830186a08080b853604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf31ba02222222222222222222222222222222222222222222222222222222222222222a02222222222222222222222222222222222222222222222222222222222222222 -``` - -{

Wait for the transaction to be mined

} - -Make sure that the transaction is included in a block on your L1 chain before continuing. - -{

Verify that the factory was deployed

} - -Run the code size check again to make sure that the factory was properly deployed: - -```bash -cast codesize 0x4e59b44847b379578588920cA78FbF26c0B4956C --rpc-url $L1_RPC_URL -``` - -
- -## Deploy the L1 contracts +
+ node -Once you've configured your network, it's time to deploy the L1 contracts necessary for the functionality of the chain. + We recommend using the latest LTS version of Node.js (currently v20).\ + [`nvm`](https://github.com/nvm-sh/nvm) is a useful tool that can help you manage multiple versions of Node.js on your machine.\ + You may experience unexpected errors on older versions of Node.js. +
-## Using `op-deployer` +
+ foundry -The `op-deployer` tool simplifies the creation of genesis and rollup configuration files (`genesis.json` and `rollup.json`). -These files are crucial for initializing the execution client (`op-geth`) and consensus client (`op-node`) for your network. + We will use cast to generate wallet addresses in this guide. +
-The recommended flow for creating a genesis file and rollup configuration file on the OP Stack is as follows: +
+ direnv + Parts of this tutorial use [`direnv`](https://direnv.net) as a way of loading environment variables from `.envrc` files into your shell.\ + This means you won't have to manually export environment variables every time you want to use them.\ + `direnv` only ever has access to files that you explicitly allow it to see. -1. **Deploy the L1 contracts** using [op-deployer](/operators/chain-operators/tools/op-deployer). -2. **Generate** both the L2 genesis file (`genesis.json`) and the rollup configuration file (`rollup.json`) using op-deployer's `inspect` commands. -3. **Initialize** your off-chain components (e.g., execution client, consensus client). + After [installing `direnv`](https://direnv.net/docs/installation.html), you will need to **make sure that [`direnv` is hooked into your shell](https://direnv.net/docs/hook.html)**.\ + Make sure you've followed [the guide on the `direnv` website](https://direnv.net/docs/hook.html), then **close your terminal and reopen it** so that the changes take effect (or `source` your config file if you know how to do that). - -Using op-deployer for chain initialization is a requirement for all chains intending to be for chains who intend to be standard and join the superchain. -This ensures standardization and compatibility across the OP Stack ecosystem. - + + Make sure that you have correctly hooked `direnv` into your shell by modifying your shell configuration file (like `~/.bashrc` or `~/.zshrc`).\ + If you haven't edited a config file then you probably haven't configured `direnv` properly (and things might not work later). + +
-### Prerequisites +
+ Docker -1. You have installed the `op-deployer` binary following the instructions in [deployer docs](/operators/chain-operators/tools/op-deployer#installation). - After installation, extract the `op-deployer` into your `PATH` and `cd op-deployer`. + Docker is used extensively in this tutorial for running various OP Stack components.\ + Make sure you have both Docker and Docker Compose installed and running on your system.\ + On Linux, you may need to [configure Docker to run without sudo](https://docs.docker.com/engine/install/linux-postinstall/#manage-docker-as-a-non-root-user). -2. You have created and customized an intent file in a `.deployer` directory, typically by running: + + If you're using Docker Desktop, ensure it's running before starting the tutorial.\ + You can verify your installation with: ```bash - ./bin/op-deployer init --l1-chain-id --l2-chain-ids --workdir .deployer + docker run hello-world ``` + +
- Replace `` and `` with their respective values, see a list of [`chainIds`](https://chainid.network/). - -3. You have edited that intent file to your liking (roles, addresses, etc.). - -### Step 1: Deploy the L1 contracts - -To deploy your chain to L1, run: - -```bash -./bin/op-deployer apply --workdir .deployer \ - --l1-rpc-url \ - --private-key -``` - -* Replace `` with the L1 RPC URL. -* Replace `` with the private key of the account used for deployment. - -This command: - -* Reads your intent file in `.deployer/.` -* Deploys the OP Stack contracts to the specified L1. -* Updates a local `state.json` file with the results of the deployment. - -### Step 2: Generate your L2 genesis file and rollup file - -After your L1 contracts have been deployed, generate the L2 genesis and rollup configuration files by inspecting the deployer's `state.json.` - -```bash -./bin/op-deployer inspect genesis --workdir .deployer > .deployer/genesis.json -./bin/op-deployer inspect rollup --workdir .deployer > .deployer/rollup.json -``` - -* genesis.json is the file you will provide to your execution client (e.g. op-geth). -* rollup.json is the file you will provide to your consensus client (e.g. op-node). - -### Step 3: Initialize your off-chain components - -Once you have `genesis.json` and `rollup.json`: - -1. Initialize op-geth using genesis.json. -2. Configure op-node with rollup.json. -3. Set up additional off-chain infrastructure as needed (block explorer, indexers, etc.). For more on architecture, see [Architecture overview](/operators/chain-operators/architecture). - -## Initialize `op-geth` - -You're almost ready to run your chain! -Now you just need to run a few commands to initialize `op-geth`. -You're going to be running a Sequencer node, so you'll need to import the `Sequencer` private key that you generated earlier. -This private key is what your Sequencer will use to sign new blocks. - - - -{

Navigate to the op-geth directory

} - -```bash -cd ~/op-geth -``` - -{

Create a data directory folder

} - -```bash -mkdir datadir -``` - -{

Build the op-geth binary

} - -```bash -make geth -``` - -{

Initialize op-geth

} +### Get access to a sepolia node -```bash -build/bin/geth init --state.scheme=hash --datadir=datadir genesis.json -``` - -
- -## Start `op-geth` - -Now you'll start `op-geth`, your Execution Client. -Note that you won't start seeing any transactions until you start the Consensus Client in the next step. - - - -{

Open up a new terminal

} - -You'll need a terminal window to run `op-geth` in. - -{

Navigate to the op-geth directory

} +Since you're deploying your OP Stack chain to Sepolia, you'll need to have access to a Sepolia node. +You can either use a node provider like [Alchemy](https://www.alchemy.com/) (easier) or run your own Sepolia node (harder). -```bash -cd ~/op-geth -``` +### Required resources -{

Run op-geth

} +* **Sepolia ETH** - You'll need about 2-3 ETH: + * Start with [Superchain Faucet](https://console.optimism.io/faucet) (gives 0.05 ETH) + * Get more from: + * [Alchemy Faucet](https://sepoliafaucet.com/) + * [Infura Faucet](https://www.infura.io/faucet/sepolia) + * [Paradigm Faucet](https://faucet.paradigm.xyz/) + * Or ask in [Optimism Discord](https://discord.gg/optimism) +* **L1 RPC URL** - An RPC endpoint to connect to the Sepolia network. You can get this from node providers like [Alchemy](https://www.alchemy.com/), [Infura](https://www.infura.io/). This is required so `op-deployer` and other services can read from and send transactions to L1. - -You're using `--gcmode=archive` to run `op-geth` here because this node will act as your Sequencer. -It's useful to run the Sequencer in archive mode because the `op-proposer` requires access to the full state. -Feel free to run other (non-Sequencer) nodes in full mode if you'd like to save disk space. Just make sure at least one other archive node exists and the `op-proposer` points to it. + + **Testnet Only**: This guide is for **testnet deployment only**. -It's important that you've already initialized the geth node at this point as per the previous section. Failure to do this will cause startup issues between `op-geth` and `op-node`. + **Follow in Order**: Each step builds on the previous one. Start with spinning up op-deployer and complete them sequentially for the best experience. -```bash -./build/bin/geth \ - --datadir ./datadir \ - --http \ - --http.corsdomain="*" \ - --http.vhosts="*" \ - --http.addr=0.0.0.0 \ - --http.api=web3,debug,eth,txpool,net,engine \ - --ws \ - --ws.addr=0.0.0.0 \ - --ws.port=8546 \ - --ws.origins="*" \ - --ws.api=debug,eth,txpool,net,engine \ - --syncmode=full \ - --gcmode=archive \ - --nodiscover \ - --maxpeers=0 \ - --networkid=42069 \ - --authrpc.vhosts="*" \ - --authrpc.addr=0.0.0.0 \ - --authrpc.port=8551 \ - --authrpc.jwtsecret=./jwt.txt \ - --rollup.disabletxpoolgossip=true -``` - -
- -## Start `op-node` - -Once you've got `op-geth` running you'll need to run `op-node`. -Like Ethereum, the OP Stack has a Consensus Client (`op-node`) and an Execution Client (`op-geth`). -The Consensus Client "drives" the Execution Client over the Engine API. - - - -{

Open up a new terminal

} - -You'll need a terminal window to run the `op-node` in. +## Directory structure -{

Navigate to the op-node directory

} +To keep your rollup deployment organized, we'll create a dedicated directory structure. All components will be set up within this structure: ```bash -cd ~/optimism/op-node +rollup/ +├── deployer/ # op-deployer files and contracts +├── sequencer/ # op-geth and op-node +├── batcher/ # op-batcher configuration +├── proposer/ # op-proposer setup +└── challenger/ # op-challenger files ``` -{

Run op-node

} - -```bash -./bin/op-node \ - --l2=http://localhost:8551 \ - --l2.jwt-secret=./jwt.txt \ - --sequencer.enabled \ - --sequencer.l1-confs=5 \ - --verifier.l1-confs=4 \ - --rollup.config=./rollup.json \ - --rpc.addr=0.0.0.0 \ - --p2p.disable \ - --rpc.enable-admin \ - --p2p.sequencer.key=$GS_SEQUENCER_PRIVATE_KEY \ - --l1=$L1_RPC_URL \ - --l1.rpckind=$L1_RPC_KIND -``` - -Once you run this command, you should start seeing the `op-node` begin to sync L2 blocks from the L1 chain. -Once the `op-node` has caught up to the tip of the L1 chain, it'll begin to send blocks to `op-geth` for execution. -At that point, you'll start to see blocks being created inside of `op-geth`. +Each component's documentation will show you how the directory structure evolves as you add files and configurations. -**By default, your `op-node` will try to use a peer-to-peer to speed up the synchronization process.** -If you're using a chain ID that is also being used by others, like the default chain ID for this tutorial (42069), your `op-node` will receive blocks signed by other sequencers. -These requests will fail and waste time and network resources. -**To avoid this, this tutorial starts with peer-to-peer synchronization disabled (`--p2p.disable`).** - -Once you have multiple nodes, you may want to enable peer-to-peer synchronization. -You can add the following options to the `op-node` command to enable peer-to-peer synchronization with specific nodes: - -``` - --p2p.static= \ - --p2p.listen.ip=0.0.0.0 \ - --p2p.listen.tcp=9003 \ - --p2p.listen.udp=9003 \ -``` - -You can alternatively also remove the [--p2p.static](/operators/node-operators/configuration/consensus-config#p2pstatic) option, but you may see failed requests from other chains using the same chain ID. + Throughout this tutorial, all file paths will be relative to this `rollup` directory structure. Make sure to adjust any commands if you use different directory names. -
- -## Start `op-batcher` +## Tutorial overview -The `op-batcher` takes transactions from the Sequencer and publishes those transactions to L1. -Once these Sequencer transactions are included in a finalized L1 block, they're officially part of the canonical chain. -The `op-batcher` is critical! - -It's best to give the `Batcher` address at least 1 Sepolia ETH to ensure that it can continue operating without running out of ETH for gas. -Keep an eye on the balance of the `Batcher` address because it can expend ETH quickly if there are a lot of transactions to publish. +This tutorial is organized into sequential steps that build upon each other: + ### **[Spin up op-deployer](/operators/chain-operators/tutorials/create-l2-rollup/op-deployer-setup)** -{

Open up a new terminal

} - -You'll need a terminal window to run the `op-batcher` in. - -{

Navigate to the op-batcher directory

} + Install op-deployer, deploy L1 contracts, and prepare your environment -```bash -cd ~/optimism/op-batcher -``` + ### **[Spin up sequencer](/operators/chain-operators/tutorials/create-l2-rollup/op-geth-setup)** -{

Run op-batcher

} + Set up and run op-geth and op-node (the execution and consensus layers) -```bash -./bin/op-batcher \ - --l2-eth-rpc=http://localhost:8545 \ - --rollup-rpc=http://localhost:9545 \ - --poll-interval=1s \ - --sub-safety-margin=6 \ - --num-confirmations=1 \ - --safe-abort-nonce-too-low-count=3 \ - --resubmission-timeout=30s \ - --rpc.addr=0.0.0.0 \ - --rpc.port=8548 \ - --rpc.enable-admin \ - --max-channel-duration=25 \ - --l1-eth-rpc=$L1_RPC_URL \ - --private-key=$GS_BATCHER_PRIVATE_KEY -``` + ### **[Spin up batcher](/operators/chain-operators/tutorials/create-l2-rollup/op-batcher-setup)** - -The [`--max-channel-duration=n`](/operators/chain-operators/configuration/batcher#set-your--op_batcher_max_channel_duration) setting tells the batcher to write all the data to L1 every `n` L1 blocks. -When it is low, transactions are written to L1 frequently and other nodes can synchronize from L1 quickly. -When it is high, transactions are written to L1 less frequently and the batcher spends less ETH. -If you want to reduce costs, either set this value to 0 to disable it or increase it to a higher value. - + Configure and start op-batcher for L1 data publishing -
- -## Start `op-proposer` - -Now start `op-proposer`, which proposes new state roots. - - - -{

Open up a new terminal

} - -You'll need a terminal window to run the `op-proposer` in. - -{

Navigate to the op-proposer directory

} - -```bash -cd ~/optimism/op-proposer -``` + ### **[Spin up proposer](/operators/chain-operators/tutorials/create-l2-rollup/op-proposer-setup)** -{

Run op-proposer

} + Set up op-proposer for state root submissions -```bash -./bin/op-proposer \ - --poll-interval=12s \ - --rpc.port=8560 \ - --rollup-rpc=http://localhost:9545 \ - --l2oo-address=$(cat ../packages/contracts-bedrock/deployments/getting-started/.deploy | jq -r .L2OutputOracleProxy) \ - --private-key=$GS_PROPOSER_PRIVATE_KEY \ - --l1-eth-rpc=$L1_RPC_URL -``` + ### **[Spin up challenger](/operators/chain-operators/tutorials/create-l2-rollup/op-challenger-setup)** + Configure op-challenger for dispute resolution monitoring
-## Connect your wallet to your chain - -You now have a fully functioning OP Stack Rollup with a Sequencer node running on `http://localhost:8545`. -You can connect your wallet to this chain the same way you'd connect your wallet to any other EVM chain. -If you need an easy way to connect to your chain, just [click here](https://chainid.link?network=opstack-getting-started). - -## Get ETH on your chain +## Ready to Start? -Once you've connected your wallet, you'll probably notice that you don't have any ETH to pay for gas on your chain. -The easiest way to deposit Sepolia ETH into your chain is to send ETH directly to the `L1StandardBridge` contract. - - - -{

Navigate to the contracts-bedrock directory

} - -```bash -cd ~/optimism/packages/contracts-bedrock -``` - -{

Get the address of the L1StandardBridgeProxy contract

} - -```bash -cat deployments/getting-started/.deploy | jq -r .L1StandardBridgeProxy -``` - -{

Send some Sepolia ETH to the L1StandardBridgeProxy contract

} - -Grab the L1 bridge proxy contract address and, using the wallet that you want to have ETH on your Rollup, send that address a small amount of ETH on Sepolia (0.1 or less is fine). -This will trigger a deposit that will mint ETH into your wallet on L2. -It may take up to 5 minutes for that ETH to appear in your wallet on L2. - -
+Now that you understand what you'll be building, let's begin with the first step! -## See your rollup in action + + Already have your dependencies? Get started and spin up op-deployer + -You can interact with your Rollup the same way you'd interact with any other EVM chain. -Send some transactions, deploy some contracts, and see what happens! +*** -## Next steps +## Need Help? -* Check out the [protocol specs](https://specs.optimism.io/?utm_source=op-docs&utm_medium=docs) for more detail about the rollup protocol. -* If you run into any problems, please visit the [Chain Operators Troubleshooting Guide](/operators/chain-operators/management/troubleshooting) for help. +* **Community Support**: Join the [Optimism Discord](https://discord.gg/optimism) +* **Development Questions**: Visit [Developer Support](https://github.com/ethereum-optimism/developers/discussions) +* **Issues**: Report bugs on [GitHub](https://github.com/ethereum-optimism/optimism/issues) diff --git a/pages/operators/chain-operators/tutorials/create-l2-rollup/_meta.json b/pages/operators/chain-operators/tutorials/create-l2-rollup/_meta.json new file mode 100644 index 000000000..43db0cad0 --- /dev/null +++ b/pages/operators/chain-operators/tutorials/create-l2-rollup/_meta.json @@ -0,0 +1,8 @@ +{ + "index": "Overview", + "op-deployer-setup": "Spin up op-deployer", + "op-geth-setup": "Spin up sequencer", + "op-batcher-setup": "Spin up batcher", + "op-proposer-setup": "Spin up proposer", + "op-challenger-setup": "Spin up challenger" +} diff --git a/pages/operators/chain-operators/tutorials/create-l2-rollup/op-batcher-setup.mdx b/pages/operators/chain-operators/tutorials/create-l2-rollup/op-batcher-setup.mdx new file mode 100644 index 000000000..c3015cd20 --- /dev/null +++ b/pages/operators/chain-operators/tutorials/create-l2-rollup/op-batcher-setup.mdx @@ -0,0 +1,422 @@ +--- +title: Spin up batcher +lang: en-US +description: Learn how to set up and configure an OP Stack batcher to submit L2 transaction batches to L1. +content_type: tutorial +topic: batcher-setup +personas: + - chain-operator +categories: + - testnet + - mainnet + - op-batcher + - batch-submission + - l2-to-l1-data + - transaction-batching +is_imported_content: 'false' +--- + +import { Callout, Steps, Card, Tabs } from 'nextra/components' + +# Spin up batcher + +After you have spun up your sequencer, you need to configure a batcher to submit L2 transaction batches to L1. + + + **Step 3 of 5**: This tutorial is designed to be followed step-by-step. Each step builds on the [previous one](/operators/chain-operators/tutorials/create-l2-rollup/op-geth-setup). + + +## Understanding the batcher's role + +The batcher (`op-batcher`) serves as a crucial component that bridges your L2 chain data to L1. Its primary responsibilities include: + +* **Batch submission**: Collecting L2 transactions and submitting them as batches to L1 +* **Data availability**: Ensuring L2 transaction data is available on L1 for verification +* **Cost optimization**: Compressing and efficiently packing transaction data to minimize L1 costs +* **Channel management**: Managing data channels for optimal batch submission timing + +The batcher reads transaction data from your sequencer and submits compressed batches to the `BatchInbox` contract on L1. + +## Prerequisites + +Before setting up your batcher, ensure you have: + +**Running infrastructure:** + +* An operational sequencer node +* Access to a L1 RPC endpoint + +**Network information:** + +* Your L2 chain ID and network configuration +* L1 network details (chain ID, RPC endpoints) +* `BatchInbox` contract address from your deployment + +For setting up the batcher, we recommend using Docker as it provides a consistent and isolated environment. Building from source is also available for more advanced users. + + + + If you prefer containerized deployment, you can use the official Docker images and do the following: + + + ### Set up directory structure and copy configuration files + + ```bash + # Create your batcher directory inside rollup + cd ../ # Go back to rollup directory if you're in sequencer + mkdir batcher + cd batcher + + # Copy configuration files from deployer + cp ../deployer/.deployer/state.json . + + # Extract the BatchInbox address + BATCH_INBOX_ADDRESS=$(cat state.json | jq -r '.opChainDeployments[0].systemConfigProxyAddress') + echo "BatchInbox Address: $BATCH_INBOX_ADDRESS" + ``` + + ### Create environment variables file + + ```bash + # Create .env file with your actual values + cat > .env << 'EOF' + # L1 Configuration - Replace with your actual RPC URLs + L1_RPC_URL=https://sepolia.infura.io/v3/YOUR_ACTUAL_INFURA_KEY + + # L2 Configuration - Should match your sequencer setup + L2_RPC_URL=http://op-geth:8545 + ROLLUP_RPC_URL=http://op-node:8547 + + # Contract addresses - Extract from your op-deployer output + BATCH_INBOX_ADDRESS=YOUR_ACTUAL_BATCH_INBOX_ADDRESS + + # Private key - Replace with your actual private key + BATCHER_PRIVATE_KEY=YOUR_ACTUAL_PRIVATE_KEY + + # Batcher configuration + POLL_INTERVAL=1s + SUB_SAFETY_MARGIN=6 + NUM_CONFIRMATIONS=1 + SAFE_ABORT_NONCE_TOO_LOW_COUNT=3 + RESUBMISSION_TIMEOUT=30s + MAX_CHANNEL_DURATION=25 + + # RPC configuration + BATCHER_RPC_PORT=8548 + EOF + ``` + + **Important**: Replace ALL placeholder values (`YOUR_ACTUAL_*`) with your real configuration values. + + ### Create a docker-compose.yml file + + + This configuration assumes your sequencer is running in a Docker container named `sequencer-node` on the same `op-stack` network. + Make sure your sequencer is running before starting the batcher. + + + ```yaml + + services: + op-batcher: + image: us-docker.pkg.dev/oplabs-tools-artifacts/images/op-batcher:v1.13.2 + volumes: + - .:/workspace + working_dir: /workspace + ports: + - "8548:8548" + env_file: + - .env + networks: + - sequencer-node_default + command: + - "op-batcher" + - "--l2-eth-rpc=${L2_RPC_URL}" + - "--rollup-rpc=${ROLLUP_RPC_URL}" + - "--poll-interval=${POLL_INTERVAL}" + - "--sub-safety-margin=${SUB_SAFETY_MARGIN}" + - "--num-confirmations=${NUM_CONFIRMATIONS}" + - "--safe-abort-nonce-too-low-count=${SAFE_ABORT_NONCE_TOO_LOW_COUNT}" + - "--resubmission-timeout=${RESUBMISSION_TIMEOUT}" + - "--rpc.addr=0.0.0.0" + - "--rpc.port=${BATCHER_RPC_PORT}" + - "--rpc.enable-admin" + - "--max-channel-duration=${MAX_CHANNEL_DURATION}" + - "--l1-eth-rpc=${L1_RPC_URL}" + - "--private-key=${BATCHER_PRIVATE_KEY}" + - "--batch-type=1" + - "--data-availability-type=blobs" + - "--log.level=info" + - "--max-pending-tx=0" + restart: unless-stopped + + networks: + sequencer-node_default: + external: false + ``` + + ### Start the batcher service + + ```bash + # Make sure your sequencer network exists + # Start the batcher + docker-compose up -d + + # View logs + docker-compose logs -f op-batcher + ``` + + ### Verify batcher is running + + ```bash + # Check container status + docker-compose ps + ``` + + ### Final directory structure + + ```bash + rollup/ + ├── deployer/ # From previous step + │ └── .deployer/ # Contains genesis.json and rollup.json + ├── sequencer/ # From previous step + └── batcher/ # You are here + ├── state.json # Copied from deployer + ├── .env # Environment variables + └── docker-compose.yml # Docker configuration + ``` + + + Your batcher is now operational and will continuously submit L2 transaction batches to L1! + + + + + To ensure you're using the latest compatible versions of OP Stack components, always check the official [releases page](https://github.com/ethereum-optimism/optimism/releases). + + Look for the latest `op-batcher/v*` release that's compatible with your sequencer setup. + + + This guide uses `op-batcher/v1.13.2` which is compatible with op-node/v1.13.3 and op-geth/v1.101511.1 from the sequencer setup. + Always check the [release notes](https://github.com/ethereum-optimism/optimism/releases) for compatibility information. + + + + ### Clone and build op-batcher + + ```bash + # If you don't already have the optimism repository from the sequencer setup + git clone https://github.com/ethereum-optimism/optimism.git + cd optimism + + # Checkout the latest release tag + git checkout op-batcher/v1.13.2 + + # Build op-batcher + cd op-batcher + just + + # Binary will be available at ./bin/op-batcher + ``` + + ### Verify installation + + Run this command to verify the installation: + + ```bash + ./bin/op-batcher --version + ``` + ### Configuration setup + + + For advanced configuration options and fine-tuning your batcher, including: + + * Batch submission policies + * Channel duration settings + * Data availability types (blobs vs calldata) + * Transaction throttling + * Network timeouts + + Check out the [Batcher Configuration Reference](/operators/chain-operators/configuration/batcher). + This will help you optimize your batcher's performance and cost-efficiency. + + + + ### Organize your workspace + + Create your batcher working directory: + + ```bash + # Create batcher directory inside rollup + cd ../ # Go back to rollup directory + mkdir batcher + cd batcher + + # Create scripts directory + mkdir scripts + ``` + + Your final directory structure should look like: + + ```bash + rollup/ + ├── deployer/ # From previous step + │ └── .deployer/ # Contains state.json + ├── optimism/ # Contains op-batcher binary + ├── sequencer/ # From previous step + └── batcher/ # You are here + ├── state.json # Copied from deployer + ├── .env # Environment variables + └── scripts/ # Startup scripts + └── start-batcher.sh + ``` + + ### Extract BatchInbox address + + Extract the `BatchInbox` contract address from your op-deployer output: + + ```bash + # Make sure you're in the rollup/batcher directory + cd rollup/batcher + + # Copy the deployment state file from deployer + cp ../deployer/.deployer/state.json . + + # Extract the BatchInbox address + BATCH_INBOX_ADDRESS=$(cat state.json | jq -r '.opChainDeployments[0].systemConfigProxyAddress') + echo "BatchInbox Address: $BATCH_INBOX_ADDRESS" + ``` + + + The batcher submits transaction batches to the `BatchInbox` contract on L1. This contract is responsible for accepting and storing L2 transaction data. + + + ### Set up environment variables + + Create your `.env` file with the actual values: + + ```bash + # Create .env file with your actual values + # L1 Configuration - Replace with your actual RPC URL + L1_RPC_URL=https://sepolia.infura.io/v3/YOUR_ACTUAL_INFURA_KEY + + # L2 Configuration - Should match your sequencer setup + L2_RPC_URL=http://op-geth:8545 + ROLLUP_RPC_URL=http://op-node:8547 + + # Contract addresses - Extract from your op-deployer output + BATCH_INBOX_ADDRESS=YOUR_ACTUAL_BATCH_INBOX_ADDRESS + + # Private key - Replace with your actual private key + BATCHER_PRIVATE_KEY=YOUR_ACTUAL_PRIVATE_KEY + + # Batcher configuration + POLL_INTERVAL=1s + SUB_SAFETY_MARGIN=6 + NUM_CONFIRMATIONS=1 + SAFE_ABORT_NONCE_TOO_LOW_COUNT=3 + RESUBMISSION_TIMEOUT=30s + MAX_CHANNEL_DURATION=25 + + # RPC configuration + BATCHER_RPC_PORT=8548 + ``` + + **Important**: Replace ALL placeholder values (`YOUR_ACTUAL_*`) with your real configuration values! + + ### Get your private key + + Get a private key from your wallet that will be used for submitting batches to L1. This account needs sufficient ETH to pay for L1 gas costs. + + + The batcher account needs to be funded with ETH on L1 to pay for batch submission transactions. Monitor this account's balance regularly as it will consume ETH for each batch submission. + + + + ### Batcher configuration + + Create `scripts/start-batcher.sh` in the same directory: + + ```bash + #!/bin/bash + + source .env + + # Path to the op-batcher binary we built + ../../optimism/op-batcher/bin/op-batcher \ + --l2-eth-rpc=$L2_RPC_URL \ + --rollup-rpc=$ROLLUP_RPC_URL \ + --poll-interval=$POLL_INTERVAL \ + --sub-safety-margin=$SUB_SAFETY_MARGIN \ + --num-confirmations=$NUM_CONFIRMATIONS \ + --safe-abort-nonce-too-low-count=$SAFE_ABORT_NONCE_TOO_LOW_COUNT \ + --resubmission-timeout=$RESUBMISSION_TIMEOUT \ + --rpc.addr=0.0.0.0 \ + --rpc.port=$BATCHER_RPC_PORT \ + --rpc.enable-admin \ + --max-channel-duration=$MAX_CHANNEL_DURATION \ + --l1-eth-rpc=$L1_RPC_URL \ + --private-key=$BATCHER_PRIVATE_KEY \ + --batch-type=1 \ + --data-availability-type=blobs \ + --log.level=info + ``` + + ### Batcher parameters explained + + * **`--poll-interval`**: How frequently the batcher checks for new L2 blocks to batch + * **`--sub-safety-margin`**: Number of confirmations to wait before considering L1 transactions safe + * **`--max-channel-duration`**: Maximum time (in L1 blocks) to keep a channel open + * **`--batch-type`**: Type of batch encoding (1 for span batches, 0 for singular batches) + * **`--data-availability-type`**: Whether to use blobs or calldata for data availability + + ### Starting the batcher + + ### Start the batcher + + ```bash + # Make the script executable + chmod +x scripts/start-batcher.sh + + # Start the batcher + ./scripts/start-batcher.sh + ``` + + + For detailed cost analysis and optimization strategies, refer to the [Fee calculation tools](/operators/chain-operators/tools/fee-calculator). + + + Your batcher is now operational and will continuously submit L2 transaction batches to L1! + + + + + + + **Understanding common startup messages** + + When starting your batcher, you might see various log messages: + + * `Added L2 block to local state`: Normal operation, shows the batcher processing blocks + * `SetMaxDASize RPC method unavailable`: Expected if the `op-geth` version used doesn't support this method. + * `context canceled` errors during shutdown: Normal cleanup messages + * `Failed to query L1 tip`: Can occur during graceful shutdowns + + Most of these messages are part of normal operation. For detailed explanations of configuration options and troubleshooting, see the [Batcher configuration reference](/operators/chain-operators/configuration/batcher). + + +## What's Next? + +Excellent! Your batcher is publishing transaction data to L1. The next step is to set up the proposer to submit state root proposals. + + + **Next**: Configure and start op-proposer to submit L2 state roots to L1 for withdrawal verification. + + +*** + +## Need Help? + +* **Community Support**: Join the [Optimism Discord](https://discord.optimism.io) +* **Batcher Configuration**: [op-batcher Configuration Reference](/operators/chain-operators/configuration/batcher) +* **Monitoring Guide**: [Chain Monitoring](/operators/chain-operators/tools/chain-monitoring) diff --git a/pages/operators/chain-operators/tutorials/create-l2-rollup/op-challenger-setup.mdx b/pages/operators/chain-operators/tutorials/create-l2-rollup/op-challenger-setup.mdx new file mode 100644 index 000000000..312ad4c33 --- /dev/null +++ b/pages/operators/chain-operators/tutorials/create-l2-rollup/op-challenger-setup.mdx @@ -0,0 +1,628 @@ +--- +title: Spin up challenger +description: Learn how to configure challenger for your OP Stack chain. +lang: en-US +content_type: tutorial +topic: configure-challenger-for-your-chain +personas: + - chain-operator +categories: + - mainnet + - testnet + - fault-proofs + - op-challenger + - chain-configuration +is_imported_content: 'false' +--- + +import { Callout, Steps, Tabs, Tab } from 'nextra/components' + +# Spin up challenger + +After you have spun up your sequencer, batcher, and proposer, the final step is to configure a challenger to monitor and respond to disputes. The challenger is the security component that ensures the integrity of your rollup by monitoring dispute games and responding to invalid claims. + + + **Step 5 of 5**: This tutorial is designed to be followed step-by-step. + Each step builds on the previous one, and this is the last part of the tutorial. + + +This guide provides step-by-step instructions for setting up the configuration and monitoring options for `op-challenger`. The challenger is a critical fault proofs component that monitors dispute games and challenges invalid claims to protect your OP Stack chain. + +See the [OP-Challenger explainer](/stack/fault-proofs/challenger) for a general overview of this fault proofs feature. + +The challenger is responsible for: + +* Monitoring dispute games created by the fault proof system +* Challenging invalid claims in dispute games +* Defending valid state transitions +* Resolving games when possible + +## Prerequisites + +### Essential requirements + +Before configuring your challenger, complete the following steps: + + + ### Deploy OP Stack chain with fault proofs enabled + +
+ Generate absolute prestate (Required) + + The challenger needs the absolute prestate to participate in dispute games. Here's how to generate it: + + 1. **Clone and checkout the correct version**: + ```bash + git clone https://github.com/ethereum-optimism/optimism.git + cd optimism + git checkout op-program/v1.6.1 # Use the latest stable version + git submodule update --init --recursive + ``` + + 2. **Copy your chain configuration**: + ```bash + # Assuming you're in rollup/challenger/optimism directory + # Replace with your actual L2 chain ID + cp ../deployer/.deployer/rollup.json op-program/chainconfig/configs/-rollup.json + cp ../deployer/.deployer/genesis.json op-program/chainconfig/configs/-genesis.json + + # Your directory structure should look like: + # rollup/ + # ├── deployer/ + # │ └── .deployer/ + # │ ├── rollup.json # Source file + # │ └── genesis.json # Source file + # └── optimism/ # You are here + # └── op-program/ + # └── chainconfig/ + # └── configs/ + # ├── -rollup.json # Destination + # └── -genesis.json # Destination + ``` + + 3. **Generate the prestate**: + ```bash + make reproducible-prestate + ``` + You'll see output like: + ```bash + -------------------- Production Prestates -------------------- + Cannon64 Absolute prestate hash: + 0x03eb07101fbdeaf3f04d9fb76526362c1eea2824e4c6e970bdb19675b72e4fc8 + ``` + + 4. **Prepare the preimage file**: + ```bash + cd op-program/bin + mv prestate-mt64.bin.gz 0x[CANNON64_PRESTATE_HASH].bin.gz + ``` + Replace `[CANNON64_PRESTATE_HASH]` with the actual hash from step 3. + + + * Use the `Cannon64` hash for production + * Keep this file accessible - you'll need it for the challenger setup + * For Superchain registry chains, you can find official prestates in the [registry](https://github.com/ethereum-optimism/superchain-registry/blob/main/validation/standard/standard-prestates.toml) + +
+ ### Set up required infrastructure access + + * L1 RPC endpoint (Ethereum, Sepolia, etc.) + * L1 Beacon node endpoint (for blob access) + + ### Prepare configuration files + + * `prestate.json` - The absolute prestate file generated in step 1 + * `rollup.json` - Rollup configuration file from the `op-deployer` guide +
+ +## Software installation + +For challenger deployment, we recommend using Docker as it provides a consistent and isolated environment. Building from source is also available for more advanced users. + + + + + ### Docker Setup + + The Docker setup provides a containerized environment for running the challenger. This method uses the official Docker image that includes embedded `op-program` server and Cannon executable. + + + ### Create challenger directory + + ```bash + # Create your challenger directory inside rollup + cd ../ # Go back to rollup directory if you're in proposer + mkdir challenger + cd challenger + ``` + + ### Create environment file + + First, create a `.env` file with your configuration values. This file will be used by Docker Compose to set up the environment variables: + + ```bash + # Create .env file with your actual values + cat > .env << 'EOF' + # L1 Configuration - Replace with your actual RPC URLs + L1_RPC_URL=https://sepolia.infura.io/v3/YOUR_ACTUAL_INFURA_KEY + L1_BEACON=https://ethereum-sepolia-beacon-api.publicnode.com + + # L2 Configuration - Replace with your actual node endpoints + L2_RPC_URL=http://op-geth:8545 + ROLLUP_RPC_URL=http://op-node:8547 + + # Private key - Replace with your actual private key + PRIVATE_KEY=YOUR_ACTUAL_PRIVATE_KEY + + # Network configuration + NETWORK=op-sepolia + GAME_FACTORY_ADDRESS=YOUR_GAME_FACTORY_ADDRESS + + # Prestate configuration - Replace with the hash from 'make reproducible-prestate' + PRESTATE_HASH=YOUR_PRESTATE_HASH + EOF + ``` + + **Important:** Replace ALL placeholder values (`YOUR_ACTUAL_*`) with your real configuration values. + + ### Set up Docker Compose + + Create a `docker-compose.yml` file that defines the challenger service. The file mounts several important files: + * `prestate-proof-mt64.json` and `${PRESTATE_HASH}.bin.gz`: Prestate files required for dispute games (the PRESTATE_HASH comes from running `make reproducible-prestate`), replace `PRESTATE_HASH` with the actual hash + + ```yaml + + services: + challenger: + image: us-docker.pkg.dev/oplabs-tools-artifacts/images/op-challenger:v1.5.0 + user: "1000" + volumes: + - ./challenger-data:/data + - ./rollup.json:/workspace/rollup.json:ro + - ./genesis-l2.json:/workspace/genesis-l2.json:ro + - ./prestate-proof-mt64.json:/workspace/prestate-proof.json:ro + - ./${PRESTATE_HASH}.bin.gz:/workspace/${PRESTATE_HASH}.bin.gz:ro + environment: + - L1_RPC_URL=${L1_RPC_URL} + - L1_BEACON=${L1_BEACON} + - L2_RPC_URL=${L2_RPC_URL} + - ROLLUP_RPC_URL=${ROLLUP_RPC_URL} + - PRIVATE_KEY=${PRIVATE_KEY} + - NETWORK=${NETWORK} + - GAME_FACTORY_ADDRESS=${GAME_FACTORY_ADDRESS} + command: + - "op-challenger" + - "--trace-type=cannon,asterisc-kona" + - "--l1-eth-rpc=${L1_RPC_URL}" + - "--l1-beacon=${L1_BEACON}" + - "--l2-eth-rpc=${L2_RPC_URL}" + - "--rollup-rpc=${ROLLUP_RPC_URL}" + - "--selective-claim-resolution" + - "--private-key=${PRIVATE_KEY}" + - "--game-factory-address=${GAME_FACTORY_ADDRESS}" + - "--datadir=/data" + - "--cannon-prestate=/workspace/prestate-proof.json" + - "--cannon-bin=/workspace/${PRESTATE_HASH}.bin.gz" + - "--asterisc-kona-prestate=/workspace/prestate-proof.json" + restart: unless-stopped + networks: + - sequencer-node_default + + networks: + sequencer-node_default: + external: false + + + ``` + + ### Launch the challenger + + Start the challenger service and monitor its logs: + + ```bash + # Start the challenger service + docker-compose up -d + + # View logs + docker-compose logs -f challenger + ``` + + + + + + To ensure you're using the latest compatible versions of OP Stack components, always check the official releases page: + + [OP Stack releases page](https://github.com/ethereum-optimism/optimism/releases) + + Look for the latest `op-challenger/v*` release. The challenger version used in this guide (op-challenger/v1.5.0) is a verified stable version. + + Always check the release notes to ensure you're using compatible versions with your chain's deployment. + + ### Build and Configure + + Building from source gives you full control over the binaries. + + **Clone and build op-challenger** + + ```bash + # Clone the optimism monorepo + git clone https://github.com/ethereum-optimism/optimism.git + cd optimism + + # Check out the latest release of op-challenger + git checkout op-challenger/v1.5.0 + + # Install dependencies and build + just op-challenger + + # Binary will be available at ./op-challenger/bin/op-challenger + ``` + + ### Verify installation + + Check that you have properly installed the challenger component: + + ```bash + # Make sure you're in the optimism directory + ./op-challenger/bin/op-challenger --help + + # You should see the challenger help output with available commands and flags + ``` + + ## Configuration setup + + + The following steps require a Cannon binary and the op-program server. + Ensure these binaries are available at the paths you configure (`CANNON_BIN` and `CANNON_SERVER`). + + + + ### Organize your workspace + + After building the binaries, create your challenger working directory: + + ```bash + # Create challenger directory inside rollup + cd ../ # Go back to rollup directory + mkdir challenger + cd challenger + + # Create necessary subdirectories + mkdir scripts + mkdir challenger-data + + # Verify the optimism directory is accessible + # Directory structure should look like: + # rollup/ + # ├── deployer/ (from previous step) + # ├── optimism/ (contains the built binaries) + # ├── sequencer/ (from previous step) + # ├── batcher/ (from previous step) + # ├── proposer/ (from previous step) + # └── challenger/ (you are here) + ``` + + ### Copy configuration files + + ```bash + # Copy configuration files to your challenger directory + # Adjust paths based on your deployment setup + cp /path/to/your/rollup.json . + cp /path/to/your/genesis-l2.json . + ``` + + ### Set up environment variables + + You'll need to gather several pieces of information before creating your configuration. Here's where to get each value: + + **L1 network access:** + + * L1 RPC URL: Your L1 node endpoint (Infura, Alchemy, or self-hosted) + * L1 Beacon URL: Beacon chain API endpoint for blob access + + **L2 network access:** + + * L2 RPC URL: Your op-geth archive node endpoint + * Rollup RPC URL: Your op-node endpoint with historical data + + **Challenger wallet:** + + * Private key for challenger operations (must be funded) + + **Network configuration:** + + * Game factory address from your contract deployment + * Network identifier (e.g., op-sepolia, op-mainnet, or custom) + + Copy and paste in your terminal, to create your env file. + + ```bash + # Create .env file with your actual values + cat > .env << 'EOF' + # L1 Configuration - Replace with your actual RPC URLs + L1_RPC_URL=https://sepolia.infura.io/v3/YOUR_ACTUAL_INFURA_KEY + + # L2 Configuration - Replace with your actual node endpoints + L2_RPC_URL=http://localhost:8545 + ROLLUP_RPC_URL=http://localhost:8547 + L1_BEACON=http://sepolia-cl-1:5051 + + # Private key - Replace with your actual private key + PRIVATE_KEY=YOUR_ACTUAL_PRIVATE_KEY + + # Network configuration + NETWORK=op-sepolia + GAME_FACTORY_ADDRESS=YOUR_GAME_FACTORY_ADDRESS + + # Trace configuration + TRACE_TYPE=permissioned,cannon + + # Data directory + DATADIR=./challenger-data + + # Configuration files from your deployment + CANNON_ROLLUP_CONFIG=./rollup.json + CANNON_L2_GENESIS=./genesis-l2.json + + # Cannon configuration + # Prestate file - Generate this using the absolute prestate guide + # Run 'make reproducible-prestate' in the optimism repo to generate it + # The Cannon binary is a specific hash file that matches your deployment + CANNON_BIN=./0x.bin.gz + # The op-program server binary is built when you run 'just op-challenger' + CANNON_SERVER=../../optimism/op-program/bin/op-program + CANNON_PRESTATE=../../optimism/op-program/bin/prestate.json + + EOF + ``` + + **Important:** Replace ALL placeholder values (`YOUR_ACTUAL_*`) with your real configuration values. + + ### Understanding key configuration flags + +
+ --l1-eth-rpc + + * This is the HTTP provider URL for a standard L1 node, can be a full node. `op-challenger` will be sending many requests, so chain operators need a node that is trusted and can easily handle many transactions. + * Note: Challenger has a lot of money, and it will spend it if it needs to interact with games. That might risk not defending games or challenging games correctly, so chain operators should really trust the nodes being pointed at Challenger. +
+ +
+ --l1-beacon + + * This is needed just to get blobs from. + * In some instances, chain operators might need a blob archiver or L1 consensus node configured not to prune blobs: + * If the chain is proposing regularly, a blob archiver isn't needed. There's only a small window in the blob retention period that games can be played. + * If the chain doesn't post a valid output root in 18 days, then a blob archiver running a challenge game is needed. If the actor gets pushed to the bottom of the game, it could lose if it's the only one protecting the chain. +
+ +
+ --l2-eth-rpc + + * This needs to be `op-geth` archive node, with `debug` enabled. + * Technically doesn't need to go to bedrock, but needs to have access to the start of any game that is still in progress. +
+ +
+ --rollup-rpc + + * This needs to be an `op-node` archive node because challenger needs access to output roots from back when the games start. See below for important configuration details: + + 1. Safe Head Database (SafeDB) Configuration for op-node: + + * The `op-node` behind the `op-conductor` must have the SafeDB enabled to ensure it is not stateless. + * To enable SafeDB, set the `--safedb.path` value in your configuration. This specifies the file path used to persist safe head update data. + * Example Configuration: + + ``` + --safedb.path # Replace with your actual path + ``` + + + If this path is not set, the SafeDB feature will be disabled. + + + 2. Ensuring Historical Data Availability: + + * Both `op-node` and `op-geth` must have data from the start of the games to maintain network consistency and allow nodes to reference historical state and transactions. + * For `op-node`: Configure it to maintain a sufficient history of blockchain data locally or use an archive node. + * For `op-geth`: Similarly, configure to store or access historical data. + * Example Configuration: + + ``` + op-node \ + --rollup-rpc \ + --safedb.path + ``` + + + Replace `` with the URL of your archive node and `` with the desired path for storing SafeDB data. + +
+ +
+ --private-key + + * Chain operators must specify a private key or use something else (like `op-signer`). + * This uses the same transaction manager arguments as `op-node` , batcher, and proposer, so chain operators can choose one of the following options: + * a mnemonic + * a private key + * `op-signer` endpoints +
+ +
+ --network + + * This identifies the L2 network `op-challenger` is running for, e.g., `op-sepolia` or `op-mainnet`. + * When using the `--network` flag, the `--game-factory-address` will be automatically pulled from the [`superchain-registry`](https://github.com/ethereum-optimism/superchain-registry/blob/main/chainList.json). + * When cannon is executed, challenger needs the roll-up config and the L2 Genesis, which is op-geth's Genesis file. Both files are automatically loaded when Cannon Network is used, but custom networks will need to specify both Cannon L2 Genesis and Cannon rollup config. + * For custom networks not in the [`superchain-registry`](https://github.com/ethereum-optimism/superchain-registry/blob/main/chainList.json), the `--game-factory-address` and rollup must be specified, as follows: + + ``` + --cannon-rollup-config rollup.json \ + --cannon-l2-genesis genesis-l2.json \ + # use this if running challenger outside of the docker image + --cannon-server ./op-program/bin/op-program \ + # json or url, version of op-program deployed on chain + # if you use the wrong one, you will lose the game + # if you deploy your own contracts, you specify the hash, the root of the json file + # op mainnet are tagged versions of op-program + # make reproducible prestate + # challenger verifies that onchain + --cannon-prestate ./op-program/bin/prestate.json \ + # load the game factory address from system config or superchain registry + # point the game factory address at the dispute game factory proxy + --game-factory-address + ``` + + + These options vary based on which `--network` is specified. Chain operators always need to specify a way to load prestates and must also specify the cannon-server whenever the docker image isn't being used. + +
+ +
+ --datadir + + * This is a directory that `op-challenger` can write to and store whatever data it needs. It will manage this directory to add or remove data as needed under that directory. + * If running in docker, it should point to a docker volume or mount point, so the data isn't lost on every restart. The data can be recreated if needed but particularly if challenger has executed cannon as part of responding to a game it may mean a lot of extra processing. +
+ +
+ --cannon-prestates-url + + The pre-state is effectively the version of `op-program` that is deployed on chain. And chain operators must use the right version. `op-challenger` will refuse to interact with games that have a different absolute prestate hash to avoid making invalid claims. If deploying your own contracts, chain operators must specify an absolute prestate hash taken from the `make reproducible-prestate` command during contract deployment, which will also build the required prestate json file. + + All governance approved releases use a tagged version of `op-program`. These can be rebuilt by checking out the version tag and running `make reproducible-prestate`. + + * There are two ways to specify the prestate to use: + * `--cannon-prestate`: specifies a path to a single Cannon pre-state Json file + * `--cannon-prestates-url`: specifies a URL to load pre-states from. This enables participating in games that use different prestates, for example due to a network upgrade. The prestates are stored in this directory named by their hash. + * Example final URL for a prestate: + * [https://example.com/prestates/0x031e3b504740d0b1264e8cf72b6dde0d497184cfb3f98e451c6be8b33bd3f808.json](https://example.com/prestates/0x031e3b504740d0b1264e8cf72b6dde0d497184cfb3f98e451c6be8b33bd3f808.json) + * This file contains the cannon memory state. + + + Challenger will refuse to interact with any games if it doesn't have the matching prestate. + Check this [guide](/operators/chain-operators/tutorials/absolute-prestate#generating-the-absolute-prestate) on how to generate an absolute prestate. + +
+
+ + ### Create challenger startup script + + Create `scripts/start-challenger.sh`: + + ```bash + #!/bin/bash + source .env + + # Path to the challenger binary + ../../optimism/op-challenger/bin/op-challenger \ + --trace-type permissioned,cannon \ + --l1-eth-rpc=$L1_RPC_URL \ + --l2-eth-rpc=$L2_RPC_URL \ + --l1-beacon=$L1_BEACON \ + --rollup-rpc=$ROLLUP_RPC_URL \ + --game-factory-address $GAME_FACTORY_ADDRESS \ + --datadir=$DATADIR \ + --cannon-bin=$CANNON_BIN \ + --cannon-rollup-config=$CANNON_ROLLUP_CONFIG \ + --cannon-l2-genesis=$CANNON_L2_GENESIS \ + --cannon-server=$CANNON_SERVER \ + --cannon-prestate=$CANNON_PRESTATE \ + --private-key="$PRIVATE_KEY" + ``` + ### Start the challenger + + ```bash + # Make sure you're in the rollup/challenger directory + cd rollup/challenger + + # Make script executable + chmod +x scripts/start-challenger.sh + + # Start challenger + ./scripts/start-challenger.sh + ``` + + ### Verify challenger is running + + Monitor challenger logs to ensure it's operating correctly: + + ```bash + # Check challenger logs + tail -f challenger-data/challenger.log + + # Or if running in foreground, monitor the output + ``` + + The challenger should show logs indicating: + + * Successful connection to L1 and L2 nodes + * Loading of prestates and configuration + * Monitoring of dispute games +
+
+ + +### Monitoring with op-dispute-mon + +Consider running [`op-dispute-mon`](/operators/chain-operators/tools/chain-monitoring#dispute-mon) for enhanced security monitoring: + +* Provides visibility into all game statuses for the last 28 days +* Essential for production challenger deployments +* Create Grafana dashboards using: [Download the Dispute Monitor JSON](/resources/grafana/dispute-monitor-1718214549035.json) + +## Congratulations + +You've successfully completed the entire L2 rollup testnet tutorial! Your rollup is now fully operational with all components running: + +* **op-deployer** - L1 contracts deployed +* **Sequencer** - Processing transactions +* **Batcher** - Publishing data to L1 +* **Proposer** - Submitting state roots +* **Challenger** - Monitoring disputes + +## Connect your wallet to your chain + +You now have a fully functioning OP Stack Rollup with a Sequencer node running on `http://localhost:8545`. You can connect your wallet to this chain the same way you'd connect your wallet to any other EVM chain. + +## Get ETH on your chain + +Once you've connected your wallet, you'll probably notice that you don't have any ETH to pay for gas on your chain. + +The easiest way to deposit Sepolia ETH into your chain is to send ETH directly to the `L1StandardBridge` contract. + +### Get the L1StandardBridge address + +The `L1StandardBridge` proxy address can be found in your deployment state file. To get it, run: + +```bash +# From your project root +jq -r .l1StandardBridgeProxyAddress /.deployer/state.json +``` + +This will output the `L1StandardBridge` proxy address that you should use for deposits. Make sure to use the proxy address, not the implementation address. + +### Deposit ETH to your L2 + +Once you have the `L1StandardBridge` address, send a small amount of Sepolia ETH (0.1 or less) to that address from the wallet you want to use on L2. +This will trigger a deposit that will mint ETH into your wallet on L2. + + + It may take up to 5 minutes for the ETH to appear in your wallet on L2. + This delay is due to the time needed for the deposit transaction to be processed and finalized. + + +## See your rollup in action + +You can interact with your Rollup the same way you'd interact with any other EVM chain. +Send some transactions, deploy some contracts, and see what happens! + +## Need Help? + +* **Community Support**: Join the [Optimism Discord](https://discord.optimism.io) +* **OP Challenger Explainer**: [Fault Proofs Overview](/stack/fault-proofs/challenger) +* **Technical Specs**: [Honest Challenger Specification](https://specs.optimism.io/fault-proof/stage-one/honest-challenger-fdg.html) +* **Developer Support**: [GitHub Discussions](https://github.com/ethereum-optimism/developers/discussions) diff --git a/pages/operators/chain-operators/tutorials/create-l2-rollup/op-deployer-setup.mdx b/pages/operators/chain-operators/tutorials/create-l2-rollup/op-deployer-setup.mdx new file mode 100644 index 000000000..6ec9958eb --- /dev/null +++ b/pages/operators/chain-operators/tutorials/create-l2-rollup/op-deployer-setup.mdx @@ -0,0 +1,400 @@ +--- +title: Deploy L1 contracts with op-deployer +description: Install op-deployer, prepare your environment, and deploy the L1 smart contracts for your rollup. +lang: en-US +content_type: tutorial +topic: create-l2-rollup-setup +personas: + - chain-operator +categories: + - testnet + - chain-deployment + - op-deployer +is_imported_content: 'false' +--- + +import {Callout, Steps, Card, Tabs} from 'nextra/components' + +# Deploy L1 contracts with op-deployer + +Welcome to the first step of creating your own L2 rollup testnet! In this section, you'll install the op-deployer tool and deploy the necessary L1 smart contracts for your rollup. + + + **Step 1 of 5**: This tutorial is designed to be followed step-by-step. Each step builds on the previous one. + + +## About op-deployer + +`op-deployer` simplifies the process of deploying the OP Stack. You define a declarative config file called an "**intent**," then run a command to apply it. `op-deployer` compares your chain's current state against the intent and makes the necessary changes to match. + +## Installation + +There are a couple of ways to install `op-deployer`: + + + + The recommended way to install `op-deployer` is to download the latest release from the monorepo's [release page](https://github.com/ethereum-optimism/optimism/releases). + + + ### Download the correct binary + + 1. Go to the [release page](https://github.com/ethereum-optimism/optimism/releases) + 2. Use the search bar to find the latest release that includes `op-deployer`. + 3. Under **assets**, download the binary that matches your system: + + * For Linux: `op-deployer-linux-amd64` + * For macOS: + * Apple Silicon (M1/M2): `op-deployer-darwin-arm64` + * Intel processors: `op-deployer-darwin-amd64` + * For Windows: `op-deployer-windows-amd64.exe` + + + Not sure which macOS version to use? + + * Open Terminal and run `uname -m` + * If it shows `arm64`, use the arm64 version + * If it shows `x86_64`, use the amd64 version + + + ### Create deployer directory and install binary + + 1. Create the rollup directory structure and enter the deployer directory: + + ```bash + # Create main rollup directory + mkdir rollup && cd rollup + + # Create and enter the deployer directory + mkdir deployer && cd deployer + ``` + + Your directory structure will now look like this: + ```bash + rollup/ + └── deployer/ # You are here + ``` + + 2. Move and rename the downloaded binary: + + + The downloaded file is likely in your Downloads folder: + + * macOS/Linux: `/Users/YOUR_USERNAME/Downloads` + * Windows WSL: `/mnt/c/Users/YOUR_USERNAME/Downloads` + + + ```bash + # Step 1: Extract the tar.gz archive in the deployer directory + # Replace USERNAME with your username and adjust the version/arch if needed + tar -xvzf /Users/USERNAME/Downloads/op-deployer-0.2.6-darwin-arm64.tar.gz + + # Step 2: Make the binary executable + chmod +x op-deployer-0.2.6-darwin-arm64 + + # Step 3: Remove macOS quarantine attribute (fixes "can't be opened" warning) + sudo xattr -dr com.apple.quarantine op-deployer-0.2.6-darwin-arm64 + + # Step 4: Move the binary to your PATH + # For Intel Macs: + sudo mv op-deployer-0.2.6-darwin-arm64 /usr/local/bin/ + # For Apple Silicon Macs: + # sudo mv op-deployer-0.2.6-darwin-arm64 /opt/homebrew/bin/ + + # Step 7: Verify installation (should print version info) + op-deployer --version + ``` + + + + + To install from source, you will need [Go](https://go.dev/doc/install), `just`, and `git`. + After installing all of that, run following: + + ```bash + git clone https://github.com/ethereum-optimism/optimism.git # you can skip this if you already have the repo + cd optimism/op-deployer + just build + cp ./bin/op-deployer /usr/local/bin/op-deployer # or any other directory in your $PATH + + # Verify installation + op-deployer --version + ``` + + + +## L1 network requirements + +Before deploying your L1 contracts, you'll need: + +**L1 RPC URL**: An Ethereum RPC endpoint for your chosen L1 network + + ```bash + # Examples: + # Sepolia (recommended for testing) + L1_RPC_URL=https://sepolia.infura.io/v3/YOUR-PROJECT-ID + # or https://eth-sepolia.g.alchemy.com/v2/YOUR-API-KEY + + # Local network + L1_RPC_URL=http://localhost:8545 + ``` + + + For testing, we recommend using Sepolia testnet. You can get free RPC access from: + + * [Infura](https://infura.io) (create account, get API key) + * [Alchemy](https://alchemy.com) (create account, get API key) + * [Ankr](https://ankr.com) (create account, get API key) + + +## Generate deployment addresses + +Your rollup needs several addresses for different roles. Let's generate them first: + + + ### Create address directory + + ```bash + # Create a address directory inside the deployer directory + mkdir -p address + cd address + ``` + + Your directory structure will now look like this: + ```bash + rollup/ + └── deployer/ + └── address/ # You are here + ``` + + ### Generate address for each role + + ```bash + # Generate 8 new wallet addresses + for role in admin base_Fee_Vault_Recipient l1_Fee_Vault_Recipient sequencer_Fee_Vault_Recipient system_config unsafe_block_signer batcher proposer ; do + wallet_output=$(cast wallet new) + echo "$wallet_output" | grep "Address:" | awk '{print $2}' > ${role}_address.txt + echo "Created wallet for $role" + done + ``` + + Save the addresses for your intent file + + + + **Important**: + + * Save these address - you'll need them to operate your chain + * You can use any address for the purpose of testing, for production, use proper key management solutions (HSMs, multisigs addresses) + + + +## Create and configure intent file + +The intent file defines your chain's configuration. + + + ### Initialize intent file + + Inside the `deployer` folder, run this command: + + ```bash + #You can use a 2-7 digit random number for your `` + op-deployer init \ + --l1-chain-id 11155111 \ + --l2-chain-ids \ + --workdir .deployer \ + --intent-type standard-overrides + ``` + +
+ Understanding intent types + + `op-deployer` supports three intent types: + + * `standard`: Uses default OP Stack configuration, minimal customization + * `standard-overrides`: Recommended. Uses defaults but allows overriding specific values + * `custom`: Full customization, requires manual configuration of all values + + For most users, `standard-overrides` provides the best balance of simplicity and flexibility. +
+ + ### Update the intent file + + Edit `.deployer/intent.toml` with your generated addresses: + + ```toml + configType = "standard-overrides" + l1ChainID = 11155111 # Sepolia + fundDevAccounts = false # Set to false for production/testnet + useInterop = false + l1ContractsLocator = "tag://op-contracts/v2.0.0" + l2ContractsLocator = "tag://op-contracts/v1.7.0-beta.1+l2-contracts" + + [superchainRoles] + proxyAdminOwner = "0x..." # admin address + protocolVersionsOwner = "0x..." # admin address + guardian = "0x..." # admin address + + [[chains]] + id = "0x000000000000000000000000000000000000000000000000000000000016de8d" + baseFeeVaultRecipient = "0x..." # base_Fee_Vault_Recipient address + l1FeeVaultRecipient = "0x..." # l1_Fee_Vault_Recipient address + sequencerFeeVaultRecipient = "0x..." # sequencer_Fee_Vault_Recipient address + eip1559DenominatorCanyon = 250 + eip1559Denominator = 50 + eip1559Elasticity = 6 + [chains.roles] + l1ProxyAdminOwner = "0x1eb2ffc903729a0f03966b917003800b145f56e2" + l2ProxyAdminOwner = "0x2fc3ffc903729a0f03966b917003800b145f67f3" + systemConfigOwner = "0x..." # system_config address + unsafeBlockSigner = "0x..." # unsafe_block_signer address + batcher = "0x..." # batcher address + proposer = "0x..." # proposer address + challenger = "0xfd1d2e729ae8eee2e146c033bf4400fe75284301" + ``` + +
+ Understanding the configuration values + + **Global Settings:** + + * `l1ChainID`: The L1 network ID (11155111 for Sepolia) + * `fundDevAccounts`: Creates test accounts with ETH if true + * `useInterop`: Enable interoperability features + * `l1ContractsLocator`: Version of L1 contracts to deploy + * `l2ContractsLocator`: Version of L2 contracts to deploy + + **Superchain Roles:** + + * `proxyAdminOwner`: Can upgrade Superchain-wide contracts + * `protocolVersionsOwner`: Can update protocol versions + * `guardian`: Can pause withdrawals and manage disputes + + **Chain Configuration:** + + * `id`: Unique identifier for your chain + * `*FeeVaultRecipient`: Addresses receiving various fees + * `eip1559*`: Parameters for gas price calculation + + **Chain Roles:** + + * `l1ProxyAdminOwner`: Updates L1 contract implementations + * `l2ProxyAdminOwner`: Updates L2 contract implementations + * `systemConfigOwner`: Manages system configuration + * `unsafeBlockSigner`: Signs pre-confirmation blocks + * `batcher`: Submits L2 transactions to L1 + * `proposer`: Submits L2 state roots to L1 + * `challenger`: Monitors and challenges invalid states +
+
+ + + Replace all `0x...` with actual addresses from your `addresses.txt` file. + Never use the default test mnemonic addresses in production or public testnets! + + +## Create environment file + +Before deploying, create a `.env` file in your `deployer` directory to store your environment variables: + +```bash +# Create .env file +cat << 'EOF' > .env +# Your L1 RPC URL (e.g., from Alchemy, Infura) +L1_RPC_URL=https://eth-sepolia.g.alchemy.com/v2/YOUR_API_KEY + +# Private key for deployment. +# Get this from your self-custody wallet, like Metamask. +PRIVATE_KEY=WALLET_PRIVATE_KEY +EOF +``` + + + Never commit your `.env` file to version control. Add it to your `.gitignore`: + + ```bash + echo ".env" >> .gitignore + ``` + + +Load the environment variables: + +```bash +source .env +``` + +## Deploy L1 Contracts + +Now that your intent file and environment variables are configured, let's deploy the L1 contracts: + +```bash +op-deployer apply \ + --workdir .deployer \ + --l1-rpc-url $L1_RPC_URL \ + --private-key $PRIVATE_KEY +``` + +This will: + +1. Deploy all required L1 contracts +2. Configure them according to your intent file +3. Save deployment information to `.deployer/state.json` + + + The deployment can take 10-15 seconds and requires multiple transactions. + + +## Generate chain configuration + +After successful deployment, generate your chain configuration files: + +```bash +# Generate genesis and rollup configs +op-deployer inspect genesis --workdir .deployer > .deployer/genesis.json +op-deployer inspect rollup --workdir .deployer > .deployer/rollup.json +``` + +## What's Next? + +Great! You've successfully: + +1. Installed `op-deployer` using the `init` and `apply` command. +2. Created and configured your intent file +3. Deployed L1 smart contracts +4. Generated chain artifacts + +Your final directory structure should look like this: +```bash +rollup/ +└── deployer/ + ├── .deployer/ # Contains deployment state and configs + │ ├── genesis.json # L2 genesis configuration + │ ├── intent.toml # Your chain configuration + │ ├── rollup.json # Rollup configuration + │ └── state.json # Deployment state + ├── .env # Environment variables + └── address/ # Generated address pairs + ├── base_Fee_Vault_Recipient_address.txt + ├── batcher_address.txt + ├── l1_Fee_Vault_Recipient_address.txt + ├── proposer_address.txt + ├── sequencer_Fee_Vault_Recipient_address.txt + ├── system_config_address.txt + └── unsafe_block_signer_address.txt + └── admin.txt + +``` + +Now you can move on to setting up your sequencer node. + + + **Next**: Set up op-geth and op-node, essential building blocks of the execution and consensus layers in your rollup. + + +*** + +## Need Help? + +* **Community Support**: Join the [Optimism Discord](https://discord.gg/optimism) +* **op-deployer Repository**: [GitHub](https://github.com/ethereum-optimism/optimism/tree/develop/op-deployer/cmd/op-deployer) +* **OPCM Documentation**: [OP Contracts Manager](/stack/opcm) diff --git a/pages/operators/chain-operators/tutorials/create-l2-rollup/op-geth-setup.mdx b/pages/operators/chain-operators/tutorials/create-l2-rollup/op-geth-setup.mdx new file mode 100644 index 000000000..9b91c4441 --- /dev/null +++ b/pages/operators/chain-operators/tutorials/create-l2-rollup/op-geth-setup.mdx @@ -0,0 +1,580 @@ +--- +title: Spin up sequencer +lang: en-US +description: Set up and run op-geth and op-node, the execution and consensus layers for your rollup. +content_type: tutorial +topic: create-l2-rollup-geth +personas: + - chain-operator +categories: + - chain-deployment + - op-geth + - op-node + - sequencer-configuration +is_imported_content: 'false' +--- + +import { Callout, Steps, Card, Tabs } from 'nextra/components' + +# Spin up sequencer + +Now that you have op-deployer configured, it's time to spin up the sequencer for your rollup. This involves running both `op-geth` and `op-node` to create a functioning sequencer. + + + **Step 2 of 5**: This tutorial builds on [Spin up op-deployer](./op-deployer-setup). Make sure you've completed that first. + + +## What you'll set up + +The sequencer node consists of two core components: + +* `op-geth`: Execution layer that processes transactions and maintains state +* `op-node`: Consensus layer that orders transactions and creates L2 blocks + +The sequencer is responsible for: + +* Ordering transactions from users +* Building L2 blocks +* Signing blocks on the P2P network + +## Software installation + +For spinning up a sequencer, we recommend using Docker, as it provides a simpler setup and consistent environment. In this guide, building from source is also provided as an alternative for those who need more control and easier debugging. + + + + + + + If you prefer containerized deployment, you can use the official Docker images, and do the following: + + ### Set up directory structure and copy configuration files + + ```bash + # Create your sequencer directory inside rollup + cd ../ # Go back to rollup directory if you're in deployer + mkdir sequencer + cd sequencer + + # Copy configuration files from deployer + cp ../deployer/.deployer/genesis.json . + cp ../deployer/.deployer/rollup.json . + + # Generate JWT secret + openssl rand -hex 32 > jwt.txt + chmod 600 jwt.txt + ``` + + ### Create environment variables file + + ```bash + # Create .env file with your actual values + cat > .env << 'EOF' + # L1 Configuration - Replace with your actual RPC URLs + L1_RPC_URL=https://sepolia.infura.io/v3/YOUR_ACTUAL_INFURA_KEY + L1_BEACON_URL=https://ethereum-sepolia-beacon-api.publicnode.com + + # Private keys - Replace with your actual private key + PRIVATE_KEY=YOUR_ACTUAL_PRIVATE_KEY + + # P2P configuration - Replace with your actual public IP + # Run `curl ifconfig.me` in a separate shell to obtain the value, then paste it below + P2P_ADVERTISE_IP=YOUR_ACTUAL_PUBLIC_IP + + EOF + ``` + + **Important**: Replace ALL placeholder values (`YOUR_ACTUAL_*`) with your real configuration values. + + ### Make sure your docker application is running + Create a `docker-compose.yml` file in the same directory + + ```yaml + + services: + op-geth: + image: us-docker.pkg.dev/oplabs-tools-artifacts/images/op-geth:v1.101511.1 + volumes: + # Mount entire directory to avoid file mounting issues + - .:/workspace + working_dir: /workspace + ports: + - "8545:8545" + - "8546:8546" + - "8551:8551" + command: + - "--datadir=/workspace/op-geth-data" + - "--http" + - "--http.addr=0.0.0.0" + - "--http.port=8545" + - "--ws" + - "--ws.addr=0.0.0.0" + - "--ws.port=8546" + - "--authrpc.addr=0.0.0.0" + - "--authrpc.port=8551" + - "--authrpc.jwtsecret=/workspace/jwt.txt" + - "--syncmode=full" + - "--gcmode=archive" + - "--rollup.disabletxpoolgossip=true" + - "--rollup.sequencerhttp=http://op-node:8547" + - "--http.vhosts=*" + - "--http.corsdomain=*" + - "--http.api=eth,net,web3,debug,txpool,admin" + - "--ws.origins=*" + - "--ws.api=eth,net,web3,debug,txpool,admin" + - "--authrpc.vhosts=*" + + op-node: + image: us-docker.pkg.dev/oplabs-tools-artifacts/images/op-node:v1.13.5 + depends_on: + - op-geth + volumes: + - .:/workspace + working_dir: /workspace + ports: + - "8547:8547" + - "9222:9222" + environment: + - L1_RPC_URL=${L1_RPC_URL} + - L1_BEACON_URL=${L1_BEACON_URL} + - PRIVATE_KEY=${PRIVATE_KEY} + - P2P_ADVERTISE_IP=${P2P_ADVERTISE_IP} + command: + - "op-node" + - "--l1=${L1_RPC_URL}" + - "--l1.beacon=${L1_BEACON_URL}" + - "--l2=http://op-geth:8551" + - "--l2.jwt-secret=/workspace/jwt.txt" + - "--rollup.config=/workspace/rollup.json" + - "--sequencer.enabled=true" + - "--sequencer.stopped=false" + - "--sequencer.max-safe-lag=3600" + - "--verifier.l1-confs=4" + - "--p2p.listen.ip=0.0.0.0" + - "--p2p.listen.tcp=9222" + - "--p2p.listen.udp=9222" + - "--p2p.advertise.ip=${P2P_ADVERTISE_IP}" + - "--p2p.advertise.tcp=9222" + - "--p2p.advertise.udp=9222" + - "--p2p.sequencer.key=${PRIVATE_KEY}" + - "--rpc.addr=0.0.0.0" + - "--rpc.port=8547" + - "--rpc.enable-admin" + - "--log.level=info" + - "--log.format=json" + ``` + + ### Initialize op-geth with Docker + + ```bash + # Make sure you're in the rollup/sequencer directory with all files copied + cd rollup/sequencer + + # Initialize op-geth using Docker + docker run --rm \ + -v $(pwd):/workspace \ + -w /workspace \ + us-docker.pkg.dev/oplabs-tools-artifacts/images/op-geth:v1.101511.1 \ + init --datadir=./op-geth-data --state.scheme=hash ./genesis.json + ``` + + ### Start the services + + ```bash + # Start both services + docker-compose up -d + + # View logs + docker-compose logs -f + ``` + + ### Final directory structure + + ```bash + rollup/ + ├── deployer/ # From previous step + │ └── .deployer/ # Contains genesis.json and rollup.json + └── sequencer/ # You are here + ├── jwt.txt # Generated JWT secret + ├── genesis.json # Copied from deployer + ├── rollup.json # Copied from deployer + ├── .env # Environment variables + ├── docker-compose.yml # Docker configuration + └── opnode_discovery_db/ # Created by Docker during initialization + └── opnode_peerstore_db/ # Created by Docker during initialization + └── op-geth-data/ # Created by Docker during initialization + ├── geth/ # Geth data + └── keystore/ # Key files + ``` + + Your sequencer node is now operational and ready to process transactions. + + + + + + To ensure you're using the latest compatible versions of OP Stack components, always check the official [release page](https://github.com/ethereum-optimism/optimism/releases). + + The main components you'll need for sequencer deployment are: + + * `op-node`: Look for the latest `op-node/v*` [release](https://github.com/ethereum-optimism/optimism/releases) + * `op-geth`: Look for the latest `op-geth/v*` [release](https://github.com/ethereum-optimism/op-geth/releases) + + + The versions used in this guide (**op-node/v1.13.5** and **op-geth/v1.101511.1**) are verified compatible versions. + + According to the **op-node v1.13.5** [release notes](https://github.com/ethereum-optimism/optimism/releases), this op-node version specifically corresponds to **op-geth v1.101511.1**. + Always check the release notes to ensure you're using compatible versions. + + Building from source gives you full control over the binaries. + + + ### Clone and build op-node + + ```bash + # Clone the optimism monorepo + git clone https://github.com/ethereum-optimism/optimism.git + cd optimism + + # Checkout the latest release tag + git checkout op-node/v1.13.5 + + # Build op-node + cd op-node + just + + # Binary will be available at ./bin/op-node + ``` + + ### Clone and build op-geth + + ```bash + # Clone op-geth repository (in a separate directory) + git clone https://github.com/ethereum-optimism/op-geth.git + cd op-geth + + # Checkout to this release tag + git checkout v1.101511.1 + + # Build op-geth + make geth + + # Binary will be available at ./build/bin/geth + ``` + + ### Verify installation + + Check that you have properly installed the needed components. + + ```bash + # Make sure you're in the right directory + ./bin/op-node --version + ./build/bin/geth version + ``` + + + ## Configuration setup + + + ### Organize your workspace + + After building the binaries, you should have the following directory structure: + + ```bash + rollup/ + ├── deployer/ # From previous step + │ └── .deployer/ # Contains genesis.json and rollup.json + ├── optimism/ # Optimism monorepo + │ └── op-node/ + │ └── bin/ + │ └── op-node # Built binary + └── op-geth/ # OP-Geth repository + └── build/ + └── bin/ + └── geth # Built binary + ``` + + Now create your sequencer working directory. We recommend creating it at the same level for easy path references: + + ```bash + # Create sequencer directory inside rollup + cd ../ # Go back to rollup directory + mkdir sequencer + cd sequencer + ``` + +
+ Alternative: Copy binaries to sequencer directory + + If you prefer to keep binaries close to your configuration, you can copy them: + + ```bash + mkdir sequencer-node/bin + cp optimism/op-node/bin/op-node sequencer-node/bin/ + cp op-geth/build/bin/geth sequencer-node/bin/ + + # Then update scripts to use: + # ./bin/geth + # ./bin/op-node + ``` +
+ + ### Generate JWT secret + + ```bash + # Generate JWT secret in the sequencer directory + openssl rand -hex 32 > jwt.txt + + # Set appropriate permissions + chmod 600 jwt.txt + ``` + + ### Set up directory structure and copy files + + In this guide, we're going to be using the binaries from their original build locations, we only need to create directories for configuration files and scripts. + + ```bash + # Create scripts directory + mkdir scripts + + # Copy configuration files from deployer + cp ../deployer/.deployer/genesis.json . + cp ../deployer/.deployer/rollup.json . + ``` + + Your final directory structure should look like: + + ```bash + rollup/ + ├── deployer/ # From previous step + │ └── .deployer/ # Contains genesis.json and rollup.json + ├── optimism/ # Contains op-node binary + ├── op-geth/ # Contains op-geth binary + └── sequencer/ # You are here + ├── jwt.txt # Generated JWT secret + ├── genesis.json # Copied from deployer + ├── rollup.json # Copied from deployer + └── scripts/ # Startup scripts + ├── start-op-geth.sh + └── start-op-node.sh + ``` + + ### Environment variables + + You'll need to gather several pieces of information before creating your configuration. Here's where to get each value: + + + ### Get L1 network access + + You need access to the L1 network (Ethereum mainnet or Sepolia testnet) and its beacon node: + + **L1 RPC URL options:** + + * **Infura**: [infura.io](https://infura.io) - Requires an API key from a project + * **Alchemy**: [alchemy.com](https://alchemy.com) - Requires an API key from an app + + **L1 Beacon URL options:** + + * **Public beacon APIs**: `https://ethereum-sepolia-beacon-api.publicnode.com` (Sepolia) or `https://ethereum-beacon-api.publicnode.com` (Mainnet) + * **Infura beacon**: `https://sepolia.infura.io/v3/YOUR_KEY` (if your Infura plan includes beacon access) + + ### Get private key from your wallet + + For this basic sequencer setup, you only need a private key during op-node initialization. + + ### Get your public IP address + + ```bash + # Find your public IP address, once you get it, update the P2P_ADVERTISE_IP in your .env + curl ifconfig.me + # or + curl ipinfo.io/ip + ``` + + ### Choose your ports + + The default ports are standard but can be changed if needed: + + * `8545`: op-geth HTTP RPC (standard Ethereum RPC port) + * `8546`: op-geth WebSocket RPC + * `8551`: op-geth Auth RPC (for op-node communication) + * `8547`: op-node RPC + * `9222`: P2P networking (must be open on firewall) + + + Now create your `.env` file and copy the values below: + +
+ Replace ALL placeholder values with your real configuration values. + + ```bash + # Create .env file with your actual values + # L1 Configuration - Replace with your actual RPC URLs + L1_RPC_URL=https://sepolia.infura.io/v3/YOUR_ACTUAL_INFURA_KEY + L1_BEACON_URL=https://ethereum-sepolia-beacon-api.publicnode.com + + # Sequencer configuration + SEQUENCER_ENABLED=true + SEQUENCER_STOPPED=false + + # Private keys + PRIVATE_KEY=YOUR_ACTUAL_PRIVATE_KEY + + # P2P configuration - Replace with your actual public IP + # Run `curl ifconfig.me` in a separate shell to obtain the value, then paste it below + P2P_LISTEN_PORT=9222 + P2P_ADVERTISE_IP=YOUR_ACTUAL_PUBLIC_IP + + # RPC configuration (can customize ports if needed) + OP_NODE_RPC_PORT=8547 + OP_GETH_HTTP_PORT=8545 + OP_GETH_WS_PORT=8546 + OP_GETH_AUTH_PORT=8551 + + # JWT secret location + JWT_SECRET=./jwt.txt + ``` +
+
+ + ## Sequencer specific configuration + + ### op-geth configuration for sequencer + + Create `scripts/start-op-geth.sh`: + + ```bash + #!/bin/bash + source .env + + # Path to the op-geth binary we built + ../../op-geth/build/bin/geth \ + --datadir=./op-geth-data \ + --http \ + --http.addr=0.0.0.0 \ + --http.port=$OP_GETH_HTTP_PORT \ + --http.vhosts="*" \ + --http.corsdomain="*" \ + --http.api=eth,net,web3,debug,txpool,admin,miner \ + --ws \ + --ws.addr=0.0.0.0 \ + --ws.port=$OP_GETH_WS_PORT \ + --ws.origins="*" \ + --ws.api=eth,net,web3,debug,txpool,admin,miner \ + --authrpc.addr=0.0.0.0 \ + --authrpc.port=$OP_GETH_AUTH_PORT \ + --authrpc.vhosts="*" \ + --authrpc.jwtsecret=$JWT_SECRET \ + --syncmode=full \ + --gcmode=archive \ + --rollup.disabletxpoolgossip=true \ + --rollup.sequencerhttp=http://localhost:$OP_NODE_RPC_PORT + ``` + + ### op-node configuration for sequencer + + Create `scripts/start-op-node.sh`: + + ```bash + #!/bin/bash + + source .env + + # Path to the op-node binary we built + ../../optimism/op-node/bin/op-node \ + --l1=$L1_RPC_URL \ + --l1.beacon=$L1_BEACON_URL \ + --l2=http://localhost:$OP_GETH_AUTH_PORT \ + --l2.jwt-secret=$JWT_SECRET \ + --rollup.config=./rollup.json \ + --sequencer.enabled=$SEQUENCER_ENABLED \ + --sequencer.stopped=$SEQUENCER_STOPPED \ + --sequencer.max-safe-lag=3600 \ + --verifier.l1-confs=4 \ + --p2p.listen.ip=0.0.0.0 \ + --p2p.listen.tcp=$P2P_LISTEN_PORT \ + --p2p.listen.udp=$P2P_LISTEN_PORT \ + --p2p.advertise.ip=$P2P_ADVERTISE_IP \ + --p2p.advertise.tcp=$P2P_LISTEN_PORT \ + --p2p.advertise.udp=$P2P_LISTEN_PORT \ + --p2p.sequencer.key=$PRIVATE_KEY \ + --rpc.addr=0.0.0.0 \ + --rpc.port=$OP_NODE_RPC_PORT \ + --rpc.enable-admin \ + --log.level=info \ + --log.format=json + ``` + + ## Initializing and starting the sequencer + + + ### Initialize op-geth with your genesis file + + ```bash + # Make sure you're in the rollup/sequencer directory + cd rollup/sequencer + + # Initialize op-geth with your genesis file + ../../op-geth/build/bin/geth init --datadir=./op-geth-data --state.scheme=hash ./genesis.json + ``` + + ### Start op-geth + + ```bash + # Make scripts executable + chmod +x scripts/start-op-geth.sh + chmod +x scripts/start-op-node.sh + + # Start op-geth in the background or in a separate terminal + ./scripts/start-op-geth.sh + ``` + + **Note**: You should see output indicating that op-geth is starting and listening on the configured ports. + + ### Start op-node + + ```bash + # In a separate terminal, navigate to the sequencer directory + cd rollup/sequencer + + # Start op-node + ./scripts/start-op-node.sh + ``` + + ### Verify sequencer is running + + Once both services are running, verify they're working correctly: + + ```bash + # Check op-geth is responding, do this in another terminal + curl -X POST -H "Content-Type: application/json" \ + --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \ + http://localhost:8545 + + # Check sequencer status + curl -X POST -H "Content-Type: application/json" \ + --data '{"jsonrpc":"2.0","method":"admin_sequencerActive","params":[],"id":1}' \ + http://localhost:8547 + ``` + + + Your sequencer node is now operational and ready to process transactions. +
+ +
+ +## What's Next? + +Great! Your sequencer is running and processing transactions. The next step is to set up the batcher to publish transaction data to L1. + + + **Next**: Configure and start op-batcher to publish L2 transaction data to L1 for data availability. + + +*** + +## Need Help? + +* **Community Support**: Join the [Optimism Discord](https://discord.optimism.io) +* **Batcher Configuration**: [op-batcher Configuration Guide](/operators/chain-operators/configuration/batcher) +* **Best Practices**: [Chain Operator Best Practices](/operators/chain-operators/management/best-practices) diff --git a/pages/operators/chain-operators/tutorials/create-l2-rollup/op-proposer-setup.mdx b/pages/operators/chain-operators/tutorials/create-l2-rollup/op-proposer-setup.mdx new file mode 100644 index 000000000..23b0bdd08 --- /dev/null +++ b/pages/operators/chain-operators/tutorials/create-l2-rollup/op-proposer-setup.mdx @@ -0,0 +1,467 @@ +--- +title: Spin up proposer +lang: en-US +description: Learn how to set up and configure an OP Stack proposer to post L2 state roots. +content_type: tutorial +topic: proposer-setup +personas: + - chain-operator +categories: + - testnet + - mainnet + - op-proposer + - state-commitment + - l2-output-submission + - withdrawal-verification +is_imported_content: 'false' +--- + +import { Callout, Steps, Card, Tabs } from 'nextra/components' + +# Spin up proposer + +After you have spun up your sequencer and batcher, you need to attach a proposer to post your L2 state roots data back onto L1 so we can prove withdrawal validity. The proposer is a critical component that enables trustless L2-to-L1 messaging and creates the authoritative view of L2 state from L1's perspective. + + + **Step 4 of 5**: This tutorial is designed to be followed step-by-step. Each step builds on the previous one. + + +This guide assumes you already have a functioning sequencer, batcher, and the necessary L1 contracts deployed using [`op-deployer`](./op-deployer-setup). If you haven't set up your sequencer and batcher yet, please refer to the [sequencer guide](./op-geth-setup) and [batcher guide](./op-batcher-setup) first. + +To see configuration info for the proposer, check out the [configuration page](/operators/chain-operators/configuration/proposer). + +## Understanding the proposer's role + +The proposer (`op-proposer`) serves as a crucial bridge between your L2 chain and L1. Its primary responsibilities include: + +* **State commitment**: Proposing L2 state roots to L1 at regular intervals +* **Withdrawal enablement**: Providing the necessary commitments for users to prove and finalize withdrawals + +The proposer creates dispute games via the `DisputeGameFactory` contract. + +## Prerequisites + +Before setting up your proposer, ensure you have: + +**Running infrastructure:** + +* An operational sequencer node +* Access to a L1 RPC endpoint + +**Network information:** + +* Your L2 chain ID and network configuration +* L1 network details (chain ID, RPC endpoints) + +For setting up the proposer, we recommend using Docker as it provides a consistent and isolated environment. Building from source is also available as an option. + + + + If you prefer containerized deployment, you can use the official Docker images and do the following: + + + ### Set up directory structure and copy configuration files + + ```bash + # Create a proposer directory inside rollup + cd ../ # Go back to rollup directory if you're in batcher + mkdir proposer + cd proposer + # inside the proposer directory, copy the state.json file from the op-deployer setup + # Copy configuration files from deployer + cp ../deployer/.deployer/state.json . + + # Extract the DisputeGameFactory address + GAME_FACTORY_ADDRESS=$(cat state.json | jq -r '.opChainDeployments[0].disputeGameFactoryProxyAddress') + echo "DisputeGameFactory Address: $GAME_FACTORY_ADDRESS" + ``` + + ### Create environment variables file + + ```bash + # Create .env file with your actual values + cat > .env << 'EOF' + # L1 Configuration - Replace with your actual RPC URLs + L1_RPC_URL=https://sepolia.infura.io/v3/YOUR_ACTUAL_INFURA_KEY + + # L2 Configuration - Should match your sequencer setup + L2_RPC_URL=http://op-geth:8545 + ROLLUP_RPC_URL=http://op-node:8547 + + # Contract addresses - Extract from your op-deployer output + GAME_FACTORY_ADDRESS=YOUR_ACTUAL_GAME_FACTORY_ADDRESS + + # Private key - Replace with your actual private key + PRIVATE_KEY=YOUR_ACTUAL_PRIVATE_KEY + + # Proposer configuration + PROPOSAL_INTERVAL=3600s + GAME_TYPE=0 + POLL_INTERVAL=20s + + # RPC configuration + PROPOSER_RPC_PORT=8560 + EOF + ``` + + **Important**: Replace ALL placeholder values (`YOUR_ACTUAL_*`) with your real configuration values. + + ### Create docker-compose.yml + + + If you get "failed to dial address" errors, ensure your proposer is in the same Docker network as your sequencer. + + Common fixes: + + * Add `networks: - sequencer-node_default` to your proposer's docker-compose.yml + * Use service names like `op-geth:8545` and `op-node:8547` in your `.env` file + * Verify your sequencer network name with `docker network ls` + + + ```yaml + + services: + op-proposer: + image: us-docker.pkg.dev/oplabs-tools-artifacts/images/op-proposer:v1.10.0 + volumes: + - .:/workspace + working_dir: /workspace + ports: + - "8560:8560" + env_file: + - .env + command: + - "op-proposer" + - "--poll-interval=${POLL_INTERVAL}" + - "--rpc.port=${PROPOSER_RPC_PORT}" + - "--rpc.enable-admin" + - "--rollup-rpc=${ROLLUP_RPC_URL}" + - "--l1-eth-rpc=${L1_RPC_URL}" + - "--private-key=${PRIVATE_KEY}" + - "--game-factory-address=${GAME_FACTORY_ADDRESS}" + - "--game-type=${GAME_TYPE}" + - "--proposal-interval=${PROPOSAL_INTERVAL}" + - "--num-confirmations=1" + - "--resubmission-timeout=30s" + - "--wait-node-sync=true" + - "--log.level=info" + restart: unless-stopped + networks: + - sequencer-node_default + + networks: + sequencer-node_default: + external: false + + ``` + + ### Start the proposer service + + ```bash + # Make sure your sequencer network exists + docker network create op-stack 2>/dev/null || true + + # Start the proposer + docker-compose up -d + + # View logs + docker-compose logs -f op-proposer + ``` + + ### Verify proposer is running + + ```bash + # Check container status + docker-compose ps + ``` + + ### Final directory structure + + ```bash + rollup/ + ├── deployer/ # From previous step + │ └── .deployer/ # Contains state.json + ├── sequencer/ # From previous step + ├── batcher/ # From previous step + └── proposer/ # You are here + ├── state.json # Copied from deployer + ├── .env # Environment variables + └── docker-compose.yml # Docker configuration + ``` + + +
+ Understanding proposer startup logs + + When you first start your proposer, you'll see several types of log messages: + + 1. **Initialization messages** (normal): + ``` + lvl=info msg="Initializing L2Output Submitter" + lvl=info msg="Connected to DisputeGameFactory" + lvl=info msg="Starting JSON-RPC server" + ``` + + 2. **Sync status messages** (expected during startup): + ``` + msg="rollup current L1 block still behind target, retrying" + current_l1=...:9094035 target_l1=9132815 + ``` + This is normal! It means: + * Your rollup is still syncing with L1 (e.g., Sepolia) + * The proposer is waiting until sync is closer to L1 tip + * You'll see the `current_l1` number increasing as it catches up + * Once caught up, the proposer will start submitting proposals + + Don't worry about the "retrying" messages - they show healthy progress as your rollup catches up to the latest L1 blocks. + + **Common log patterns:** + + * Startup: You'll see initialization messages as services start + * Sync: "block still behind target" messages while catching up + * Normal operation: Regular proposal submissions once synced + * Network: Connection messages to L1/L2 endpoints + + If you see errors about "failed to dial" or connection issues: + + * For source build: Verify your localhost ports and services +
+ + Your proposer is now operational and will continuously submit state roots to L1! +
+ + + + ### Finding the current stable releases + + To ensure you're using the latest compatible versions of OP Stack components, always check the official [releases page](https://github.com/ethereum-optimism/optimism/releases). + + Look for the latest `op-proposer/v*` release that's compatible with your sequencer setup. + + + This guide uses `op-proposer/v1.10.0` which is compatible with op-node/v1.13.3 and op-geth/v1.101511.1 from the sequencer setup. + Always check the [release notes](https://github.com/ethereum-optimism/optimism/releases) for compatibility information. + + Building from source gives you full control over the binaries. + + + ### Clone and build op-proposer + + ```bash + # If you don't already have the optimism repository from the sequencer setup + git clone https://github.com/ethereum-optimism/optimism.git + cd optimism + + # Checkout the latest release tag + git checkout op-proposer/v1.10.0 + + # Build op-proposer + cd op-proposer + just + + # Binary will be available at ./bin/op-proposer + ``` + + ### Verify installation + + Run this command to verify the installation: + + ```bash + ./bin/op-proposer --version + ``` + + + ## Configuration setup + + + The rest of this guide assumes you're using the **build-from-source** approach. + If you chose Docker, all the necessary configuration was covered in the Docker tab above. + + + + ### Organize your workspace + + Create your proposer working directory at the same level as your sequencer: + + ```bash + # Create proposer directory inside rollup + cd ../ # Go back to rollup directory + mkdir proposer + cd proposer + + # Create scripts directory + mkdir scripts + ``` + + ### Extract DisputeGameFactory address + + Extract the `DisputeGameFactory` contract address from your op-deployer output: + + ```bash + # Make sure you're in the rollup/proposer directory + cd rollup/proposer + + # Copy the state.json from deployer + cp ../deployer/.deployer/state.json . + + # Extract the DisputeGameFactory address + GAME_FACTORY_ADDRESS=$(cat state.json | jq -r '.opChainDeployments[0].disputeGameFactoryProxyAddress') + echo "DisputeGameFactory Address: $GAME_FACTORY_ADDRESS" + ``` + + + The proposer only needs the `DisputeGameFactory` address to submit proposals. + The `GAME_TYPE=0` represents the standard fault proof game type. + + + ### Set up environment variables + + Create your `.env` file with the actual values: + + ```bash + # Create .env file with your actual values + # L1 Configuration - Replace with your actual RPC URL + L1_RPC_URL=https://sepolia.infura.io/v3/YOUR_ACTUAL_INFURA_KEY + + # L2 Configuration - Should match your sequencer setup + L2_RPC_URL=http://localhost:8545 + ROLLUP_RPC_URL=http://localhost:8547 + + # Contract addresses - Extract from your op-deployer output + GAME_FACTORY_ADDRESS=YOUR_ACTUAL_GAME_FACTORY_ADDRESS + + # Private key - Replace with your actual private key + PRIVATE_KEY=YOUR_ACTUAL_PRIVATE_KEY + + # Proposer configuration + PROPOSAL_INTERVAL=3600s + GAME_TYPE=0 + POLL_INTERVAL=20s + + # RPC configuration + PROPOSER_RPC_PORT=8560 + ``` + + **Important**: Replace ALL placeholder values (`YOUR_ACTUAL_*`) with your real configuration values! + + ### Get your private key + + Get a private key from your wallet that will be used for submitting proposals to L1. This account needs sufficient ETH to pay for L1 gas costs. + + + The proposer account needs to be funded with ETH on L1 to pay for proposal submission transactions. Monitor this account's balance regularly as it will consume ETH for each proposal submission. + + + + ## Proposer configuration + + Create `scripts/start-proposer.sh`: + + ```bash + #!/bin/bash + + source .env + + # Path to the op-proposer binary we built + ../../optimism/op-proposer/bin/op-proposer \ + --poll-interval=$POLL_INTERVAL \ + --rpc.port=$PROPOSER_RPC_PORT \ + --rpc.enable-admin \ + --rollup-rpc=$ROLLUP_RPC_URL \ + --l1-eth-rpc=$L1_RPC_URL \ + --private-key=$PRIVATE_KEY \ + --game-factory-address=$GAME_FACTORY_ADDRESS \ + --game-type=$GAME_TYPE \ + --proposal-interval=$PROPOSAL_INTERVAL \ + --num-confirmations=1 \ + --resubmission-timeout=30s \ + --wait-node-sync=true \ + --log.level=info + ``` + + Your final directory structure should look like: + + ```bash + rollup/ + ├── deployer/ # From previous step + │ └── .deployer/ # Contains state.json + ├── optimism/ # Contains op-proposer binary + ├── sequencer/ # From previous step + ├── batcher/ # From previous step + └── proposer/ # You are here + ├── state.json # Copied from deployer + ├── .env # Environment variables + └── scripts/ # Startup scripts + └── start-proposer.sh + ``` + + ## Starting the proposer + + + ### Start the proposer + + ```bash + # Make the script executable + chmod +x scripts/start-proposer.sh + + # Start the proposer + ./scripts/start-proposer.sh + ``` + + +
+ Understanding proposer startup logs + + When you first start your proposer, you'll see several types of log messages: + + 1. **Initialization messages** (normal): + ``` + lvl=info msg="Initializing L2Output Submitter" + lvl=info msg="Connected to DisputeGameFactory" + lvl=info msg="Starting JSON-RPC server" + ``` + + 2. **Sync status messages** (expected during startup): + ``` + msg="rollup current L1 block still behind target, retrying" + current_l1=...:9094035 target_l1=9132815 + ``` + This is normal! It means: + * Your rollup is still syncing with L1 (e.g., Sepolia) + * The proposer is waiting until sync is closer to L1 tip + * You'll see the `current_l1` number increasing as it catches up + * Once caught up, the proposer will start submitting proposals + + Don't worry about the "retrying" messages - they show healthy progress as your rollup catches up to the latest L1 blocks. + + **Common log patterns:** + + * Startup: You'll see initialization messages as services start + * Sync: "block still behind target" messages while catching up + * Normal operation: Regular proposal submissions once synced + * Network: Connection messages to L1/L2 endpoints + + If you see errors about "failed to dial" or connection issues: + + * For Docker: Check your network configuration and service names +
+ + Your proposer is now operational! +
+
+ +## What's Next? + +Perfect! Your proposer is submitting state roots to L1. The final step is to set up the challenger to monitor and respond to disputes. + + + **Next**: Configure and start op-challenger to monitor disputes and maintain your rollup's security. + + +*** + +## Need Help? + +* **Community Support**: Join the [Optimism Discord](https://discord.optimism.io) +* **Proposer Configuration**: [op-proposer Configuration Reference](/operators/chain-operators/configuration/proposer) +* **Dispute Games**: [Deploying Dispute Games with OPCM](/operators/chain-operators/tutorials/dispute-games)