# Running a Node

This guide explains how to run your own Ethscriptions AppChain node using Docker Compose.

## Prerequisites

* **Docker Desktop** (includes the Compose plugin)
* **L1 RPC endpoint** - Archive-quality recommended for historical sync

## Quick Start

```bash
# Clone the repository
git clone https://github.com/ethscriptions-protocol/ethscriptions-node.git
cd ethscriptions-node

# Copy the environment template
cp docker-compose/.env.example docker-compose/.env

# Edit .env with your settings (see Environment Reference below)
# At minimum, set L1_RPC_URL to your L1 endpoint

# Bring up the stack
cd docker-compose
docker compose --env-file .env up -d

# Follow logs while it syncs
docker compose logs -f node

# Query the L2 RPC (default port 8545)
curl -X POST http://localhost:8545 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'

# Shut down when done
docker compose down
```

## Services

The stack runs two containers:

| Service | Description                                               |
| ------- | --------------------------------------------------------- |
| `geth`  | Ethscriptions-customized Ethereum execution client (L2)   |
| `node`  | Ruby derivation app that processes L1 data into L2 blocks |

The node waits for geth to be healthy before starting. Both services communicate via a shared IPC socket.

## Environment Reference

Key variables in `docker-compose/.env`:

### Core Configuration

| Variable               | Description                                       | Default                      |
| ---------------------- | ------------------------------------------------- | ---------------------------- |
| `COMPOSE_PROJECT_NAME` | Docker resource naming prefix                     | `ethscriptions-evm`          |
| `JWT_SECRET`           | 32-byte hex for Engine API auth (must match geth) | —                            |
| `L1_NETWORK`           | Ethereum network (mainnet, sepolia, etc.)         | `mainnet`                    |
| `L1_RPC_URL`           | Archive-quality L1 RPC endpoint                   | —                            |
| `L1_GENESIS_BLOCK`     | L1 block where the rollup anchors                 | `17478949`                   |
| `GENESIS_FILE`         | Genesis snapshot filename                         | `ethscriptions-mainnet.json` |
| `GETH_EXTERNAL_PORT`   | Host port for L2 RPC                              | `8545`                       |

### Performance Tuning

| Variable              | Description                   | Default |
| --------------------- | ----------------------------- | ------- |
| `L1_PREFETCH_FORWARD` | Blocks to prefetch ahead      | `200`   |
| `L1_PREFETCH_THREADS` | Prefetch worker threads       | `10`    |
| `JOB_CONCURRENCY`     | SolidQueue worker concurrency | `6`     |
| `JOB_THREADS`         | Job worker threads            | `3`     |

### Geth Configuration

| Variable           | Description                                 | Default  |
| ------------------ | ------------------------------------------- | -------- |
| `GC_MODE`          | `full` (pruned) or `archive` (full history) | `full`   |
| `STATE_HISTORY`    | State trie history depth                    | `100000` |
| `TX_HISTORY`       | Transaction history depth                   | `100000` |
| `ENABLE_PREIMAGES` | Retain preimages                            | `true`   |
| `CACHE_SIZE`       | State cache size                            | `25000`  |

### Validation (Optional)

| Variable                     | Description                            | Default |
| ---------------------------- | -------------------------------------- | ------- |
| `VALIDATION_ENABLED`         | Enable validator against reference API | `false` |
| `ETHSCRIPTIONS_API_BASE_URL` | Reference API endpoint                 | —       |
| `ETHSCRIPTIONS_API_KEY`      | API authentication key                 | —       |

## Monitoring

### View Logs

```bash
# All services
docker compose logs -f

# Just the derivation node
docker compose logs -f node

# Just geth
docker compose logs -f geth
```

### Check Block Height

```bash
# L2 block number
curl -s -X POST http://localhost:8545 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' | jq -r '.result' | xargs printf "%d\n"
```

### Check Sync Status

The derivation node logs show the current L1 block being processed. Compare this to the current L1 head to gauge sync progress.

## Validator (Optional)

The validator compares L2 state against a reference Ethscriptions API to verify derivation correctness. It pauses the importer when discrepancies appear so you can investigate.

To enable:

```bash
VALIDATION_ENABLED=true
ETHSCRIPTIONS_API_BASE_URL=https://your-api-endpoint.com
ETHSCRIPTIONS_API_KEY=your-api-key
```

The temporary SQLite databases in `storage/` and the SolidQueue worker pool support this reconciliation. Once historical import is verified, the derivation app remains stateless.

## Local Development

If you want to modify the Ruby code outside of Docker:

```bash
# Install Ruby 3.4.x (via rbenv, rvm, or asdf)
ruby --version  # Should show 3.4.x

# Install dependencies
bundle install

# Initialize local SQLite files
bin/setup

# Run the derivation (requires running ethscriptions-geth and L1 RPC)
# See bin/jobs and config/derive_ethscriptions_blocks.rb
```

The Docker Compose stack is recommended for production-like runs.

## Troubleshooting

### Node won't start

* Check that geth is healthy: `docker compose ps`
* Verify `L1_RPC_URL` is accessible
* Ensure `JWT_SECRET` matches between services

### Slow sync

* Increase `L1_PREFETCH_FORWARD` and `L1_PREFETCH_THREADS`
* Use a faster L1 RPC endpoint
* Consider archive mode (`GC_MODE=archive`) only if needed

### Out of disk space

* Pruned mode (`GC_MODE=full`) uses less space
* Reduce `STATE_HISTORY` and `TX_HISTORY`

## Resources

* [GitHub Repository](https://github.com/ethscriptions-protocol/ethscriptions-node)
* [ethscriptions-geth](https://github.com/ethscriptions-protocol/ethscriptions-geth)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.ethscriptions.com/ethscriptions-appchain/running-a-node.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
