Jesse A. Green / notebook

Go-Ethereum (Geth) User Guide

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.

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.

# 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
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:

./build/bin/geth attach
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

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

Build all tools

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

Plain go build

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:

./build/bin/geth version
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:

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.

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:

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)
# 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).

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.

# 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:

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.

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

geth --dev --http --http.api eth,net,web3,debug --datadir /tmp/geth-dev
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

geth account new
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:

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

geth account list
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

geth account import /path/to/key.prv
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

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

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:

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:

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

# 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:

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

// 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
> eth.syncing
{
  currentBlock: 19000000,
  highestBlock: 19000123,
  startingBlock: 18999000,
  ...
}

5.4 Peer management from the console

// 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

# 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
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:

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

Get an account balance:

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:

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:

geth --mainnet --http --graphql
# GraphQL endpoint: http://localhost:8545/graphql
# GraphiQL UI:      http://localhost:8545/graphql/ui
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.

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

7. Monitoring and Metrics

Geth can export operational metrics for dashboards and alerting.

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

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

InfluxDB v2

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

# 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:

# 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

# 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

# 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

# Remove blockchain and state databases (keeps your keystore!)
geth removedb
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

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

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.

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.

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

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.

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

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

echo "0xc20102" | rlpdump

9.7 abidump — interpret ABI calldata

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

abidump a9059cbb000000000000000000000000ea0e2dc7d65a50e77fc7e84bff3fd2a9e781ff5c0000000000000000000000000000000000000000000000015af1d78b58c40000
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:

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

# 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

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

10.3 Watch sync progress

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

10.4 Run a private network

# 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

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

# 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