eth: dial nodes from discv5 (#30302)
Here I am adding a discv5 nodes source into the p2p dial iterator. It's an improved version of #29533. Unlike discv4, the discv5 random nodes iterator will always provide full ENRs. This means we can apply filtering to the results and will only try dialing nodes which explictly opt into the eth protocol with a matching chain. I have also removed the dial iterator from snap. We don't have an official DNS list for snap anymore, and I doubt anyone else is running one. While we could potentially filter for snap on discv5, there will be very few nodes announcing it, and the extra iterator would just stall the dialer. --------- Co-authored-by: lightclient <lightclient@protonmail.com>
This commit is contained in:
parent
7a149a159a
commit
6eb42a6b4f
@ -64,15 +64,13 @@ type Config = ethconfig.Config
|
||||
|
||||
// Ethereum implements the Ethereum full node service.
|
||||
type Ethereum struct {
|
||||
config *ethconfig.Config
|
||||
// core protocol objects
|
||||
config *ethconfig.Config
|
||||
txPool *txpool.TxPool
|
||||
blockchain *core.BlockChain
|
||||
|
||||
// Handlers
|
||||
txPool *txpool.TxPool
|
||||
|
||||
blockchain *core.BlockChain
|
||||
handler *handler
|
||||
ethDialCandidates enode.Iterator
|
||||
snapDialCandidates enode.Iterator
|
||||
handler *handler
|
||||
discmix *enode.FairMix
|
||||
|
||||
// DB interfaces
|
||||
chainDb ethdb.Database // Block chain database
|
||||
@ -162,6 +160,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
|
||||
bloomRequests: make(chan chan *bloombits.Retrieval),
|
||||
bloomIndexer: core.NewBloomIndexer(chainDb, params.BloomBitsBlocks, params.BloomConfirms),
|
||||
p2pServer: stack.Server(),
|
||||
discmix: enode.NewFairMix(0),
|
||||
shutdownTracker: shutdowncheck.NewShutdownTracker(chainDb),
|
||||
}
|
||||
bcVersion := rawdb.ReadDatabaseVersion(chainDb)
|
||||
@ -266,17 +265,6 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
|
||||
}
|
||||
eth.APIBackend.gpo = gasprice.NewOracle(eth.APIBackend, config.GPO, config.Miner.GasPrice)
|
||||
|
||||
// Setup DNS discovery iterators.
|
||||
dnsclient := dnsdisc.NewClient(dnsdisc.Config{})
|
||||
eth.ethDialCandidates, err = dnsclient.NewIterator(eth.config.EthDiscoveryURLs...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
eth.snapDialCandidates, err = dnsclient.NewIterator(eth.config.SnapDiscoveryURLs...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Start the RPC service
|
||||
eth.netRPCService = ethapi.NewNetAPI(eth.p2pServer, networkID)
|
||||
|
||||
@ -359,9 +347,9 @@ func (s *Ethereum) BloomIndexer() *core.ChainIndexer { return s.bloomIndexer }
|
||||
// Protocols returns all the currently configured
|
||||
// network protocols to start.
|
||||
func (s *Ethereum) Protocols() []p2p.Protocol {
|
||||
protos := eth.MakeProtocols((*ethHandler)(s.handler), s.networkID, s.ethDialCandidates)
|
||||
protos := eth.MakeProtocols((*ethHandler)(s.handler), s.networkID, s.discmix)
|
||||
if s.config.SnapshotCache > 0 {
|
||||
protos = append(protos, snap.MakeProtocols((*snapHandler)(s.handler), s.snapDialCandidates)...)
|
||||
protos = append(protos, snap.MakeProtocols((*snapHandler)(s.handler))...)
|
||||
}
|
||||
return protos
|
||||
}
|
||||
@ -369,7 +357,7 @@ func (s *Ethereum) Protocols() []p2p.Protocol {
|
||||
// Start implements node.Lifecycle, starting all internal goroutines needed by the
|
||||
// Ethereum protocol implementation.
|
||||
func (s *Ethereum) Start() error {
|
||||
eth.StartENRUpdater(s.blockchain, s.p2pServer.LocalNode())
|
||||
s.setupDiscovery()
|
||||
|
||||
// Start the bloom bits servicing goroutines
|
||||
s.startBloomHandlers(params.BloomBitsBlocks)
|
||||
@ -382,12 +370,43 @@ func (s *Ethereum) Start() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Ethereum) setupDiscovery() error {
|
||||
eth.StartENRUpdater(s.blockchain, s.p2pServer.LocalNode())
|
||||
|
||||
// Add eth nodes from DNS.
|
||||
dnsclient := dnsdisc.NewClient(dnsdisc.Config{})
|
||||
if len(s.config.EthDiscoveryURLs) > 0 {
|
||||
iter, err := dnsclient.NewIterator(s.config.EthDiscoveryURLs...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.discmix.AddSource(iter)
|
||||
}
|
||||
|
||||
// Add snap nodes from DNS.
|
||||
if len(s.config.SnapDiscoveryURLs) > 0 {
|
||||
iter, err := dnsclient.NewIterator(s.config.SnapDiscoveryURLs...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.discmix.AddSource(iter)
|
||||
}
|
||||
|
||||
// Add DHT nodes from discv5.
|
||||
if s.p2pServer.DiscoveryV5() != nil {
|
||||
filter := eth.NewNodeFilter(s.blockchain)
|
||||
iter := enode.Filter(s.p2pServer.DiscoveryV5().RandomNodes(), filter)
|
||||
s.discmix.AddSource(iter)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Stop implements node.Lifecycle, terminating all internal goroutines used by the
|
||||
// Ethereum protocol.
|
||||
func (s *Ethereum) Stop() error {
|
||||
// Stop all the peer-related stuff first.
|
||||
s.ethDialCandidates.Close()
|
||||
s.snapDialCandidates.Close()
|
||||
s.discmix.Close()
|
||||
s.handler.Stop()
|
||||
|
||||
// Then stop everything else.
|
||||
|
@ -64,3 +64,17 @@ func currentENREntry(chain *core.BlockChain) *enrEntry {
|
||||
ForkID: forkid.NewID(chain.Config(), chain.Genesis(), head.Number.Uint64(), head.Time),
|
||||
}
|
||||
}
|
||||
|
||||
// NewNodeFilter returns a filtering function that returns whether the provided
|
||||
// enode advertises a forkid compatible with the current chain.
|
||||
func NewNodeFilter(chain *core.BlockChain) func(*enode.Node) bool {
|
||||
filter := forkid.NewFilter(chain)
|
||||
return func(n *enode.Node) bool {
|
||||
var entry enrEntry
|
||||
if err := n.Load(entry); err != nil {
|
||||
return false
|
||||
}
|
||||
err := filter(entry.ForkID)
|
||||
return err == nil
|
||||
}
|
||||
}
|
||||
|
@ -113,8 +113,7 @@ func MakeProtocols(backend Backend, network uint64, dnsdisc enode.Iterator) []p2
|
||||
PeerInfo: func(id enode.ID) interface{} {
|
||||
return backend.PeerInfo(id)
|
||||
},
|
||||
Attributes: []enr.Entry{currentENREntry(backend.Chain())},
|
||||
DialCandidates: dnsdisc,
|
||||
Attributes: []enr.Entry{currentENREntry(backend.Chain())},
|
||||
})
|
||||
}
|
||||
return protocols
|
||||
|
@ -82,13 +82,7 @@ type Backend interface {
|
||||
}
|
||||
|
||||
// MakeProtocols constructs the P2P protocol definitions for `snap`.
|
||||
func MakeProtocols(backend Backend, dnsdisc enode.Iterator) []p2p.Protocol {
|
||||
// Filter the discovery iterator for nodes advertising snap support.
|
||||
dnsdisc = enode.Filter(dnsdisc, func(n *enode.Node) bool {
|
||||
var snap enrEntry
|
||||
return n.Load(&snap) == nil
|
||||
})
|
||||
|
||||
func MakeProtocols(backend Backend) []p2p.Protocol {
|
||||
protocols := make([]p2p.Protocol, len(ProtocolVersions))
|
||||
for i, version := range ProtocolVersions {
|
||||
version := version // Closure
|
||||
@ -108,8 +102,7 @@ func MakeProtocols(backend Backend, dnsdisc enode.Iterator) []p2p.Protocol {
|
||||
PeerInfo: func(id enode.ID) interface{} {
|
||||
return backend.PeerInfo(id)
|
||||
},
|
||||
Attributes: []enr.Entry{&enrEntry{}},
|
||||
DialCandidates: dnsdisc,
|
||||
Attributes: []enr.Entry{&enrEntry{}},
|
||||
}
|
||||
}
|
||||
return protocols
|
||||
|
Loading…
Reference in New Issue
Block a user