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
- Variables
- type Config
- type IPDiscovery
- type IPDiscoveryConfig
- type IPDiscoveryStats
- type Service
- func (s *Service) FindNode(n *node.Node, distances []uint) ([]*node.Node, error)
- func (s *Service) Handler() *protocol.Handler
- func (s *Service) LocalNode() *node.Node
- func (s *Service) Ping(n *node.Node) error
- func (s *Service) Sessions() *session.Cache
- func (s *Service) Start() error
- func (s *Service) Stop() error
- func (s *Service) TalkReq(n *node.Node, protocolName string, request []byte) ([]byte, error)
- type Transport
Constants ¶
const DefaultMajorityThreshold = 0.75
DefaultMajorityThreshold is the percentage threshold for IP consensus (0.0-1.0)
const DefaultMinReports = 5
DefaultMinReports is the minimum number of PONG responses needed before considering IP valid
const DefaultRecentWindow = 5 * time.Minute
DefaultRecentWindow is the time window to consider reports "recent" for IP change detection
const DefaultReportExpiry = 30 * time.Minute
DefaultReportExpiry is how long to keep IP reports before expiring them
Variables ¶
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.
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 ¶
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 ¶
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 ¶
Handler returns the protocol handler.
This allows higher-level services to access the handler for sending requests and managing the protocol.
func (*Service) Ping ¶
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) Start ¶
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 ¶
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 ¶
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)
}
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. |