2021-10-28 14:41:17 +02:00
|
|
|
package tests
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"context"
|
2023-11-07 22:43:19 +05:30
|
|
|
"crypto/ecdsa"
|
2021-11-12 10:19:42 +01:00
|
|
|
"crypto/rand"
|
|
|
|
|
"encoding/hex"
|
2021-10-28 14:41:17 +02:00
|
|
|
"fmt"
|
|
|
|
|
"io"
|
2023-11-07 22:43:19 +05:30
|
|
|
"math"
|
2021-10-28 14:41:17 +02:00
|
|
|
"net"
|
2023-11-07 22:43:19 +05:30
|
|
|
"strconv"
|
2021-10-28 14:41:17 +02:00
|
|
|
"testing"
|
|
|
|
|
|
2023-11-07 22:43:19 +05:30
|
|
|
gcrypto "github.com/ethereum/go-ethereum/crypto"
|
2022-05-30 11:55:30 -04:00
|
|
|
"github.com/ethereum/go-ethereum/log"
|
2023-11-07 22:43:19 +05:30
|
|
|
"github.com/ethereum/go-ethereum/p2p/enode"
|
|
|
|
|
"github.com/ethereum/go-ethereum/p2p/enr"
|
2021-10-28 14:41:17 +02:00
|
|
|
"github.com/libp2p/go-libp2p"
|
2023-11-07 22:43:19 +05:30
|
|
|
"github.com/libp2p/go-libp2p/config"
|
2022-10-19 15:39:32 -04:00
|
|
|
"github.com/libp2p/go-libp2p/core/crypto"
|
2023-11-07 22:43:19 +05:30
|
|
|
libp2pcrypto "github.com/libp2p/go-libp2p/core/crypto"
|
2022-10-19 15:39:32 -04:00
|
|
|
"github.com/libp2p/go-libp2p/core/host"
|
2023-06-05 10:39:38 -04:00
|
|
|
"github.com/libp2p/go-libp2p/p2p/host/peerstore/pstoremem"
|
2021-10-28 14:41:17 +02:00
|
|
|
"github.com/multiformats/go-multiaddr"
|
2023-11-07 22:43:19 +05:30
|
|
|
"github.com/stretchr/testify/require"
|
2023-08-03 21:51:15 +05:30
|
|
|
"github.com/waku-org/go-waku/waku/v2/peerstore"
|
2023-11-07 22:43:19 +05:30
|
|
|
wenr "github.com/waku-org/go-waku/waku/v2/protocol/enr"
|
2022-11-09 15:53:01 -04:00
|
|
|
"github.com/waku-org/go-waku/waku/v2/protocol/pb"
|
2023-11-07 22:43:19 +05:30
|
|
|
"github.com/waku-org/go-waku/waku/v2/utils"
|
|
|
|
|
"go.uber.org/zap"
|
2021-10-28 14:41:17 +02:00
|
|
|
)
|
|
|
|
|
|
2022-04-25 23:31:26 +04:00
|
|
|
// GetHostAddress returns the first listen address used by a host
|
2022-10-19 15:39:32 -04:00
|
|
|
func GetHostAddress(ha host.Host) multiaddr.Multiaddr {
|
2021-10-28 14:41:17 +02:00
|
|
|
return ha.Addrs()[0]
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-25 23:31:26 +04:00
|
|
|
// FindFreePort returns an available port number
|
2021-10-28 14:41:17 +02:00
|
|
|
func FindFreePort(t *testing.T, host string, maxAttempts int) (int, error) {
|
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
|
|
if host == "" {
|
|
|
|
|
host = "localhost"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for i := 0; i < maxAttempts; i++ {
|
|
|
|
|
addr, err := net.ResolveTCPAddr("tcp", net.JoinHostPort(host, "0"))
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Logf("unable to resolve tcp addr: %v", err)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
l, err := net.ListenTCP("tcp", addr)
|
|
|
|
|
if err != nil {
|
|
|
|
|
l.Close()
|
|
|
|
|
t.Logf("unable to listen on addr %q: %v", addr, err)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
port := l.Addr().(*net.TCPAddr).Port
|
|
|
|
|
l.Close()
|
|
|
|
|
return port, nil
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0, fmt.Errorf("no free port found")
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-11 22:20:23 -04:00
|
|
|
// FindFreePort returns an available port number
|
|
|
|
|
func FindFreeUDPPort(t *testing.T, host string, maxAttempts int) (int, error) {
|
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
|
|
if host == "" {
|
|
|
|
|
host = "localhost"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for i := 0; i < maxAttempts; i++ {
|
|
|
|
|
addr, err := net.ResolveUDPAddr("udp", net.JoinHostPort(host, "0"))
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Logf("unable to resolve tcp addr: %v", err)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
l, err := net.ListenUDP("udp", addr)
|
|
|
|
|
if err != nil {
|
|
|
|
|
l.Close()
|
|
|
|
|
t.Logf("unable to listen on addr %q: %v", addr, err)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
port := l.LocalAddr().(*net.UDPAddr).Port
|
|
|
|
|
l.Close()
|
|
|
|
|
return port, nil
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0, fmt.Errorf("no free port found")
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-25 23:31:26 +04:00
|
|
|
// MakeHost creates a Libp2p host with a random key on a specific port
|
2021-10-28 14:41:17 +02:00
|
|
|
func MakeHost(ctx context.Context, port int, randomness io.Reader) (host.Host, error) {
|
|
|
|
|
// Creates a new RSA key pair for this host.
|
|
|
|
|
prvKey, _, err := crypto.GenerateKeyPairWithReader(crypto.RSA, 2048, randomness)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Error(err.Error())
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 0.0.0.0 will listen on any interface device.
|
2023-06-07 16:18:37 -04:00
|
|
|
sourceMultiAddr, err := multiaddr.NewMultiaddr(fmt.Sprintf("/ip4/127.0.0.1/tcp/%d", port))
|
2023-06-05 10:39:38 -04:00
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ps, err := pstoremem.NewPeerstore()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-03 21:51:15 +05:30
|
|
|
psWrapper := peerstore.NewWakuPeerstore(ps)
|
2023-06-05 10:39:38 -04:00
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
2021-10-28 14:41:17 +02:00
|
|
|
|
|
|
|
|
// libp2p.New constructs a new libp2p Host.
|
|
|
|
|
// Other options can be added here.
|
|
|
|
|
return libp2p.New(
|
2023-06-05 10:39:38 -04:00
|
|
|
libp2p.Peerstore(psWrapper),
|
2021-10-28 14:41:17 +02:00
|
|
|
libp2p.ListenAddrs(sourceMultiAddr),
|
|
|
|
|
libp2p.Identity(prvKey),
|
|
|
|
|
)
|
|
|
|
|
}
|
2021-10-28 09:03:23 -04:00
|
|
|
|
2022-04-25 23:31:26 +04:00
|
|
|
// CreateWakuMessage creates a WakuMessage protobuffer with default values and a custom contenttopic and timestamp
|
2023-11-07 15:48:43 -04:00
|
|
|
func CreateWakuMessage(contentTopic string, timestamp *int64, optionalPayload ...string) *pb.WakuMessage {
|
2023-08-14 23:29:00 +03:00
|
|
|
var payload []byte
|
|
|
|
|
if len(optionalPayload) > 0 {
|
|
|
|
|
payload = []byte(optionalPayload[0])
|
|
|
|
|
} else {
|
|
|
|
|
payload = []byte{1, 2, 3}
|
|
|
|
|
}
|
2023-11-07 15:48:43 -04:00
|
|
|
return &pb.WakuMessage{Payload: payload, ContentTopic: contentTopic, Timestamp: timestamp}
|
2021-10-28 09:03:23 -04:00
|
|
|
}
|
2021-11-12 10:19:42 +01:00
|
|
|
|
2022-04-25 23:31:26 +04:00
|
|
|
// RandomHex returns a random hex string of n bytes
|
2021-11-12 10:19:42 +01:00
|
|
|
func RandomHex(n int) (string, error) {
|
|
|
|
|
bytes := make([]byte, n)
|
|
|
|
|
if _, err := rand.Read(bytes); err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
return hex.EncodeToString(bytes), nil
|
|
|
|
|
}
|
2023-11-07 22:43:19 +05:30
|
|
|
|
|
|
|
|
func NewLocalnode(priv *ecdsa.PrivateKey, ipAddr *net.TCPAddr, udpPort int, wakuFlags wenr.WakuEnrBitfield, advertiseAddr *net.IP, log *zap.Logger) (*enode.LocalNode, error) {
|
|
|
|
|
db, err := enode.OpenDB("")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
localnode := enode.NewLocalNode(db, priv)
|
|
|
|
|
localnode.SetFallbackUDP(udpPort)
|
|
|
|
|
localnode.Set(enr.WithEntry(wenr.WakuENRField, wakuFlags))
|
|
|
|
|
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 CreateHost(t *testing.T, opts ...config.Option) (host.Host, int, *ecdsa.PrivateKey) {
|
|
|
|
|
privKey, err := gcrypto.GenerateKey()
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
|
|
sPrivKey := libp2pcrypto.PrivKey(utils.EcdsaPrivKeyToSecp256k1PrivKey(privKey))
|
|
|
|
|
|
|
|
|
|
port, err := 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)
|
|
|
|
|
|
|
|
|
|
opts = append(opts, libp2p.ListenAddrs(sourceMultiAddr),
|
|
|
|
|
libp2p.Identity(sPrivKey))
|
|
|
|
|
|
|
|
|
|
host, err := libp2p.New(opts...)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
|
|
return host, port, privKey
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
}
|