waku-org/go-waku

View on GitHub
library/discovery.go

Summary

Maintainability
A
40 mins
Test Coverage
package library

import (
    "context"
    "encoding/json"
    "errors"
    "time"

    "github.com/ethereum/go-ethereum/p2p/enode"
    "github.com/waku-org/go-waku/waku/v2/dnsdisc"
)

type dnsDiscoveryItem struct {
    PeerID    string   `json:"peerID"`
    Addresses []string `json:"multiaddrs"`
    ENR       string   `json:"enr,omitempty"`
}

// DNSDiscovery executes dns discovery on an url and returns a list of nodes
func DNSDiscovery(url string, nameserver string, ms int) (string, error) {
    var ctx context.Context
    var cancel context.CancelFunc

    if ms > 0 {
        ctx, cancel = context.WithTimeout(context.Background(), time.Duration(int(ms))*time.Millisecond)
        defer cancel()
    } else {
        ctx = context.Background()
    }

    var dnsDiscOpt []dnsdisc.DNSDiscoveryOption
    if nameserver != "" {
        dnsDiscOpt = append(dnsDiscOpt, dnsdisc.WithNameserver(nameserver))
    }

    nodes, err := dnsdisc.RetrieveNodes(ctx, url, dnsDiscOpt...)
    if err != nil {
        return "", err
    }

    var response []dnsDiscoveryItem
    for _, n := range nodes {
        item := dnsDiscoveryItem{
            PeerID: n.PeerID.String(),
        }
        for _, addr := range n.PeerInfo.Addrs {
            item.Addresses = append(item.Addresses, addr.String())
        }

        if n.ENR != nil {
            item.ENR = n.ENR.String()
        }

        response = append(response, item)
    }

    return marshalJSON(response)
}

// StartDiscoveryV5 starts discv5 discovery
func StartDiscoveryV5(instance *WakuInstance) error {
    if err := validateInstance(instance, MustBeStarted); err != nil {
        return err
    }

    if instance.node.DiscV5() == nil {
        return errors.New("DiscV5 is not mounted")
    }
    return instance.node.DiscV5().Start(instance.ctx)
}

// StopDiscoveryV5 stops discv5 discovery
func StopDiscoveryV5(instance *WakuInstance) error {
    if err := validateInstance(instance, MustBeStarted); err != nil {
        return err
    }

    if instance.node.DiscV5() == nil {
        return errors.New("DiscV5 is not mounted")
    }
    instance.node.DiscV5().Stop()
    return nil
}

// SetBootnodes is used to update the bootnodes receiving a JSON array of ENRs
func SetBootnodes(instance *WakuInstance, bootnodes string) error {
    if err := validateInstance(instance, MustBeStarted); err != nil {
        return err
    }

    if instance.node.DiscV5() == nil {
        return errors.New("DiscV5 is not mounted")
    }

    var tmp []json.RawMessage
    if err := json.Unmarshal([]byte(bootnodes), &tmp); err != nil {
        return err
    }

    var enrList []string
    for _, el := range tmp {
        var enr string
        if err := json.Unmarshal(el, &enr); err != nil {
            return err
        }
        enrList = append(enrList, enr)
    }

    var nodes []*enode.Node
    for _, addr := range enrList {
        node, err := enode.Parse(enode.ValidSchemes, addr)
        if err != nil {
            return err
        }
        nodes = append(nodes, node)
    }

    return instance.node.DiscV5().SetBootnodes(nodes)
}