feat(c-bindings): expose enrs via dns discovery

This commit is contained in:
Richard Ramos 2023-02-16 18:10:20 -04:00 committed by RichΛrd
parent 2c9df85c51
commit abcadd1bcf
8 changed files with 62 additions and 35 deletions

View File

@ -1045,7 +1045,7 @@ An `error` message otherwise.
## DNS Discovery ## DNS Discovery
### `extern char* waku_dns_discovery(char* url, char* nameserver, int timeoutMs)` ### `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** **Parameters**
@ -1060,16 +1060,21 @@ Returns a list of multiaddress given a url to a DNS discoverable ENR tree
**Returns** **Returns**
A [`JsonResponse`](#jsonresponse-type). 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. An `error` message otherwise.
```json ```json
{ {
"result":[ "result":[
{
"peerID":"16Uiu2HAmPLe7Mzm8TsYUubgCAW1aJoeFScxrLj8ppHFivPo97bUZ",
"multiaddrs":[
"/ip4/134.209.139.210/tcp/30303/p2p/16Uiu2HAmPLe7Mzm8TsYUubgCAW1aJoeFScxrLj8ppHFivPo97bUZ", "/ip4/134.209.139.210/tcp/30303/p2p/16Uiu2HAmPLe7Mzm8TsYUubgCAW1aJoeFScxrLj8ppHFivPo97bUZ",
"/ip4/104.154.239.128/tcp/30303/p2p/16Uiu2HAmJb2e28qLXxT5kZxVUUoJt72EMzNGXB47Rxx5hw3q4YjS", "/dns4/node-01.do-ams3.wakuv2.test.statusim.net/tcp/8000/wss/p2p/16Uiu2HAmPLe7Mzm8TsYUubgCAW1aJoeFScxrLj8ppHFivPo97bUZ"
"/ip4/47.242.210.73/tcp/30303/p2p/16Uiu2HAkvWiyFsgRhuJEb9JfjYxEkoHLgnUQmr1N5mKWnYjxYRVm" ],
] "enr":"enr:-M-4QCtJKX2WDloRYDT4yjeMGKUCRRcMlsNiZP3cnPO0HZn6IdJ035RPCqsQ5NvTyjqHzKnTM6pc2LoKliV4CeV0WrgBgmlkgnY0gmlwhIbRi9KKbXVsdGlhZGRyc7EALzYobm9kZS0wMS5kby1hbXMzLndha3V2Mi50ZXN0LnN0YXR1c2ltLm5ldAYfQN4DiXNlY3AyNTZrMaEDnr03Tuo77930a7sYLikftxnuG3BbC3gCFhA4632ooDaDdGNwgnZfg3VkcIIjKIV3YWt1Mg8"
},
...
} }
``` ```

View File

@ -6,7 +6,8 @@ import (
mobile "github.com/waku-org/go-waku/mobile" 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 // The nameserver can optionally be specified to resolve the enrtree url. Otherwise NULL or
// empty to automatically use the default system dns. // empty to automatically use the default system dns.
// If ms is greater than 0, the subscription must happen before the timeout // If ms is greater than 0, the subscription must happen before the timeout

View File

@ -8,6 +8,12 @@ import (
"github.com/waku-org/go-waku/waku/v2/dnsdisc" "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 { func DnsDiscovery(url string, nameserver string, ms int) string {
var ctx context.Context var ctx context.Context
var cancel context.CancelFunc var cancel context.CancelFunc
@ -29,34 +35,43 @@ func DnsDiscovery(url string, nameserver string, ms int) string {
return MakeJSONResponse(err) return MakeJSONResponse(err)
} }
var ma []string var response []DnsDiscoveryItem
for _, n := range nodes { for _, n := range nodes {
for _, addr := range n.Addresses { item := DnsDiscoveryItem{
ma = append(ma, addr.String()) 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 { func StartDiscoveryV5() string {
if wakuNode == nil { if wakuState.node == nil {
return MakeJSONResponse(errWakuNodeNotReady) return MakeJSONResponse(errWakuNodeNotReady)
} }
if wakuNode.DiscV5() == nil { if wakuState.node.DiscV5() == nil {
return MakeJSONResponse(errors.New("DiscV5 is not mounted")) return MakeJSONResponse(errors.New("DiscV5 is not mounted"))
} }
err := wakuNode.DiscV5().Start(context.Background()) err := wakuState.node.DiscV5().Start(context.Background())
if err != nil {
return MakeJSONResponse(err) return MakeJSONResponse(err)
} }
func StopDiscoveryV5() string { return MakeJSONResponse(nil)
if wakuNode == nil { }
return MakeJSONResponse(errWakuNodeNotReady)
} func StopDiscoveryV5() string {
if wakuNode.DiscV5() == nil { if wakuState.node == nil {
return MakeJSONResponse(errors.New("DiscV5 is not mounted")) return MakeJSONResponse(errWakuNodeNotReady)
} }
wakuNode.DiscV5().Stop() if wakuState.node.DiscV5() == nil {
return MakeJSONResponse(errors.New("DiscV5 is not mounted"))
}
wakuState.node.DiscV5().Stop()
return MakeJSONResponse(nil) return MakeJSONResponse(nil)
} }

View File

@ -288,7 +288,7 @@ func (d *DiscoveryV5) iterate(ctx context.Context) error {
break break
} }
addresses, err := utils.Multiaddress(iterator.Node()) _, addresses, err := utils.Multiaddress(iterator.Node())
if err != nil { if err != nil {
d.log.Error("extracting multiaddrs from enr", zap.Error(err)) d.log.Error("extracting multiaddrs from enr", zap.Error(err))
continue continue

View File

@ -6,6 +6,7 @@ import (
"github.com/ethereum/go-ethereum/p2p/dnsdisc" "github.com/ethereum/go-ethereum/p2p/dnsdisc"
"github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/p2p/enr" "github.com/ethereum/go-ethereum/p2p/enr"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/waku-org/go-waku/waku/v2/utils" "github.com/waku-org/go-waku/waku/v2/utils"
ma "github.com/multiformats/go-multiaddr" ma "github.com/multiformats/go-multiaddr"
@ -25,6 +26,7 @@ func WithNameserver(nameserver string) DnsDiscoveryOption {
} }
type DiscoveredNode struct { type DiscoveredNode struct {
PeerID peer.ID
Addresses []ma.Multiaddr Addresses []ma.Multiaddr
ENR *enode.Node ENR *enode.Node
} }
@ -48,12 +50,16 @@ func RetrieveNodes(ctx context.Context, url string, opts ...DnsDiscoveryOption)
} }
for _, node := range tree.Nodes() { for _, node := range tree.Nodes() {
m, err := utils.Multiaddress(node) peerID, m, err := utils.Multiaddress(node)
if err != nil { if err != nil {
return nil, err return nil, err
} }
d := DiscoveredNode{Addresses: m} d := DiscoveredNode{
PeerID: peerID,
Addresses: m,
}
if hasUDP(node) { if hasUDP(node) {
d.ENR = node d.ENR = node
} }

View File

@ -343,7 +343,7 @@ func (wakuPX *WakuPeerExchange) iterate(ctx context.Context) error {
break break
} }
addresses, err := utils.Multiaddress(iterator.Node()) _, addresses, err := utils.Multiaddress(iterator.Node())
if err != nil { if err != nil {
wakuPX.log.Error("extracting multiaddrs from enr", zap.Error(err)) wakuPX.log.Error("extracting multiaddrs from enr", zap.Error(err))
continue continue

View File

@ -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 // 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()) pubKey := EcdsaPubKeyToSecp256k1PublicKey(node.Pubkey())
peerID, err := peer.IDFromPublicKey(pubKey) peerID, err := peer.IDFromPublicKey(pubKey)
if err != nil { if err != nil {
return nil, err return "", nil, err
} }
var result []multiaddr.Multiaddr var result []multiaddr.Multiaddr
addr, err := enodeToMultiAddr(node) addr, err := enodeToMultiAddr(node)
if err != nil { if err != nil {
return nil, err return "", nil, err
} }
result = append(result, addr) result = append(result, addr)
var multiaddrRaw []byte var multiaddrRaw []byte
if err := node.Record().Load(enr.WithEntry(MultiaddrENRField, &multiaddrRaw)); err != nil { if err := node.Record().Load(enr.WithEntry(MultiaddrENRField, &multiaddrRaw)); err != nil {
if !enr.IsNotFound(err) { if !enr.IsNotFound(err) {
return nil, err return "", nil, err
} else { } else {
// No multiaddr entry on enr // No multiaddr entry on enr
return result, nil return peerID, result, nil
} }
} }
if len(multiaddrRaw) < 2 { if len(multiaddrRaw) < 2 {
// There was no error loading the multiaddr field, but its length is incorrect // 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())) hostInfo, err := multiaddr.NewMultiaddr(fmt.Sprintf("/p2p/%s", peerID.Pretty()))
if err != nil { if err != nil {
return nil, err return "", nil, err
} }
offset := 0 offset := 0
for { for {
maSize := binary.BigEndian.Uint16(multiaddrRaw[offset : offset+2]) maSize := binary.BigEndian.Uint16(multiaddrRaw[offset : offset+2])
if len(multiaddrRaw) < offset+2+int(maSize) { 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)] maRaw := multiaddrRaw[offset+2 : offset+2+int(maSize)]
addr, err := multiaddr.NewMultiaddrBytes(maRaw) addr, err := multiaddr.NewMultiaddrBytes(maRaw)
if err != nil { 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)) 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 // EnodeToPeerInfo extracts the peer ID and multiaddresses defined in an ENR
func EnodeToPeerInfo(node *enode.Node) (*peer.AddrInfo, error) { func EnodeToPeerInfo(node *enode.Node) (*peer.AddrInfo, error) {
addresses, err := Multiaddress(node) _, addresses, err := Multiaddress(node)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -156,6 +156,6 @@ func TestMultiaddr(t *testing.T) {
_ = localNode.Node() // Should not panic _ = localNode.Node() // Should not panic
_, err = Multiaddress(localNode.Node()) _, _, err = Multiaddress(localNode.Node())
require.NoError(t, err) require.NoError(t, err)
} }