From abcadd1bcfdf2df9a510fffd60139be55a582250 Mon Sep 17 00:00:00 2001 From: Richard Ramos Date: Thu, 16 Feb 2023 18:10:20 -0400 Subject: [PATCH] feat(c-bindings): expose enrs via dns discovery --- library/README.md | 19 ++++++---- library/api_discovery.go | 3 +- mobile/api_discovery.go | 37 +++++++++++++------ waku/v2/discv5/discover.go | 2 +- waku/v2/dnsdisc/enr.go | 10 ++++- .../peer_exchange/waku_peer_exchange.go | 2 +- waku/v2/utils/enr.go | 22 +++++------ waku/v2/utils/enr_test.go | 2 +- 8 files changed, 62 insertions(+), 35 deletions(-) diff --git a/library/README.md b/library/README.md index 0ee293ad..a8dabda9 100644 --- a/library/README.md +++ b/library/README.md @@ -1045,7 +1045,7 @@ An `error` message otherwise. ## DNS Discovery ### `extern char* waku_dns_discovery(char* url, char* nameserver, int timeoutMs)` -Returns a list of multiaddress given a url to a DNS discoverable ENR tree +Returns a list of multiaddress and enrs given a url to a DNS discoverable ENR tree **Parameters** @@ -1060,16 +1060,21 @@ Returns a list of multiaddress given a url to a DNS discoverable ENR tree **Returns** A [`JsonResponse`](#jsonresponse-type). -If the execution is successful, the `result` field contains an array with multiaddresses. +If the execution is successful, the `result` field contains an array objects describing the multiaddresses, enr and peerID each node found has. An `error` message otherwise. ```json { - "result": [ - "/ip4/134.209.139.210/tcp/30303/p2p/16Uiu2HAmPLe7Mzm8TsYUubgCAW1aJoeFScxrLj8ppHFivPo97bUZ", - "/ip4/104.154.239.128/tcp/30303/p2p/16Uiu2HAmJb2e28qLXxT5kZxVUUoJt72EMzNGXB47Rxx5hw3q4YjS", - "/ip4/47.242.210.73/tcp/30303/p2p/16Uiu2HAkvWiyFsgRhuJEb9JfjYxEkoHLgnUQmr1N5mKWnYjxYRVm" - ] + "result":[ + { + "peerID":"16Uiu2HAmPLe7Mzm8TsYUubgCAW1aJoeFScxrLj8ppHFivPo97bUZ", + "multiaddrs":[ + "/ip4/134.209.139.210/tcp/30303/p2p/16Uiu2HAmPLe7Mzm8TsYUubgCAW1aJoeFScxrLj8ppHFivPo97bUZ", + "/dns4/node-01.do-ams3.wakuv2.test.statusim.net/tcp/8000/wss/p2p/16Uiu2HAmPLe7Mzm8TsYUubgCAW1aJoeFScxrLj8ppHFivPo97bUZ" + ], + "enr":"enr:-M-4QCtJKX2WDloRYDT4yjeMGKUCRRcMlsNiZP3cnPO0HZn6IdJ035RPCqsQ5NvTyjqHzKnTM6pc2LoKliV4CeV0WrgBgmlkgnY0gmlwhIbRi9KKbXVsdGlhZGRyc7EALzYobm9kZS0wMS5kby1hbXMzLndha3V2Mi50ZXN0LnN0YXR1c2ltLm5ldAYfQN4DiXNlY3AyNTZrMaEDnr03Tuo77930a7sYLikftxnuG3BbC3gCFhA4632ooDaDdGNwgnZfg3VkcIIjKIV3YWt1Mg8" + }, + ... } ``` diff --git a/library/api_discovery.go b/library/api_discovery.go index 1ba0cdce..c22618c7 100644 --- a/library/api_discovery.go +++ b/library/api_discovery.go @@ -6,7 +6,8 @@ import ( mobile "github.com/waku-org/go-waku/mobile" ) -// Returns a list of multiaddress given a url to a DNS discoverable ENR tree +// Returns a list of objects containing the peerID, enr and multiaddresses for each node found +// given a url to a DNS discoverable ENR tree // The nameserver can optionally be specified to resolve the enrtree url. Otherwise NULL or // empty to automatically use the default system dns. // If ms is greater than 0, the subscription must happen before the timeout diff --git a/mobile/api_discovery.go b/mobile/api_discovery.go index 2b92501a..d467b522 100644 --- a/mobile/api_discovery.go +++ b/mobile/api_discovery.go @@ -8,6 +8,12 @@ import ( "github.com/waku-org/go-waku/waku/v2/dnsdisc" ) +type DnsDiscoveryItem struct { + PeerID string `json:"peerID,omitempty"` + Addresses []string `json:"multiaddrs,omitempty"` + ENR string `json:"enr,omitempty"` +} + func DnsDiscovery(url string, nameserver string, ms int) string { var ctx context.Context var cancel context.CancelFunc @@ -29,34 +35,43 @@ func DnsDiscovery(url string, nameserver string, ms int) string { return MakeJSONResponse(err) } - var ma []string + var response []DnsDiscoveryItem for _, n := range nodes { - for _, addr := range n.Addresses { - ma = append(ma, addr.String()) + item := DnsDiscoveryItem{ + PeerID: n.PeerID.String(), } + for _, addr := range n.Addresses { + item.Addresses = append(item.Addresses, addr.String()) + } + item.ENR = n.ENR.String() + response = append(response, item) } - return PrepareJSONResponse(ma, nil) + return PrepareJSONResponse(response, nil) } func StartDiscoveryV5() string { - if wakuNode == nil { + if wakuState.node == nil { return MakeJSONResponse(errWakuNodeNotReady) } - if wakuNode.DiscV5() == nil { + if wakuState.node.DiscV5() == nil { return MakeJSONResponse(errors.New("DiscV5 is not mounted")) } - err := wakuNode.DiscV5().Start(context.Background()) - return MakeJSONResponse(err) + err := wakuState.node.DiscV5().Start(context.Background()) + if err != nil { + return MakeJSONResponse(err) + } + + return MakeJSONResponse(nil) } func StopDiscoveryV5() string { - if wakuNode == nil { + if wakuState.node == nil { return MakeJSONResponse(errWakuNodeNotReady) } - if wakuNode.DiscV5() == nil { + if wakuState.node.DiscV5() == nil { return MakeJSONResponse(errors.New("DiscV5 is not mounted")) } - wakuNode.DiscV5().Stop() + wakuState.node.DiscV5().Stop() return MakeJSONResponse(nil) } diff --git a/waku/v2/discv5/discover.go b/waku/v2/discv5/discover.go index c4f0c04b..21178596 100644 --- a/waku/v2/discv5/discover.go +++ b/waku/v2/discv5/discover.go @@ -288,7 +288,7 @@ func (d *DiscoveryV5) iterate(ctx context.Context) error { break } - addresses, err := utils.Multiaddress(iterator.Node()) + _, addresses, err := utils.Multiaddress(iterator.Node()) if err != nil { d.log.Error("extracting multiaddrs from enr", zap.Error(err)) continue diff --git a/waku/v2/dnsdisc/enr.go b/waku/v2/dnsdisc/enr.go index 74b5c3ad..b50fa8a5 100644 --- a/waku/v2/dnsdisc/enr.go +++ b/waku/v2/dnsdisc/enr.go @@ -6,6 +6,7 @@ import ( "github.com/ethereum/go-ethereum/p2p/dnsdisc" "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enr" + "github.com/libp2p/go-libp2p/core/peer" "github.com/waku-org/go-waku/waku/v2/utils" ma "github.com/multiformats/go-multiaddr" @@ -25,6 +26,7 @@ func WithNameserver(nameserver string) DnsDiscoveryOption { } type DiscoveredNode struct { + PeerID peer.ID Addresses []ma.Multiaddr ENR *enode.Node } @@ -48,12 +50,16 @@ func RetrieveNodes(ctx context.Context, url string, opts ...DnsDiscoveryOption) } for _, node := range tree.Nodes() { - m, err := utils.Multiaddress(node) + peerID, m, err := utils.Multiaddress(node) if err != nil { return nil, err } - d := DiscoveredNode{Addresses: m} + d := DiscoveredNode{ + PeerID: peerID, + Addresses: m, + } + if hasUDP(node) { d.ENR = node } diff --git a/waku/v2/protocol/peer_exchange/waku_peer_exchange.go b/waku/v2/protocol/peer_exchange/waku_peer_exchange.go index 3d6230ad..3fd387c9 100644 --- a/waku/v2/protocol/peer_exchange/waku_peer_exchange.go +++ b/waku/v2/protocol/peer_exchange/waku_peer_exchange.go @@ -343,7 +343,7 @@ func (wakuPX *WakuPeerExchange) iterate(ctx context.Context) error { break } - addresses, err := utils.Multiaddress(iterator.Node()) + _, addresses, err := utils.Multiaddress(iterator.Node()) if err != nil { wakuPX.log.Error("extracting multiaddrs from enr", zap.Error(err)) continue diff --git a/waku/v2/utils/enr.go b/waku/v2/utils/enr.go index 655c3daa..4f7f4707 100644 --- a/waku/v2/utils/enr.go +++ b/waku/v2/utils/enr.go @@ -56,51 +56,51 @@ func enodeToMultiAddr(node *enode.Node) (multiaddr.Multiaddr, error) { } // Multiaddress is used to extract all the multiaddresses that are part of a ENR record -func Multiaddress(node *enode.Node) ([]multiaddr.Multiaddr, error) { +func Multiaddress(node *enode.Node) (peer.ID, []multiaddr.Multiaddr, error) { pubKey := EcdsaPubKeyToSecp256k1PublicKey(node.Pubkey()) peerID, err := peer.IDFromPublicKey(pubKey) if err != nil { - return nil, err + return "", nil, err } var result []multiaddr.Multiaddr addr, err := enodeToMultiAddr(node) if err != nil { - return nil, err + return "", nil, err } result = append(result, addr) var multiaddrRaw []byte if err := node.Record().Load(enr.WithEntry(MultiaddrENRField, &multiaddrRaw)); err != nil { if !enr.IsNotFound(err) { - return nil, err + return "", nil, err } else { // No multiaddr entry on enr - return result, nil + return peerID, result, nil } } if len(multiaddrRaw) < 2 { // There was no error loading the multiaddr field, but its length is incorrect - return result, nil + return peerID, result, nil } hostInfo, err := multiaddr.NewMultiaddr(fmt.Sprintf("/p2p/%s", peerID.Pretty())) if err != nil { - return nil, err + return "", nil, err } offset := 0 for { maSize := binary.BigEndian.Uint16(multiaddrRaw[offset : offset+2]) if len(multiaddrRaw) < offset+2+int(maSize) { - return nil, errors.New("invalid multiaddress field length") + return "", nil, errors.New("invalid multiaddress field length") } maRaw := multiaddrRaw[offset+2 : offset+2+int(maSize)] addr, err := multiaddr.NewMultiaddrBytes(maRaw) if err != nil { - return nil, fmt.Errorf("invalid multiaddress field length") + return "", nil, fmt.Errorf("invalid multiaddress field length") } result = append(result, addr.Encapsulate(hostInfo)) @@ -111,12 +111,12 @@ func Multiaddress(node *enode.Node) ([]multiaddr.Multiaddr, error) { } } - return result, nil + return peerID, result, nil } // EnodeToPeerInfo extracts the peer ID and multiaddresses defined in an ENR func EnodeToPeerInfo(node *enode.Node) (*peer.AddrInfo, error) { - addresses, err := Multiaddress(node) + _, addresses, err := Multiaddress(node) if err != nil { return nil, err } diff --git a/waku/v2/utils/enr_test.go b/waku/v2/utils/enr_test.go index cda2efb1..00e486bc 100644 --- a/waku/v2/utils/enr_test.go +++ b/waku/v2/utils/enr_test.go @@ -156,6 +156,6 @@ func TestMultiaddr(t *testing.T) { _ = localNode.Node() // Should not panic - _, err = Multiaddress(localNode.Node()) + _, _, err = Multiaddress(localNode.Node()) require.NoError(t, err) }