Skip to main content

Geth

Go Ethereum, the reference execution client. Since the Merge a full node needs two processes: an execution client (Geth) and a consensus client (Lighthouse, Prysm, Teku, Nimbus), connected over the Engine API with a shared JWT secret. Geth alone no longer syncs mainnet.

For local development that separation is avoidable — geth --dev runs a single-process chain that seals a block whenever a transaction arrives.

Install

# Windows: add the install directory to PATH
C:\Program Files\Geth
geth version

Development chain

The quickest path, and what most local work needs:

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

--dev pre-funds a developer account, uses instant sealing and needs no genesis file. Note that Anvil and the Hardhat network are usually more convenient for contract work — see Development tools. Reach for Geth when the node's own behaviour is what you are testing.

Private chain

genesis.json describes the chain's parameters and initial state. It is not the genesis block itself — Geth builds that from it.

{
"config": {
"chainId": 15,
"homesteadBlock": 0,
"eip150Block": 0,
"eip155Block": 0,
"eip158Block": 0,
"byzantiumBlock": 0,
"constantinopleBlock": 0,
"petersburgBlock": 0,
"istanbulBlock": 0,
"berlinBlock": 0,
"londonBlock": 0,
"clique": {
"period": 5,
"epoch": 30000
}
},
"difficulty": "0x1",
"gasLimit": "0x1c9c380",
"extradata": "0x0000000000000000000000000000000000000000000000000000000000000000SEALER_ADDRESS_WITHOUT_0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"alloc": {
"0xYOUR_ADDRESS": { "balance": "1000000000000000000000" }
}
}

Things the short version of this file gets wrong:

  • chainId, not chainID. The JSON key is case-sensitive; the wrong spelling is ignored and the chain ID defaults to 0, which breaks EIP-155 replay protection and every wallet that connects.
  • gasLimit must be realistic. "0x0000008" is 8 gas — not enough for any transaction, so the chain accepts nothing. 0x1c9c380 is 30 000 000, matching mainnet.
  • Proof of work is gone. difficulty and mining no longer apply after the Merge. A standalone private chain uses Clique proof of authority, which needs the clique config block and the sealer address embedded in extradata.
  • Declare every fork. Omitting fork blocks leaves the chain on ancient rules, so recent opcodes are unavailable and contracts compiled with a current Solidity version fail to deploy.
  • alloc pre-funds accounts. Without it there is no ether on the chain and nothing can be deployed, since PoA gives no block rewards.

Setting up the extradata field by hand is error-prone. puppeth used to generate it and has been removed; the practical alternative for a throwaway chain is geth --dev, and for a persistent one, a tool such as ethereum-genesis-generator.

Initialise

geth init --datadir "E:\temp\eth-data" "E:\temp\eth-data\genesis.json"

Run this once per data directory. Re-running against an existing chain fails rather than resetting it — delete the geth subdirectory to start over, but keep keystore, which holds the accounts.

Run

geth --datadir "E:\temp\eth-data" --networkid 15 --http --http.addr 127.0.0.1 --http.api eth,net,web3
FlagPurpose
--datadirChain data and keystore location
--networkidMust match chainId for a private chain
--httpEnable the JSON-RPC HTTP server (port 8545)
--http.addrBind address
--http.apiWhich API namespaces to expose
--devEphemeral development chain, instant sealing

--syncmode light no longer exists. Light client support (LES) was deprecated and removed; the modes are snap (default) and full.

Binding to --http.addr 0.0.0.0 exposes the RPC endpoint to the network. On a node holding real keys that is remote control of the funds — bind to 127.0.0.1 and put a proxy in front if remote access is genuinely needed.

Accounts

The personal API was removed in Geth 1.14. Account management is now a subcommand or an external signer:

geth account new --datadir "E:\temp\eth-data"
geth account list --datadir "E:\temp\eth-data"
geth account import --datadir "E:\temp\eth-data" private-key.txt

For signing from scripts, use Clef, the standalone signer, rather than unlocking an account inside the node.

JavaScript console

geth attach # IPC, same machine
geth attach ipc:\\.\pipe\geth.ipc # Windows named pipe
geth attach http://127.0.0.1:8545 # over HTTP
// Node information
admin.nodeInfo
admin.nodeInfo.enode // the address other nodes connect to
admin.peers

// Accounts and balances
eth.accounts
eth.blockNumber
eth.getBalance(eth.accounts[0])
web3.fromWei(eth.getBalance(eth.accounts[0]), "ether")

// Transactions
eth.sendTransaction({
from: eth.accounts[0],
to: eth.accounts[1],
value: web3.toWei(5, "ether")
})
eth.getBlock(6)
eth.getTransaction("0x3b446dd1241a0caaac0c33c66770205fa01368b2772ab391f9526436817402a8")
eth.getTransactionReceipt("0x...") // status 0x1 succeeded, 0x0 reverted

// Pending transactions
txpool.status
txpool.inspect

The console bundles an old web3.js 0.x, which is why it uses web3.toWei rather than web3.utils.toWei. That applies only inside the console — application code uses whatever version you installed.

These no longer work:

personal.newAccount() // removed in Geth 1.14
personal.unlockAccount(...) // removed
miner.start(1) // proof of work; removed after the Merge
admin.sleepBlocks(1) // removed