diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e350f8..4373e83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ The format is based on [Keep a Changelog][keepachangelog] and adheres to [Semant ### Added +- LibP2P added support over NAT + ### Changed ### Deprecated diff --git a/Makefile b/Makefile index 2c93cdd..b6d9927 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,7 @@ test-e2e: .PHONY: build clean test run-node run-node2 run-node3 run-example deps tidy fmt vet lint clear-ports -VERSION := 0.51.5-beta +VERSION := 0.51.6-beta COMMIT ?= $(shell git rev-parse --short HEAD 2>/dev/null || echo unknown) DATE ?= $(shell date -u +%Y-%m-%dT%H:%M:%SZ) LDFLAGS := -X 'main.version=$(VERSION)' -X 'main.commit=$(COMMIT)' -X 'main.date=$(DATE)' diff --git a/pkg/node/node.go b/pkg/node/node.go index 1415471..2bf1f02 100644 --- a/pkg/node/node.go +++ b/pkg/node/node.go @@ -16,7 +16,6 @@ import ( "github.com/libp2p/go-libp2p/core/peer" noise "github.com/libp2p/go-libp2p/p2p/security/noise" - "github.com/libp2p/go-libp2p/p2p/transport/tcp" "github.com/multiformats/go-multiaddr" "go.uber.org/zap" @@ -83,6 +82,39 @@ func (n *Node) startRQLite(ctx context.Context) error { return nil } +// bootstrapPeerSource returns a PeerSource that yields peers from BootstrapPeers. +func bootstrapPeerSource(bootstrapAddrs []string, logger *zap.Logger) func(context.Context, int) <-chan peer.AddrInfo { + return func(ctx context.Context, num int) <-chan peer.AddrInfo { + out := make(chan peer.AddrInfo, num) + go func() { + defer close(out) + count := 0 + for _, s := range bootstrapAddrs { + if count >= num { + return + } + ma, err := multiaddr.NewMultiaddr(s) + if err != nil { + logger.Debug("invalid bootstrap multiaddr", zap.String("addr", s), zap.Error(err)) + continue + } + ai, err := peer.AddrInfoFromP2pAddr(ma) + if err != nil { + logger.Debug("failed to parse bootstrap peer", zap.String("addr", s), zap.Error(err)) + continue + } + select { + case out <- *ai: + count++ + case <-ctx.Done(): + return + } + } + }() + return out + } +} + // hasBootstrapConnections checks if we're connected to any bootstrap peers func (n *Node) hasBootstrapConnections() bool { if n.host == nil || len(n.config.Discovery.BootstrapPeers) == 0 { @@ -212,31 +244,27 @@ func (n *Node) connectToBootstrapPeers(ctx context.Context) error { func (n *Node) startLibP2P() error { n.logger.ComponentInfo(logging.ComponentLibP2P, "Starting LibP2P host") - // Get listen addresses - listenAddrs, err := n.config.ParseMultiaddrs() - if err != nil { - return fmt.Errorf("failed to parse listen addresses: %w", err) - } - // Load or create persistent identity identity, err := n.loadOrCreateIdentity() if err != nil { return fmt.Errorf("failed to load identity: %w", err) } - // Create LibP2P host with persistent identity - // Build options allowing conditional proxying via Anyone SOCKS5 + // Create LibP2P host with NAT traversal support var opts []libp2p.Option opts = append(opts, libp2p.Identity(identity), - libp2p.ListenAddrs(listenAddrs...), libp2p.Security(noise.ID, noise.New), libp2p.DefaultMuxers, + libp2p.EnableNATService(), + libp2p.EnableAutoNATv2(), + libp2p.EnableRelay(), + libp2p.NATPortMap(), + libp2p.EnableAutoRelayWithPeerSource( + bootstrapPeerSource(n.config.Discovery.BootstrapPeers, n.logger.Logger), + ), ) - // TCP transport with optional SOCKS5 dialer override - opts = append(opts, libp2p.Transport(tcp.NewTCPTransport)) - h, err := libp2p.New(opts...) if err != nil { return err