Skip to main content
The devp2p command is a low-level utility for working with the Ethereum peer-to-peer network stack. It lets you inspect and test node discovery, decode Ethereum Node Records (ENRs), manage DNS discovery trees, and run conformance tests for the eth and snap wire protocols — all without a running Geth instance.

Installation

devp2p is built alongside the rest of go-ethereum:
git clone https://github.com/ethereum/go-ethereum.git
cd go-ethereum
make all
# binary at ./build/bin/devp2p
Or install it directly:
go install github.com/ethereum/go-ethereum/cmd/devp2p@latest

Subcommands

SubcommandDescription
enrdumpDecode and pretty-print an Ethereum Node Record
keyGenerate and convert node key files
discv4Node Discovery v4 tools
discv5Node Discovery v5 tools
dnsDNS-based node discovery operations
nodesetInspect and filter JSON node set files
rlpxRLPx connection and protocol tests

ENR decoding (devp2p enrdump)

Decodes a base64-encoded Ethereum Node Record and prints its fields in a human-readable form.
devp2p enrdump enr:-IS4QHCYrYZbAKWCBRlAy5zzaDZXJBGkcnh4MHcBFZntXNFrdvJjX04jRzjzCBOonrkTfj499SZuOh8R33Ls8RRcy5wBgmlkgnY0gmlwhH8AAAGJc2VjcDI1NmsxoQPKY0yuDUmstAHYpMa2_oxVtw0RW_QAdpzBQA8yWM0xOIN1ZHCCdl8
You can also read from a file:
devp2p enrdump --file node.enr

Node key management (devp2p key)

# Create a new node key.
devp2p key generate mynode.key

# Convert a key to an enode:// URL.
devp2p key to-enode mynode.key -ip 127.0.0.1 -tcp 30303

Discovery v4 (devp2p discv4)

The discv4 subcommand interacts with the Kademlia-based Node Discovery v4 protocol.
# Ping a node and wait for a pong.
devp2p discv4 ping <enode-or-ENR>

# Resolve the most recent record for a node in the DHT.
devp2p discv4 resolve <enode-or-ENR>

# Request a node's ENR using EIP-868.
devp2p discv4 requestenr <enode-or-ENR>

# Crawl the DHT and write discovered nodes to a JSON file.
devp2p discv4 crawl nodes.json

# Re-resolve all nodes already in a nodes.json file.
devp2p discv4 resolve-json nodes.json

Discovery v4 test suite

# Assign a second loopback address (macOS example).
sudo ifconfig lo0 add 127.0.0.2

# Run the test suite against a node.
export NODE="enr:-..."
devp2p discv4 test -listen1 127.0.0.1 -listen2 127.0.0.2 $NODE

Discovery v5 (devp2p discv5)

Discovery v5 uses a separate protocol from v4 and is the basis for the ENR-based discovery used in post-merge Ethereum.
# Ping a node.
devp2p discv5 ping <ENR>

# Resolve the most recent record for a node.
devp2p discv5 resolve <ENR>

# Run a discovery v5 node that listens for peers.
devp2p discv5 listen

# Crawl the discv5 DHT and update a node set.
devp2p discv5 crawl nodes.json

Discovery v5 test suite

export NODE="enr:-..."
devp2p discv5 test -listen1 127.0.0.1 -listen2 127.0.0.2 $NODE

DNS discovery (devp2p dns)

DNS discovery (EIP-1459) lets clients bootstrap by resolving a DNS name instead of hardcoded bootnodes.
# Download a complete DNS discovery tree to a local directory.
devp2p dns sync enrtree://... ./my-tree

# Sign a local tree directory (updates the root signature).
devp2p dns sign ./my-tree keyfile.key

# Generate DNS TXT records from a signed tree.
devp2p dns to-txt ./my-tree records.txt

# Publish to Cloudflare DNS.
devp2p dns to-cloudflare ./my-tree

# Publish to Amazon Route 53.
devp2p dns to-route53 ./my-tree

Node sets (devp2p nodeset)

Node set files are JSON files produced by the discovery crawlers and consumed by the DNS deployer commands.
# Display statistics about a node set.
devp2p nodeset info nodes.json

# Filter a node set and write the result to stdout.
devp2p nodeset filter nodes.json -eth-network mainnet -snap -limit 20

Filter flags

FlagDescription
-limit <N>Keep only the top N nodes by score
-ip <CIDR>Keep only nodes in the given IP subnet
-min-age <duration>Keep only nodes first seen before this duration
-eth-network <name>Filter by ETH network: mainnet, sepolia, or holesky
-snapKeep only nodes that advertise snap protocol support
-les-serverKeep only nodes that advertise LES server support

RLPx (devp2p rlpx)

The rlpx subcommand tests low-level RLPx encrypted transport and the eth/snap application protocols.
# Perform an RLPx handshake ping.
devp2p rlpx ping <enode-or-ENR>

Running the eth protocol test suite

1

Initialize Geth with the test chain

geth init --datadir /tmp/ethtest ./cmd/devp2p/internal/ethtest/testdata/genesis.json
2

Import test blocks

geth import --datadir /tmp/ethtest ./cmd/devp2p/internal/ethtest/testdata/chain.rlp
3

Start Geth with the test configuration

geth \
  --datadir /tmp/ethtest \
  --nodiscover \
  --nat=none \
  --networkid 3503995874084926 \
  --authrpc.jwtsecret jwt.secret
4

Run the eth protocol tests

devp2p rlpx eth-test \
  --chain ./cmd/devp2p/internal/ethtest/testdata \
  --node enode://... \
  --engineapi http://127.0.0.1:8551 \
  --jwtsecret $(cat jwt.secret)
# Run snap protocol tests.
devp2p rlpx snap-test \
  --chain ./cmd/devp2p/internal/ethtest/testdata \
  --node enode://... \
  --engineapi http://127.0.0.1:8551 \
  --jwtsecret $(cat jwt.secret)
Re-initialize the node from genesis before each test run. The test suite relies on a specific chain state and will fail if the node has processed extra transactions.

Build docs developers (and LLMs) love