discv5

package
v0.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 2, 2025 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

Package discv5 implements the Ethereum Discovery v5 protocol.

This is a generic discv5 implementation providing:

  • UDP transport for network communication
  • Session management for encrypted communication
  • Protocol handler for message processing
  • ENR (Ethereum Node Record) support

Index

Constants

View Source
const DefaultMajorityThreshold = 0.75

DefaultMajorityThreshold is the percentage threshold for IP consensus (0.0-1.0)

View Source
const DefaultMinReports = 5

DefaultMinReports is the minimum number of PONG responses needed before considering IP valid

View Source
const DefaultRecentWindow = 5 * time.Minute

DefaultRecentWindow is the time window to consider reports "recent" for IP change detection

View Source
const DefaultReportExpiry = 30 * time.Minute

DefaultReportExpiry is how long to keep IP reports before expiring them

Variables

View Source
var (
	ErrMissingPrivateKey = fmt.Errorf("private key is required")
	ErrInvalidPort       = fmt.Errorf("invalid port number")
	ErrAlreadyRunning    = fmt.Errorf("service is already running")
	ErrNotRunning        = fmt.Errorf("service is not running")
)

Common errors

Functions

This section is empty.

Types

type Config

type Config struct {
	// Service context
	Context context.Context

	// PrivateKey is the node's private key
	PrivateKey *ecdsa.PrivateKey

	// BindIP is the IP address to bind to
	BindIP net.IP

	// BindPort is the UDP port to bind to
	BindPort int

	// ENRIP is the IPv4 address to advertise in the ENR (optional, uses BindIP if nil)
	ENRIP net.IP

	// ENRIP6 is the IPv6 address to advertise in the ENR (optional)
	ENRIP6 net.IP

	// ENRPort is the UDP port to advertise in the ENR (0 = use BindPort)
	ENRPort int

	// ETH2Data is the eth2 field to include in the ENR (optional)
	// This should be the 16-byte encoded eth2 field containing fork digest and next fork info
	ETH2Data []byte

	// LocalENR is an already-initialized ENR to use for this node (optional)
	// If provided, this ENR will be used instead of creating a new one.
	// The higher-level service is responsible for loading, creating, and persisting this ENR.
	LocalENR *enr.Record

	// OnHandshakeComplete is called when a handshake completes successfully
	OnHandshakeComplete protocol.OnHandshakeCompleteCallback

	// OnNodeUpdate is called when a node's ENR is updated
	OnNodeUpdate protocol.OnNodeUpdateCallback

	// OnNodeSeen is called when a node is seen (receives a message)
	OnNodeSeen protocol.OnNodeSeenCallback

	// OnFindNode is called when a FINDNODE request is received
	OnFindNode protocol.OnFindNodeCallback

	// OnTalkReq is called when a TALKREQ request is received
	OnTalkReq protocol.OnTalkReqCallback

	// OnPongReceived is called when a PONG response is received
	OnPongReceived protocol.OnPongReceivedCallback

	// SessionLifetime is how long sessions remain valid (default 30 minutes)
	SessionLifetime time.Duration

	// MaxSessions is the maximum number of cached sessions (default 1000)
	MaxSessions int

	// Logger for debug messages
	Logger logrus.FieldLogger
}

Config contains configuration for the discv5 service.

func DefaultConfig

func DefaultConfig() *Config

DefaultConfig returns a default configuration.

func (*Config) Validate

func (c *Config) Validate() error

Validate validates the configuration.

type IPDiscovery

type IPDiscovery struct {
	// contains filtered or unexported fields
}

IPDiscovery tracks external IP addresses and ports reported by peers via PONG messages.

It implements a consensus mechanism to detect the node's public IP address and port:

  • Collects IP:Port from PONG responses (shows our address as seen by remote peer)
  • Tracks IPv4 and IPv6 independently (separate consensus for each)
  • Requires minimum number of reports before considering an address valid
  • Requires majority threshold (e.g., 75%) for consensus
  • Expires old reports to handle IP/port changes

func NewIPDiscovery

func NewIPDiscovery(cfg IPDiscoveryConfig) *IPDiscovery

NewIPDiscovery creates a new IP discovery service.

func (*IPDiscovery) GetConsensusIP

func (ipd *IPDiscovery) GetConsensusIP() net.IP

GetConsensusIP returns the current consensus IPv4 address, or nil if no consensus. For IPv6, this returns nil. Use GetStats() for complete information.

func (*IPDiscovery) GetStats

func (ipd *IPDiscovery) GetStats() IPDiscoveryStats

GetStats returns current statistics.

func (*IPDiscovery) ReportIP

func (ipd *IPDiscovery) ReportIP(ip net.IP, port uint16, reporterID string)

ReportIP records an IP address and port from a PONG response.

Parameters:

  • ip: The IP address as reported by the remote peer
  • port: The port as reported by the remote peer
  • reporterID: The node ID of the peer that sent the PONG (for tracking)

func (*IPDiscovery) Reset

func (ipd *IPDiscovery) Reset()

Reset clears all reports and resets consensus state. This can be used when the node's network changes.

type IPDiscoveryConfig

type IPDiscoveryConfig struct {
	// MinReports is the minimum number of PONG responses needed (default: 3)
	MinReports int

	// MajorityThreshold is the percentage needed for consensus (default: 0.75)
	MajorityThreshold float64

	// ReportExpiry is how long to keep reports (default: 30 minutes)
	ReportExpiry time.Duration

	// RecentWindow is the time window to consider reports "recent" (default: 5 minutes)
	// Used for detecting IP changes - recent reports get priority
	RecentWindow time.Duration

	// OnConsensusReached is called when IP:Port consensus is reached or changes
	// isIPv6 indicates whether this is an IPv6 address (true) or IPv4 (false)
	OnConsensusReached func(ip net.IP, port uint16, isIPv6 bool)

	// Logger for debug messages
	Logger logrus.FieldLogger
}

IPDiscoveryConfig contains configuration for IP discovery

type IPDiscoveryStats

type IPDiscoveryStats struct {
	TotalReportsIPv4     int
	TotalReportsIPv6     int
	UniqueIPv4Addrs      int
	UniqueIPv6Addrs      int
	ConsensusReachedIPv4 bool
	ConsensusReachedIPv6 bool
	ConsensusIPv4Addr    string         // "IP:Port" format
	ConsensusIPv6Addr    string         // "IP:Port" format
	IPv4Reports          map[string]int // "IP:Port" -> count
	IPv6Reports          map[string]int // "IP:Port" -> count
}

GetStats returns statistics about IP discovery.

type Service

type Service struct {
	// contains filtered or unexported fields
}

Service is the main discv5 service.

It provides a minimal, generic discv5 implementation that can be extended by higher-level services (e.g., beacon bootnode).

func New

func New(cfg *Config) (*Service, error)

New creates a new discv5 service.

Example:

privKey, _ := crypto.GenerateKey()
config := DefaultConfig()
config.PrivateKey = privKey

service, err := New(config)
if err != nil {
    log.Fatal(err)
}
defer service.Stop()

func (*Service) FindNode

func (s *Service) FindNode(n *node.Node, distances []uint) ([]*node.Node, error)

FindNode sends a FINDNODE request to a node and returns the discovered nodes.

The distances parameter specifies which distance buckets to query (0-255). Use distance 0 to request the node's own ENR.

Returns a slice of discovered nodes, or an error if the request fails.

Example:

// Find nodes at distance 256 (all nodes)
nodes, err := service.FindNode(targetNode, []uint{256})
if err != nil {
    log.Printf("findnode failed: %v", err)
}

func (*Service) Handler

func (s *Service) Handler() *protocol.Handler

Handler returns the protocol handler.

This allows higher-level services to access the handler for sending requests and managing the protocol.

func (*Service) LocalNode

func (s *Service) LocalNode() *node.Node

LocalNode returns our local node information.

func (*Service) Ping

func (s *Service) Ping(n *node.Node) error

Ping sends a PING request to a node and waits for a PONG response.

Returns an error if the ping fails or times out.

Example:

if err := service.Ping(targetNode); err != nil {
    log.Printf("ping failed: %v", err)
}

func (*Service) Sessions

func (s *Service) Sessions() *session.Cache

Sessions returns the session cache.

func (*Service) Start

func (s *Service) Start() error

Start starts the discv5 service.

This starts the UDP packet receiver.

func (*Service) Stop

func (s *Service) Stop() error

Stop stops the discv5 service.

This gracefully shuts down all components.

func (*Service) TalkReq

func (s *Service) TalkReq(n *node.Node, protocolName string, request []byte) ([]byte, error)

TalkReq sends a TALKREQ request to a node and returns the response.

The protocolName parameter identifies the application protocol. The request parameter contains the application-specific request data.

Returns the response data, or an error if the request fails.

Example:

resp, err := service.TalkReq(targetNode, "my-protocol", []byte("my-request"))
if err != nil {
    log.Printf("talkreq failed: %v", err)
}

func (*Service) Transport

func (s *Service) Transport() *transport.UDPTransport

Transport returns the UDP transport.

Directories

Path Synopsis
Package crypto provides cryptographic utilities for the discv5 protocol.
Package crypto provides cryptographic utilities for the discv5 protocol.
Package enr implements Ethereum Node Records (ENR) as defined in EIP-778.
Package enr implements Ethereum Node Records (ENR) as defined in EIP-778.
Package node provides core types for representing network nodes.
Package node provides core types for representing network nodes.
Package protocol implements the discv5 wire protocol message types and codec.
Package protocol implements the discv5 wire protocol message types and codec.
Package session implements session management and encryption for discv5.
Package session implements session management and encryption for discv5.
Package transport provides the UDP transport layer for discv5.
Package transport provides the UDP transport layer for discv5.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL