# Go-Ethereum (Geth) User Guide

Geth (`go-ethereum`) is the official Go implementation of an Ethereum **execution-layer client**. It connects to the Ethereum peer-to-peer network, downloads and verifies the blockchain, maintains the current world state, executes the Ethereum Virtual Machine (EVM), and exposes a complete JSON-RPC interface for reading chain data and broadcasting transactions. The main binary is `geth`; the repository also ships a suite of focused command-line tools (`abigen`, `evm`, `devp2p`, `ethkey`, `era`, `rlpdump`, `abidump`, `blsync`, and more).

This guide covers installing Geth, running a node on mainnet and the test networks, managing accounts, using the JavaScript console and JSON-RPC APIs, operating the companion tools, and troubleshooting common problems. Written from the source at commit `f5c62d0`.

> [!IMPORTANT]
> Since Ethereum's transition to proof-of-stake (The Merge), **Geth alone is not a full Ethereum node**. Geth handles the *execution layer* (transactions, state, the EVM) but no longer drives consensus. You must run a separate **consensus-layer client** (also called a beacon node — for example Lighthouse, Prysm, Teku, Nimbus, or Lodestar) alongside Geth. The two communicate over the authenticated **Engine API** (default `localhost:8551`) using a shared JWT secret. A Geth process with no consensus client attached will sync peer data but will **never advance to the chain head**.

---

## 1. Quick Start

The fastest path to a synced mainnet node is to build Geth, generate a JWT secret, start Geth with the Engine API enabled, and point a consensus client at it.

```bash
# 1. Build geth from source (requires Go 1.24+)
git clone https://github.com/ethereum/go-ethereum.git
cd go-ethereum
make geth

# 2. Create the JWT secret shared with your consensus client
openssl rand -hex 32 | tr -d "\n" > /etc/ethereum/jwt.hex

# 3. Start geth on mainnet with the Engine API and HTTP-RPC enabled
./build/bin/geth \
  --mainnet \
  --http --http.api eth,net,web3 \
  --authrpc.jwtsecret /etc/ethereum/jwt.hex \
  --authrpc.addr localhost --authrpc.port 8551
```

```text
INFO [06-04|10:00:00.000] Starting Geth on Ethereum mainnet...
INFO [06-04|10:00:00.100] Maximum peer count                       ETH=50 total=50
INFO [06-04|10:00:00.200] Set global gas cap                       cap=50,000,000
INFO [06-04|10:00:01.000] Started P2P networking                   self=enode://...@127.0.0.1:30303
INFO [06-04|10:00:01.500] Looking for peers                        peercount=0 tried=12 static=0
```

> [!NOTE]
> Geth will print `WARN ... Post-merge network, but no beacon client seen. Please launch one to follow the chain!` until you connect a consensus client. This is expected on a fresh start.

Then launch your consensus client with the matching JWT secret and Engine API endpoint. Once both are running, Geth begins **snap sync** and reaches the head within hours.

Attach a console to inspect the node:

```bash
./build/bin/geth attach
```

```text
Welcome to the Geth JavaScript console!

instance: Geth/v1.16.0-stable/linux-amd64/go1.24.0
at block: 0 (Thu Jan 01 1970 00:00:00 GMT+0000)
 datadir: /home/user/.ethereum
 modules: admin:1.0 debug:1.0 eth:1.0 net:1.0 rpc:1.0 txpool:1.0 web3:1.0

>
```

---

## 2. Installation

Geth requires **Go 1.24.0 or newer** to build from source. A C compiler is needed for the bundled `secp256k1` and `blst` cgo packages.

### 2.1 Build from source

=== "Linux / macOS"

    ```bash
    git clone https://github.com/ethereum/go-ethereum.git
    cd go-ethereum
    make geth
    # binary lands in ./build/bin/geth
    ```

=== "Build all tools"

    ```bash
    # Builds geth plus abigen, evm, devp2p, ethkey, era, rlpdump, etc.
    make all
    # binaries land in ./build/bin/
    ```

=== "Plain go build"

    ```bash
    go build -o geth ./cmd/geth
    go build -o abigen ./cmd/abigen
    ```

The `make geth` target embeds version and git-commit metadata into the binary. After building, verify the result:

```bash
./build/bin/geth version
```

```text
Geth
Version: 1.16.0-stable
Git Commit: f5c62d0...
Architecture: amd64
Go Version: go1.24.0
Operating System: linux
```

> [!TIP]
> Place `./build/bin` on your `PATH` (or copy `geth` to `/usr/local/bin`) so you can invoke `geth` directly instead of by full path. The remainder of this guide assumes `geth` is on your `PATH`.

### 2.2 Docker

The repository includes a `Dockerfile`. Build and run a container, mapping a host directory for persistent chain data and exposing the RPC and P2P ports:

```bash
docker build -t geth .
docker run -d --name geth-node \
  -v /srv/geth:/root/.ethereum \
  -p 8545:8545 -p 30303:30303 -p 30303:30303/udp \
  geth \
  --mainnet --http --http.addr 0.0.0.0 --http.api eth,net,web3 \
  --authrpc.addr 0.0.0.0 --authrpc.jwtsecret /root/jwt.hex
```

> [!WARNING]
> Binding `--http.addr 0.0.0.0` exposes the JSON-RPC server on all interfaces. Only do this behind a firewall or reverse proxy. See [Securing your node](#114-securing-your-node).

### 2.3 Hardware and disk requirements

| Resource | Mainnet recommendation |
|----------|------------------------|
| CPU | 4+ cores |
| RAM | 16 GB+ (32 GB for archive) |
| Disk | Fast SSD/NVMe; a snap-synced full node is large and grows continuously. Plan for terabyte-class storage and headroom. |
| Network | Stable broadband; open TCP+UDP port `30303` for best peering |

> [!CAUTION]
> Geth's chain data **must** live on an SSD or NVMe drive. Spinning disks (HDD) cannot keep up with state access during sync or block import and will cause the node to fall behind the chain head indefinitely.

> [!NOTE]
> Geth automatically shuts down to protect your filesystem when free disk space runs low. The threshold is controlled by `--datadir.minfreedisk` (in MB). Monitor free space and keep ample headroom.

---

## 3. Running a Node

### 3.1 The data directory

Geth stores everything — chain database, state, keystore, node key, and IPC socket — under a single **data directory** (`datadir`). The default location is platform-specific:

| Platform | Default datadir |
|----------|-----------------|
| Linux | `~/.ethereum` |
| macOS | `~/Library/Ethereum` |
| Windows | `%LOCALAPPDATA%\Ethereum` |

Override it with `--datadir`:

```bash
geth --datadir /srv/geth/mainnet --mainnet
```

You can relocate just the bulky ancient (frozen) data with `--datadir.ancient` and pre-merge Era history with `--datadir.era`, which is useful when chain data spans multiple volumes.

### 3.2 Selecting a network

Geth selects mainnet by default. Use a network flag to choose a pre-configured network instead:

| Flag | Network |
|------|---------|
| `--mainnet` | Ethereum mainnet (default) |
| `--sepolia` | Sepolia — pre-configured proof-of-stake test network |
| `--holesky` | Holesky — pre-configured proof-of-stake test network |
| `--hoodi` | Hoodi — pre-configured proof-of-stake test network |
| `--dev` | Ephemeral single-node proof-of-authority network with a pre-funded developer account, mining enabled |
| `--networkid <int>` | Explicitly set a custom network ID (for private networks) |

```bash
# Run a Sepolia testnet node
geth --sepolia --http --http.api eth,net,web3 \
  --authrpc.jwtsecret /etc/ethereum/jwt.hex
```

> [!NOTE]
> The network flags are mutually exclusive. For private networks, use `--networkid` together with a custom genesis (see [Private networks](#103-running-a-private-network)).

### 3.3 Connecting a consensus client (the Engine API)

Geth exposes a separate, **authenticated** RPC endpoint dedicated to the consensus client — the **Engine API**. It listens on `localhost:8551` by default and is protected by a JWT secret rather than being publicly reachable.

```bash
# Generate a 32-byte hex JWT secret once
openssl rand -hex 32 | tr -d "\n" > /etc/ethereum/jwt.hex
```

Pass the same file to both Geth and your consensus client:

```bash
geth --mainnet \
  --authrpc.addr localhost \
  --authrpc.port 8551 \
  --authrpc.vhosts localhost \
  --authrpc.jwtsecret /etc/ethereum/jwt.hex
```

| Engine API flag | Default | Purpose |
|-----------------|---------|---------|
| `--authrpc.addr` | `localhost` | Listening address for authenticated APIs |
| `--authrpc.port` | `8551` | Listening port for authenticated APIs |
| `--authrpc.vhosts` | `localhost` | Accepted virtual hostnames (server enforced; `*` wildcard allowed) |
| `--authrpc.jwtsecret` | (auto-generated in datadir) | Path to the JWT secret shared with the consensus client |

> [!IMPORTANT]
> If you do not pass `--authrpc.jwtsecret`, Geth generates a secret at `<datadir>/geth/jwtsecret` on startup. Your consensus client must be pointed at that exact file. Specifying the path explicitly on both sides avoids confusion.

> [!TIP]
> `blsync` (shipped in this repository) is a lightweight beacon-chain **light client** that can drive Geth's Engine API for testing or low-resource setups. It is not a substitute for a full consensus client on mainnet but is handy for experimentation — see [Section 9.8](#98-blsync--beacon-light-client).

### 3.4 Sync modes

Geth supports two blockchain sync modes, chosen with `--syncmode`:

| Mode | Behavior |
|------|----------|
| `snap` (default) | Downloads recent state via the snap protocol, then fills in blocks. Fastest way to reach the head. |
| `full` | Re-executes every block from genesis, rebuilding state locally. Slower but executes the entire history. |

```bash
geth --mainnet --syncmode full      # full re-execution from genesis
geth --mainnet --syncmode snap      # default — fast state sync
```

The amount of historical state and indexes Geth retains is governed by garbage-collection and history flags:

| Flag | Default | Purpose |
|------|---------|---------|
| `--gcmode` | `full` | `full` prunes old state; `archive` keeps **all** historical state (huge disk use) |
| `--state.scheme` | `path` | State storage scheme: `path` (modern, prunable) or `hash` (legacy) |
| `--history.state` | 90,000 blocks | Recent blocks to retain state history for (path scheme; `0` = entire chain) |
| `--history.transactions` | ~1 year | Recent blocks to keep the transaction index for (`0` = entire chain) |
| `--history.logs` | ~1 year | Recent blocks to keep the log-search index for (`0` = entire chain) |
| `--history.chain` | `all` | Block-body/receipt retention: `all`, `postmerge`, or `postprague` |

> [!TIP]
> Run an **archive node** (every historical state, queryable at any block) with `--gcmode archive --syncmode full`. Expect dramatically larger disk usage and longer sync times than a pruned full node. Only run archive if you specifically need historical-state queries.

> [!CAUTION]
> Switching `--state.scheme` or `--gcmode` on an existing database is not a live toggle. The scheme is fixed at database creation; changing it generally requires re-syncing or an explicit migration. Decide before your first sync.

### 3.5 Developer mode

For local contract development and testing, `--dev` spins up an ephemeral, single-node proof-of-authority chain with a pre-funded account and instant or interval mining — no consensus client required:

```bash
geth --dev --http --http.api eth,net,web3,debug --datadir /tmp/geth-dev
```

```text
INFO [06-04|10:00:00.000] Using developer account                  address=0x71562b71999873DB5b286dF957af199Ec94617F7
INFO [06-04|10:00:00.000] Starting Geth in ephemeral dev mode...
```

| Flag | Purpose |
|------|---------|
| `--dev` | Ephemeral PoA dev network, mining enabled, pre-funded account |
| `--dev.period <n>` | Block period in seconds (`0` = mine only when a transaction is pending) |
| `--dev.gaslimit <n>` | Initial block gas limit |

> [!WARNING]
> Dev-mode chain data is ephemeral — it lives in a temporary directory and is wiped on restart unless you pass an explicit `--datadir`. Never use developer mode for anything requiring persistence or real value.

### 3.6 Graceful shutdown

Stop Geth with `Ctrl-C` (or `SIGINT`/`SIGTERM` to the process). Geth flushes in-memory state to disk on shutdown.

> [!CAUTION]
> Do **not** `kill -9` (SIGKILL) a running Geth. An ungraceful kill can leave the trie cache unflushed, forcing a slow state-recovery rewind on the next start, or in rare cases require a resync. Always allow Geth time to shut down cleanly.

---

## 4. Managing Accounts

Geth stores accounts as encrypted **keystore** files under `<datadir>/keystore`. Each file holds one private key encrypted with a password you choose.

> [!IMPORTANT]
> Account management commands operate on the local keystore only. The legacy `personal` RPC namespace for remote account unlocking has been **removed** from Geth — there is no `personal_unlockAccount` over RPC. For programmatic signing, manage keys with `ethkey`, an external signer (`--signer`), or a hardware wallet.

### 4.1 Create a new account

```bash
geth account new
```

```text
Your new account is locked with a password. Please give a password. Do not forget this password.
Password:
Repeat password:

Your new key was generated

Public address of the key:   0xfcad0b19bb29d4674531d6f115237e16afce377c
Path of the secret key file: /home/user/.ethereum/keystore/UTC--2026-06-04T...--fcad0b19...
- You can share your public address with anyone. Others need it to interact with you.
- You must NEVER share the secret key with anyone! The key controls access to your funds!
- You must BACKUP your key file! Without the key, it's impossible to access account funds!
- You must REMEMBER your password! Without the password, it's impossible to decrypt the key!
```

For non-interactive (scripted) use, supply a password file:

```bash
geth account new --password /path/to/password.txt
```

> [!WARNING]
> Passing `--password` reads the password from a plaintext file. This is intended for test networks and known-safe automated environments only. Never store a mainnet account password on disk in plaintext.

### 4.2 List accounts

```bash
geth account list
```

```text
Account #0: {7ef5a6135f1fd6a02593eedc869c6d41d934aef8} keystore:///home/user/.ethereum/keystore/UTC--2016-03-22T12-57-55...
Account #1: {f466859ead1932d743d622cb74fc058882e8648a} keystore:///home/user/.ethereum/keystore/aaa
```

### 4.3 Import a private key

```bash
geth account import /path/to/key.prv
```

```text
Address: {fcad0b19bb29d4674531d6f115237e16afce377c}
```

The key file must contain an unencrypted private key in hexadecimal. Geth encrypts it with a password you provide and writes a new keystore file.

### 4.4 Update (re-encrypt) an account

```bash
geth account update f466859ead1932d743d622cb74fc058882e8648a
```

This prompts for the current password and a new one — use it to change a password or migrate an old keystore format to the current one.

### 4.5 Import a presale wallet

```bash
geth wallet import /path/to/presale.wallet
```

### 4.6 Lightweight key derivation

For resource-constrained machines, `--lightkdf` reduces the RAM and CPU cost of key derivation at the expense of KDF strength:

```bash
geth account new --lightkdf
```

> [!CAUTION]
> `--lightkdf` makes keystore files faster to brute-force. Use it only on test networks or where the account holds no real value.

### 4.7 Hardware wallets

Geth can monitor and manage USB hardware wallets (Ledger, Trezor, KeepKey-class devices) and smartcard wallets when enabled:

```bash
geth --usb --mainnet
```

| Flag | Purpose |
|------|---------|
| `--usb` | Enable monitoring and management of USB hardware wallets |
| `--pcscdpath <path>` | Path to the smartcard daemon (`pcscd`) socket file |

Connected wallets and their derived accounts then appear in `admin.peers`-style listings and are usable for signing through the node.

---

## 5. The JavaScript Console

Geth includes an interactive JavaScript console built on the web3 object, extended with Geth-specific management namespaces.

### 5.1 Opening a console

```bash
# Start a node AND open a console in one process
geth --mainnet console

# Attach a console to an ALREADY-RUNNING node over IPC (recommended)
geth attach

# Attach over HTTP or WebSocket
geth attach http://localhost:8545
geth attach ws://localhost:8546
```

> [!TIP]
> Prefer `geth attach` (over the IPC socket) for day-to-day inspection. It connects to your running node without starting a second instance and has full access to all local namespaces regardless of which APIs you exposed over HTTP/WS.

Pass custom HTTP headers to the target when attaching to a remote endpoint:

```bash
geth attach -H "Authorization: Bearer <token>" https://node.example.com
```

### 5.2 Console namespaces

The console exposes these management namespaces (in addition to standard web3/eth methods):

| Namespace | What it covers |
|-----------|----------------|
| `eth` | Accounts, balances, blocks, transactions, calls, gas estimation |
| `net` | Peer count, listening status, network ID |
| `web3` | Utility helpers (hashing, unit conversion, encoding) |
| `admin` | Node info, peer management, start/stop RPC servers, import/export chain |
| `debug` | Tracing, state dumps, profiling, database introspection |
| `txpool` | Pending/queued transaction pool contents and status |
| `miner` | Block-building parameters (gas limit, extra data, fee recipient) |
| `clique` | Proof-of-authority signer management (PoA networks only) |
| `rpc` | RPC module listing |
| `dev` | Developer-mode helpers |

### 5.3 Common console commands

```javascript
// Current sync status (false once fully synced)
eth.syncing

// Latest block number
eth.blockNumber

// Balance of an address, converted to ether
web3.fromWei(eth.getBalance("0xfcad0b19bb29d4674531d6f115237e16afce377c"), "ether")

// Number of connected peers
net.peerCount

// Node identity and enode URL
admin.nodeInfo.enode

// Connected peers
admin.peers

// Pending transaction pool snapshot
txpool.status
```

```text
> eth.syncing
{
  currentBlock: 19000000,
  highestBlock: 19000123,
  startingBlock: 18999000,
  ...
}
```

### 5.4 Peer management from the console

```javascript
// Manually connect to a peer by enode URL
admin.addPeer("enode://<pubkey>@<ip>:30303")

// Add a peer that bypasses connection limits
admin.addTrustedPeer("enode://<pubkey>@<ip>:30303")

// Remove a peer
admin.removePeer("enode://<pubkey>@<ip>:30303")
```

### 5.5 Preloading scripts and one-off execution

```bash
# Preload JS helper files into the console
geth attach --preload /path/to/helpers.js

# Execute a single statement and exit
geth attach --exec "eth.blockNumber"
```

> [!NOTE]
> The standalone `geth js <file>` subcommand is **deprecated**. Use `geth attach --exec` or `--preload` instead.

---

## 6. JSON-RPC, WebSocket, IPC, and GraphQL

Geth speaks JSON-RPC over four transports. Each transport is disabled by default except IPC.

### 6.1 Enabling the transports

| Transport | Enable flag | Default address | Default port |
|-----------|-------------|-----------------|--------------|
| IPC (local socket) | enabled by default (`--ipcdisable` to turn off) | `<datadir>/geth.ipc` | — |
| HTTP | `--http` | `localhost` | `8545` |
| WebSocket | `--ws` | `localhost` | `8546` |
| GraphQL | `--graphql` (rides on the HTTP server) | (HTTP address) | `8545` |
| Engine API (auth) | always on for consensus client | `localhost` | `8551` |

```bash
geth --mainnet \
  --http --http.addr localhost --http.port 8545 --http.api eth,net,web3,txpool \
  --ws   --ws.addr   localhost --ws.port   8546 --ws.api   eth,net,web3 \
  --graphql \
  --authrpc.jwtsecret /etc/ethereum/jwt.hex
```

> [!IMPORTANT]
> The default API module set for HTTP and WebSocket is `net,web3` only. You must explicitly list namespaces with `--http.api` / `--ws.api` to expose `eth`, `txpool`, `debug`, etc. The `engine` and `eth` namespaces are served on the authenticated port automatically for the consensus client.

### 6.2 Key RPC server flags

| Flag | Default | Purpose |
|------|---------|---------|
| `--http.api` | `net,web3` | Comma-separated namespaces offered over HTTP |
| `--http.corsdomain` | (none) | Domains allowed for cross-origin requests (browser enforced) |
| `--http.vhosts` | `localhost` | Accepted virtual hostnames (server enforced; `*` wildcard) |
| `--http.rpcprefix` | `/` | HTTP path prefix on which JSON-RPC is served |
| `--ws.origins` | (none) | Origins allowed to open WebSocket connections |
| `--ipcpath` | `geth.ipc` | IPC socket/pipe filename within the datadir |
| `--rpc.gascap` | 50,000,000 | Gas cap for `eth_call`/`eth_estimateGas` (`0` = infinite) |
| `--rpc.txfeecap` | 1 ether | Max transaction fee allowed via RPC (`0` = no cap) |
| `--rpc.evmtimeout` | (set) | Timeout for `eth_call` (`0` = infinite) |
| `--rpc.batch-request-limit` | (set) | Maximum number of requests in a batch |

### 6.3 Making JSON-RPC calls

Over HTTP with `curl`:

```bash
curl -s -X POST http://localhost:8545 \
  -H "Content-Type: application/json" \
  --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
```

```text
{"jsonrpc":"2.0","id":1,"result":"0x121eac0"}
```

Get an account balance:

```bash
curl -s -X POST http://localhost:8545 \
  -H "Content-Type: application/json" \
  --data '{"jsonrpc":"2.0","method":"eth_getBalance","params":["0xfcad0b19bb29d4674531d6f115237e16afce377c","latest"],"id":1}'
```

Over IPC with the bundled tooling or any socket client:

```bash
geth attach --exec "eth.blockNumber"
```

### 6.4 GraphQL

When `--graphql` is set (alongside an enabled HTTP server), Geth serves a GraphQL endpoint and the interactive GraphiQL explorer:

```bash
geth --mainnet --http --graphql
# GraphQL endpoint: http://localhost:8545/graphql
# GraphiQL UI:      http://localhost:8545/graphql/ui
```

```bash
curl -s -X POST http://localhost:8545/graphql \
  -H "Content-Type: application/json" \
  --data '{"query":"{ block { number hash } }"}'
```

> [!NOTE]
> GraphQL can only start if the HTTP server is also started (`--http`). Enabling `--graphql` without `--http` has no effect.

### 6.5 Environment-variable equivalents

Every Geth flag has a matching environment variable of the form `GETH_<FLAG_NAME>` (uppercased, dots/dashes replaced with underscores). For example, `--http.port 8545` is equivalent to `GETH_HTTP_PORT=8545`. This is convenient for containerized deployments.

```bash
GETH_HTTP=true GETH_HTTP_API=eth,net,web3 geth --mainnet
```

---

## 7. Monitoring and Metrics

Geth can export operational metrics for dashboards and alerting.

```bash
geth --mainnet \
  --metrics \
  --metrics.addr 127.0.0.1 --metrics.port 6060
```

This serves metrics over HTTP. The standalone metrics server exposes:

| Path | Content |
|------|---------|
| `/debug/metrics` | Geth's internal metrics registry (JSON) |
| `/debug/metrics/prometheus` | Prometheus-format metrics for scraping |
| `/debug/vars` | Go expvar variables |

To push metrics to InfluxDB instead of (or in addition to) scraping:

=== "InfluxDB v1"

    ```bash
    geth --metrics --metrics.influxdb \
      --metrics.influxdb.endpoint http://localhost:8086 \
      --metrics.influxdb.database geth \
      --metrics.influxdb.username geth --metrics.influxdb.password secret
    ```

=== "InfluxDB v2"

    ```bash
    geth --metrics --metrics.influxdbv2 \
      --metrics.influxdb.endpoint http://localhost:8086 \
      --metrics.influxdb.token <token> \
      --metrics.influxdb.bucket geth \
      --metrics.influxdb.organization my-org
    ```

> [!TIP]
> A standard monitoring stack is Geth → Prometheus (scraping `/debug/metrics/prometheus`) → Grafana. The most useful health signals are `eth.syncing` (should be `false`), peer count, and chain-head block age.

Geth also supports OpenTelemetry tracing for RPC requests via the `--rpc.telemetry*` family of flags (endpoint, sampling ratio, basic-auth credentials), for sites that already operate an OTLP collector.

---

## 8. Database and History Maintenance

These `geth` subcommands operate on the local database. Most require the node to be **stopped** first.

### 8.1 Importing and exporting blocks

```bash
# Export the canonical chain to a file
geth export /backup/chain.rlp

# Export a block range (first and last block numbers)
geth export /backup/chain.rlp 0 1000000

# Import a previously exported chain file
geth import /backup/chain.rlp
```

### 8.2 Era history archives

Geth uses **Era** files for compact pre-merge and historical block archives:

```bash
# Export blockchain history to Era archives
geth export-history /backup/era

# Import an Era archive
geth import-history /backup/era

# Fetch era1 files (pre-merge history) from an HTTP endpoint
geth download-era --dir /backup/era
```

### 8.3 Pruning history

```bash
# Prune block bodies and receipts up to a point (frees disk)
geth prune-history
```

> [!WARNING]
> History pruning is irreversible for the pruned range. A pruned node can no longer serve those historical bodies/receipts to peers or to local queries. Keep an archive elsewhere if you need them.

### 8.4 Inspecting and repairing the database

```bash
# Print genesis JSON for the configured network
geth dumpgenesis

# Dump a specific block's state
geth dump <blockHashOrNumber>

# Low-level database operations
geth db inspect-trie ...
geth db metadata
geth db check-state-content      # verify state is cryptographically correct
```

### 8.5 Resetting the database

```bash
# Remove blockchain and state databases (keeps your keystore!)
geth removedb
```

```text
Remove this database? [y/N]
```

> [!IMPORTANT]
> `geth removedb` deletes chain and state data but **does not** touch your `keystore` directory — your accounts are safe. After `removedb`, the node re-syncs from scratch on next start. This is the standard fix for a corrupted database.

### 8.6 Snapshot maintenance

```bash
geth snapshot verify-state     # recompute and verify the state root against the snapshot
geth snapshot prune-state      # prune stale state using the snapshot
```

### 8.7 Initializing a custom genesis

```bash
geth --datadir /srv/private init genesis.json
```

> [!CAUTION]
> `geth init` is a destructive action that defines which network the datadir participates in. Run it only on a fresh datadir or one you intend to reinitialize.

---

## 9. Companion Tools

Building with `make all` produces these standalone binaries alongside `geth`.

### 9.1 `abigen` — Go bindings from contract ABIs

Generates type-safe Go bindings for Ethereum smart contracts.

```bash
abigen --abi token.abi --pkg main --type Token --out token.go
abigen --combined-json build/combined.json --pkg main --out contracts.go
abigen --abi token.abi --bin token.bin --pkg main --type Token --out token.go --v2
```

| Flag | Purpose |
|------|---------|
| `--abi` | Path to the contract ABI JSON (`-` for STDIN) |
| `--bin` | Path to contract bytecode (generates a deploy method) |
| `--combined-json` | Combined-JSON output from the Solidity compiler |
| `--pkg` | Go package name for the generated binding (required) |
| `--type` | Struct name for the binding (default = package name) |
| `--out` | Output file (default = stdout) |
| `--exc` | Comma-separated types to exclude |
| `--alias` | Comma-separated function/event renames (`orig1=alias1,...`) |
| `--v2` | Generate v2 bindings |

### 9.2 `evm` — standalone EVM and state-transition tool

Executes EVM bytecode and runs Ethereum state tests outside a full node.

```bash
# Run a full state transition (t8n — used by test fixtures)
evm transition --input.alloc alloc.json --input.env env.json --input.txs txs.json \
  --output.result result.json

# Trace execution of EVM code
evm --trace --trace.format json run <bytecode>
```

| Subcommand | Purpose |
|------------|---------|
| `transition` (alias `t8n`) | Execute a full state transition |
| `verkle` (alias `vkt`) | Binary-trie helpers |
| `run` | Execute raw EVM bytecode |

Tracing flags (`--trace`, `--trace.format json\|struct\|md`, `--trace.nomemory`, `--trace.nostack`, `--trace.nostorage`) control the opcode-level trace output.

### 9.3 `devp2p` — P2P network diagnostics

A toolkit for the Ethereum devp2p discovery and wire protocols.

```bash
devp2p enrdump <enr>                 # decode an Ethereum Node Record
devp2p discv4 ping <enode>           # ping a node over discovery v4
devp2p discv5 ...                    # discovery v5 operations
devp2p dns ...                       # DNS-based node-list operations
devp2p rlpx ...                      # RLPx transport operations
```

| Subcommand | Purpose |
|------------|---------|
| `enrdump` | Pretty-print an Ethereum Node Record (ENR) |
| `key` | Node-key utilities |
| `discv4` / `discv5` | Discovery protocol v4 / v5 operations |
| `dns` | DNS node-list tooling |
| `nodeset` | Manage node sets |
| `rlpx` | RLPx transport operations |

### 9.4 `ethkey` — offline key management

Operates on key files without a running node.

```bash
ethkey generate keyfile.json         # create a new key file
ethkey inspect keyfile.json          # show address / public key
ethkey signmessage keyfile.json "hello"
ethkey verifymessage <address> <signature> "hello"
ethkey changepassword keyfile.json
```

| Subcommand | Purpose |
|------------|---------|
| `generate` | Create a new key file |
| `inspect` | Print address/public key (add `--json` for machine output) |
| `signmessage` | Sign a message with the key |
| `verifymessage` | Verify a signed message |
| `changepassword` | Re-encrypt the key with a new password |

### 9.5 `era` — Era archive inspection

```bash
era block --dir ./eras --network mainnet 15000000   # print a block from an Era store
era info --dir ./eras 1000                           # epoch information
era verify --dir ./eras roots.txt                    # verify against expected accumulator roots
```

### 9.6 `rlpdump` — decode RLP

Pretty-prints RLP-encoded data (the encoding Ethereum uses for blocks, transactions, and network messages).

```bash
echo "0xc20102" | rlpdump
```

### 9.7 `abidump` — interpret ABI calldata

Decodes raw transaction calldata against the bundled 4byte signature database.

```bash
abidump a9059cbb000000000000000000000000ea0e2dc7d65a50e77fc7e84bff3fd2a9e781ff5c0000000000000000000000000000000000000000000000015af1d78b58c40000
```

```text
Info: transfer(address to, uint256 value)
```

### 9.8 `blsync` — beacon light client

Drives Geth's Engine API from a beacon-chain light client, useful for testing the execution client without a full consensus node:

```bash
blsync --mainnet \
  --beacon.api https://beacon.example.com \
  --blsync.engine.api http://localhost:8551 \
  --blsync.jwtsecret /etc/ethereum/jwt.hex
```

> [!NOTE]
> Without `--blsync.engine.api`, `blsync` performs a dry run (it follows the beacon chain but does not drive an execution client).

### 9.9 `workload` and `fetchpayload`

`workload` runs RPC workload/benchmark queries against a node; `fetchpayload` fetches an Engine-API payload. Both are development and testing utilities rather than everyday operational tools.

---

## 10. Common Tasks (Recipes)

### 10.1 Run a fully-validating mainnet node

```bash
# 1. JWT secret
openssl rand -hex 32 | tr -d "\n" > /etc/ethereum/jwt.hex

# 2. Geth (execution layer)
geth --mainnet \
  --datadir /srv/geth \
  --http --http.api eth,net,web3 --http.addr 127.0.0.1 \
  --authrpc.jwtsecret /etc/ethereum/jwt.hex \
  --metrics --metrics.addr 127.0.0.1

# 3. Start your consensus client pointed at http://localhost:8551 with the same jwt.hex
```

### 10.2 Query an address balance without writing code

```bash
geth attach --exec 'web3.fromWei(eth.getBalance("0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"),"ether")'
```

### 10.3 Watch sync progress

```bash
watch -n 5 'geth attach --exec "eth.syncing"'
```

### 10.4 Run a private network

```bash
# On every node:
geth --datadir ./node1 init genesis.json
geth --datadir ./node1 --networkid 12345 \
  --nodiscover --http --http.api eth,net,web3,admin \
  --port 30303
# Connect nodes manually with admin.addPeer(...) from the console
```

### 10.5 Generate Go bindings for a contract and use them

```bash
solc --combined-json abi,bin Token.sol > build/Token.json
abigen --combined-json build/Token.json --pkg contracts --out contracts/token.go
```

### 10.6 Back up and restore accounts

```bash
# Back up: copy the keystore directory (and remember each password!)
cp -r ~/.ethereum/keystore /backup/keystore

# Restore: place files back; Geth picks them up automatically
cp -r /backup/keystore ~/.ethereum/
```

> [!TIP]
> The keystore directory is portable between nodes and platforms — copying it is the entire backup. The password is **not** stored in the file; back it up separately and securely.

---

## 11. How It Works (Concepts)

A brief conceptual model; for architecture and internals see the Admin Guide.

### 11.1 Execution layer vs. consensus layer

Since The Merge, Ethereum runs on two cooperating clients per node:

- **Execution layer (Geth):** maintains the account/state database, mempool, and EVM; executes transactions; serves user JSON-RPC.
- **Consensus layer (beacon node):** runs proof-of-stake, attests, and tells the execution client which block is canonical.

They communicate over the **Engine API** (authenticated, port `8551`). The consensus client sends `engine_forkchoiceUpdated` and `engine_newPayload` calls; Geth executes and validates the payloads.

### 11.2 Snap sync

Snap sync downloads a recent snapshot of account and storage state directly from peers (the snap protocol), rather than re-executing every historical block. This is why a fresh node reaches the head in hours instead of weeks. After state arrives, Geth backfills block bodies and switches to full validation.

### 11.3 State storage: path vs. hash scheme

Geth's modern default is the **path-based** state scheme (`--state.scheme path`), which stores trie nodes by path and supports efficient online pruning of historical state. The legacy **hash-based** scheme keys nodes by hash. The scheme is chosen at database creation and is not toggled live.

### 11.4 Securing your node

> [!CAUTION]
> The JSON-RPC interface is powerful. Anyone who can reach an exposed `eth`/`debug`/`admin` endpoint can read your node's data and submit transactions. Follow these rules:
>
> - Keep `--http.addr`/`--ws.addr` bound to `localhost` unless you have a firewall and reverse proxy in front.
> - Never expose `admin` or `debug` namespaces to untrusted networks.
> - Protect the **Engine API** JWT secret file (`chmod 600`); it authenticates your consensus client.
> - Use `--http.vhosts` / `--http.corsdomain` to restrict which hosts and origins may call the node.
> - Account passwords and keystore files are your funds — back them up offline and never share them.

---

## 12. Troubleshooting

Errors below are formatted as the message Geth prints, its cause, the fix, and how to prevent recurrence.

### Error: `Post-merge network, but no beacon client seen. Please launch one to follow the chain!`

- **Cause:** Geth is running on a post-merge network with no consensus client attached to the Engine API.
- **Solution:** Start a consensus-layer client (Lighthouse, Prysm, Teku, Nimbus, Lodestar, or `blsync` for testing) pointed at Geth's `--authrpc.port` (`8551`) with the same JWT secret.
- **Prevention:** Always run a consensus client alongside Geth on mainnet and testnets.

### Error: `Failed to read JWT secret` / consensus client cannot authenticate

- **Cause:** Geth and the consensus client are using different JWT secret files, or the file is missing/unreadable.
- **Solution:** Generate one secret (`openssl rand -hex 32 | tr -d "\n" > jwt.hex`) and pass the same path to both via `--authrpc.jwtsecret` (Geth) and your CL's equivalent flag.
- **Prevention:** Specify the JWT path explicitly on both clients rather than relying on the auto-generated `<datadir>/geth/jwtsecret`.

### Error: `Fatal: Failed to load the private key: invalid character '...' at end of key file`

- **Cause:** `geth account import` was given a file that is not a clean hex private key (extra characters, trailing newline issues, or a keystore JSON instead of a raw key).
- **Solution:** Ensure the file contains only the 64-hex-character private key. Use `ethkey inspect` to validate a key file.
- **Prevention:** Export raw keys carefully; for keystore files use the keystore directory directly rather than `account import`.

### Error: `could not decrypt key with given password`

- **Cause:** Wrong password for the keystore file during `wallet import`, `account update`, or unlocking.
- **Solution:** Re-enter the correct password. There is no recovery if the password is lost — the key is unrecoverable without it.
- **Prevention:** Store account passwords in a secure password manager at creation time.

### Error: `Fatal: Passwords do not match`

- **Cause:** The two password entries during `account new`/`account update` differed.
- **Solution:** Re-run and enter the same password both times.

### Symptom: Node stuck at `Looking for peers` / `peercount=0`

- **Cause:** P2P port blocked, NAT misconfiguration, or no reachable bootnodes.
- **Solution:** Open TCP **and** UDP port `30303` on your firewall/router. Set `--nat extip:<your-public-ip>` if behind NAT, or `--nat upnp`/`--nat pmp` for automatic mapping.
- **Prevention:** Forward port `30303` (both protocols) when running behind a router.

### Symptom: Sync never completes / `eth.syncing` keeps moving but head never reached

- **Cause:** Slow disk (HDD), insufficient peers, or no consensus client driving fork choice.
- **Solution:** Move chain data to NVMe/SSD; ensure a consensus client is attached; verify peer count is healthy (`net.peerCount`).
- **Prevention:** Always run on fast storage and keep the consensus client running.

### Error: `database contains incompatible genesis` / wrong network on start

- **Cause:** The datadir was initialized for a different network or genesis than the flag you passed.
- **Solution:** Use a separate `--datadir` per network, or `geth removedb` and re-init/re-sync for the intended network.
- **Prevention:** Keep one datadir per network.

### Symptom: Node shuts down with a low-disk message

- **Cause:** Free disk space dropped below `--datadir.minfreedisk` (MB), triggering Geth's auto-shutdown protection.
- **Solution:** Free space or move chain data to a larger volume; consider `--gcmode full` (not archive) and history pruning.
- **Prevention:** Provision generous storage headroom and monitor free space.

### Symptom: Slow startup with a long state-recovery rewind after a crash

- **Cause:** Geth was killed ungracefully (`kill -9` or power loss), leaving the trie cache unflushed.
- **Solution:** Let the recovery complete; it rewinds to the last flushed state and replays. If the database is corrupt, `geth removedb` and re-sync.
- **Prevention:** Always shut Geth down with `Ctrl-C`/`SIGTERM` and allow it to finish.

### Error: `exceeds block gas limit` / `gas required exceeds allowance` on `eth_call`

- **Cause:** A call or estimate exceeded the RPC gas cap (`--rpc.gascap`, default 50,000,000).
- **Solution:** Raise `--rpc.gascap` (or set `0` for unlimited) if you genuinely need larger calls; otherwise review the call.
- **Prevention:** Keep call gas within sane bounds; raise the cap deliberately.

### Error: `method <name> does not exist/is not available`

- **Cause:** The namespace for that method was not exposed on the transport you called.
- **Solution:** Add the namespace to `--http.api`/`--ws.api` (e.g. include `debug` or `txpool`), or use `geth attach` over IPC which exposes local namespaces.
- **Prevention:** Enumerate the namespaces you need when enabling HTTP/WS.

---

## 13. Frequently Asked Questions

**Q: Is Geth a complete Ethereum node by itself?**
No. Geth is the execution-layer client. Since The Merge you must also run a consensus-layer (beacon) client connected over the Engine API. Geth alone will not follow the chain head.

**Q: Which consensus clients work with Geth?**
Any standards-compliant consensus client — Lighthouse, Prysm, Teku, Nimbus, or Lodestar — connected to Geth's `--authrpc` endpoint with a shared JWT secret. For testing, the bundled `blsync` light client can drive the Engine API.

**Q: What's the difference between snap and full sync?**
`snap` (default) downloads recent state directly from peers and reaches the head fastest. `full` re-executes every block from genesis, rebuilding state locally. Neither, by itself, keeps all *historical* state — that's what archive mode is for.

**Q: How do I run an archive node?**
`geth --syncmode full --gcmode archive`. Expect much larger disk usage and longer sync. Only needed for historical-state queries.

**Q: Where are my accounts stored?**
In `<datadir>/keystore` as encrypted JSON files. Back up that directory (and remember each password). The directory is portable between nodes.

**Q: Can I unlock an account over RPC like older Geth versions?**
No. The `personal` RPC namespace has been removed. Sign with an external signer (`--signer`), a hardware wallet, or manage keys offline with `ethkey`.

**Q: What ports does Geth use?**
P2P: `30303` (TCP+UDP). HTTP-RPC: `8545`. WebSocket: `8546`. Engine API (auth): `8551`. Metrics: `6060` (when enabled with `--metrics.port`).

**Q: How do I expose RPC to another machine safely?**
Bind `--http.addr 0.0.0.0` only behind a firewall/reverse proxy, restrict `--http.vhosts` and `--http.corsdomain`, expose only the `eth,net,web3` namespaces, and never expose `admin`/`debug` publicly.

**Q: Which networks does Geth support out of the box?**
Mainnet plus the Sepolia, Holesky, and Hoodi proof-of-stake test networks, and an ephemeral `--dev` PoA network. Older testnets (Goerli, Rinkeby, Ropsten) are no longer included.

**Q: How do I reset a corrupted database without losing my accounts?**
`geth removedb`. It deletes chain/state data but leaves the `keystore` directory intact, then re-syncs on next start.

**Q: What is the `era` / `--datadir.era` directory?**
Era files are compact archives of historical (largely pre-merge) blocks. You can export/import them with `geth export-history`/`import-history` and fetch them with `geth download-era`. Storing them on a separate volume via `--datadir.era` keeps the main database lean.

**Q: How do I generate Go code to interact with a contract?**
Use `abigen` with the contract ABI (and optionally bytecode) to produce a type-safe Go binding.

**Q: Does Geth still mine?**
Geth does not perform proof-of-work mining. On a post-merge network the consensus client requests block payloads and Geth's payload builder constructs them. The `miner.*` flags configure block-building parameters (gas ceiling, extra data, fee recipient), not PoW mining.

**Q: How do I see what my node is doing in real time?**
Watch the logs, or `geth attach` and inspect `eth.syncing`, `eth.blockNumber`, `net.peerCount`, `txpool.status`, and `admin.peers`.

---

## 14. Command and Flag Reference

### 14.1 `geth` subcommands

| Subcommand | Purpose |
|------------|---------|
| `account` | Manage accounts (`list`, `new`, `update`, `import`) |
| `wallet` | Manage presale wallets (`import`) |
| `init` | Bootstrap and initialize a new genesis block |
| `dumpgenesis` | Dump the genesis JSON configuration to stdout |
| `import` / `export` | Import/export the blockchain to/from a file |
| `import-history` / `export-history` | Import/export Era history archives |
| `download-era` | Fetch era1 (pre-merge history) files over HTTP |
| `import-preimages` | Import the preimage database from an RLP stream |
| `prune-history` | Prune block bodies and receipts up to a point |
| `dump` | Dump a specific block's state from storage |
| `console` | Start a node and open an interactive JS console |
| `attach` | Attach a JS console to a running node |
| `js` | (Deprecated) Execute JavaScript files |
| `db` | Low-level database operations (`metadata`, `inspect-trie`, `check-state-content`, `delete`, `put`, `inspect-history`, …) |
| `removedb` | Remove blockchain and state databases (keeps keystore) |
| `snapshot` | Snapshot maintenance (`prune-state`, `verify-state`, …) |
| `bintrie` | Binary-trie operations (`convert`) |
| `version` / `license` | Print version / license information |
| `dumpconfig` | Dump the effective configuration as TOML |
| `show-deprecated-flags` | List deprecated flags |

### 14.2 Most-used flags

| Flag | Default | Purpose |
|------|---------|---------|
| `--datadir <dir>` | platform-specific | Data directory for databases and keystore |
| `--mainnet` / `--sepolia` / `--holesky` / `--hoodi` | `--mainnet` | Select a pre-configured network |
| `--dev` | off | Ephemeral developer PoA network |
| `--networkid <int>` | mainnet ID | Custom network ID |
| `--syncmode <mode>` | `snap` | `snap` or `full` |
| `--gcmode <mode>` | `full` | `full` (prune) or `archive` (keep all state) |
| `--http` | off | Enable HTTP-RPC server |
| `--http.api <list>` | `net,web3` | Namespaces over HTTP |
| `--ws` | off | Enable WebSocket-RPC server |
| `--graphql` | off | Enable GraphQL (needs `--http`) |
| `--authrpc.jwtsecret <file>` | auto | JWT secret for the Engine API |
| `--authrpc.port <port>` | `8551` | Engine API port |
| `--port <port>` | `30303` | P2P listening port |
| `--bootnodes <enodes>` | network default | Comma-separated bootstrap enode URLs |
| `--nat <spec>` | `any` | NAT mapping (`any\|none\|upnp\|pmp\|extip:<IP>\|stun:<IP:PORT>`) |
| `--maxpeers <n>` | 50 | Maximum network peers (`0` disables networking) |
| `--metrics` | off | Enable metrics collection |
| `--cache <MB>` | 1024 (varies) | Megabytes of memory for internal caching |
| `--verbosity <0-5>` | 3 | Logging verbosity (via `debug` flags) |

### 14.3 Default ports

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

### 14.4 RPC / console namespaces

| Namespace | Console | Description |
|-----------|:------:|-------------|
| `eth` | ✓ | Core chain, accounts, transactions, calls |
| `net` | ✓ | Network/peer info |
| `web3` | ✓ | Client version and utility helpers |
| `txpool` | ✓ | Transaction pool inspection |
| `debug` | ✓ | Tracing, state dumps, profiling |
| `admin` | ✓ | Node and peer management |
| `miner` | ✓ | Block-building parameters |
| `clique` | ✓ | PoA signer management (clique networks) |
| `engine` | — | Engine API (authenticated port, for the consensus client) |
| `rpc` | ✓ | RPC module listing |

---

_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._
