# What Is the OP Stack's Rollup Node (op-node)? Architecture and Responsibilities Explained

> Discover the OP Stack's rollup node op-node. Learn how this middleware component aggregates batches, anchors to L1, validates state, and manages P2P networking for Optimism L2 nodes.

- Repository: [Base/node](https://github.com/base/node)
- Tags: deep-dive
- Published: 2026-03-03

---

**The OP Stack's rollup node (op-node) is the middleware component that transforms a standard execution client into a full Optimism L2 node by handling batch aggregation, L1 anchoring, state validation, and P2P networking.**

The `base/node` repository packages the **OP Stack's rollup node** into production-ready Docker images that combine `op-node` with execution clients like Reth, Geth, or Nethermind. This architecture enables operators to run a Base L2 node that synchronizes with Ethereum mainnet by processing transaction batches, validating state roots against L1, and exposing L2 RPC endpoints for decentralized applications.

## Core Responsibilities of the Rollup Node

The `op-node` binary serves as the consensus and data availability layer between the L1 Ethereum chain and the L2 execution client. According to the source code in the `base/node` repository, the rollup node fulfills six critical functions.

### Batch Aggregation and L1 Submission

The rollup node collects L2 transaction batches from the execution client and constructs rollup blocks for submission to the Optimism L1 portal contract. This process ensures that L2 state transitions are permanently recorded on Ethereum mainnet. The specific version of `op-node` performing this aggregation is declared in [[`versions.json`](https://github.com/base/node/blob/main/versions.json)](https://github.com/base/node/blob/main/versions.json), which pins the binary to tag `op-node/v1.16.6` for reproducible builds.

### State Validation and Fraud Proofs

`op-node` re-executes L2 blocks to verify state roots against L1 data, ensuring the rollup state remains consistent with the anchored L1 chain. The node listens for L1 challenge events and implements fraud-proof verification logic to trigger dispute resolution if it detects fraudulent batches. This validation logic is compiled into the upstream binary that the repository imports via `COPY --from=op /app/op-node/bin/op-node ./` in the client-specific Dockerfiles.

### P2P Networking and Node Discovery

The rollup node runs a libp2p overlay network that advertises the node's public IP address, enabling other rollup nodes to discover and synchronize with it. The IP discovery logic resides in [`op-node-entrypoint`](https://github.com/base/node/blob/main/op-node-entrypoint), which detects the host's public address and exports it as `OP_NODE_P2P_ADVERTISE_IP` before executing the binary.

### L2 RPC Gateway

`op-node` exposes HTTP and WebSocket RPC interfaces on ports `7545`, `9222`, `7300`, and `6060` (as defined in [[`docker-compose.yml`](https://github.com/base/node/blob/main/docker-compose.yml)](https://github.com/base/node/blob/main/docker-compose.yml)), allowing applications to query rollup state and submit transactions. The entrypoint script forwards the process to the compiled `op-node` binary via `exec ./op-node`, which then handles L2 state requests while delegating pure EVM execution to the paired client.

## How the Repository Orchestrates the Rollup Node

The `base/node` repository does not implement the rollup logic from scratch; instead, it wires the upstream Optimism `op-node` binary into a containerized environment with proper configuration management.

### Version Management and Build Process

The repository pins the exact `op-node` release in [`versions.json`](https://github.com/base/node/blob/main/versions.json) (line 24), then builds the binary in a multi-stage Dockerfile. For example, in `geth/Dockerfile` (and equivalents for Reth and Nethermind), the build stage executes:

```bash
RUN . /tmp/versions.env && cd op-node && make VERSION=$OP_NODE_TAG op-node

```

This compiled binary is then copied into the final image alongside the execution client, ensuring both components share a consistent filesystem and network namespace.

### Startup Sequence and Environment Validation

When the container launches, [`op-node-entrypoint`](https://github.com/base/node/blob/main/op-node-entrypoint) performs pre-flight checks:

1. Validates required environment variables (`OP_NODE_L1_ETH_RPC`, `OP_NODE_L1_BEACON`) at lines 25-28
2. Waits for the execution client RPC to become ready
3. Discovers the public IP address for P2P advertisement
4. Writes the L2 engine authentication token to `/app/jwt-secret`
5. Executes the rollup node binary with `exec ./op-node`

The [`docker-compose.yml`](https://github.com/base/node/blob/main/docker-compose.yml) orchestrates this by defining two services—`execution` (the client) and `node` (the rollup node)—that share the same `.env` file containing L1 RPC endpoints.

## Configuration and Deployment Examples

### Starting the Rollup Node

Deploy the complete stack using Docker Compose with the default Reth client on mainnet:

```bash
docker compose up --build

```

To run on Sepolia testnet with Geth instead:

```bash
NETWORK_ENV=.env.sepolia CLIENT=geth docker compose up --build

```

The `node` service executes `op-node-entrypoint`, which in turn launches the compiled `op-node` binary with the appropriate configuration.

### Required Environment Variables

The rollup node requires specific L1 connectivity parameters defined in `.env.mainnet` or `.env.sepolia`:

```bash
OP_NODE_L1_ETH_RPC=https://mainnet.infura.io/v3/<API_KEY>
OP_NODE_L1_BEACON=https://beaconcha.in/api/v1/eth/v2/beacon/blocks
OP_NODE_L1_BEACON_ARCHIVER=https://archive.beaconcha.in
OP_NODE_NETWORK=base-mainnet
OP_NODE_ROLLUP_CONFIG=/app/rollup.json

```

These variables are consumed by the `op-node` binary to locate L1 endpoints, select the rollup configuration, and identify the target network.

### Verifying the Binary

Inspect the built `op-node` artifact inside the running image:

```bash
docker run --rm base-node:latest ls -l /app/op-node

# Output: -rwxr-xr-x 1 root root 12M /app/op-node

```

The 12MB binary is compiled from the Optimism upstream source at the exact tag specified in [`versions.json`](https://github.com/base/node/blob/main/versions.json).

## Key Files in the Repository

- **`op-node-entrypoint`** – Bash wrapper that validates environment variables, discovers public IP, and executes the rollup binary.
- **[`docker-compose.yml`](https://github.com/base/node/blob/main/docker-compose.yml)** – Defines the dual-service architecture exposing ports `7545`, `9222`, `7300`, and `6060`.
- **[`versions.json`](https://github.com/base/node/blob/main/versions.json)** – Pins the `op-node` version (currently `v1.16.6`) for reproducible builds.
- **[`supervisord.conf`](https://github.com/base/node/blob/main/supervisord.conf)** – Configures process supervision when running both components in a single container.
- **Client Dockerfiles** – Multi-stage builds that compile `op-node` alongside Reth, Geth, or Nethermind.

## Summary

- **`op-node`** is the **OP Stack's rollup node** that sits between L1 Ethereum and L2 execution clients, enabling Optimism-compatible rollup functionality.
- The node handles **batch aggregation**, **state validation**, **fraud-proof verification**, **P2P discovery**, and **L2 RPC exposure**.
- The `base/node` repository packages the upstream binary into Docker images with automated build pipelines defined in [`versions.json`](https://github.com/base/node/blob/main/versions.json) and client-specific Dockerfiles.
- **Environment variables** like `OP_NODE_L1_ETH_RPC` and `OP_NODE_L1_BEACON` configure L1 connectivity, while `op-node-entrypoint` manages startup sequencing and IP discovery.
- The architecture separates **execution** (EVM state transitions) from **consensus/data availability** (rollup logic), with [`docker-compose.yml`](https://github.com/base/node/blob/main/docker-compose.yml) orchestrating both services.

## Frequently Asked Questions

### What is the difference between op-node and the execution client?

**`op-node`** is the rollup consensus node that handles batch submission, L1 anchoring, and P2P networking, while the **execution client** (Reth, Geth, or Nethermind) handles pure EVM state transitions and state storage. The `base/node` repository combines both into a single deployable unit, but they communicate via the Engine API using an authentication token generated at startup.

### How does op-node discover its public IP for P2P networking?

The [`op-node-entrypoint`](https://github.com/base/node/blob/main/op-node-entrypoint) script detects the host's public IP address during container initialization and sets the `OP_NODE_P2P_ADVERTISE_IP` environment variable before executing the binary. This allows other rollup nodes on the network to discover and connect to your node via libp2p.

### Where does the actual rollup logic implementation live?

While the `base/node` repository provides Docker packaging and orchestration, the actual **rollup implementation** lives in the upstream [Optimism repository](https://github.com/ethereum-optimism/optimism/tree/master/op-node). The `base/node` images compile this source code at a specific tag (e.g., `op-node/v1.16.6`) defined in [`versions.json`](https://github.com/base/node/blob/main/versions.json) and distribute it as a compiled binary.

### What L1 endpoints does op-node require to function?

According to the configuration in `.env.mainnet` and the validation logic in `op-node-entrypoint`, the rollup node requires **`OP_NODE_L1_ETH_RPC`** (standard Ethereum JSON-RPC) and **`OP_NODE_L1_BEACON`** (consensus layer REST API). For historical block retrieval, **`OP_NODE_L1_BEACON_ARCHIVER`** is also recommended to ensure the node can reconstruct L2 state from L1 batches.