2021-11-16 14:22:01 +00:00
|
|
|
package dnsdisc
|
2021-09-27 17:52:56 +00:00
|
|
|
|
|
|
|
import (
|
2021-09-30 23:03:19 +00:00
|
|
|
"context"
|
2023-12-01 05:04:32 +00:00
|
|
|
"errors"
|
2021-09-27 17:52:56 +00:00
|
|
|
|
|
|
|
"github.com/ethereum/go-ethereum/p2p/dnsdisc"
|
2022-05-05 19:17:35 +00:00
|
|
|
"github.com/ethereum/go-ethereum/p2p/enode"
|
|
|
|
"github.com/ethereum/go-ethereum/p2p/enr"
|
2023-02-16 22:10:20 +00:00
|
|
|
"github.com/libp2p/go-libp2p/core/peer"
|
2023-08-16 01:40:00 +00:00
|
|
|
"github.com/prometheus/client_golang/prometheus"
|
2023-04-20 18:51:13 +00:00
|
|
|
wenr "github.com/waku-org/go-waku/waku/v2/protocol/enr"
|
2023-08-16 01:40:00 +00:00
|
|
|
"github.com/waku-org/go-waku/waku/v2/utils"
|
|
|
|
"go.uber.org/zap"
|
2021-09-27 17:52:56 +00:00
|
|
|
)
|
|
|
|
|
2022-04-25 19:31:26 +00:00
|
|
|
type dnsDiscoveryParameters struct {
|
2021-09-30 23:03:19 +00:00
|
|
|
nameserver string
|
2023-11-29 10:16:28 +00:00
|
|
|
resolver dnsdisc.Resolver
|
2021-09-30 23:03:19 +00:00
|
|
|
}
|
|
|
|
|
2023-12-01 05:04:32 +00:00
|
|
|
type DNSDiscoveryOption func(*dnsDiscoveryParameters) error
|
|
|
|
|
|
|
|
var ErrExclusiveOpts = errors.New("cannot set both nameserver and resolver")
|
2021-09-30 23:03:19 +00:00
|
|
|
|
2022-07-25 15:28:17 +00:00
|
|
|
// WithNameserver is a DnsDiscoveryOption that configures the nameserver to use
|
2023-09-11 14:24:05 +00:00
|
|
|
func WithNameserver(nameserver string) DNSDiscoveryOption {
|
2023-12-01 05:04:32 +00:00
|
|
|
return func(params *dnsDiscoveryParameters) error {
|
|
|
|
if params.resolver != nil {
|
|
|
|
return ErrExclusiveOpts
|
|
|
|
}
|
2021-09-30 23:03:19 +00:00
|
|
|
params.nameserver = nameserver
|
2023-12-01 05:04:32 +00:00
|
|
|
return nil
|
2021-09-30 23:03:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-29 10:16:28 +00:00
|
|
|
func WithResolver(resolver dnsdisc.Resolver) DNSDiscoveryOption {
|
2023-12-01 05:04:32 +00:00
|
|
|
return func(params *dnsDiscoveryParameters) error {
|
|
|
|
if params.nameserver != "" {
|
|
|
|
return ErrExclusiveOpts
|
|
|
|
}
|
2023-11-29 10:16:28 +00:00
|
|
|
params.resolver = resolver
|
2023-12-01 05:04:32 +00:00
|
|
|
return nil
|
2023-11-29 10:16:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-05 19:17:35 +00:00
|
|
|
type DiscoveredNode struct {
|
2023-05-10 14:13:10 +00:00
|
|
|
PeerID peer.ID
|
|
|
|
PeerInfo peer.AddrInfo
|
|
|
|
ENR *enode.Node
|
2022-05-05 19:17:35 +00:00
|
|
|
}
|
|
|
|
|
2023-09-11 14:24:05 +00:00
|
|
|
var metrics Metrics
|
2023-08-16 01:40:00 +00:00
|
|
|
|
|
|
|
// SetPrometheusRegisterer is used to setup a custom prometheus registerer for metrics
|
|
|
|
func SetPrometheusRegisterer(reg prometheus.Registerer, logger *zap.Logger) {
|
|
|
|
metrics = newMetrics(reg)
|
|
|
|
}
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
SetPrometheusRegisterer(prometheus.DefaultRegisterer, utils.Logger())
|
|
|
|
}
|
|
|
|
|
2022-04-25 19:31:26 +00:00
|
|
|
// RetrieveNodes returns a list of multiaddress given a url to a DNS discoverable ENR tree
|
2023-09-11 14:24:05 +00:00
|
|
|
func RetrieveNodes(ctx context.Context, url string, opts ...DNSDiscoveryOption) ([]DiscoveredNode, error) {
|
2022-05-05 19:17:35 +00:00
|
|
|
var discoveredNodes []DiscoveredNode
|
2021-09-27 17:52:56 +00:00
|
|
|
|
2022-04-25 19:31:26 +00:00
|
|
|
params := new(dnsDiscoveryParameters)
|
2021-09-30 23:03:19 +00:00
|
|
|
for _, opt := range opts {
|
2023-12-01 05:04:32 +00:00
|
|
|
err := opt(params)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2021-09-30 23:03:19 +00:00
|
|
|
}
|
|
|
|
|
2023-11-29 10:16:28 +00:00
|
|
|
if params.resolver == nil {
|
|
|
|
params.resolver = GetResolver(ctx, params.nameserver)
|
|
|
|
}
|
|
|
|
|
2021-09-30 23:03:19 +00:00
|
|
|
client := dnsdisc.NewClient(dnsdisc.Config{
|
2023-11-29 10:16:28 +00:00
|
|
|
Resolver: params.resolver,
|
2021-09-30 23:03:19 +00:00
|
|
|
})
|
2021-09-27 17:52:56 +00:00
|
|
|
|
|
|
|
tree, err := client.SyncTree(url)
|
|
|
|
if err != nil {
|
2023-08-16 01:40:00 +00:00
|
|
|
metrics.RecordError(treeSyncFailure)
|
2021-09-27 17:52:56 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, node := range tree.Nodes() {
|
2023-04-20 18:51:13 +00:00
|
|
|
peerID, m, err := wenr.Multiaddress(node)
|
2021-09-27 17:52:56 +00:00
|
|
|
if err != nil {
|
2023-08-16 01:40:00 +00:00
|
|
|
metrics.RecordError(peerInfoFailure)
|
2021-09-27 17:52:56 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2023-05-10 14:13:10 +00:00
|
|
|
infoAddr, err := peer.AddrInfosFromP2pAddrs(m...)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
var info peer.AddrInfo
|
|
|
|
for _, i := range infoAddr {
|
|
|
|
if i.ID == peerID {
|
|
|
|
info = i
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-16 22:10:20 +00:00
|
|
|
d := DiscoveredNode{
|
2023-05-10 14:13:10 +00:00
|
|
|
PeerID: peerID,
|
|
|
|
PeerInfo: info,
|
2023-02-16 22:10:20 +00:00
|
|
|
}
|
|
|
|
|
2022-05-05 19:17:35 +00:00
|
|
|
if hasUDP(node) {
|
|
|
|
d.ENR = node
|
|
|
|
}
|
|
|
|
|
|
|
|
discoveredNodes = append(discoveredNodes, d)
|
2021-09-27 17:52:56 +00:00
|
|
|
}
|
|
|
|
|
2023-08-16 01:40:00 +00:00
|
|
|
metrics.RecordDiscoveredNodes(len(discoveredNodes))
|
|
|
|
|
2022-05-05 19:17:35 +00:00
|
|
|
return discoveredNodes, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func hasUDP(node *enode.Node) bool {
|
|
|
|
enrUDP := new(enr.UDP)
|
|
|
|
if err := node.Record().Load(enr.WithEntry(enrUDP.ENRKey(), enrUDP)); err != nil {
|
2022-09-15 22:54:37 +00:00
|
|
|
return false
|
2022-05-05 19:17:35 +00:00
|
|
|
}
|
2022-09-15 22:54:37 +00:00
|
|
|
return true
|
2021-09-27 17:52:56 +00:00
|
|
|
}
|