2021-11-16 14:22:01 +00:00
|
|
|
package discv5
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"crypto/ecdsa"
|
|
|
|
"fmt"
|
2022-06-13 18:30:35 +00:00
|
|
|
"math"
|
|
|
|
"net"
|
|
|
|
"strconv"
|
2021-11-16 14:22:01 +00:00
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
gcrypto "github.com/ethereum/go-ethereum/crypto"
|
|
|
|
"github.com/ethereum/go-ethereum/p2p/enode"
|
2022-06-13 18:30:35 +00:00
|
|
|
"github.com/ethereum/go-ethereum/p2p/enr"
|
2023-04-20 18:51:13 +00:00
|
|
|
wenr "github.com/waku-org/go-waku/waku/v2/protocol/enr"
|
|
|
|
|
2021-11-16 14:22:01 +00:00
|
|
|
"github.com/multiformats/go-multiaddr"
|
|
|
|
"github.com/stretchr/testify/require"
|
2022-11-09 19:53:01 +00:00
|
|
|
"github.com/waku-org/go-waku/tests"
|
|
|
|
"github.com/waku-org/go-waku/waku/v2/utils"
|
2022-06-13 18:30:35 +00:00
|
|
|
"go.uber.org/zap"
|
2021-11-16 14:22:01 +00:00
|
|
|
|
|
|
|
"github.com/libp2p/go-libp2p"
|
2022-10-19 19:39:32 +00:00
|
|
|
libp2pcrypto "github.com/libp2p/go-libp2p/core/crypto"
|
|
|
|
"github.com/libp2p/go-libp2p/core/host"
|
2021-11-16 14:22:01 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func createHost(t *testing.T) (host.Host, int, *ecdsa.PrivateKey) {
|
|
|
|
privKey, err := gcrypto.GenerateKey()
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
2022-05-27 19:55:35 +00:00
|
|
|
sPrivKey := libp2pcrypto.PrivKey(utils.EcdsaPrivKeyToSecp256k1PrivKey(privKey))
|
2021-11-16 14:22:01 +00:00
|
|
|
|
|
|
|
port, err := tests.FindFreePort(t, "127.0.0.1", 3)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
sourceMultiAddr, err := multiaddr.NewMultiaddr(fmt.Sprintf("/ip4/127.0.0.1/tcp/%d", port))
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
host, err := libp2p.New(
|
|
|
|
libp2p.ListenAddrs(sourceMultiAddr),
|
|
|
|
libp2p.Identity(sPrivKey),
|
|
|
|
)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
return host, port, privKey
|
|
|
|
}
|
|
|
|
|
2023-04-20 18:51:13 +00:00
|
|
|
func newLocalnode(priv *ecdsa.PrivateKey, ipAddr *net.TCPAddr, udpPort int, wakuFlags wenr.WakuEnrBitfield, advertiseAddr *net.IP, log *zap.Logger) (*enode.LocalNode, error) {
|
2022-06-13 18:30:35 +00:00
|
|
|
db, err := enode.OpenDB("")
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
localnode := enode.NewLocalNode(db, priv)
|
|
|
|
localnode.SetFallbackUDP(udpPort)
|
2023-04-20 18:51:13 +00:00
|
|
|
localnode.Set(enr.WithEntry(wenr.WakuENRField, wakuFlags))
|
2022-06-13 18:30:35 +00:00
|
|
|
localnode.SetFallbackIP(net.IP{127, 0, 0, 1})
|
|
|
|
localnode.SetStaticIP(ipAddr.IP)
|
|
|
|
|
|
|
|
if udpPort > 0 && udpPort <= math.MaxUint16 {
|
|
|
|
localnode.Set(enr.UDP(uint16(udpPort))) // lgtm [go/incorrect-integer-conversion]
|
|
|
|
} else {
|
|
|
|
log.Error("setting udpPort", zap.Int("port", udpPort))
|
|
|
|
}
|
|
|
|
|
|
|
|
if ipAddr.Port > 0 && ipAddr.Port <= math.MaxUint16 {
|
|
|
|
localnode.Set(enr.TCP(uint16(ipAddr.Port))) // lgtm [go/incorrect-integer-conversion]
|
|
|
|
} else {
|
|
|
|
log.Error("setting tcpPort", zap.Int("port", ipAddr.Port))
|
|
|
|
}
|
|
|
|
|
|
|
|
if advertiseAddr != nil {
|
|
|
|
localnode.SetStaticIP(*advertiseAddr)
|
|
|
|
}
|
|
|
|
|
|
|
|
return localnode, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func extractIP(addr multiaddr.Multiaddr) (*net.TCPAddr, error) {
|
|
|
|
ipStr, err := addr.ValueForProtocol(multiaddr.P_IP4)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
portStr, err := addr.ValueForProtocol(multiaddr.P_TCP)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
port, err := strconv.Atoi(portStr)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return &net.TCPAddr{
|
|
|
|
IP: net.ParseIP(ipStr),
|
|
|
|
Port: port,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2021-11-16 14:22:01 +00:00
|
|
|
func TestDiscV5(t *testing.T) {
|
|
|
|
// Host1 <-> Host2 <-> Host3
|
|
|
|
|
2022-06-13 18:30:35 +00:00
|
|
|
// H1
|
2022-03-30 00:02:33 +00:00
|
|
|
host1, _, prvKey1 := createHost(t)
|
2023-01-12 02:20:23 +00:00
|
|
|
udpPort1, err := tests.FindFreeUDPPort(t, "127.0.0.1", 3)
|
2021-11-16 14:22:01 +00:00
|
|
|
require.NoError(t, err)
|
2022-06-13 18:30:35 +00:00
|
|
|
ip1, _ := extractIP(host1.Addrs()[0])
|
2023-04-20 18:51:13 +00:00
|
|
|
l1, err := newLocalnode(prvKey1, ip1, udpPort1, wenr.NewWakuEnrBitfield(true, true, true, true), nil, utils.Logger())
|
2022-06-13 18:30:35 +00:00
|
|
|
require.NoError(t, err)
|
2023-01-13 23:58:22 +00:00
|
|
|
peerconn1 := tests.NewTestPeerDiscoverer()
|
2023-04-17 00:04:12 +00:00
|
|
|
d1, err := NewDiscoveryV5(prvKey1, l1, peerconn1, utils.Logger(), WithUDPPort(uint(udpPort1)))
|
2021-11-16 14:22:01 +00:00
|
|
|
require.NoError(t, err)
|
2023-04-17 00:04:12 +00:00
|
|
|
d1.SetHost(host1)
|
2021-11-16 14:22:01 +00:00
|
|
|
|
2022-06-13 18:30:35 +00:00
|
|
|
// H2
|
2022-03-30 00:02:33 +00:00
|
|
|
host2, _, prvKey2 := createHost(t)
|
2022-06-13 18:30:35 +00:00
|
|
|
ip2, _ := extractIP(host2.Addrs()[0])
|
2023-01-12 02:20:23 +00:00
|
|
|
udpPort2, err := tests.FindFreeUDPPort(t, "127.0.0.1", 3)
|
2021-11-16 14:22:01 +00:00
|
|
|
require.NoError(t, err)
|
2023-04-20 18:51:13 +00:00
|
|
|
l2, err := newLocalnode(prvKey2, ip2, udpPort2, wenr.NewWakuEnrBitfield(true, true, true, true), nil, utils.Logger())
|
2022-06-13 18:30:35 +00:00
|
|
|
require.NoError(t, err)
|
2023-01-13 23:58:22 +00:00
|
|
|
peerconn2 := tests.NewTestPeerDiscoverer()
|
2023-04-17 00:04:12 +00:00
|
|
|
d2, err := NewDiscoveryV5(prvKey2, l2, peerconn2, utils.Logger(), WithUDPPort(uint(udpPort2)), WithBootnodes([]*enode.Node{d1.localnode.Node()}))
|
2021-11-16 14:22:01 +00:00
|
|
|
require.NoError(t, err)
|
2023-04-17 00:04:12 +00:00
|
|
|
d2.SetHost(host2)
|
2021-11-16 14:22:01 +00:00
|
|
|
|
2022-06-13 18:30:35 +00:00
|
|
|
// H3
|
2022-03-30 00:02:33 +00:00
|
|
|
host3, _, prvKey3 := createHost(t)
|
2022-06-13 18:30:35 +00:00
|
|
|
ip3, _ := extractIP(host3.Addrs()[0])
|
2023-01-12 02:20:23 +00:00
|
|
|
udpPort3, err := tests.FindFreeUDPPort(t, "127.0.0.1", 3)
|
2021-11-16 14:22:01 +00:00
|
|
|
require.NoError(t, err)
|
2023-04-20 18:51:13 +00:00
|
|
|
l3, err := newLocalnode(prvKey3, ip3, udpPort3, wenr.NewWakuEnrBitfield(true, true, true, true), nil, utils.Logger())
|
2022-06-13 18:30:35 +00:00
|
|
|
require.NoError(t, err)
|
2023-01-13 23:58:22 +00:00
|
|
|
peerconn3 := tests.NewTestPeerDiscoverer()
|
2023-04-17 00:04:12 +00:00
|
|
|
d3, err := NewDiscoveryV5(prvKey3, l3, peerconn3, utils.Logger(), WithUDPPort(uint(udpPort3)), WithBootnodes([]*enode.Node{d2.localnode.Node()}))
|
2021-11-16 14:22:01 +00:00
|
|
|
require.NoError(t, err)
|
2023-04-17 00:04:12 +00:00
|
|
|
d3.SetHost(host3)
|
2021-11-16 14:22:01 +00:00
|
|
|
|
2021-11-23 15:03:12 +00:00
|
|
|
defer d1.Stop()
|
|
|
|
defer d2.Stop()
|
|
|
|
defer d3.Stop()
|
|
|
|
|
2022-12-10 15:38:18 +00:00
|
|
|
err = d1.Start(context.Background())
|
2021-11-16 14:22:01 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
2022-12-10 15:38:18 +00:00
|
|
|
err = d2.Start(context.Background())
|
2021-11-16 14:22:01 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
2022-12-10 15:38:18 +00:00
|
|
|
err = d3.Start(context.Background())
|
2021-11-16 14:22:01 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
2023-01-13 23:58:22 +00:00
|
|
|
time.Sleep(2 * time.Second) // Wait for nodes to be discovered
|
2022-11-29 17:39:34 +00:00
|
|
|
|
2023-01-13 23:58:22 +00:00
|
|
|
require.True(t, peerconn3.HasPeer(host1.ID()) && peerconn3.HasPeer(host2.ID()))
|
2021-11-16 14:22:01 +00:00
|
|
|
|
2021-11-18 12:26:36 +00:00
|
|
|
d3.Stop()
|
2023-01-13 23:58:22 +00:00
|
|
|
peerconn3.Clear()
|
2021-11-18 12:26:36 +00:00
|
|
|
|
|
|
|
// Restart peer search
|
2022-12-10 15:38:18 +00:00
|
|
|
err = d3.Start(context.Background())
|
2021-11-18 12:26:36 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
2023-01-13 23:58:22 +00:00
|
|
|
time.Sleep(2 * time.Second) // Wait for nodes to be discovered
|
2021-11-18 12:26:36 +00:00
|
|
|
|
2023-01-13 23:58:22 +00:00
|
|
|
require.True(t, peerconn3.HasPeer(host1.ID()) && peerconn3.HasPeer(host2.ID()))
|
2021-11-16 14:22:01 +00:00
|
|
|
}
|