Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions bootnode/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,12 @@ type Config struct {
// EnableDiscv5 enables Discovery v5 protocol (default: true)
EnableDiscv5 bool

// ServeAll disables EL/CL classification and fork-ID/digest filtering. Every
// discovered node is pooled (into every enabled table) and served to every
// requester, turning the bootnode into a plain discv5 rendezvous that relays
// all peers regardless of eth/eth2 fields. Default: false (classify + filter).
ServeAll bool

// SessionLifetime is the discv5 session lifetime (default: 12 hours)
SessionLifetime time.Duration

Expand Down
38 changes: 29 additions & 9 deletions bootnode/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -254,8 +254,8 @@ func New(cfg *Config) (*Service, error) {
Alpha: 3,
LookupTimeout: 30 * time.Second,
OnNodeFound: func(n *nodes.Node) bool {
// Filter by fork ID before adding to table
if n.Record() != nil && s.enrManager != nil {
// Filter by fork ID before adding to table (skipped in serve-all).
if !cfg.ServeAll && n.Record() != nil && s.enrManager != nil {
if isEL, _ := s.enrManager.FilterELNode(n.Record()); !isEL {
// Mark as bad node
if err := cfg.Database.StoreBadNode(n.IDBytes(), db.LayerEL, "invalid_fork_id"); err != nil {
Expand Down Expand Up @@ -337,8 +337,8 @@ func New(cfg *Config) (*Service, error) {
Alpha: 3,
LookupTimeout: 30 * time.Second,
OnNodeFound: func(n *nodes.Node) bool {
// Filter by fork digest before adding to table
if n.Record() != nil && s.enrManager != nil {
// Filter by fork digest before adding to table (skipped in serve-all).
if !cfg.ServeAll && n.Record() != nil && s.enrManager != nil {
if !s.enrManager.FilterCLNode(n.Record()) {
// Mark as bad node
if err := cfg.Database.StoreBadNode(n.IDBytes(), db.LayerCL, "invalid_fork_digest"); err != nil {
Expand Down Expand Up @@ -1042,14 +1042,26 @@ func (s *Service) onNodeSeen(n *v5node.Node, timestamp time.Time) {
if s.enrManager != nil {
nodeID := n.ID()

if isEL, _ := s.enrManager.FilterELNode(n.Record()); isEL && s.elTable != nil && s.elNodeDB != nil {
// Look up the generic node from the table
isEL, _ := s.enrManager.FilterELNode(n.Record())
isCL := s.enrManager.FilterCLNode(n.Record())

// Serve-all pools a node into every table, so refresh last-seen wherever it
// actually lives (checking both tables) rather than by classification.
if s.config.ServeAll {
isEL = s.elTable != nil
isCL = s.clTable != nil
} else if isEL {
// Classified mode is EL-xor-CL: keep the original precedence.
isCL = false
}

if isEL && s.elTable != nil && s.elNodeDB != nil {
if genericNode := s.elTable.Get(nodeID); genericNode != nil {
genericNode.SetLastSeen(timestamp) // This marks it dirty
s.elNodeDB.QueueUpdate(genericNode)
}
} else if s.enrManager.FilterCLNode(n.Record()) && s.clTable != nil && s.clNodeDB != nil {
// Look up the generic node from the table
}
if isCL && s.clTable != nil && s.clNodeDB != nil {
if genericNode := s.clTable.Get(nodeID); genericNode != nil {
genericNode.SetLastSeen(timestamp) // This marks it dirty
s.clNodeDB.QueueUpdate(genericNode)
Expand All @@ -1069,7 +1081,8 @@ func (s *Service) onFindNodeV5(id *identity, msg *v5protocol.FindNode, sourceNod
// A shared identity serves both layers under one ID, so classify a known
// requester by its ENR and serve only its layer(s); an unclassifiable known
// peer gets nothing, an unknown one (no ENR yet) falls through to both.
if id.servesEL && id.servesCL && sourceNode != nil && s.enrManager != nil {
// Serve-all skips this: every requester gets nodes from every served layer.
if !s.config.ServeAll && id.servesEL && id.servesCL && sourceNode != nil && s.enrManager != nil {
sourceRecord := sourceNode.Record()
serveEL, _ = s.enrManager.FilterELNode(sourceRecord)
serveCL = s.enrManager.FilterCLNode(sourceRecord)
Expand Down Expand Up @@ -1268,6 +1281,13 @@ func (s *Service) checkAndAddNode(n *v5node.Node) bool {
isEL, _ := s.enrManager.FilterELNode(n.Record())
isCL := s.enrManager.FilterCLNode(n.Record())

// Serve-all: skip classification and pool into every enabled table, so a node
// is admitted regardless of whether it advertises an eth/eth2 field.
if s.config.ServeAll {
isEL = s.elTable != nil
isCL = s.clTable != nil
}

// Add to appropriate table(s)
added := false
if isEL && s.elTable != nil {
Expand Down
7 changes: 7 additions & 0 deletions cmd/bootnodoor/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ var (
enableEL bool
enableCL bool

// Rendezvous mode
serveAll bool

// WebUI flags
enableWebUI bool
webUIHost string
Expand Down Expand Up @@ -148,6 +151,9 @@ func init() {
rootCmd.Flags().BoolVar(&enableEL, "enable-el", true, "Enable Execution Layer support (discv4 + discv5)")
rootCmd.Flags().BoolVar(&enableCL, "enable-cl", true, "Enable Consensus Layer support (discv5)")

// Rendezvous mode
rootCmd.Flags().BoolVar(&serveAll, "serve-all", false, "Disable EL/CL classification and fork-ID filtering: pool and serve every discovered node to everyone (plain discv5 rendezvous)")

// WebUI
rootCmd.Flags().BoolVar(&enableWebUI, "web-ui", false, "Enable web UI")
rootCmd.Flags().StringVar(&webUIHost, "web-host", "0.0.0.0", "Web UI host")
Expand Down Expand Up @@ -512,6 +518,7 @@ func runBootnode(cmd *cobra.Command, args []string) error {
config.ENRPort = enrUDPPort
config.EnableDiscv4 = enableDiscv4
config.EnableDiscv5 = enableDiscv5
config.ServeAll = serveAll
config.MaxActiveNodes = maxActiveNodes
config.MaxNodesPerIP = maxNodesPerIP
config.Logger = logger
Expand Down