Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions skill/references/cli/frozen-rpc-router.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# frozen-rpc-router

`frozen-rpc-router` exposes an HTTP EVM JSON-RPC endpoint that proxies requests to a live node and any number of freeze-height-frozen nodes, routing each request by block number (added in sei-chain #frozen-rpc-router, v6.6.3).

## Freeze height model

A freeze height is an **exclusive** boundary. A node started with `seid start ... --freeze-height 100` serves blocks through height 99. The router therefore sends height 99 to that node and height 100 to the next configured interval (or to the live node).

To run a frozen node, start `seid` with the `--freeze-height` flag:

```sh
seid start --chain-id sei --inv-check-period 0 --freeze-height 100
```

## Usage

```sh
go run ./cmd/frozen-rpc-router \
--listen-address 0.0.0.0:8545 \
--live-node localhost:9545 \
--frozen-node 1000000=localhost:9546 \
--frozen-node 2000000=10.0.0.12:8545
```

Or build and run the binary:

```sh
make build-frozen-rpc-router
./build/frozen-rpc-router --live-node localhost:9545 --frozen-node 1000000=localhost:9546
```

## Flags

| Flag | Default | Description |
|------|---------|-------------|
| `--listen-address` | `127.0.0.1:8545` | Address on which the router listens. |
| `--live-node` | (required) | HTTP RPC address of the live node. |
| `--frozen-node` | — | `freeze-height=ip:port` pair; repeat once per frozen node. |
| `--max-request-body-bytes` | `5242880` (5 MiB) | Maximum JSON-RPC request body size. Must be positive. |
| `--max-block-reference-depth` | `16` | Maximum nested block reference depth when parsing block references. Must be positive. |


| `--batch-request-limit` | `1000` | Maximum number of calls in a JSON-RPC batch. Must be positive. |
| `--write-timeout` | `30s` | Maximum duration for writing an HTTP response. Must be positive. |
| `--shutdown-timeout` | `10s` | Graceful shutdown timeout. Must be positive. |

- `--live-node` is required; omitting it fails with `--live-node is required`.
- Each `--frozen-node` value must be `freeze-height=ip:port`; the freeze height must be a positive integer no greater than `math.MaxInt64`, and freeze heights must be unique (duplicates fail with `duplicate freeze height <n>`).
- Node addresses may include an explicit `http://` or `https://` scheme; a bare `ip:port` is treated as `http://`.
- Frozen nodes may be listed in any order; the router sorts them by freeze height internally.

## Routing behaviour

- **Methods with explicit numeric block parameters** (e.g. `eth_getBlockByNumber`, `eth_getBalance`, `eth_call`, `eth_getStorageAt`, `debug_traceBlockByNumber`, and others) are routed to the frozen interval whose freeze height is greater than the requested height, or to the live node if no frozen interval covers it. The `earliest` tag routes to the lowest frozen interval (height 0).
- **`eth_getLogs` and `eth_feeHistory`** are routed only when their entire explicit block range falls within one interval. A range crossing an interval boundary returns JSON-RPC error `-32000` (`block ranges spanning multiple frozen-node intervals are not supported`). For a notification (no `id`), no error is returned.
- **Latest-style block tags** (`latest`, `pending`, `safe`, `finalized`), methods without block numbers, `eth_getLogs` by `blockHash`, EIP-1898 `blockHash` references, stateful filter methods, subscriptions, and WebSocket / non-POST requests all go to the **live** node.

## Sei-RPC-Route response header

Every HTTP response carries a `Sei-RPC-Route` header describing where the request was served:

- `frozen:<height>` — served entirely by the frozen node with that freeze height.
- `live` — served entirely by the live node.
- `mixed` — a batch request split across multiple backends.

## Other error codes

- `-32700` parse error (invalid JSON).
- `-32600` invalid request.
- `-32000` unsupported (range spanning intervals).
- `-32001` upstream request failed.
- Requests exceeding `--max-request-body-bytes` return HTTP `413 Request Entity Too Large`.
32 changes: 32 additions & 0 deletions skill/references/cli/seid-cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,38 @@ seid tx evm call-precompile <precompile-name> <method> [args...]

Available precompile names: `distribution`, `json`, `p256`, `staking`. See [EVM Precompiles](https://docs.sei.io/evm/precompiles) for method signatures.



## Node Start (`seid start`)

### `--freeze-height`

Stops the node *before* executing a target block while keeping the process and RPC servers running (unlike `--halt-height`, which gracefully shuts the node down). Block sync and consensus stop before executing the block at the configured height and do not advance beyond it.

```bash
seid start --freeze-height <uint64>
```

- Default `0` disables freeze mode.
- Also settable via the `freeze-height` field in the `[base]` section of `app.toml` (`freeze-height = 0` by default).

Constraints:
- Must not exceed `MaxInt64`.
- Cannot be combined with `--halt-height`/`halt-height` or `--halt-time`/`halt-time`.
- Cannot be combined with grpc-only mode (`--grpc-only`).
- State sync is disabled under freeze mode and falls back to block sync.
- Not supported with seed mode or Autobahn.
- The target height must be above the node's initial height and must not already be reached by the application, block store, or state store — otherwise the node refuses to start.
- Auto-remediation restart halts at the freeze boundary rather than restarting past it.

The freeze height is an *exclusive* boundary: a node started with `--freeze-height 100` serves blocks through height 99 and never executes block 100. This is the interval semantics the `frozen-rpc-router` relies on when routing requests by block number (see [Frozen RPC Router](frozen-rpc-router.md)).

Example — freeze a node just before executing block 5,000,000 while continuing to serve RPC (the node serves blocks through height 4,999,999):

```bash
seid start --freeze-height 5000000
```

## curl and JSON-RPC

Use `curl` when the user wants raw EVM RPC access, debug methods, or JSON-RPC examples. Use `seid` for everything else.
Expand Down
36 changes: 36 additions & 0 deletions skill/references/ecosystem/node-operations.md
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,42 @@ make install
sudo systemctl restart seid
```



---

## Freeze Height (`--freeze-height` / `freeze-height`)

Stops the node **before executing** a target block while **continuing to serve RPC** (the process and gRPC/JSON-RPC servers keep running). Unlike `halt-height`, which gracefully shuts the node down, freeze mode keeps the node alive and queryable at `freeze-height - 1`.

Enable it via the start flag or the `app.toml` `BaseConfig` field (both default `0` = disabled):

```bash
# CLI flag on the start command
seid start --chain-id pacific-1 --freeze-height 12345678
```

```toml
# app.toml (BaseConfig section, alongside halt-height / halt-time)
freeze-height = 12345678
```

### Behavior

- Block sync and consensus stop before executing the block at `freeze-height` and never advance beyond it — the node settles at `freeze-height - 1`.
- The node keeps serving RPC while frozen (no WAL writes, no new consensus rounds).
- **State sync is disabled** when freeze mode is active and the node falls back to block sync.
- Auto-remediation restart halts at the freeze boundary rather than restarting past it.

### Validation constraints (startup fails if violated)

- `freeze-height` **cannot be combined with `halt-height` or `halt-time`**.
- `--freeze-height` **cannot be used with grpc-only mode**.
- **Not supported in seed mode** (`mode = seed`).
- **Not supported with Autobahn** (fails if `autobahn-config-file` is set).
- Must **not exceed `MaxInt64`** (`9223372036854775807`).
- Must be **above the genesis initial height** and **above the current application, block store, and state store heights** — you cannot freeze at a height the node has already reached or passed.

---

## Database Management
Expand Down