diff --git a/eth/backend.go b/eth/backend.go index 15243ad5c9..ad83e6585b 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -487,6 +487,15 @@ func (s *Ethereum) setupDiscovery() error { s.discmix.AddSource(iter) } + // Add DHT nodes from discv4. + if s.p2pServer.DiscoveryV4() != nil { + asyncFilter := s.p2pServer.DiscoveryV4().RequestENR + filter := eth.NewNodeFilter(s.blockchain) + iter := enode.AsyncFilter(s.p2pServer.DiscoveryV4().RandomNodes(), asyncFilter) + iter = enode.Filter(iter, filter) + s.discmix.AddSource(iter) + } + // Add DHT nodes from discv5. if s.p2pServer.DiscoveryV5() != nil { filter := eth.NewNodeFilter(s.blockchain) diff --git a/p2p/enode/iter.go b/p2p/enode/iter.go index 4b7e28929e..0c252a33ec 100644 --- a/p2p/enode/iter.go +++ b/p2p/enode/iter.go @@ -152,6 +152,37 @@ func (f *filterIter) Next() bool { return false } +// AsyncFilter wraps an iterator such that Next only returns nodes for which +// the 'check' function returns a (possibly modified) node. +func AsyncFilter(it Iterator, check func(*Node) (*Node, error)) Iterator { + return &AsyncFilterIter{it, nil, check} +} + +type AsyncFilterIter struct { + it Iterator + buffer *Node + check func(*Node) (*Node, error) +} + +func (f *AsyncFilterIter) Next() bool { + for f.it.Next() { + nn, err := f.check(f.it.Node()) + if err == nil { + f.buffer = nn + return true + } + } + return false +} + +func (f *AsyncFilterIter) Node() *Node { + return f.buffer +} + +func (f *AsyncFilterIter) Close() { + f.it.Close() +} + // FairMix aggregates multiple node iterators. The mixer itself is an iterator which ends // only when Close is called. Source iterators added via AddSource are removed from the // mix when they end. diff --git a/p2p/server.go b/p2p/server.go index f3a58bba29..30b7a63017 100644 --- a/p2p/server.go +++ b/p2p/server.go @@ -483,7 +483,6 @@ func (srv *Server) setupDiscovery() error { return err } srv.discv4 = ntab - srv.discmix.AddSource(ntab.RandomNodes()) } if srv.Config.DiscoveryV5 { cfg := discover.Config{