discv5

package
v0.0.2 Latest Latest
Warning

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

Go to latest
Published: Dec 9, 2025 License: MIT Imports: 12 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

	// LocalNode is the pre-created local node (optional, preferred)
	// If provided, this takes precedence over LocalENR and ENR-related config
	LocalNode *node.Node

	// PrivateKey is the node's private key (required if LocalNode is nil)
	PrivateKey *ecdsa.PrivateKey

	// ENRIP is the IPv4 address to advertise in the ENR (optional)
	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 (optional)
	// If not specified, the port will be obtained from the transport layer
	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, transport Transport) (*Service, error)

New creates a new discv5 service.

The transport must be created first and passed to New(). The service will register its packet handler with the transport.

Example:

transport, _ := transport.NewUDPTransport(&transport.Config{
    ListenAddr: "0.0.0.0:9000",
})

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

service, err := New(config, transport)
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.

Note: The transport is started separately and passed to New(). This method is kept for compatibility and lifecycle management.

func (*Service) Stop

func (s *Service) Stop() error

Stop stops the discv5 service.

Note: This does NOT close the transport as it's managed externally. The caller is responsible for closing the transport.

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)
}

type Transport added in v0.0.2

type Transport interface {
	protocol.Transport
	LocalAddr() *net.UDPAddr
	AddHandler(handler func(data []byte, from *net.UDPAddr, localAddr *net.UDPAddr) bool)
}

Transport is the interface for sending packets. It must have a LocalAddr() method to get the bind address.

Directories

Path Synopsis
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.

Jump to

Keyboard shortcuts

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