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
| Subcommand | Description |
|---|
enrdump | Decode and pretty-print an Ethereum Node Record |
key | Generate and convert node key files |
discv4 | Node Discovery v4 tools |
discv5 | Node Discovery v5 tools |
dns | DNS-based node discovery operations |
nodeset | Inspect and filter JSON node set files |
rlpx | RLPx 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
| Flag | Description |
|---|
-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 |
-snap | Keep only nodes that advertise snap protocol support |
-les-server | Keep 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
Initialize Geth with the test chain
geth init --datadir /tmp/ethtest ./cmd/devp2p/internal/ethtest/testdata/genesis.json
Import test blocks
geth import --datadir /tmp/ethtest ./cmd/devp2p/internal/ethtest/testdata/chain.rlp
Start Geth with the test configuration
geth \
--datadir /tmp/ethtest \
--nodiscover \
--nat=none \
--networkid 3503995874084926 \
--authrpc.jwtsecret jwt.secret
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.