# Go-Ethereum (Geth) Administrator & Architecture Guide

This guide is for node operators, infrastructure engineers, protocol developers, and architects who deploy, operate, secure, or extend Geth. It documents the system architecture, the complete configuration surface, deployment and operations procedures, security hardening, and the internal package design — written from the `go-ethereum` source at commit `f5c62d0` (Go 1.24).

For installation and day-to-day usage, see the companion User Guide. This guide assumes familiarity with Ethereum concepts (accounts, transactions, the EVM, proof-of-stake) and focuses on how Geth is built, wired together, and run in production.

---

## 1. Executive Summary

Geth is the official Go implementation of an Ethereum **execution-layer (EL) client**. It is one process in a two-client node: Geth executes transactions and maintains state, while a separate **consensus-layer (CL) client** drives proof-of-stake fork choice. The two communicate over the authenticated **Engine API**.

| Aspect | Detail |
|--------|--------|
| Language / toolchain | Go 1.24, cgo (secp256k1, blst) |
| Role | Ethereum execution-layer client |
| Primary binary | `geth` (`cmd/geth`) |
| Companion tools | `abigen`, `evm`, `devp2p`, `ethkey`, `era`, `rlpdump`, `abidump`, `blsync`, `workload`, `fetchpayload` |
| CLI framework | `urfave/cli/v2` |
| Storage engines | Pebble (default) or LevelDB, plus an "ancient" freezer and Era archives |
| State model | Merkle-Patricia trie over a path-based or hash-based node store; experimental binary trie |
| Networking | devp2p (discovery v4/v5, RLPx transport, `eth`/`snap` wire protocols) |
| External interfaces | JSON-RPC (HTTP/WS/IPC), GraphQL, Engine API, metrics |
| License | GNU LGPL-3.0 (library) / GPL-3.0 (binaries) |

> [!IMPORTANT]
> The single most consequential operational fact: **a Geth process is not self-sufficient.** Production deployment is always "Geth + a CL client + a shared JWT secret." Plan capacity, monitoring, and incident response around the pair, not Geth in isolation.

---

## 2. Architecture

### 2.1 High-level component diagram

```text
                         ┌──────────────────────────────────────────────┐
                         │                cmd/geth (CLI)                  │
                         │  urfave/cli app · flag parsing · subcommands   │
                         └───────────────────────┬──────────────────────┘
                                                 │ builds
                                                 ▼
        ┌────────────────────────────────────────────────────────────────────────┐
        │                              node.Node                                   │
        │  Service container: lifecycle, account manager, P2P server,              │
        │  RPC stack (IPC/HTTP/WS/Auth), GraphQL, datadir/keystore resolution      │
        └───────┬───────────────────────────────┬───────────────────────┬─────────┘
                │ registers                      │ exposes               │ auth port
                ▼                                ▼                       ▼
   ┌─────────────────────────┐      ┌──────────────────────┐   ┌──────────────────┐
   │      eth.Ethereum       │      │  rpc + internal/      │   │  eth/catalyst    │
   │  (the EL service)       │      │  ethapi + graphql     │   │  Engine API impl │
   │                         │      │  JSON-RPC / GraphQL   │   │  (CL <-> EL)     │
   │  ┌───────────────────┐  │      └──────────────────────┘   └──────────────────┘
   │  │ core.BlockChain   │  │
   │  │  · state processor│  │      ┌──────────────────────┐   ┌──────────────────┐
   │  │  · core/vm (EVM)  │  │      │   eth/downloader     │   │  miner (payload  │
   │  │  · consensus      │  │◄────►│  snap / full sync    │   │  building)       │
   │  └───────────────────┘  │      └──────────────────────┘   └──────────────────┘
   │  ┌───────────────────┐  │
   │  │ core/txpool       │  │      ┌──────────────────────────────────────────┐
   │  │  legacy + blob    │  │      │  eth/protocols (eth, snap) · eth/fetcher  │
   │  └───────────────────┘  │◄────►│  wire protocols over p2p                  │
   └───────────┬─────────────┘      └──────────────────────────────────────────┘
               │ reads/writes
               ▼
   ┌──────────────────────────────────────────────────────────────────────────┐
   │  State & storage: core/state (StateDB) → trie → triedb (hashdb|pathdb)     │
   │  → ethdb (pebble|leveldb) + core/rawdb (schema) + freezer/ancient + era    │
   └──────────────────────────────────────────────────────────────────────────┘
               ▲
               │ transport
   ┌───────────┴──────────────────────────────────────────────────────────────┐
   │  p2p: discover(v4/v5) · enode/enr · rlpx · dnsdisc · nat · netutil          │
   └────────────────────────────────────────────────────────────────────────────┘
```

### 2.2 The `node` service container

`node.Node` (package `node`) is the lifecycle and resource container that everything else plugs into. It owns:

- **Datadir and keystore resolution** — resolves the data directory, keystore path, and node key; manages the instance directory lock.
- **P2P server** — the devp2p `p2p.Server` that handles discovery and peer connections.
- **The account manager** (`accounts.Manager`) — aggregates keystore, USB, and smartcard backends.
- **The RPC stack** — IPC, HTTP, WebSocket, and the separate authenticated (Engine API) server, plus optional GraphQL. Default hosts/ports come from `node.DefaultConfig`:

| Endpoint | Default host | Default port | Default modules |
|----------|--------------|--------------|-----------------|
| HTTP | `localhost` | `8545` | `net,web3` |
| WebSocket | `localhost` | `8546` | `net,web3` |
| Auth (Engine API) | `localhost` | `8551` | `eth,engine` |
| IPC | — (`geth.ipc` in datadir) | — | all local |

Services register with the node and are started/stopped in dependency order. `cmd/geth`'s `makeFullNode` wires `eth.Ethereum` and its satellites into the node.

### 2.3 The `eth` execution service

`eth.Ethereum` (package `eth`) is the main EL service. It composes:

- **`core.BlockChain`** — the canonical chain, block insertion/validation, the state processor that runs each block through the EVM, and reorg handling.
- **`core/vm`** — the Ethereum Virtual Machine: opcode interpreter, gas accounting, and precompiled contracts.
- **`core/txpool`** — the transaction mempool, split into the legacy pool (`legacypool`) for normal transactions and `blobpool` for EIP-4844 blob transactions.
- **`eth/downloader`** — orchestrates snap and full sync.
- **`eth/protocols/eth` and `eth/protocols/snap`** — the wire protocols spoken to peers; `eth/fetcher` pulls announced blocks and transactions.
- **`eth/filters`** — log/event filtering backing `eth_getLogs` and subscriptions, accelerated by `core/filtermaps` log indexes.
- **`eth/gasprice`** — the gas-price oracle backing fee suggestions.
- **`eth/tracers`** — transaction tracing engines (native Go tracers and JavaScript tracers via `goja`).
- **`miner`** — block/payload construction, invoked when the CL requests a payload via the Engine API.

`eth/ethconfig` defines the service's configuration struct and its defaults (sync mode, cache splits, txpool sizing, GPO parameters, RPC caps, history retention).

### 2.4 Consensus and the Engine API

Geth supports multiple consensus engines behind the `consensus.Engine` interface:

| Package | Engine | Use |
|---------|--------|-----|
| `consensus/beacon` | Beacon (post-merge) | Wraps an inner engine; defers fork choice to the CL via the Engine API. The production path for mainnet. |
| `consensus/clique` | Clique | Proof-of-authority, used by `--dev` and private PoA networks. |
| `consensus/ethash` | Ethash | Legacy proof-of-work **verification** (historical blocks); not used for live mining. |
| `consensus/misc` | — | Shared fork rules (EIP-1559 base fee, EIP-4844 blob fee). |

`eth/catalyst` implements the **Engine API** — the `engine_forkchoiceUpdated`, `engine_newPayload`, and payload-building methods the CL calls on the authenticated port. `beacon/engine` defines the shared request/response types. The `beacon/` tree also contains a full **beacon light client** (`beacon/light`, `beacon/blsync`) that powers the `blsync` tool.

### 2.5 State and storage stack

State storage is layered from high-level abstraction down to bytes on disk:

```text
core/state.StateDB        ← accounts, balances, nonces, code, storage slots
        │
        ▼
trie (Merkle-Patricia)    ← cryptographic state commitment; trie/bintrie = experimental binary trie
        │
        ▼
triedb                    ← node store with two schemes:
        ├─ hashdb         ← legacy: nodes keyed by hash
        └─ pathdb         ← modern default: nodes keyed by path, online pruning, state history
        │
        ▼
ethdb (KV interface)      ← pebble (default) | leveldb | memorydb | remotedb
        │
        ▼
core/rawdb                ← concrete key schema; "ancient"/freezer for immutable old data
        └─ eradb / internal/era  ← Era archive format for historical blocks
```

- **`triedb/pathdb`** is the largest single module in the codebase and the modern default (`--state.scheme path`). It supports efficient pruning and bounded state history.
- **`triedb/hashdb`** is the legacy hash-keyed scheme.
- The **freezer (ancient store)** moves immutable old blocks out of the hot KV store into append-only flat files (`--datadir.ancient`), dramatically shrinking the live database.
- **Era files** (`--datadir.era`, `geth import-history`/`export-history`/`download-era`) provide compact, verifiable archives of historical blocks.

### 2.6 Networking stack (`p2p`)

| Package | Responsibility |
|---------|----------------|
| `p2p` | The peer server, connection lifecycle, protocol multiplexing |
| `p2p/discover` | Node discovery DHT — protocol v4 and v5 |
| `p2p/enode`, `p2p/enr` | Node identity and Ethereum Node Records |
| `p2p/rlpx` | The encrypted RLPx transport |
| `p2p/dnsdisc` | DNS-based node lists |
| `p2p/nat` | NAT traversal (UPnP, NAT-PMP, STUN, explicit ext-IP) |
| `p2p/netutil`, `p2p/msgrate`, `p2p/tracker` | IP restriction, peer message-rate estimation, request tracking |

`core/forkid` computes the fork identity used during the handshake so peers only connect to compatible chains.

### 2.7 Supporting subsystems

| Package | Role |
|---------|------|
| `rpc` | The JSON-RPC server/client framework (codecs, subscriptions, batching) |
| `internal/ethapi` | Implementations of the `eth`/`debug`-namespace RPC methods |
| `graphql` | GraphQL schema and resolvers (plus GraphiQL UI) |
| `accounts` | Account abstraction; `keystore`, `usbwallet`, `scwallet` backends; `abi` for contract encoding |
| `signer` | Offline/structured signing helpers (`fourbyte` selector DB, `storage`, `core` types) |
| `ethclient` | A Go client library for talking to a node (used by tooling and `simulated` backends) |
| `metrics` | Instrumentation registry with Prometheus and InfluxDB exporters |
| `log` | Structured, leveled logging |
| `params` | Chain configurations, fork schedules, and protocol constants |
| `rlp` | Recursive Length Prefix serialization |
| `common` | Hashing, hex, big-int, LRU, and primitive types |
| `ethstats` | Optional reporting to an ethstats dashboard |
| `internal/debug` | pprof, the `--verbosity`/log flags, and the `debug` runtime namespace |

---

## 3. System Requirements

| Resource | Full (pruned) node | Archive node |
|----------|--------------------|--------------|
| CPU | 4+ cores | 8+ cores |
| RAM | 16 GB | 32 GB+ |
| Disk | Terabyte-class NVMe/SSD with headroom | Multi-terabyte NVMe |
| Disk type | **NVMe/SSD required** | **NVMe required** |
| Network | Stable broadband, port `30303` open (TCP+UDP) | same |

> [!CAUTION]
> Mechanical disks (HDD) are not viable for any sync mode. State access during sync and block import is random-IO heavy; an HDD will cause the node to fall permanently behind the chain head. This is the most common cause of "node never syncs" support cases.

> [!NOTE]
> Geth auto-shuts-down when free disk falls below `--datadir.minfreedisk` (MB). Provision generous headroom; chain data grows continuously even on a pruned node.

---

## 4. Configuration Mastery

Geth has roughly 250 command-line flags. Every flag has a matching `GETH_<NAME>` environment variable (via `flags.AutoEnvVars`), and the full effective configuration can be dumped and reloaded as TOML.

### 4.1 Configuration precedence and the TOML file

```bash
# Dump the effective configuration to TOML
geth dumpconfig --mainnet > geth.toml

# Run with a config file (flags still override individual values)
geth --config geth.toml --mainnet
```

Precedence (highest wins): explicit CLI flags → environment variables (`GETH_*`) → `--config` TOML file → built-in defaults.

> [!TIP]
> For reproducible production deployments, generate a `geth.toml` with `dumpconfig`, commit it to configuration management, and pass `--config`. Keep only environment-specific values (datadir, JWT path, RPC exposure) as CLI flags.

### 4.2 Data, database, and history

| Flag | Default | Purpose |
|------|---------|---------|
| `--datadir <dir>` | platform-specific | Databases and keystore root |
| `--datadir.ancient <dir>` | inside chaindata | Freezer (ancient) data root |
| `--datadir.era <dir>` | inside ancient/chain | Era1 history root |
| `--datadir.minfreedisk <MB>` | `--cache.gc`-derived | Free-disk floor before auto-shutdown (`0` = disabled) |
| `--keystore <dir>` | inside datadir | Keystore directory |
| `--db.engine <name>` | `pebble` | Backing KV store: `pebble` or `leveldb` |
| `--remotedb <url>` | — | Connect to a remote database |
| `--state.scheme <scheme>` | `path` | `path` (modern, prunable) or `hash` (legacy) |
| `--gcmode <mode>` | `full` | `full` (prune state) or `archive` (retain all) |
| `--history.state <n>` | 90,000 | Blocks of state history to retain (path scheme; `0` = all) |
| `--history.transactions <n>` | ~1 year | Blocks of transaction index (`0` = all) |
| `--history.logs <n>` | ~1 year | Blocks of log-search index (`0` = all) |
| `--history.logs.disable` | off | Do not maintain a log index |
| `--history.chain <mode>` | `all` | Body/receipt retention: `all`, `postmerge`, `postprague` |

### 4.3 Sync and cache

| Flag | Default | Purpose |
|------|---------|---------|
| `--syncmode <mode>` | `snap` | `snap` or `full` |
| `--snapshot` | enabled | Enable snapshot-database acceleration |
| `--cache <MB>` | 1024 | Total memory for internal caching |
| `--cache.database <pct>` | — | Share of cache for DB IO |
| `--cache.trie <pct>` | 15% full / 30% archive | Share for trie caching |
| `--cache.gc <pct>` | 25% full / 0% archive | Share for trie pruning |
| `--cache.snapshot <pct>` | 10% full / 20% archive | Share for snapshot caching |
| `--cache.noprefetch` | off | Disable heuristic state prefetch |
| `--cache.preimages` | off | Record keccak preimages of trie keys |
| `--fdlimit <n>` | system limit | Raise the open-file-descriptor limit |

> [!TIP]
> On a memory-rich machine, raising `--cache` (e.g. `--cache 8192`) materially speeds sync and block import. The percentage sub-flags rebalance how that budget is split; the defaults are sensible for full mode.

### 4.4 Networking and discovery

| Flag | Default | Purpose |
|------|---------|---------|
| `--port <n>` | `30303` | P2P listening port (TCP) |
| `--discovery.port <n>` | `30303` | UDP discovery port |
| `--maxpeers <n>` | 50 | Max peers (`0` disables networking) |
| `--maxpendpeers <n>` | (default) | Max pending connection attempts |
| `--bootnodes <enodes>` | network default | Bootstrap enode URLs |
| `--nat <spec>` | `any` | `any\|none\|upnp\|pmp\|pmp:<IP>\|extip:<IP>\|stun:<IP:PORT>` |
| `--nodiscover` | off | Disable discovery (manual peers only) |
| `--discovery.v4` / `--discovery.v5` | on | Toggle discovery protocols (aliases `discv4`/`discv5`) |
| `--netrestrict <CIDR>` | — | Restrict peers to given IP networks |
| `--discovery.dns <urls>` | network default | DNS discovery entry points (`""` to disable) |
| `--nodekey <file>` / `--nodekeyhex <hex>` | auto | P2P node key |
| `--identity <name>` | — | Custom node name |

### 4.5 RPC, Engine API, and GraphQL

| Flag | Default | Purpose |
|------|---------|---------|
| `--http` / `--http.addr` / `--http.port` | off / `localhost` / `8545` | HTTP-RPC server |
| `--http.api <list>` | `net,web3` | HTTP namespaces |
| `--http.corsdomain <list>` | — | Allowed CORS origins (browser enforced) |
| `--http.vhosts <list>` | `localhost` | Allowed virtual hosts (server enforced) |
| `--http.rpcprefix <path>` | `/` | HTTP path prefix for JSON-RPC |
| `--ws` / `--ws.addr` / `--ws.port` | off / `localhost` / `8546` | WebSocket-RPC server |
| `--ws.api <list>` / `--ws.origins <list>` | `net,web3` / — | WS namespaces / allowed origins |
| `--ipcdisable` / `--ipcpath <name>` | enabled / `geth.ipc` | IPC server toggle / socket name |
| `--graphql` | off | GraphQL on the HTTP server |
| `--authrpc.addr` / `--authrpc.port` | `localhost` / `8551` | Engine API listener |
| `--authrpc.vhosts <list>` | `localhost` | Engine API virtual hosts |
| `--authrpc.jwtsecret <file>` | auto (`<datadir>/geth/jwtsecret`) | JWT secret for the Engine API |
| `--rpc.gascap <n>` | 50,000,000 | Gas cap for `eth_call`/`estimateGas` (`0` = infinite) |
| `--rpc.txfeecap <ether>` | 1 | Max tx fee via RPC (`0` = no cap) |
| `--rpc.evmtimeout <dur>` | (set) | `eth_call` timeout (`0` = infinite) |
| `--rpc.batch-request-limit <n>` | (set) | Max requests per batch |
| `--rpc.batch-response-max-size <n>` | (set) | Max batch response bytes |
| `--rpc.allow-unprotected-txs` | off | Allow non-EIP-155 (unprotected) txs via RPC |

> [!WARNING]
> `--http.vhosts` and `--http.corsdomain` default to `localhost`/empty for a reason. Setting either to `*` removes a layer of protection against DNS-rebinding and cross-origin attacks. Only widen them behind a trusted reverse proxy.

### 4.6 Transaction pool

| Flag | Purpose |
|------|---------|
| `--txpool.locals <accts>` | Accounts treated as local (no flush, priority inclusion) |
| `--txpool.nolocals` | Disable price exemptions for local txs |
| `--txpool.journal <file>` / `--txpool.rejournal <dur>` | Local-tx journal and regeneration interval |
| `--txpool.pricelimit <n>` | Minimum gas-price tip for acceptance |
| `--txpool.pricebump <pct>` | Replacement price bump |
| `--txpool.accountslots` / `--txpool.globalslots` | Executable slot limits per account / global |
| `--txpool.accountqueue` / `--txpool.globalqueue` | Non-executable (queued) slot limits |
| `--txpool.lifetime <dur>` | Max time non-executable txs are queued |
| `--blobpool.datadir` / `--blobpool.datacap` / `--blobpool.pricebump` | Blob-transaction pool storage and sizing |

### 4.7 Block building (miner / payload)

| Flag | Purpose |
|------|---------|
| `--miner.gaslimit <n>` | Target gas ceiling for built blocks |
| `--miner.gasprice <wei>` | Minimum gas price to include a transaction |
| `--miner.extradata <str>` | Block extra-data (default = client version) |
| `--miner.recommit <dur>` | Interval to rebuild the in-progress block |
| `--miner.maxblobs <n>` | Max blobs per block |
| `--miner.pending.feeRecipient <addr>` | Fee recipient for the *pending* block (not actual production) |

> [!NOTE]
> On a post-merge network the actual fee recipient for produced blocks is supplied by the CL via the Engine API's payload attributes, not by a Geth flag. The `--miner.*` flags configure block-building **parameters**; they do not enable PoW mining.

### 4.8 Metrics, telemetry, and gas-price oracle

| Flag group | Purpose |
|------------|---------|
| `--metrics`, `--metrics.addr`, `--metrics.port` | Enable and serve the metrics HTTP endpoint |
| `--metrics.influxdb*` / `--metrics.influxdbv2*` | Push metrics to InfluxDB v1 / v2 |
| `--rpc.telemetry*` | OpenTelemetry tracing for RPC (OTLP endpoint, auth, sample ratio) |
| `--gpo.blocks`, `--gpo.percentile`, `--gpo.maxprice`, `--gpo.ignoreprice` | Gas-price-oracle tuning |
| `--ethstats <url>` | Report to an ethstats service (`nodename:secret@host:port`) |

### 4.9 Fork overrides

| Flag | Purpose |
|------|---------|
| `--override.osaka <ts>` | Override the bundled Osaka fork timestamp |
| `--override.bpo1` / `--override.bpo2 <ts>` | Override BPO fork timestamps |
| `--override.ubt <ts>` | Override the UBT (binary-trie) fork timestamp |
| `--override.genesis <file>` | Load genesis and config from a file |

> [!CAUTION]
> Fork-override flags are for testing and emergency coordination. Setting an incorrect fork timestamp will fork your node off the canonical chain. Do not use them on a production mainnet node unless following explicit, official guidance.

---

## 5. Deployment

### 5.1 Reference topology

```text
            ┌────────────── host (firewalled) ──────────────┐
   :30303   │  ┌───────────┐  Engine API     ┌────────────┐ │
 ◄── P2P ──►│  │   geth    │◄── :8551 + JWT ──│ CL client  │ │
            │  │  (EL)     │                  │ (beacon)   │◄┼─► :9000 CL P2P
   :8545    │  └─────┬─────┘                  └────────────┘ │
 ◄── RPC ───┼────────┘ (localhost only)                      │
 (proxy)    │  jwt.hex (chmod 600) shared between the two     │
            └─────────────────────────────────────────────────┘
```

### 5.2 systemd unit (Geth)

```ini
# /etc/systemd/system/geth.service
[Unit]
Description=Go Ethereum (execution layer)
After=network-online.target
Wants=network-online.target

[Service]
User=geth
Group=geth
Type=simple
Restart=on-failure
RestartSec=5
TimeoutStopSec=300
ExecStart=/usr/local/bin/geth \
  --mainnet \
  --datadir /srv/geth \
  --http --http.addr 127.0.0.1 --http.api eth,net,web3 \
  --authrpc.addr localhost --authrpc.port 8551 \
  --authrpc.jwtsecret /etc/ethereum/jwt.hex \
  --metrics --metrics.addr 127.0.0.1
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
```

```bash
sudo systemctl daemon-reload
sudo systemctl enable --now geth
journalctl -u geth -f
```

> [!IMPORTANT]
> Set `TimeoutStopSec` generously (≥ 300s). Geth needs time to flush state on shutdown; a short stop timeout causes systemd to `SIGKILL` it, leading to a slow state-recovery rewind on the next start.

### 5.3 JWT secret provisioning

```bash
sudo mkdir -p /etc/ethereum
openssl rand -hex 32 | tr -d "\n" | sudo tee /etc/ethereum/jwt.hex >/dev/null
sudo chown geth:geth /etc/ethereum/jwt.hex
sudo chmod 600 /etc/ethereum/jwt.hex
```

Point both Geth (`--authrpc.jwtsecret`) and the CL client at this file.

### 5.4 Docker / Compose

```yaml
# docker-compose.yml (excerpt)
services:
  geth:
    build: .
    command:
      - --mainnet
      - --datadir=/data
      - --http
      - --http.addr=0.0.0.0
      - --http.api=eth,net,web3
      - --authrpc.addr=0.0.0.0
      - --authrpc.jwtsecret=/jwt/jwt.hex
    volumes:
      - geth-data:/data
      - ./jwt:/jwt:ro
    ports:
      - "127.0.0.1:8545:8545"
      - "30303:30303"
      - "30303:30303/udp"
volumes:
  geth-data:
```

> [!WARNING]
> Inside containers you must bind `--http.addr 0.0.0.0` so the port is reachable, but publish it to `127.0.0.1` on the host (as above) — never `0.0.0.0:8545:8545` on a public host.

### 5.5 Deployment checklist

- [ ] Chain data on NVMe/SSD with terabyte-class headroom
- [ ] `LimitNOFILE`/`--fdlimit` raised (≥ 65536)
- [ ] JWT secret generated, `chmod 600`, shared with the CL client
- [ ] RPC bound to `localhost` (or behind a reverse proxy with auth)
- [ ] Only required namespaces in `--http.api`; `admin`/`debug` not public
- [ ] P2P port `30303` open (TCP **and** UDP); NAT configured if applicable
- [ ] Metrics endpoint scraped; alerts on sync status, peer count, head age
- [ ] Consensus client running and authenticated
- [ ] Graceful-shutdown timeout (`TimeoutStopSec`) ≥ 300s
- [ ] Backup of `keystore` and `jwt.hex` stored securely off-host

---

## 6. Security

### 6.1 Threat model and surfaces

| Surface | Risk | Mitigation |
|---------|------|------------|
| JSON-RPC (HTTP/WS) | Data exfiltration, tx submission, DoS | Bind localhost; restrict namespaces; vhosts/corsdomain; reverse proxy with auth/TLS |
| `admin`/`debug` namespaces | Peer manipulation, resource-heavy traces | Never expose publicly; IPC-only |
| Engine API (`8551`) | Unauthorized fork-choice control | JWT secret (`chmod 600`); bind localhost |
| Keystore | Key theft → loss of funds | File permissions; offline backup; strong passwords; hardware wallets |
| P2P | Eclipse/DoS | `--netrestrict`, trusted peers, adequate `--maxpeers` |
| Unprotected txs | Replay across chains | Keep `--rpc.allow-unprotected-txs` off |

### 6.2 Hardening rules

> [!CAUTION]
> Apply all of the following on any internet-connected node:
>
> 1. **Default-deny RPC exposure.** Keep `--http.addr`/`--ws.addr` on `localhost`. If remote access is required, terminate TLS and authentication at a reverse proxy; never expose Geth's raw RPC port to the internet.
> 2. **Minimize namespaces.** Expose only `eth,net,web3` over HTTP/WS. `admin`, `debug`, and `txpool` belong on the IPC socket.
> 3. **Lock the vhost/CORS gates.** Leave `--http.vhosts`/`--http.corsdomain` at their restrictive defaults unless a proxy requires otherwise. Avoid `*`.
> 4. **Protect the JWT secret.** `chmod 600`, owned by the service user. It is the credential that lets the CL drive your node.
> 5. **Treat the keystore as cash.** Back it up offline; the password is not stored in the file. Use `--lightkdf` only on test networks.
> 6. **Run as a non-root user** with a dedicated datadir and minimal filesystem permissions.

### 6.3 Removed legacy surface (negative knowledge)

> [!NOTE]
> The legacy **`personal` RPC namespace** (remote account unlock/sign over RPC) has been removed from Geth and is **not** available. Do not design integrations around `personal_unlockAccount` or `personal_sendTransaction`. Use an external signer (`--signer`), hardware wallets, or offline key management (`ethkey`) instead. This repository also does **not** ship the `clef` signer binary or a standalone `bootnode` binary — discovery/bootnode duties are covered by the `devp2p` tool.

### 6.4 Malicious-input resistance

Geth includes an extensive fuzzing suite (`tests/fuzzers`: bls12381, bn256, rangeproof, secp256k1, txfetcher, difficulty) and documented post-mortems (`docs/postmortems`) and security audits (`docs/audits`). Consensus-critical code paths (EVM, trie, crypto, RLP) are the primary fuzz targets. Operators should track upstream security advisories and apply patch releases promptly, as a consensus bug can fork a node off the network.

---

## 7. Operations

### 7.1 Start, stop, status

```bash
sudo systemctl start geth
sudo systemctl stop geth          # graceful; allow up to TimeoutStopSec
sudo systemctl status geth
journalctl -u geth -f             # follow logs
```

Health check from a console:

```bash
geth attach --exec 'eth.syncing'        # false when synced
geth attach --exec 'net.peerCount'      # healthy peer count
geth attach --exec 'eth.blockNumber'    # head should advance ~every 12s
```

### 7.2 Logging

Verbosity is controlled by the `debug` flag group: `--verbosity <0-5>` (0=silent, 3=info default, 5=trace). `--log.format`, `--log.file`, and pprof flags are available for structured output and profiling. The `internal/debug` package also exposes a runtime `debug` RPC namespace and an embedded pprof server.

### 7.3 Backup and restore

| Asset | Backup method | Notes |
|-------|---------------|-------|
| Keystore | Copy `<datadir>/keystore` | Portable; passwords stored separately |
| JWT secret | Copy `/etc/ethereum/jwt.hex` | Regenerate + restart both clients if rotated |
| Chain data | Snapshot the volume while Geth is stopped | Or simply re-sync; chain data is reproducible |
| Era archives | Copy `--datadir.era` / export with `export-history` | Verifiable against accumulator roots |

> [!TIP]
> Chain and state data are fully reproducible from the network, so the only *irreplaceable* assets are the keystore and (for coordination) the JWT secret. Prioritize those in backup policy; treat chain data as a cache that can be rebuilt by re-syncing.

### 7.4 Database maintenance

```bash
# Stop geth first for most of these
geth snapshot verify-state          # integrity check of state vs. snapshot
geth db check-state-content         # verify state is cryptographically correct
geth db metadata                    # inspect database metadata
geth prune-history                  # reclaim space from old bodies/receipts
geth removedb                       # nuke chain/state (keeps keystore) → re-sync
```

> [!WARNING]
> `geth db delete`/`geth db put` perform raw key mutations and can corrupt the database — the help text says so explicitly. Use them only when you understand the exact key schema in `core/rawdb`.

### 7.5 Upgrades

```bash
sudo systemctl stop geth
# build/install the new geth binary
geth version                        # confirm the new build
sudo systemctl start geth
journalctl -u geth -f               # watch for migration/recovery messages
```

> [!IMPORTANT]
> Read the release notes before upgrading across a network fork. Some releases change the state scheme, require a database migration, or carry a hard-fork activation. Upgrade the CL client and Geth in the order the release notes specify, and never skip a fork-activating release on mainnet.

### 7.6 Incident playbook

| Symptom | First checks | Action |
|---------|--------------|--------|
| Head not advancing | Is the CL running and authenticated? `eth.syncing`? | Restart CL; verify JWT; check Engine API logs |
| Falling behind | Disk type/IO, peer count, CPU | Move to NVMe; raise `--cache`; check peers |
| Crash-loop on start | State recovery / corrupt DB messages | Allow recovery; if corrupt, `removedb` + re-sync |
| Out of disk | `df`; `--datadir.minfreedisk` triggered | Free/extend volume; enable history pruning |
| No peers | Firewall, NAT, bootnodes | Open `30303` TCP+UDP; set `--nat`; check `--bootnodes` |
| RPC unreachable | Was `--http` set? Right addr/vhosts? | Enable transport; check bind address and namespaces |

---

## 8. Repository Structure (Developer Reference)

The codebase is organized by subsystem. Top-level packages and their roles:

| Path | Role |
|------|------|
| `cmd/geth` | The `geth` binary: CLI app, subcommands, node assembly |
| `cmd/utils` | Shared flag definitions and node/config builders (the config surface) |
| `cmd/{abigen,evm,devp2p,ethkey,era,rlpdump,abidump,blsync,workload,fetchpayload}` | Companion tools |
| `node` | Service container, RPC stack, lifecycle |
| `eth` | The execution-layer service; `eth/ethconfig` holds its config |
| `eth/downloader` | Snap/full sync engine |
| `eth/protocols/{eth,snap}` | Wire protocols |
| `eth/fetcher` | Block/transaction fetching |
| `eth/filters` | Log/event filtering (`eth_getLogs`, subscriptions) |
| `eth/gasprice` | Gas-price oracle |
| `eth/tracers` | Native + JS transaction tracers |
| `eth/catalyst` | Engine API implementation |
| `core` | Blockchain, genesis, state processor |
| `core/vm` | The EVM |
| `core/state` | StateDB and state objects |
| `core/txpool` (`legacypool`, `blobpool`) | Transaction mempool |
| `core/rawdb` | Low-level DB schema + freezer |
| `core/filtermaps` | Log index |
| `core/tracing` | Tracing hooks |
| `core/forkid` | Fork identity |
| `consensus/{beacon,clique,ethash,misc}` | Consensus engines and fork rules |
| `trie`, `trie/bintrie`, `trie/trienode` | State trie (MPT + experimental binary trie) |
| `triedb`, `triedb/{pathdb,hashdb}` | Trie node store schemes |
| `ethdb` (`pebble`, `leveldb`, `memorydb`, `remotedb`) | KV database abstraction |
| `p2p` (`discover`, `enode`, `enr`, `rlpx`, `dnsdisc`, `nat`, `netutil`) | Networking stack |
| `accounts` (`keystore`, `usbwallet`, `scwallet`, `abi`) | Account management |
| `signer` (`fourbyte`, `core`, `storage`) | Signing helpers |
| `rpc` | JSON-RPC framework |
| `internal/ethapi` | RPC method implementations |
| `graphql` | GraphQL API |
| `miner` | Block/payload building |
| `beacon` (`light`, `blsync`, `engine`, `params`, `merkle`) | Beacon light client + Engine types |
| `metrics`, `log`, `params`, `rlp`, `common` | Cross-cutting infrastructure |
| `ethclient` | Go client library |
| `internal/era`, `core/rawdb/eradb` | Era archive format |
| `ethstats` | ethstats reporting |

### 8.1 Building and testing

```bash
make geth          # build the geth binary
make all           # build all binaries
go test ./...      # run the full test suite
go test ./core/... # subsystem-scoped tests
```

The repository uses code generation (`go:generate` with `gencodec`, `stringer`, `protoc-gen-go`; see the `tool` directive in `go.mod`) and `rlp/rlpgen` for RLP codecs. Regenerate generated code rather than hand-editing it.

### 8.2 Contributing

Contributions follow upstream Go conventions: `gofmt`-clean code, focused commits, and full test coverage for consensus-critical changes. Consensus-affecting code (EVM, trie, crypto, RLP, fork rules) carries the highest review bar because a divergence forks nodes off the network. The fuzzing harnesses in `tests/fuzzers` should be extended alongside changes to parsing or cryptographic code paths.

---

## 9. Internals Deep Dive: Request and Block Lifecycles

### 9.1 Inbound block (from a peer)

1. A peer announces a block via the `eth` protocol; `eth/fetcher` requests the body.
2. `core.BlockChain` validates the header (consensus engine) and re-executes transactions through `core/vm`, mutating a `core/state.StateDB`.
3. The resulting state trie is committed via `trie` → `triedb` → `ethdb`; immutable old data eventually migrates to the freezer.
4. If the block extends the canonical chain (per CL fork choice), the head advances; otherwise a reorg is evaluated.

### 9.2 Engine API payload (from the CL)

1. The CL calls `engine_forkchoiceUpdated` with payload attributes (incl. fee recipient) on the authenticated port.
2. `eth/catalyst` instructs `miner` to build a payload: pull transactions from `core/txpool`, execute them, and assemble a block.
3. The CL retrieves the payload, and after consensus, calls `engine_newPayload` to commit it; Geth validates and imports it as in §9.1.

### 9.3 JSON-RPC call (`eth_call`)

1. The `rpc` server decodes the request and routes it to the `eth` namespace handler in `internal/ethapi`.
2. The handler snapshots state at the requested block, runs the call through `core/vm` under the `--rpc.gascap` and `--rpc.evmtimeout` limits, and returns the result without mutating state.

### 9.4 Sync (snap)

1. `eth/downloader` selects a pivot and requests account/storage ranges via `eth/protocols/snap`.
2. State is reconstructed into `triedb`; block bodies are backfilled.
3. Once the pivot is reached, the node switches to full validation and follows the head under CL fork choice.

---

## 10. Improvements and Technical Notes

Observations relevant to operators and maintainers, derived from the source structure:

1. **State-scheme migration friction.** Switching between `path` and `hash` schemes (or `full` ↔ `archive`) is not a live toggle and generally requires a re-sync. Operators should choose deliberately at first sync; documentation and tooling that make the migration path clearer would reduce a common operational pitfall.
2. **Binary trie is in flight.** `trie/bintrie`, the `geth bintrie convert` command, and the `--override.ubt` fork flag indicate an in-progress migration toward a binary state trie. Treat `bintrie` features as experimental and not for production state.
3. **Two-client coordination is the dominant failure mode.** The majority of "node won't sync" situations reduce to a missing/misauthenticated CL client. Surfacing Engine-API connectivity prominently in health output and logs continues to pay off.
4. **Large modules.** `triedb/pathdb`, `core`, `core/rawdb`, `trie`, and `core/state` are the largest and most consensus-critical modules; changes there warrant the deepest review and fuzzing.
5. **Open upstream issues to track** (from the community issue tracker at analysis time): a reported freezer error (`canonical hash missing, can't freeze block`) and an external-signer EIP-7702 authorization-list handling issue. Operators relying on freezer pruning or external signers with set-code (EIP-7702) transactions should monitor these.
6. **Config reproducibility.** The `dumpconfig`/`--config` TOML round-trip plus `GETH_*` env vars make Geth well-suited to declarative configuration management; standardizing on a committed `geth.toml` reduces drift across a fleet.

---

## 11. Quick Reference

### 11.1 Default ports

| Service | Port | Protocol |
|---------|------|----------|
| P2P (discovery + transport) | `30303` | TCP + UDP |
| HTTP-RPC | `8545` | TCP |
| WebSocket-RPC | `8546` | TCP |
| Engine API (auth) | `8551` | TCP |
| Metrics (when enabled) | `6060` | TCP |

### 11.2 Default RPC modules

| Endpoint | Default modules |
|----------|-----------------|
| HTTP | `net,web3` |
| WebSocket | `net,web3` |
| Auth (Engine API) | `eth,engine` |
| IPC / console | all local namespaces |

### 11.3 Essential operations

| Task | Command |
|------|---------|
| Build | `make geth` |
| Dump config | `geth dumpconfig --mainnet > geth.toml` |
| Attach console | `geth attach` |
| Check sync | `geth attach --exec 'eth.syncing'` |
| Reset DB (keep keys) | `geth removedb` |
| Verify state | `geth snapshot verify-state` |
| Export/import chain | `geth export <file>` / `geth import <file>` |
| Init custom genesis | `geth --datadir <dir> init genesis.json` |

### 11.4 Key file locations

| Path | Contents |
|------|----------|
| `<datadir>/keystore` | Encrypted account keys |
| `<datadir>/geth/chaindata` | Chain and state database |
| `<datadir>/geth/jwtsecret` | Auto-generated Engine API JWT (if not overridden) |
| `<datadir>/geth.ipc` | IPC socket |
| `--datadir.ancient` | Freezer (frozen old blocks) |
| `--datadir.era` | Era history archives |

---

_Generated June 2026 from ethereum/go-ethereum at f5c62d0. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
