Skip to content

discv4

Classes

Name
struct discv4::ChainPeerCacheRefreshResult
Result of refreshing the local chain peer cache from a remote URL.
struct discv4::ChainPeerConfig
Parsed chain configuration shared across peer discovery and ETH session setup.
struct discv4::ChainPeerCacheSignatureVerificationResult
Verification result for a signed chain peer cache JSON document.
class discv4::DialHistory
Tracks recently-dialed peers and suppresses retry attempts until a configurable cooldown expires.
struct discv4::ValidatedPeer
A discovered peer whose public key has already been validated.
struct discv4::WatcherPoolConfig
Configurable connection limits for a WatcherPool. Defaults keep three active dial/watch slots per chain.
struct discv4::WatcherPool
Global resource pool shared across all chain DialSchedulers. Enforces a two-level fd cap: total across all chains, and per chain.
struct discv4::DialScheduler
Per-chain dial scheduler mirroring go-ethereum's dialScheduler. Maintains up to pool->max_per_chain concurrent dial coroutines, respecting the global pool->max_total cap across all chains. All methods run on the single io_context thread — no mutex needed.
struct discv4::DiscoveredPeer
struct discv4::discv4Config
class discv4::discv4_client
Discovery v4 protocol client.
struct discv4::discv4_enr_request
ENRRequest packet — discv4 wire type 0x05 (EIP-868).
struct discv4::ForkId
Fork identifier per EIP-2124.
struct discv4::discv4_enr_response
Parsed ENRResponse — discv4 wire type 0x06 (EIP-868).
class discv4::discv4_packet
Base class for all Discovery V4 packets.
class discv4::discv4_ping
struct discv4::discv4_pong
class discv4::PacketFactory

Types

Name
enum class ChainDiscoveryDefault
enum class DiscoveryForkFilter
enum class discv4Error { kNetworkSendFailed, kNetworkReceiveFailed, kPacketTooSmall, kInvalidPacketType, kHashMismatch, kSignatureParseFailed, kSignatureRecoveryFailed, kSigningFailed, kContextCreationFailed, kInvalidPublicKey, kRlpPayloadEmpty, kPongTimeout, kPongParseFailed}
Discovery v4 protocol error codes.
enum class PacketError
using ChainPeerCacheRefreshResult BootstrapCacheRefreshResult
using ChainPeerConfig BootstrapChainConfig
using ChainPeerCacheSignatureVerificationResult BootstrapSignatureVerificationResult
using std::function< void( ValidatedPeer vp, std::function< void(rlpx::DisconnectReason)> on_done, std::function< void(std::shared_ptr< rlpx::RlpxSession >)> on_connected, boost::asio::yield_context yield)> DialFn
using std::function< void( const ValidatedPeer & vp, rlpx::DisconnectReason reason, bool was_connected)> DialFeedbackFn
Callback signature for dial/session exit feedback.
using std::function< bool(const DiscoveredPeer &)> FilterFn
Predicate applied to a DiscoveredPeer before it is enqueued for dialing. Return true to allow dialing, false to drop. When unset (nullptr), all peers are accepted. Mirrors go-ethereum UDPv4::NewNodeFilter (eth/protocols/eth/discovery.go).
using asio::ip::udp udp
using std::array< uint8_t, 64 > NodeId
using std::function< void(const DiscoveredPeer &)> PeerDiscoveredCallback
using std::function< void(const std::string &)> ErrorCallback
template <typename T >
using outcome::result< T, discv4Error, outcome::policy::all_narrow >
Result
Result type for Discovery v4 operations.
using outcome::result< void, discv4Error, outcome::policy::all_narrow > VoidResult
Result type for Discovery v4 operations without return value.
using outcome::result< void, PacketError > PacketResult
using std::function< void(const std::vector< uint8_t > &, const udp::endpoint &)> SendCallback
using std::shared_ptr< spdlog::logger > Logger

Functions

Name
std::filesystem::path bootstrap_cache_json_path(const std::string & argv0)
std::optional< std::filesystem::path > find_bootstrap_peers_json_path(const std::string & argv0, const std::string & override_path)
std::optional< std::string > download_bootstrap_json(const std::string & url)
bool write_bootstrap_cache_json_if_changed(const std::filesystem::path & json_path, const std::string & json_text)
std::optional< BootstrapCacheRefreshResult > refresh_bootstrap_cache_json(const std::filesystem::path & json_path, const std::string & url)
std::vector< ValidatedPeer > load_bootstrap_peers_from_json_text(const std::string & chain_name, const std::string & json_text)
std::vector< ValidatedPeer > load_bootstrap_peers_from_json(const std::string & chain_name, const std::filesystem::path & json_path)
std::optional< std::array< uint8_t, 4 > > load_bootstrap_fork_id_hash_from_json_text(const std::string & chain_name, const std::string & json_text)
std::optional< std::array< uint8_t, 4 > > load_bootstrap_fork_id_hash_from_json(const std::string & chain_name, const std::filesystem::path & json_path)
std::optional< BootstrapChainConfig > load_bootstrap_chain_config_from_json_text(const std::string & chain_name, const std::string & json_text)
std::optional< BootstrapChainConfig > load_bootstrap_chain_config_from_json(const std::string & chain_name, const std::filesystem::path & json_path)
BootstrapSignatureVerificationResult verify_bootstrap_json_signature(const std::string & json_text, const std::string & expected_signer_address)
std::optional< ValidatedPeer > make_validated_peer_from_enode(const std::string & enode)
Parse an enode:// peer URI into a validated peer entry.
std::optional< ValidatedPeer > make_validated_peer_from_enr(const std::string & enr_uri)
Parse an enr: peer URI into a validated peer entry.
std::filesystem::path chain_peer_cache_json_path(const std::string & argv0)
Return the default local cache path for chain_enodes.json next to the executable.
std::optional< std::filesystem::path > find_chain_peer_cache_json_path(const std::string & argv0, const std::string & override_path)
Locate a local chain peer cache JSON file.
std::optional< std::string > download_chain_peer_cache_json(const std::string & url)
Download the chain peer cache JSON payload from a remote URL. Supports either raw JSON or gzip-compressed JSON bodies.
bool write_chain_peer_cache_json_if_changed(const std::filesystem::path & json_path, const std::string & json_text)
Write the chain peer JSON cache only when the contents changed.
std::optional< ChainPeerCacheRefreshResult > refresh_chain_peer_cache_json(const std::filesystem::path & json_path, const std::string & url)
Refresh a local chain peer cache from a remote URL.
std::vector< ValidatedPeer > load_chain_peers_from_json_text(const std::string & chain_name, const std::string & json_text)
Load cached peers for a specific chain from JSON text.
std::vector< ValidatedPeer > load_chain_peers_from_json(const std::string & chain_name, const std::filesystem::path & json_path)
Load cached peers for a specific chain from a JSON or gzip-compressed JSON file.
std::optional< std::array< uint8_t, 4 > > load_chain_fork_id_hash_from_json_text(const std::string & chain_name, const std::string & json_text)
Load the first available peer fork hash for a specific chain from JSON text.
std::optional< std::array< uint8_t, 4 > > load_chain_fork_id_hash_from_json(const std::string & chain_name, const std::filesystem::path & json_path)
Load the first available peer fork hash for a specific chain from a JSON or gzip-compressed JSON file.
std::optional< ChainPeerConfig > load_chain_peer_config_from_json_text(const std::string & chain_name, const std::string & json_text)
Load the parsed chain configuration from JSON text.
std::optional< ChainPeerConfig > load_chain_peer_config_from_json(const std::string & chain_name, const std::filesystem::path & json_path)
Load the parsed chain configuration from a JSON or gzip-compressed JSON file.
ChainPeerCacheSignatureVerificationResult verify_chain_peer_cache_json_signature(const std::string & json_text, const std::string & expected_signer_address)
Verify the top-level chain_enodes.json signature.
const char * to_string(discv4Error error)
Convert error code to human-readable string.
FilterFn make_fork_id_filter(const std::array< uint8_t, 4U > & expected_hash)
Create a FilterFn that accepts only peers whose ENR eth entry carries a ForkId with the given 4-byte hash (CRC32 of genesis + applied forks).
std::shared_ptr< spdlog::logger > createLogger(const std::string & tag, const std::string & basepath ="")
Create a logger instance.

Attributes

Name
size_t kHashSize
size_t kSigSize
size_t kPacketTypeSize
size_t kPacketHeaderSize
size_t kPacketTypeOffset
size_t kUncompressedPubKey
std::array< uint8_t, 3U > kEthKey
size_t kWireHashSize
Outer Keccak-256 hash.
size_t kWireSigSize
Recoverable ECDSA signature.
size_t kWirePacketTypeSize
Single packet-type byte.
size_t kWireRecoveryIdSize
Recoverable ECDSA recovery id.
size_t kWireCompactSigSize
size_t kWireHeaderSize
size_t kWirePacketTypeOffset
size_t kNodeIdSize
Node identity.
size_t kNodeIdHexSize
size_t kUncompressedPubKeySize
0x04 prefix + 64 bytes
size_t kIPv4Size
Network.
size_t kUdpBufferSize
uint8_t kPacketTypePing
Packet type identifiers.
uint8_t kPacketTypePong
uint8_t kPacketTypeFindNode
uint8_t kPacketTypeNeighbours
uint8_t kPacketTypeEnrRequest
uint8_t kPacketTypeEnrResponse
uint8_t kProtocolVersion
Protocol version advertised in PING packets.
uint32_t kPacketExpirySeconds
Default packet expiry window (seconds).
auto kDefaultPingTimeout
Default networking timers.
auto kDefaultPeerExpiry
auto kDefaultDialHistoryExpiry
size_t kEnrSeqSize
ENR sequence number field size in PONG (optional, 6-byte big-endian uint48).

Types Documentation

enum ChainDiscoveryDefault

Enumerator Value Description
kAuto
kDiscv4
kCacheEnrDiscv5
kEnrTree

enum DiscoveryForkFilter

Enumerator Value Description
kRequire
kDisabled

enum discv4Error

Enumerator Value Description
kNetworkSendFailed
kNetworkReceiveFailed
kPacketTooSmall
kInvalidPacketType
kHashMismatch
kSignatureParseFailed
kSignatureRecoveryFailed
kSigningFailed
kContextCreationFailed
kInvalidPublicKey
kRlpPayloadEmpty
kPongTimeout
kPongParseFailed

Discovery v4 protocol error codes.

enum PacketError

Enumerator Value Description
kNullPacket
kSignFailure

using BootstrapCacheRefreshResult

using discv4::BootstrapCacheRefreshResult = ChainPeerCacheRefreshResult;

using BootstrapChainConfig

using discv4::BootstrapChainConfig = ChainPeerConfig;

using BootstrapSignatureVerificationResult

using discv4::BootstrapSignatureVerificationResult = ChainPeerCacheSignatureVerificationResult;

using DialFn

using discv4::DialFn = std::function<void(
   ValidatedPeer                                               vp,
   std::function<void(rlpx::DisconnectReason)>                 on_done,
   std::function<void(std::shared_ptr<rlpx::RlpxSession>)>    on_connected,
   boost::asio::yield_context                                  yield)>;

Callback signature for what to run per dial attempt. vp — the peer to connect to on_done — call on every exit path with the disconnect/failure reason (recycling the slot) on_connected — call once the ETH handshake is confirmed yield — coroutine yield context

using DialFeedbackFn

using discv4::DialFeedbackFn = std::function<void(
   const ValidatedPeer&     vp,
   rlpx::DisconnectReason   reason,
   bool                     was_connected)>;

Callback signature for dial/session exit feedback.

using FilterFn

using discv4::FilterFn = std::function<bool( const DiscoveredPeer& )>;

Predicate applied to a DiscoveredPeer before it is enqueued for dialing. Return true to allow dialing, false to drop. When unset (nullptr), all peers are accepted. Mirrors go-ethereum UDPv4::NewNodeFilter (eth/protocols/eth/discovery.go).

using udp

using discv4::udp = asio::ip::udp;

using NodeId

using discv4::NodeId = std::array<uint8_t, 64>;

using PeerDiscoveredCallback

using discv4::PeerDiscoveredCallback = std::function<void(const DiscoveredPeer&)>;

using ErrorCallback

using discv4::ErrorCallback = std::function<void(const std::string&)>;

using Result

template <typename T >
using discv4::Result = outcome::result<T, discv4Error, outcome::policy::all_narrow>;

Result type for Discovery v4 operations.

Template Parameters:

  • T The success value type

using VoidResult

using discv4::VoidResult = outcome::result<void, discv4Error, outcome::policy::all_narrow>;

Result type for Discovery v4 operations without return value.

using PacketResult

using discv4::PacketResult = outcome::result<void, PacketError>;

using SendCallback

using discv4::SendCallback = std::function<void(const std::vector<uint8_t>&, const udp::endpoint&)>;

using Logger

using rlp::base::Logger = std::shared_ptr<spdlog::logger>;

Functions Documentation

function bootstrap_cache_json_path

std::filesystem::path bootstrap_cache_json_path(
    const std::string & argv0
)

function find_bootstrap_peers_json_path

std::optional< std::filesystem::path > find_bootstrap_peers_json_path(
    const std::string & argv0,
    const std::string & override_path
)

function download_bootstrap_json

std::optional< std::string > download_bootstrap_json(
    const std::string & url
)

function write_bootstrap_cache_json_if_changed

bool write_bootstrap_cache_json_if_changed(
    const std::filesystem::path & json_path,
    const std::string & json_text
)

function refresh_bootstrap_cache_json

std::optional< BootstrapCacheRefreshResult > refresh_bootstrap_cache_json(
    const std::filesystem::path & json_path,
    const std::string & url
)

function load_bootstrap_peers_from_json_text

std::vector< ValidatedPeer > load_bootstrap_peers_from_json_text(
    const std::string & chain_name,
    const std::string & json_text
)

function load_bootstrap_peers_from_json

std::vector< ValidatedPeer > load_bootstrap_peers_from_json(
    const std::string & chain_name,
    const std::filesystem::path & json_path
)

function load_bootstrap_fork_id_hash_from_json_text

std::optional< std::array< uint8_t, 4 > > load_bootstrap_fork_id_hash_from_json_text(
    const std::string & chain_name,
    const std::string & json_text
)

function load_bootstrap_fork_id_hash_from_json

std::optional< std::array< uint8_t, 4 > > load_bootstrap_fork_id_hash_from_json(
    const std::string & chain_name,
    const std::filesystem::path & json_path
)

function load_bootstrap_chain_config_from_json_text

std::optional< BootstrapChainConfig > load_bootstrap_chain_config_from_json_text(
    const std::string & chain_name,
    const std::string & json_text
)

function load_bootstrap_chain_config_from_json

std::optional< BootstrapChainConfig > load_bootstrap_chain_config_from_json(
    const std::string & chain_name,
    const std::filesystem::path & json_path
)

function verify_bootstrap_json_signature

BootstrapSignatureVerificationResult verify_bootstrap_json_signature(
    const std::string & json_text,
    const std::string & expected_signer_address
)

function make_validated_peer_from_enode

std::optional< ValidatedPeer > make_validated_peer_from_enode(
    const std::string & enode
)

Parse an enode:// peer URI into a validated peer entry.

Parameters:

Return: Parsed validated peer, or std::nullopt when the URI is malformed.

function make_validated_peer_from_enr

std::optional< ValidatedPeer > make_validated_peer_from_enr(
    const std::string & enr_uri
)

Parse an enr: peer URI into a validated peer entry.

Parameters:

  • enr_uri Peer ENR URI.

Return: Parsed validated peer, or std::nullopt when the URI is malformed.

function chain_peer_cache_json_path

std::filesystem::path chain_peer_cache_json_path(
    const std::string & argv0
)

Return the default local cache path for chain_enodes.json next to the executable.

Parameters:

  • argv0 Program path used to locate the executable directory.

Return: Cache file path.

function find_chain_peer_cache_json_path

std::optional< std::filesystem::path > find_chain_peer_cache_json_path(
    const std::string & argv0,
    const std::string & override_path
)

Locate a local chain peer cache JSON file.

Parameters:

  • argv0 Program path used to locate the executable directory.
  • override_path Optional explicit file path.

Return: Existing JSON or gzip-compressed JSON file path, or std::nullopt if none exists.

function download_chain_peer_cache_json

std::optional< std::string > download_chain_peer_cache_json(
    const std::string & url
)

Download the chain peer cache JSON payload from a remote URL. Supports either raw JSON or gzip-compressed JSON bodies.

Parameters:

  • url Source URL.

Return: Decoded JSON text, or std::nullopt on failure.

function write_chain_peer_cache_json_if_changed

bool write_chain_peer_cache_json_if_changed(
    const std::filesystem::path & json_path,
    const std::string & json_text
)

Write the chain peer JSON cache only when the contents changed.

Parameters:

  • json_path Destination cache path.
  • json_text JSON text to store.

Return: true when the cache contents changed and were rewritten.

function refresh_chain_peer_cache_json

std::optional< ChainPeerCacheRefreshResult > refresh_chain_peer_cache_json(
    const std::filesystem::path & json_path,
    const std::string & url
)

Refresh a local chain peer cache from a remote URL.

Parameters:

  • json_path Destination cache path.
  • url Source URL.

Return: Refresh metadata when download succeeded, or std::nullopt on failure.

function load_chain_peers_from_json_text

std::vector< ValidatedPeer > load_chain_peers_from_json_text(
    const std::string & chain_name,
    const std::string & json_text
)

Load cached peers for a specific chain from JSON text.

Parameters:

  • chain_name Canonical top-level JSON key.
  • json_text JSON document contents.

Return: Parsed validated peers.

function load_chain_peers_from_json

std::vector< ValidatedPeer > load_chain_peers_from_json(
    const std::string & chain_name,
    const std::filesystem::path & json_path
)

Load cached peers for a specific chain from a JSON or gzip-compressed JSON file.

Parameters:

  • chain_name Canonical top-level JSON key.
  • json_path JSON file path.

Return: Parsed validated peers.

function load_chain_fork_id_hash_from_json_text

std::optional< std::array< uint8_t, 4 > > load_chain_fork_id_hash_from_json_text(
    const std::string & chain_name,
    const std::string & json_text
)

Load the first available peer fork hash for a specific chain from JSON text.

Parameters:

  • chain_name Canonical top-level JSON key.
  • json_text JSON document contents.

Return: 4-byte fork hash when present, or std::nullopt.

function load_chain_fork_id_hash_from_json

std::optional< std::array< uint8_t, 4 > > load_chain_fork_id_hash_from_json(
    const std::string & chain_name,
    const std::filesystem::path & json_path
)

Load the first available peer fork hash for a specific chain from a JSON or gzip-compressed JSON file.

Parameters:

  • chain_name Canonical top-level JSON key.
  • json_path JSON file path.

Return: 4-byte fork hash when present, or std::nullopt.

function load_chain_peer_config_from_json_text

std::optional< ChainPeerConfig > load_chain_peer_config_from_json_text(
    const std::string & chain_name,
    const std::string & json_text
)

Load the parsed chain configuration from JSON text.

Parameters:

  • chain_name Canonical top-level JSON key.
  • json_text JSON document contents.

Return: Parsed chain config, or std::nullopt when missing or invalid.

function load_chain_peer_config_from_json

std::optional< ChainPeerConfig > load_chain_peer_config_from_json(
    const std::string & chain_name,
    const std::filesystem::path & json_path
)

Load the parsed chain configuration from a JSON or gzip-compressed JSON file.

Parameters:

  • chain_name Canonical top-level JSON key.
  • json_path JSON file path.

Return: Parsed chain config, or std::nullopt when missing or invalid.

function verify_chain_peer_cache_json_signature

ChainPeerCacheSignatureVerificationResult verify_chain_peer_cache_json_signature(
    const std::string & json_text,
    const std::string & expected_signer_address
)

Verify the top-level chain_enodes.json signature.

Parameters:

  • json_text JSON document contents.
  • expected_signer_address Expected Ethereum signer address.

Return: Verification result.

function to_string

const char * to_string(
    discv4Error error
)

Convert error code to human-readable string.

Parameters:

  • error The error code

Return: Error description string

function make_fork_id_filter

inline FilterFn make_fork_id_filter(
    const std::array< uint8_t, 4U > & expected_hash
)

Create a FilterFn that accepts only peers whose ENR eth entry carries a ForkId with the given 4-byte hash (CRC32 of genesis + applied forks).

Parameters:

  • expected_hash 4-byte CRC32 fork hash to match against.

Return: FilterFn suitable for assignment to DialScheduler::filter_fn.

Mirrors go-ethereum NewNodeFilter (eth/protocols/eth/discovery.go):

return func(n *enode.Node) bool {
    var entry enrEntry
    if err := n.Load(&entry); err != nil { return false }
    return filter(entry.ForkID) == nil
}

Peers with no eth_fork_id (ENR absent or eth entry missing) are dropped.

function createLogger

std::shared_ptr< spdlog::logger > createLogger(
    const std::string & tag,
    const std::string & basepath =""
)

Create a logger instance.

Parameters:

  • tag Tagging name for identifying logger.
  • basepath Optional base path for log output (platform dependent).

Return: Logger object.

Attributes Documentation

variable kHashSize

static size_t kHashSize = kWireHashSize;

variable kSigSize

static size_t kSigSize = kWireSigSize;

variable kPacketTypeSize

static size_t kPacketTypeSize = kWirePacketTypeSize;

variable kPacketHeaderSize

static size_t kPacketHeaderSize = kWireHeaderSize;

variable kPacketTypeOffset

static size_t kPacketTypeOffset = kWirePacketTypeOffset;

variable kUncompressedPubKey

static size_t kUncompressedPubKey = kUncompressedPubKeySize;

variable kEthKey

static std::array< uint8_t, 3U > kEthKey { 0x65U, 0x74U, 0x68U };

variable kWireHashSize

static size_t kWireHashSize = 32;

Outer Keccak-256 hash.

discv4 wire-packet layout constants Layout: hash(32) || signature(65) || packet-type(1) || RLP(payload)

variable kWireSigSize

static size_t kWireSigSize = 65;

Recoverable ECDSA signature.

variable kWirePacketTypeSize

static size_t kWirePacketTypeSize = 1;

Single packet-type byte.

variable kWireRecoveryIdSize

static size_t kWireRecoveryIdSize = 1;

Recoverable ECDSA recovery id.

variable kWireCompactSigSize

static size_t kWireCompactSigSize = kWireSigSize - kWireRecoveryIdSize;

variable kWireHeaderSize

static size_t kWireHeaderSize = kWireHashSize + kWireSigSize + kWirePacketTypeSize;

variable kWirePacketTypeOffset

static size_t kWirePacketTypeOffset = kWireHashSize + kWireSigSize;

variable kNodeIdSize

static size_t kNodeIdSize = 64;

Node identity.

Uncompressed secp256k1 pubkey without 0x04 prefix

variable kNodeIdHexSize

static size_t kNodeIdHexSize = kNodeIdSize * 2;

variable kUncompressedPubKeySize

static size_t kUncompressedPubKeySize = kNodeIdSize + kWirePacketTypeSize;

0x04 prefix + 64 bytes

variable kIPv4Size

static size_t kIPv4Size = 4;

Network.

variable kUdpBufferSize

static size_t kUdpBufferSize = 2048;

variable kPacketTypePing

static uint8_t kPacketTypePing = 0x01U;

Packet type identifiers.

variable kPacketTypePong

static uint8_t kPacketTypePong = 0x02U;

variable kPacketTypeFindNode

static uint8_t kPacketTypeFindNode = 0x03U;

variable kPacketTypeNeighbours

static uint8_t kPacketTypeNeighbours = 0x04U;

variable kPacketTypeEnrRequest

static uint8_t kPacketTypeEnrRequest = 0x05U;

variable kPacketTypeEnrResponse

static uint8_t kPacketTypeEnrResponse = 0x06U;

variable kProtocolVersion

static uint8_t kProtocolVersion = 0x04U;

Protocol version advertised in PING packets.

variable kPacketExpirySeconds

static uint32_t kPacketExpirySeconds = 60U;

Default packet expiry window (seconds).

variable kDefaultPingTimeout

auto kDefaultPingTimeout = std::chrono::milliseconds(5000);

Default networking timers.

variable kDefaultPeerExpiry

auto kDefaultPeerExpiry = std::chrono::seconds(300);

variable kDefaultDialHistoryExpiry

auto kDefaultDialHistoryExpiry = std::chrono::seconds(35);

variable kEnrSeqSize

static size_t kEnrSeqSize = 6;

ENR sequence number field size in PONG (optional, 6-byte big-endian uint48).


Updated on 2026-06-05 at 17:22:18 -0700