From e98adba1ef4fcaeaa826f7a9f438ccdd31a7c3f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jano=C5=A1=20Gulja=C5=A1?= Date: Thu, 4 Dec 2025 17:07:08 +0100 Subject: [PATCH 01/24] hive: remove ping --- pkg/hive/hive.go | 91 ++++++++----------------------------------- pkg/hive/hive_test.go | 30 +------------- 2 files changed, 19 insertions(+), 102 deletions(-) diff --git a/pkg/hive/hive.go b/pkg/hive/hive.go index f5fe1b3bf53..4293aaf8d9d 100644 --- a/pkg/hive/hive.go +++ b/pkg/hive/hive.go @@ -12,7 +12,6 @@ package hive import ( "context" - "encoding/hex" "errors" "fmt" "sync" @@ -41,8 +40,7 @@ const ( peersStreamName = "peers" messageTimeout = 1 * time.Minute // maximum allowed time for a message to be read or written. maxBatchSize = 30 - pingTimeout = time.Second * 15 // time to wait for ping to succeed - batchValidationTimeout = 5 * time.Minute // prevent lock contention on peer validation + batchValidationTimeout = 5 * time.Minute // prevent lock contention on peer validation ) var ( @@ -53,7 +51,7 @@ var ( ) type Service struct { - streamer p2p.StreamerPinger + streamer p2p.Streamer addressBook addressbook.GetPutter addPeersHandler func(...swarm.Address) networkID uint64 @@ -69,7 +67,7 @@ type Service struct { allowPrivateCIDRs bool } -func New(streamer p2p.StreamerPinger, addressbook addressbook.GetPutter, networkID uint64, bootnode bool, allowPrivateCIDRs bool, logger log.Logger) *Service { +func New(streamer p2p.Streamer, addressbook addressbook.GetPutter, networkID uint64, bootnode bool, allowPrivateCIDRs bool, logger log.Logger) *Service { svc := &Service{ streamer: streamer, logger: logger.WithName(loggerName).Register(), @@ -274,72 +272,6 @@ func (s *Service) startCheckPeersHandler() { func (s *Service) checkAndAddPeers(ctx context.Context, peers pb.Peers) { var peersToAdd []swarm.Address - mtx := sync.Mutex{} - wg := sync.WaitGroup{} - - addPeer := func(newPeer *pb.BzzAddress, multiUnderlay []ma.Multiaddr) { - err := s.sem.Acquire(ctx, 1) - if err != nil { - return - } - - wg.Add(1) - go func() { - s.metrics.PeerConnectAttempts.Inc() - - defer func() { - s.sem.Release(1) - wg.Done() - }() - - ctx, cancel := context.WithTimeout(ctx, pingTimeout) - defer cancel() - - var ( - pingSuccessful bool - start time.Time - ) - for _, underlay := range multiUnderlay { - // ping each underlay address, pick first available - start = time.Now() - if _, err := s.streamer.Ping(ctx, underlay); err != nil { - s.logger.Debug("unreachable peer underlay", "peer_address", hex.EncodeToString(newPeer.Overlay), "underlay", underlay, "error", err) - continue - } - pingSuccessful = true - s.logger.Debug("reachable peer underlay", "peer_address", hex.EncodeToString(newPeer.Overlay), "underlay", underlay) - break - } - - if !pingSuccessful { - // none of underlay addresses is available - s.metrics.PingFailureTime.Observe(time.Since(start).Seconds()) - s.metrics.UnreachablePeers.Inc() - return - } - - s.metrics.PingTime.Observe(time.Since(start).Seconds()) - s.metrics.ReachablePeers.Inc() - - bzzAddress := bzz.Address{ - Overlay: swarm.NewAddress(newPeer.Overlay), - Underlays: multiUnderlay, - Signature: newPeer.Signature, - Nonce: newPeer.Nonce, - } - - err := s.addressBook.Put(bzzAddress.Overlay, bzzAddress) - if err != nil { - s.metrics.StorePeerErr.Inc() - s.logger.Warning("skipping peer in response", "peer_address", newPeer.String(), "error", err) - return - } - - mtx.Lock() - peersToAdd = append(peersToAdd, bzzAddress.Overlay) - mtx.Unlock() - }() - } for _, p := range peers.Peers { multiUnderlays, err := bzz.DeserializeUnderlays(p.Underlay) @@ -361,10 +293,21 @@ func (s *Service) checkAndAddPeers(ctx context.Context, peers pb.Peers) { continue } - // add peer does not exist in the addressbook - addPeer(p, multiUnderlays) + bzzAddress := bzz.Address{ + Overlay: swarm.NewAddress(p.Overlay), + Underlays: multiUnderlays, + Signature: p.Signature, + Nonce: p.Nonce, + } + + if err := s.addressBook.Put(bzzAddress.Overlay, bzzAddress); err != nil { + s.metrics.StorePeerErr.Inc() + s.logger.Warning("skipping peer in response", "peer_address", p.String(), "error", err) + return + } + + peersToAdd = append(peersToAdd, bzzAddress.Overlay) } - wg.Wait() if s.addPeersHandler != nil && len(peersToAdd) > 0 { s.addPeersHandler(peersToAdd...) diff --git a/pkg/hive/hive_test.go b/pkg/hive/hive_test.go index 1f0d6eecd53..d12bdde144d 100644 --- a/pkg/hive/hive_test.go +++ b/pkg/hive/hive_test.go @@ -8,7 +8,6 @@ import ( "bytes" "context" "encoding/hex" - "errors" "fmt" "strconv" "testing" @@ -48,7 +47,7 @@ func TestHandlerRateLimit(t *testing.T) { addressbookclean := ab.New(mock.NewStateStore()) - // new recorder for handling Ping + // new recorder streamer := streamtest.New() // create a hive server that handles the incoming stream server := hive.New(streamer, addressbookclean, networkID, false, true, logger) @@ -192,7 +191,6 @@ func TestBroadcastPeers(t *testing.T) { wantOverlays []swarm.Address wantBzzAddresses []bzz.Address allowPrivateCIDRs bool - pingErr func(addr ma.Multiaddr) (time.Duration, error) }{ "OK - single record": { addresee: swarm.MustParseHexAddress("ca1e9f3938cc1425c6061b96ad9eb93e134dfe8734ad490164ef20af9d1cf59c"), @@ -234,24 +232,6 @@ func TestBroadcastPeers(t *testing.T) { wantBzzAddresses: bzzAddresses[:2*hive.MaxBatchSize], allowPrivateCIDRs: true, }, - "OK - single batch - skip ping failures": { - addresee: swarm.MustParseHexAddress("ca1e9f3938cc1425c6061b96ad9eb93e134dfe8734ad490164ef20af9d1cf59c"), - peers: overlays[:15], - wantMsgs: []pb.Peers{{Peers: wantMsgs[0].Peers[:15]}}, - wantOverlays: overlays[:10], - wantBzzAddresses: bzzAddresses[:10], - allowPrivateCIDRs: true, - pingErr: func(addr ma.Multiaddr) (rtt time.Duration, err error) { - for _, v := range bzzAddresses[10:15] { - for _, underlay := range v.Underlays { - if underlay.Equal(addr) { - return rtt, errors.New("ping failure") - } - } - } - return rtt, nil - }, - }, "Ok - don't advertise private CIDRs only": { addresee: overlays[len(overlays)-1], peers: overlays[:15], @@ -291,13 +271,7 @@ func TestBroadcastPeers(t *testing.T) { addressbookclean := ab.New(mock.NewStateStore()) - // new recorder for handling Ping - var streamer *streamtest.Recorder - if tc.pingErr != nil { - streamer = streamtest.New(streamtest.WithPingErr(tc.pingErr)) - } else { - streamer = streamtest.New() - } + streamer := streamtest.New() // create a hive server that handles the incoming stream server := hive.New(streamer, addressbookclean, networkID, false, true, logger) testutil.CleanupCloser(t, server) From a8faeb3b08127e788d65a5ebf4f61ea1f058311e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jano=C5=A1=20Gulja=C5=A1?= Date: Thu, 4 Dec 2025 17:26:45 +0100 Subject: [PATCH 02/24] pullsync: remove make offer timeout --- pkg/pullsync/pullsync.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pkg/pullsync/pullsync.go b/pkg/pullsync/pullsync.go index 8dd604c596a..436600a2f76 100644 --- a/pkg/pullsync/pullsync.go +++ b/pkg/pullsync/pullsync.go @@ -49,7 +49,6 @@ const ( MaxCursor = math.MaxUint64 DefaultMaxPage uint64 = 250 pageTimeout = time.Second - makeOfferTimeout = 15 * time.Minute handleMaxChunksPerSecond = 250 handleRequestsLimitRate = time.Second / handleMaxChunksPerSecond // handle max `handleMaxChunksPerSecond` chunks per second per peer ) @@ -402,9 +401,6 @@ func (s *Syncer) Sync(ctx context.Context, peer swarm.Address, bin uint8, start // makeOffer tries to assemble an offer for a given requested interval. func (s *Syncer) makeOffer(ctx context.Context, rn pb.Get) (*pb.Offer, error) { - ctx, cancel := context.WithTimeout(ctx, makeOfferTimeout) - defer cancel() - addrs, top, err := s.collectAddrs(ctx, uint8(rn.Bin), rn.Start) if err != nil { return nil, err From f1a869a8f100ec105e4f11e13e42f7815988310a Mon Sep 17 00:00:00 2001 From: Ljubisa Gacevic Date: Tue, 9 Dec 2025 12:55:14 +0100 Subject: [PATCH 03/24] fix(libp2p): consolidate AddrsFactory logic for all transports --- go.mod | 2 +- go.sum | 4 ++-- pkg/p2p/libp2p/libp2p.go | 28 +++++++++++++++++----------- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/go.mod b/go.mod index e629193a4e4..0dd9e214275 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/ethereum/go-ethereum v1.15.11 github.com/ethersphere/batch-archive v0.0.4 github.com/ethersphere/go-price-oracle-abi v0.6.9 - github.com/ethersphere/go-storage-incentives-abi v0.9.4 + github.com/ethersphere/go-storage-incentives-abi v0.9.3-rc4 github.com/ethersphere/go-sw3-abi v0.6.9 github.com/ethersphere/langos v1.0.0 github.com/go-playground/validator/v10 v10.11.1 diff --git a/go.sum b/go.sum index b2918edd460..ce118f3ca08 100644 --- a/go.sum +++ b/go.sum @@ -239,8 +239,8 @@ github.com/ethersphere/batch-archive v0.0.4 h1:PHmwQfmUEyDJgoX2IqI/R0alQ63+aLPXf github.com/ethersphere/batch-archive v0.0.4/go.mod h1:41BPb192NoK9CYjNB8BAE1J2MtiI/5aq0Wtas5O7A7Q= github.com/ethersphere/go-price-oracle-abi v0.6.9 h1:bseen6he3PZv5GHOm+KD6s4awaFmVSD9LFx+HpB6rCU= github.com/ethersphere/go-price-oracle-abi v0.6.9/go.mod h1:sI/Qj4/zJ23/b1enzwMMv0/hLTpPNVNacEwCWjo6yBk= -github.com/ethersphere/go-storage-incentives-abi v0.9.4 h1:mSIWXQXg5OQmH10QvXMV5w0vbSibFMaRlBL37gPLTM0= -github.com/ethersphere/go-storage-incentives-abi v0.9.4/go.mod h1:SXvJVtM4sEsaSKD0jc1ClpDLw8ErPoROZDme4Wrc/Nc= +github.com/ethersphere/go-storage-incentives-abi v0.9.3-rc4 h1:YK9FpiQz29ctU5V46CuwMt+4X5Xn8FTBwy6E2v/ix8s= +github.com/ethersphere/go-storage-incentives-abi v0.9.3-rc4/go.mod h1:SXvJVtM4sEsaSKD0jc1ClpDLw8ErPoROZDme4Wrc/Nc= github.com/ethersphere/go-sw3-abi v0.6.9 h1:TnWLnYkWE5UvC17mQBdUmdkzhPhO8GcqvWy4wvd1QJQ= github.com/ethersphere/go-sw3-abi v0.6.9/go.mod h1:BmpsvJ8idQZdYEtWnvxA8POYQ8Rl/NhyCdF0zLMOOJU= github.com/ethersphere/langos v1.0.0 h1:NBtNKzXTTRSue95uOlzPN4py7Aofs0xWPzyj4AI1Vcc= diff --git a/pkg/p2p/libp2p/libp2p.go b/pkg/p2p/libp2p/libp2p.go index 0a26f7b287d..a8137040c78 100644 --- a/pkg/p2p/libp2p/libp2p.go +++ b/pkg/p2p/libp2p/libp2p.go @@ -391,13 +391,20 @@ func New(ctx context.Context, signer beecrypto.Signer, networkID uint64, overlay if o.EnableWSS { wsOpt := ws.WithTLSConfig(certManager.TLSConfig()) transports = append(transports, libp2p.Transport(ws.New, wsOpt)) - // AddrsFactory takes the multiaddrs we're listening on and sets the multiaddrs to advertise to the network. - // We use the AutoTLS address factory so that the `*` in the AutoTLS address string is replaced with the - // actual IP address of the host once detected - certManagerAddressFactory := certManager.AddressFactory() - opts = append(opts, libp2p.AddrsFactory(func(addrs []ma.Multiaddr) []ma.Multiaddr { - addrs = includeNatResolvedAddresses(addrs, newCompositeAddressResolver(tcpResolver, wssResolver), logger) + } + + if o.EnableWS { + transports = append(transports, libp2p.Transport(ws.New)) + } + + opts = append(opts, libp2p.AddrsFactory(func(addrs []ma.Multiaddr) []ma.Multiaddr { + addrs = includeNatResolvedAddresses(addrs, newCompositeAddressResolver(tcpResolver, wssResolver), logger) + if o.EnableWSS { + // AddrsFactory takes the multiaddrs we're listening on and sets the multiaddrs to advertise to the network. + // We use the AutoTLS address factory so that the `*` in the AutoTLS address string is replaced with the + // actual IP address of the host once detected + certManagerAddressFactory := certManager.AddressFactory() addrs = certManagerAddressFactory(addrs) slices.SortStableFunc(addrs, func(a, b ma.Multiaddr) int { @@ -413,11 +420,10 @@ func New(ctx context.Context, signer beecrypto.Signer, networkID uint64, overlay } return 0 }) - return addrs - })) - } else if o.EnableWS { - transports = append(transports, libp2p.Transport(ws.New)) - } + } + + return addrs + })) opts = append(opts, transports...) From 2f10842a3536abfa5795e774e5f2610c5efef436 Mon Sep 17 00:00:00 2001 From: Ljubisa Gacevic Date: Tue, 9 Dec 2025 17:48:52 +0100 Subject: [PATCH 04/24] fix(libp2p): increase ping timeout to 5s --- pkg/p2p/libp2p/libp2p.go | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/pkg/p2p/libp2p/libp2p.go b/pkg/p2p/libp2p/libp2p.go index a8137040c78..a98af640761 100644 --- a/pkg/p2p/libp2p/libp2p.go +++ b/pkg/p2p/libp2p/libp2p.go @@ -388,37 +388,34 @@ func New(ctx context.Context, signer beecrypto.Signer, networkID uint64, overlay wssResolver = r } + // Add WebSocket transport(s) based on configuration if o.EnableWSS { wsOpt := ws.WithTLSConfig(certManager.TLSConfig()) transports = append(transports, libp2p.Transport(ws.New, wsOpt)) - } - - if o.EnableWS { + } else if o.EnableWS { transports = append(transports, libp2p.Transport(ws.New)) } opts = append(opts, libp2p.AddrsFactory(func(addrs []ma.Multiaddr) []ma.Multiaddr { + // Always include NAT-resolved addresses (both cases use the same resolver logic addrs = includeNatResolvedAddresses(addrs, newCompositeAddressResolver(tcpResolver, wssResolver), logger) + // Only apply cert manager address rewriting when WSS is enabled if o.EnableWSS { - // AddrsFactory takes the multiaddrs we're listening on and sets the multiaddrs to advertise to the network. - // We use the AutoTLS address factory so that the `*` in the AutoTLS address string is replaced with the - // actual IP address of the host once detected certManagerAddressFactory := certManager.AddressFactory() addrs = certManagerAddressFactory(addrs) + // Sort to prioritize public addresses (only meaningful with WSS, but harmless otherwise) slices.SortStableFunc(addrs, func(a, b ma.Multiaddr) int { aPub := manet.IsPublicAddr(a) bPub := manet.IsPublicAddr(b) - switch { - case aPub == bPub: + if aPub == bPub { return 0 - case aPub: + } + if aPub { return -1 - case bPub: - return 1 } - return 0 + return 1 }) } @@ -485,6 +482,7 @@ func New(ctx context.Context, signer beecrypto.Signer, networkID uint64, overlay return nil, fmt.Errorf("handshake service: %w", err) } + // TODO: check if it needs to have own isolated peerstore with dedicated resource manager? // Create a new dialer for libp2p ping protocol. This ensures that the protocol // uses a different set of keys to do ping. It prevents inconsistencies in peerstore as // the addresses used are not dialable and hence should be cleaned up. We should create @@ -1082,9 +1080,10 @@ func (s *Service) Connect(ctx context.Context, addrs []ma.Multiaddr) (address *b return nil, fmt.Errorf("connect full close %w", err) } + // TODO: do we need to ping here? the handshake already verifies liveness? var pingErr error for _, addr := range addrs { - pingCtx, cancel := context.WithTimeout(ctx, 500*time.Millisecond) + pingCtx, cancel := context.WithTimeout(ctx, 5*time.Second) _, err := s.Ping(pingCtx, addr) cancel() // Cancel immediately after use if err == nil { From c5fbf5a9d4d19d19188645b6c3723140b404685b Mon Sep 17 00:00:00 2001 From: Ljubisa Gacevic Date: Wed, 10 Dec 2025 11:58:41 +0100 Subject: [PATCH 05/24] fix(libp2p): remove ping after handshake --- pkg/p2p/libp2p/libp2p.go | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/pkg/p2p/libp2p/libp2p.go b/pkg/p2p/libp2p/libp2p.go index a98af640761..3166f629ed5 100644 --- a/pkg/p2p/libp2p/libp2p.go +++ b/pkg/p2p/libp2p/libp2p.go @@ -388,7 +388,6 @@ func New(ctx context.Context, signer beecrypto.Signer, networkID uint64, overlay wssResolver = r } - // Add WebSocket transport(s) based on configuration if o.EnableWSS { wsOpt := ws.WithTLSConfig(certManager.TLSConfig()) transports = append(transports, libp2p.Transport(ws.New, wsOpt)) @@ -404,19 +403,6 @@ func New(ctx context.Context, signer beecrypto.Signer, networkID uint64, overlay if o.EnableWSS { certManagerAddressFactory := certManager.AddressFactory() addrs = certManagerAddressFactory(addrs) - - // Sort to prioritize public addresses (only meaningful with WSS, but harmless otherwise) - slices.SortStableFunc(addrs, func(a, b ma.Multiaddr) int { - aPub := manet.IsPublicAddr(a) - bPub := manet.IsPublicAddr(b) - if aPub == bPub { - return 0 - } - if aPub { - return -1 - } - return 1 - }) } return addrs @@ -1080,24 +1066,6 @@ func (s *Service) Connect(ctx context.Context, addrs []ma.Multiaddr) (address *b return nil, fmt.Errorf("connect full close %w", err) } - // TODO: do we need to ping here? the handshake already verifies liveness? - var pingErr error - for _, addr := range addrs { - pingCtx, cancel := context.WithTimeout(ctx, 5*time.Second) - _, err := s.Ping(pingCtx, addr) - cancel() // Cancel immediately after use - if err == nil { - pingErr = nil - break - } - pingErr = err - } - - if pingErr != nil { - _ = s.Disconnect(overlay, "peer disconnected immediately after handshake") - return nil, p2p.ErrPeerNotFound - } - if !s.peers.Exists(overlay) { return nil, p2p.ErrPeerNotFound } From a519468a0e3fbc09d3abcefcde0b63d04aaffb27 Mon Sep 17 00:00:00 2001 From: Ljubisa Gacevic Date: Wed, 10 Dec 2025 12:05:03 +0100 Subject: [PATCH 06/24] fix(hive): remove unused context --- pkg/hive/hive.go | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/pkg/hive/hive.go b/pkg/hive/hive.go index 4293aaf8d9d..d05cbbd873a 100644 --- a/pkg/hive/hive.go +++ b/pkg/hive/hive.go @@ -35,12 +35,11 @@ import ( const loggerName = "hive" const ( - protocolName = "hive" - protocolVersion = "1.1.0" - peersStreamName = "peers" - messageTimeout = 1 * time.Minute // maximum allowed time for a message to be read or written. - maxBatchSize = 30 - batchValidationTimeout = 5 * time.Minute // prevent lock contention on peer validation + protocolName = "hive" + protocolVersion = "1.1.0" + peersStreamName = "peers" + messageTimeout = 1 * time.Minute // maximum allowed time for a message to be read or written. + maxBatchSize = 30 ) var ( @@ -261,16 +260,14 @@ func (s *Service) startCheckPeersHandler() { return case newPeers := <-s.peersChan: s.wg.Go(func() { - cctx, cancel := context.WithTimeout(ctx, batchValidationTimeout) - defer cancel() - s.checkAndAddPeers(cctx, newPeers) + s.checkAndAddPeers(newPeers) }) } } }) } -func (s *Service) checkAndAddPeers(ctx context.Context, peers pb.Peers) { +func (s *Service) checkAndAddPeers(peers pb.Peers) { var peersToAdd []swarm.Address for _, p := range peers.Peers { From ada691361a815e994aee2980326286d5559e56cf Mon Sep 17 00:00:00 2001 From: Ljubisa Gacevic Date: Wed, 10 Dec 2025 13:03:51 +0100 Subject: [PATCH 07/24] fix: skip self connect --- pkg/hive/hive.go | 18 ++++++++++++++++-- pkg/hive/hive_test.go | 14 ++++++++------ pkg/node/bootstrap.go | 2 +- pkg/node/node.go | 2 +- pkg/p2p/libp2p/libp2p.go | 13 +++++++++++++ pkg/topology/kademlia/kademlia.go | 11 +++++++++++ 6 files changed, 50 insertions(+), 10 deletions(-) diff --git a/pkg/hive/hive.go b/pkg/hive/hive.go index d05cbbd873a..1d4b1cc773d 100644 --- a/pkg/hive/hive.go +++ b/pkg/hive/hive.go @@ -64,9 +64,10 @@ type Service struct { sem *semaphore.Weighted bootnode bool allowPrivateCIDRs bool + overlay swarm.Address } -func New(streamer p2p.Streamer, addressbook addressbook.GetPutter, networkID uint64, bootnode bool, allowPrivateCIDRs bool, logger log.Logger) *Service { +func New(streamer p2p.Streamer, addressbook addressbook.GetPutter, networkID uint64, bootnode bool, allowPrivateCIDRs bool, overlay swarm.Address, logger log.Logger) *Service { svc := &Service{ streamer: streamer, logger: logger.WithName(loggerName).Register(), @@ -80,6 +81,7 @@ func New(streamer p2p.Streamer, addressbook addressbook.GetPutter, networkID uin sem: semaphore.NewWeighted(int64(swarm.MaxBins)), bootnode: bootnode, allowPrivateCIDRs: allowPrivateCIDRs, + overlay: overlay, } if !bootnode { @@ -174,6 +176,11 @@ func (s *Service) sendPeers(ctx context.Context, peer swarm.Address, peers []swa w, _ := protobuf.NewWriterAndReader(stream) var peersRequest pb.Peers for _, p := range peers { + if p.Equal(s.overlay) { + s.logger.Debug("skipping self-address in broadcast", "overlay", p.String()) + continue + } + addr, err := s.addressBook.Get(p) if err != nil { if errors.Is(err, addressbook.ErrNotFound) { @@ -290,8 +297,15 @@ func (s *Service) checkAndAddPeers(peers pb.Peers) { continue } + overlayAddr := swarm.NewAddress(p.Overlay) + + if overlayAddr.Equal(s.overlay) { + s.logger.Debug("skipping self-address in peer list", "overlay", overlayAddr.String()) + continue + } + bzzAddress := bzz.Address{ - Overlay: swarm.NewAddress(p.Overlay), + Overlay: overlayAddr, Underlays: multiUnderlays, Signature: p.Signature, Nonce: p.Nonce, diff --git a/pkg/hive/hive_test.go b/pkg/hive/hive_test.go index d12bdde144d..510a807f443 100644 --- a/pkg/hive/hive_test.go +++ b/pkg/hive/hive_test.go @@ -50,10 +50,9 @@ func TestHandlerRateLimit(t *testing.T) { // new recorder streamer := streamtest.New() // create a hive server that handles the incoming stream - server := hive.New(streamer, addressbookclean, networkID, false, true, logger) - testutil.CleanupCloser(t, server) - serverAddress := swarm.RandAddress(t) + server := hive.New(streamer, addressbookclean, networkID, false, true, serverAddress, logger) + testutil.CleanupCloser(t, server) // setup the stream recorder to record stream data serverRecorder := streamtest.New( @@ -94,7 +93,8 @@ func TestHandlerRateLimit(t *testing.T) { } // create a hive client that will do broadcast - client := hive.New(serverRecorder, addressbook, networkID, false, true, logger) + clientAddress := swarm.RandAddress(t) + client := hive.New(serverRecorder, addressbook, networkID, false, true, clientAddress, logger) err := client.BroadcastPeers(context.Background(), serverAddress, peers...) if err != nil { t.Fatal(err) @@ -273,7 +273,8 @@ func TestBroadcastPeers(t *testing.T) { streamer := streamtest.New() // create a hive server that handles the incoming stream - server := hive.New(streamer, addressbookclean, networkID, false, true, logger) + serverAddress := swarm.RandAddress(t) + server := hive.New(streamer, addressbookclean, networkID, false, true, serverAddress, logger) testutil.CleanupCloser(t, server) // setup the stream recorder to record stream data @@ -282,7 +283,8 @@ func TestBroadcastPeers(t *testing.T) { ) // create a hive client that will do broadcast - client := hive.New(recorder, addressbook, networkID, false, tc.allowPrivateCIDRs, logger) + clientAddress := swarm.RandAddress(t) + client := hive.New(recorder, addressbook, networkID, false, tc.allowPrivateCIDRs, clientAddress, logger) if err := client.BroadcastPeers(context.Background(), tc.addresee, tc.peers...); err != nil { t.Fatal(err) diff --git a/pkg/node/bootstrap.go b/pkg/node/bootstrap.go index cc2b5f6df96..eab32166ec9 100644 --- a/pkg/node/bootstrap.go +++ b/pkg/node/bootstrap.go @@ -117,7 +117,7 @@ func bootstrapNode( b.p2pService = p2ps b.p2pHalter = p2ps - hive := hive.New(p2ps, addressbook, networkID, o.BootnodeMode, o.AllowPrivateCIDRs, logger) + hive := hive.New(p2ps, addressbook, networkID, o.BootnodeMode, o.AllowPrivateCIDRs, swarmAddress, logger) if err = p2ps.AddProtocol(hive.Protocol()); err != nil { return nil, fmt.Errorf("hive service: %w", err) diff --git a/pkg/node/node.go b/pkg/node/node.go index 5f2a108617b..59027cc2490 100644 --- a/pkg/node/node.go +++ b/pkg/node/node.go @@ -748,7 +748,7 @@ func NewBee( return nil, fmt.Errorf("pingpong service: %w", err) } - hive := hive.New(p2ps, addressbook, networkID, o.BootnodeMode, o.AllowPrivateCIDRs, logger) + hive := hive.New(p2ps, addressbook, networkID, o.BootnodeMode, o.AllowPrivateCIDRs, swarmAddress, logger) if err = p2ps.AddProtocol(hive.Protocol()); err != nil { return nil, fmt.Errorf("hive service: %w", err) diff --git a/pkg/p2p/libp2p/libp2p.go b/pkg/p2p/libp2p/libp2p.go index 3166f629ed5..0755c2207d6 100644 --- a/pkg/p2p/libp2p/libp2p.go +++ b/pkg/p2p/libp2p/libp2p.go @@ -948,6 +948,7 @@ func (s *Service) Connect(ctx context.Context, addrs []ma.Multiaddr) (address *b var info *libp2ppeer.AddrInfo var peerID libp2ppeer.ID var connectErr error + skippedSelf := false // Try to connect to each underlay address one by one. // @@ -965,6 +966,13 @@ func (s *Service) Connect(ctx context.Context, addrs []ma.Multiaddr) (address *b info = ai peerID = ai.ID + // Check if attempting to connect to self + if peerID == s.host.ID() { + s.logger.Debug("skipping connection to self", "peer_id", peerID, "underlay", info.Addrs) + skippedSelf = true + continue + } + hostAddr, err := buildHostAddress(info.ID) if err != nil { return nil, fmt.Errorf("build host address: %w", err) @@ -997,6 +1005,11 @@ func (s *Service) Connect(ctx context.Context, addrs []ma.Multiaddr) (address *b return nil, fmt.Errorf("libp2p connect: %w", connectErr) } + // If we skipped all addresses due to self-connection, return an error + if skippedSelf && info != nil && info.ID == s.host.ID() { + return nil, fmt.Errorf("cannot connect to self") + } + if info == nil { return nil, fmt.Errorf("unable to identify peer from addresses: %v", addrs) } diff --git a/pkg/topology/kademlia/kademlia.go b/pkg/topology/kademlia/kademlia.go index 4761b15519a..f1257e5a6ab 100644 --- a/pkg/topology/kademlia/kademlia.go +++ b/pkg/topology/kademlia/kademlia.go @@ -449,6 +449,11 @@ func (k *Kad) connectionAttemptsHandler(ctx context.Context, wg *sync.WaitGroup, return } + if peer.addr.Equal(k.base) { + k.logger.Debug("skipping self-address in connected peers", "overlay", peer.addr, "method", "connect") + return + } + k.waitNext.Set(peer.addr, time.Now().Add(k.opt.ShortRetry), 0) k.connectedPeers.Add(peer.addr) @@ -1190,6 +1195,12 @@ func (k *Kad) Connected(ctx context.Context, peer p2p.Peer, forceConnection bool } func (k *Kad) onConnected(ctx context.Context, addr swarm.Address) error { + // Prevent adding self to connected peers + if addr.Equal(k.base) { + k.logger.Debug("skipping self-address in connected peers", "overlay", addr, "method", "onConnected") + return nil + } + if err := k.Announce(ctx, addr, true); err != nil { return err } From dcf09a7fb728f912d3075fbac9643f2a59efdf17 Mon Sep 17 00:00:00 2001 From: Ljubisa Gacevic Date: Wed, 10 Dec 2025 21:43:25 +0100 Subject: [PATCH 08/24] fix(pushsync): return after FullClose in handler --- pkg/pushsync/pushsync.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/pushsync/pushsync.go b/pkg/pushsync/pushsync.go index 78720473e6f..05c4aef3d41 100644 --- a/pkg/pushsync/pushsync.go +++ b/pkg/pushsync/pushsync.go @@ -188,6 +188,7 @@ func (ps *PushSync) handler(ctx context.Context, p p2p.Peer, stream p2p.Stream) if !attemptedWrite { if writeErr := w.WriteMsgWithContext(ctx, &pb.Receipt{Err: err.Error()}); writeErr == nil { _ = stream.FullClose() + return } } _ = stream.Reset() From 5d4ee00bd088f838e694580644bea419a6378581 Mon Sep 17 00:00:00 2001 From: Ljubisa Gacevic Date: Wed, 10 Dec 2025 21:44:43 +0100 Subject: [PATCH 09/24] chore: revert go-storage-incentives-abi to v0.9.4 --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 0dd9e214275..e629193a4e4 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/ethereum/go-ethereum v1.15.11 github.com/ethersphere/batch-archive v0.0.4 github.com/ethersphere/go-price-oracle-abi v0.6.9 - github.com/ethersphere/go-storage-incentives-abi v0.9.3-rc4 + github.com/ethersphere/go-storage-incentives-abi v0.9.4 github.com/ethersphere/go-sw3-abi v0.6.9 github.com/ethersphere/langos v1.0.0 github.com/go-playground/validator/v10 v10.11.1 diff --git a/go.sum b/go.sum index ce118f3ca08..b2918edd460 100644 --- a/go.sum +++ b/go.sum @@ -239,8 +239,8 @@ github.com/ethersphere/batch-archive v0.0.4 h1:PHmwQfmUEyDJgoX2IqI/R0alQ63+aLPXf github.com/ethersphere/batch-archive v0.0.4/go.mod h1:41BPb192NoK9CYjNB8BAE1J2MtiI/5aq0Wtas5O7A7Q= github.com/ethersphere/go-price-oracle-abi v0.6.9 h1:bseen6he3PZv5GHOm+KD6s4awaFmVSD9LFx+HpB6rCU= github.com/ethersphere/go-price-oracle-abi v0.6.9/go.mod h1:sI/Qj4/zJ23/b1enzwMMv0/hLTpPNVNacEwCWjo6yBk= -github.com/ethersphere/go-storage-incentives-abi v0.9.3-rc4 h1:YK9FpiQz29ctU5V46CuwMt+4X5Xn8FTBwy6E2v/ix8s= -github.com/ethersphere/go-storage-incentives-abi v0.9.3-rc4/go.mod h1:SXvJVtM4sEsaSKD0jc1ClpDLw8ErPoROZDme4Wrc/Nc= +github.com/ethersphere/go-storage-incentives-abi v0.9.4 h1:mSIWXQXg5OQmH10QvXMV5w0vbSibFMaRlBL37gPLTM0= +github.com/ethersphere/go-storage-incentives-abi v0.9.4/go.mod h1:SXvJVtM4sEsaSKD0jc1ClpDLw8ErPoROZDme4Wrc/Nc= github.com/ethersphere/go-sw3-abi v0.6.9 h1:TnWLnYkWE5UvC17mQBdUmdkzhPhO8GcqvWy4wvd1QJQ= github.com/ethersphere/go-sw3-abi v0.6.9/go.mod h1:BmpsvJ8idQZdYEtWnvxA8POYQ8Rl/NhyCdF0zLMOOJU= github.com/ethersphere/langos v1.0.0 h1:NBtNKzXTTRSue95uOlzPN4py7Aofs0xWPzyj4AI1Vcc= From 5a0524d86bcdde3a957d6addaaf937d6a51a0614 Mon Sep 17 00:00:00 2001 From: Ljubisa Gacevic Date: Wed, 10 Dec 2025 23:55:13 +0100 Subject: [PATCH 10/24] fix(hive): preallocate peersToAdd slice --- pkg/hive/hive.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/hive/hive.go b/pkg/hive/hive.go index d05cbbd873a..8bc07f42791 100644 --- a/pkg/hive/hive.go +++ b/pkg/hive/hive.go @@ -268,7 +268,7 @@ func (s *Service) startCheckPeersHandler() { } func (s *Service) checkAndAddPeers(peers pb.Peers) { - var peersToAdd []swarm.Address + peersToAdd := make([]swarm.Address, 0, len(peers.Peers)) for _, p := range peers.Peers { multiUnderlays, err := bzz.DeserializeUnderlays(p.Underlay) From b27bd1ba6225a019bb10ebf2db9b38fc22c12c46 Mon Sep 17 00:00:00 2001 From: Ljubisa Gacevic Date: Thu, 11 Dec 2025 11:38:21 +0100 Subject: [PATCH 11/24] fix(pushsync): return after FullClose in handler --- pkg/pushsync/pushsync.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/pushsync/pushsync.go b/pkg/pushsync/pushsync.go index 78720473e6f..05c4aef3d41 100644 --- a/pkg/pushsync/pushsync.go +++ b/pkg/pushsync/pushsync.go @@ -188,6 +188,7 @@ func (ps *PushSync) handler(ctx context.Context, p p2p.Peer, stream p2p.Stream) if !attemptedWrite { if writeErr := w.WriteMsgWithContext(ctx, &pb.Receipt{Err: err.Error()}); writeErr == nil { _ = stream.FullClose() + return } } _ = stream.Reset() From 805a1608fb1fce525779f14501aa09a5c212e21e Mon Sep 17 00:00:00 2001 From: Ljubisa Gacevic Date: Thu, 11 Dec 2025 11:39:12 +0100 Subject: [PATCH 12/24] fix(libp2p): improve flow for addrFactory when we have ws and wss --- pkg/p2p/libp2p/libp2p.go | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/pkg/p2p/libp2p/libp2p.go b/pkg/p2p/libp2p/libp2p.go index 3166f629ed5..172a8f861b1 100644 --- a/pkg/p2p/libp2p/libp2p.go +++ b/pkg/p2p/libp2p/libp2p.go @@ -395,18 +395,23 @@ func New(ctx context.Context, signer beecrypto.Signer, networkID uint64, overlay transports = append(transports, libp2p.Transport(ws.New)) } - opts = append(opts, libp2p.AddrsFactory(func(addrs []ma.Multiaddr) []ma.Multiaddr { - // Always include NAT-resolved addresses (both cases use the same resolver logic - addrs = includeNatResolvedAddresses(addrs, newCompositeAddressResolver(tcpResolver, wssResolver), logger) - - // Only apply cert manager address rewriting when WSS is enabled - if o.EnableWSS { - certManagerAddressFactory := certManager.AddressFactory() - addrs = certManagerAddressFactory(addrs) + compositeResolver := newCompositeAddressResolver(tcpResolver, wssResolver) + + var addrFactory config.AddrsFactory + if o.EnableWSS { + certManagerFactory := certManager.AddressFactory() + addrFactory = func(addrs []ma.Multiaddr) []ma.Multiaddr { + addrs = includeNatResolvedAddresses(addrs, compositeResolver, logger) + addrs = certManagerFactory(addrs) + return addrs + } + } else { + addrFactory = func(addrs []ma.Multiaddr) []ma.Multiaddr { + return includeNatResolvedAddresses(addrs, compositeResolver, logger) } + } - return addrs - })) + opts = append(opts, libp2p.AddrsFactory(addrFactory)) opts = append(opts, transports...) From 8598fd4347512be9ec3eb26226477133b55d5392 Mon Sep 17 00:00:00 2001 From: Ljubisa Gacevic Date: Thu, 11 Dec 2025 11:51:46 +0100 Subject: [PATCH 13/24] fix(libp2p): remove TODO comment --- pkg/p2p/libp2p/libp2p.go | 1 - 1 file changed, 1 deletion(-) diff --git a/pkg/p2p/libp2p/libp2p.go b/pkg/p2p/libp2p/libp2p.go index 172a8f861b1..c1731d15833 100644 --- a/pkg/p2p/libp2p/libp2p.go +++ b/pkg/p2p/libp2p/libp2p.go @@ -473,7 +473,6 @@ func New(ctx context.Context, signer beecrypto.Signer, networkID uint64, overlay return nil, fmt.Errorf("handshake service: %w", err) } - // TODO: check if it needs to have own isolated peerstore with dedicated resource manager? // Create a new dialer for libp2p ping protocol. This ensures that the protocol // uses a different set of keys to do ping. It prevents inconsistencies in peerstore as // the addresses used are not dialable and hence should be cleaned up. We should create From b3e9f7da06bd0d6b4a7bf8e5027b0a55fd8d6f80 Mon Sep 17 00:00:00 2001 From: Ljubisa Gacevic Date: Tue, 16 Dec 2025 20:35:18 +0100 Subject: [PATCH 14/24] chore: bump deps --- go.mod | 44 +++++++++++++------------- go.sum | 97 ++++++++++++++++++++++++++-------------------------------- 2 files changed, 65 insertions(+), 76 deletions(-) diff --git a/go.mod b/go.mod index 355799bd55c..604bec0dee7 100644 --- a/go.mod +++ b/go.mod @@ -16,21 +16,21 @@ require ( github.com/ethersphere/go-storage-incentives-abi v0.9.4 github.com/ethersphere/go-sw3-abi v0.6.9 github.com/ethersphere/langos v1.0.0 - github.com/go-playground/validator/v10 v10.11.1 + github.com/go-playground/validator/v10 v10.19.0 github.com/gogo/protobuf v1.3.2 github.com/google/go-cmp v0.7.0 github.com/google/uuid v1.6.0 github.com/gorilla/handlers v1.4.2 - github.com/gorilla/mux v1.8.0 + github.com/gorilla/mux v1.8.1 github.com/gorilla/websocket v1.5.3 github.com/hashicorp/go-multierror v1.1.1 github.com/hashicorp/golang-lru/v2 v2.0.7 github.com/ipfs/go-cid v0.5.0 - github.com/ipshipyard/p2p-forge v0.6.1 + github.com/ipshipyard/p2p-forge v0.7.0 github.com/kardianos/service v1.2.2 github.com/klauspost/reedsolomon v1.11.8 - github.com/libp2p/go-libp2p v0.44.0 - github.com/multiformats/go-multiaddr v0.16.0 + github.com/libp2p/go-libp2p v0.46.0 + github.com/multiformats/go-multiaddr v0.16.1 github.com/multiformats/go-multiaddr-dns v0.4.1 github.com/multiformats/go-multihash v0.2.3 github.com/multiformats/go-multistream v0.6.1 @@ -39,10 +39,10 @@ require ( github.com/spf13/afero v1.6.0 github.com/spf13/cobra v1.8.1 github.com/spf13/viper v1.7.0 - github.com/stretchr/testify v1.10.0 + github.com/stretchr/testify v1.11.1 github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 github.com/uber/jaeger-client-go v2.24.0+incompatible - github.com/vmihailenco/msgpack/v5 v5.3.4 + github.com/vmihailenco/msgpack/v5 v5.4.1 github.com/wealdtech/go-ens/v3 v3.5.1 gitlab.com/nolash/go-mockbytes v0.0.7 go.uber.org/atomic v1.11.0 @@ -60,7 +60,7 @@ require ( ) require ( - github.com/BurntSushi/toml v1.1.0 // indirect + github.com/BurntSushi/toml v1.3.2 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/StackExchange/wmi v1.2.1 // indirect github.com/benbjohnson/clock v1.3.5 // indirect @@ -73,7 +73,7 @@ require ( github.com/consensys/gnark-crypto v0.18.1 // indirect github.com/crate-crypto/go-eth-kzg v1.3.0 // indirect github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a // indirect - github.com/davecgh/go-spew v1.1.1 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect github.com/deckarep/golang-set/v2 v2.6.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect @@ -81,18 +81,17 @@ require ( github.com/ethereum/go-verkle v0.2.2 // indirect github.com/felixge/fgprof v0.9.5 github.com/flynn/noise v1.1.0 // indirect - github.com/francoispqt/gojay v1.2.13 // indirect - github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/fsnotify/fsnotify v1.9.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/go-kit/log v0.2.1 // indirect - github.com/go-logfmt/logfmt v0.5.1 // indirect + github.com/go-logfmt/logfmt v0.6.0 // indirect github.com/go-ole/go-ole v1.3.0 // indirect - github.com/go-playground/locales v0.14.0 // indirect - github.com/go-playground/universal-translator v0.18.0 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/pprof v0.0.0-20250607225305-033d6d78b36a // indirect - github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 // indirect - github.com/hashicorp/errwrap v1.0.0 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/holiman/uint256 v1.3.2 // indirect github.com/huin/goupnp v1.3.0 // indirect @@ -100,10 +99,9 @@ require ( github.com/ipfs/go-log/v2 v2.6.0 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect - github.com/klauspost/compress v1.18.0 // indirect github.com/klauspost/cpuid/v2 v2.2.10 // indirect github.com/koron/go-ssdp v0.0.6 // indirect - github.com/leodido/go-urn v1.2.1 // indirect + github.com/leodido/go-urn v1.4.0 // indirect github.com/libdns/libdns v0.2.2 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/libp2p/go-flow-metrics v0.2.0 // indirect @@ -156,12 +154,12 @@ require ( github.com/prometheus/client_model v0.6.2 // indirect github.com/prometheus/common v0.64.0 github.com/prometheus/procfs v0.16.1 // indirect - github.com/prometheus/statsd_exporter v0.22.7 // indirect - github.com/quic-go/qpack v0.5.1 // indirect - github.com/quic-go/quic-go v0.55.0 // indirect + github.com/prometheus/statsd_exporter v0.26.1 // indirect + github.com/quic-go/qpack v0.6.0 // indirect + github.com/quic-go/quic-go v0.57.1 // indirect github.com/quic-go/webtransport-go v0.9.0 // indirect + github.com/rogpeppe/go-internal v1.13.1 // indirect github.com/shirou/gopsutil v3.21.5+incompatible // indirect - github.com/smartystreets/assertions v1.1.1 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/spf13/cast v1.3.0 // indirect github.com/spf13/jwalterweatherman v1.0.0 // indirect @@ -189,7 +187,7 @@ require ( golang.org/x/text v0.31.0 // indirect golang.org/x/tools v0.38.0 // indirect google.golang.org/protobuf v1.36.6 // indirect - gopkg.in/ini.v1 v1.57.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect lukechampine.com/blake3 v1.4.1 // indirect ) diff --git a/go.sum b/go.sum index 3348d40305e..7b0f87f302a 100644 --- a/go.sum +++ b/go.sum @@ -59,8 +59,8 @@ github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I= -github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= @@ -200,8 +200,9 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU= github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U= github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= @@ -255,12 +256,13 @@ github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI github.com/flynn/noise v1.1.0 h1:KjPQoQCEFdZDiP03phOvGi11+SVVhBG2wOWAorLsstg= github.com/flynn/noise v1.1.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= -github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= +github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= @@ -283,20 +285,21 @@ github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBj github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= +github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= -github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= -github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= -github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= -github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= -github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= -github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ= -github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU= +github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.19.0 h1:ol+5Fu+cSq9JD7SoSqe04GMI92cbn0+wvQ3bZ8b/AU4= +github.com/go-playground/validator/v10 v10.19.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -397,12 +400,10 @@ github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE0 github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 h1:l5lAOZEym3oK3SQ2HBHWsJUfbNBiTXJDeW2QDxw9AQ0= -github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/handlers v1.4.2 h1:0QniY0USkHQ1RGCLfKxeNHK9bkDHGRYGNDFBCS+YARg= github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= -github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= -github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= +github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= @@ -416,8 +417,9 @@ github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpg github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= @@ -479,8 +481,8 @@ github.com/ipfs/go-cid v0.5.0 h1:goEKKhaGm0ul11IHA7I6p1GmKz8kEYniqFopaB5Otwg= github.com/ipfs/go-cid v0.5.0/go.mod h1:0L7vmeNXpQpUS9vt+yEARkJ8rOg43DF3iPgn4GIN0mk= github.com/ipfs/go-log/v2 v2.6.0 h1:2Nu1KKQQ2ayonKp4MPo6pXCjqw1ULc9iohRqWV5EYqg= github.com/ipfs/go-log/v2 v2.6.0/go.mod h1:p+Efr3qaY5YXpx9TX7MoLCSEZX5boSWj9wh86P5HJa8= -github.com/ipshipyard/p2p-forge v0.6.1 h1:987/hUC1YxI56CcMX6iTB+9BLjFV0d2SJnig9Z1pf8A= -github.com/ipshipyard/p2p-forge v0.6.1/go.mod h1:pj8Zcs+ex5OMq5a1bFLHqW0oL3qYO0v5eGLZmit0l7U= +github.com/ipshipyard/p2p-forge v0.7.0 h1:PQayexxZC1FR2Vx0XOSbmZ6wDPliidS48I+xXWuF+YU= +github.com/ipshipyard/p2p-forge v0.7.0/go.mod h1:i2wg0p7WmHGyo5vYaK9COZBp8BN5Drncfu3WoQNZlQY= github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= @@ -504,7 +506,6 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jsternberg/zap-logfmt v1.0.0/go.mod h1:uvPs/4X51zdkcm5jXl5SYoN+4RK21K8mysFmDaM/h+o= -github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= @@ -540,7 +541,6 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -554,8 +554,8 @@ github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2 github.com/leanovate/gopter v0.2.11 h1:vRjThO1EKPb/1NsDXuDrzldR28RLkBflWYcU9CvzWu4= github.com/leanovate/gopter v0.2.11/go.mod h1:aK3tzZP/C+p1m3SPRE4SYZFGP7jjkuSI4f7Xvpt0S9c= github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs= -github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= -github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= +github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= +github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/libdns/libdns v0.2.2 h1:O6ws7bAfRPaBsgAYt8MDe2HcNBGC29hkZ9MX2eUSX3s= github.com/libdns/libdns v0.2.2/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ= @@ -563,8 +563,8 @@ github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6 github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= github.com/libp2p/go-flow-metrics v0.2.0 h1:EIZzjmeOE6c8Dav0sNv35vhZxATIXWZg6j/C08XmmDw= github.com/libp2p/go-flow-metrics v0.2.0/go.mod h1:st3qqfu8+pMfh+9Mzqb2GTiwrAGjIPszEjZmtksN8Jc= -github.com/libp2p/go-libp2p v0.44.0 h1:5Gtt8OrF8yiXmH+Mx4+/iBeFRMK1TY3a8OrEBDEqAvs= -github.com/libp2p/go-libp2p v0.44.0/go.mod h1:NovCojezAt4dnDd4fH048K7PKEqH0UFYYqJRjIIu8zc= +github.com/libp2p/go-libp2p v0.46.0 h1:0T2yvIKpZ3DVYCuPOFxPD1layhRU486pj9rSlGWYnDM= +github.com/libp2p/go-libp2p v0.46.0/go.mod h1:TbIDnpDjBLa7isdgYpbxozIVPBTmM/7qKOJP4SFySrQ= github.com/libp2p/go-libp2p-asn-util v0.4.1 h1:xqL7++IKD9TBFMgnLPZR6/6iYhawHKHl950SO9L6n94= github.com/libp2p/go-libp2p-asn-util v0.4.1/go.mod h1:d/NI6XZ9qxw67b4e+NgpQexCIiFYJjErASrYW4PFDN8= github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA= @@ -660,8 +660,8 @@ github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= github.com/multiformats/go-multiaddr v0.2.2/go.mod h1:NtfXiOtHvghW9KojvtySjH5y0u0xW5UouOmQQrn6a3Y= github.com/multiformats/go-multiaddr v0.3.2/go.mod h1:lCKNGP1EQ1eZ35Za2wlqnabm9xQkib3fyB+nZXHLag0= -github.com/multiformats/go-multiaddr v0.16.0 h1:oGWEVKioVQcdIOBlYM8BH1rZDWOGJSqr9/BKl6zQ4qc= -github.com/multiformats/go-multiaddr v0.16.0/go.mod h1:JSVUmXDjsVFiW7RjIFMP7+Ev+h1DTbiJgVeTV/tcmP0= +github.com/multiformats/go-multiaddr v0.16.1 h1:fgJ0Pitow+wWXzN9do+1b8Pyjmo8m5WhGfzpL82MpCw= +github.com/multiformats/go-multiaddr v0.16.1/go.mod h1:JSVUmXDjsVFiW7RjIFMP7+Ev+h1DTbiJgVeTV/tcmP0= github.com/multiformats/go-multiaddr-dns v0.4.1 h1:whi/uCLbDS3mSEUMb1MsoT4uzUeZB0N32yzufqS0i5M= github.com/multiformats/go-multiaddr-dns v0.4.1/go.mod h1:7hfthtB4E4pQwirrz+J0CcDUfbWzTqEzVyYKKIKpgkc= github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= @@ -774,7 +774,6 @@ github.com/pion/turn/v4 v4.0.2 h1:ZqgQ3+MjP32ug30xAbD6Mn+/K4Sxi3SdNOTFf+7mpps= github.com/pion/turn/v4 v4.0.2/go.mod h1:pMMKP/ieNAG/fN5cZiN4SDuyKsXtNTr0ccN7IToA1zs= github.com/pion/webrtc/v4 v4.1.2 h1:mpuUo/EJ1zMNKGE79fAdYNFZBX790KE7kQQpLMjjR54= github.com/pion/webrtc/v4 v4.1.2/go.mod h1:xsCXiNAmMEjIdFxAYU0MbB3RwRieJsegSB2JZsGN+8U= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -828,14 +827,15 @@ github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= -github.com/prometheus/statsd_exporter v0.22.7 h1:7Pji/i2GuhK6Lu7DHrtTkFmNBCudCPT1pX2CziuyQR0= github.com/prometheus/statsd_exporter v0.22.7/go.mod h1:N/TevpjkIh9ccs6nuzY3jQn9dFqnUakOjnEuMPJJJnI= +github.com/prometheus/statsd_exporter v0.26.1 h1:ucbIAdPmwAUcA+dU+Opok8Qt81Aw8HanlO+2N/Wjv7w= +github.com/prometheus/statsd_exporter v0.26.1/go.mod h1:XlDdjAmRmx3JVvPPYuFNUg+Ynyb5kR69iPPkQjxXFMk= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/prometheus/tsdb v0.10.0/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSgwXEyGCt4= -github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI= -github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg= -github.com/quic-go/quic-go v0.55.0 h1:zccPQIqYCXDt5NmcEabyYvOnomjs8Tlwl7tISjJh9Mk= -github.com/quic-go/quic-go v0.55.0/go.mod h1:DR51ilwU1uE164KuWXhinFcKWGlEjzys2l8zUl5Ss1U= +github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8= +github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII= +github.com/quic-go/quic-go v0.57.1 h1:25KAAR9QR8KZrCZRThWMKVAwGoiHIrNbT72ULHTuI10= +github.com/quic-go/quic-go v0.57.1/go.mod h1:ly4QBAjHA2VhdnxhojRsCUOeJwKYg+taDlos92xb1+s= github.com/quic-go/webtransport-go v0.9.0 h1:jgys+7/wm6JarGDrW+lD/r9BGqBAmqY/ssklE09bA70= github.com/quic-go/webtransport-go v0.9.0/go.mod h1:4FUYIiUc75XSsF6HShcLeXXYZJ9AGwo/xh3L8M/P1ao= github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= @@ -845,10 +845,8 @@ github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRr github.com/rjeczalik/notify v0.9.2/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= -github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= @@ -891,9 +889,6 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/assertions v1.1.1 h1:T/YLemO5Yp7KPzS+lVtu+WsHn8yoSwTfItdAd1r3cck= -github.com/smartystreets/assertions v1.1.1/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= -github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= @@ -934,8 +929,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= @@ -968,8 +963,8 @@ github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w= github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= -github.com/vmihailenco/msgpack/v5 v5.3.4 h1:qMKAwOV+meBw2Y8k9cVwAy7qErtYCwBzZ2ellBfvnqc= -github.com/vmihailenco/msgpack/v5 v5.3.4/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= github.com/wealdtech/go-ens/v3 v3.5.1 h1:0VqkCjIGfIVdwHIf2QqYWWt3bbR1UE7RwBGx7YPpufQ= @@ -1055,7 +1050,6 @@ golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWP golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= @@ -1151,7 +1145,6 @@ golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= @@ -1251,14 +1244,12 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1472,8 +1463,8 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.57.0 h1:9unxIsFcTt4I55uWluz+UmL95q4kdJ0buvQ1ZIqVQww= -gopkg.in/ini.v1 v1.57.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/mail.v2 v2.3.1/go.mod h1:htwXN1Qh09vZJ1NVKxQqHPBaCBbzKhp5GzuJEA4VJWw= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= From 8d050a5a195c599ced9c9d890c2a475a6474e150 Mon Sep 17 00:00:00 2001 From: Ljubisa Gacevic Date: Tue, 16 Dec 2025 21:10:21 +0100 Subject: [PATCH 15/24] fix(kademlia): prevent self dial on AddPeers handler --- pkg/topology/kademlia/kademlia.go | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/pkg/topology/kademlia/kademlia.go b/pkg/topology/kademlia/kademlia.go index f1257e5a6ab..b5bff41fc9a 100644 --- a/pkg/topology/kademlia/kademlia.go +++ b/pkg/topology/kademlia/kademlia.go @@ -449,11 +449,6 @@ func (k *Kad) connectionAttemptsHandler(ctx context.Context, wg *sync.WaitGroup, return } - if peer.addr.Equal(k.base) { - k.logger.Debug("skipping self-address in connected peers", "overlay", peer.addr, "method", "connect") - return - } - k.waitNext.Set(peer.addr, time.Now().Add(k.opt.ShortRetry), 0) k.connectedPeers.Add(peer.addr) @@ -1120,8 +1115,17 @@ func (k *Kad) AnnounceTo(ctx context.Context, addressee, peer swarm.Address, ful // This does not guarantee that a connection will immediately // be made to the peer. func (k *Kad) AddPeers(addrs ...swarm.Address) { - k.knownPeers.Add(addrs...) - k.notifyManageLoop() + toAdd := make([]swarm.Address, 0, len(addrs)) + for _, addr := range addrs { + if !addr.Equal(k.base) { + toAdd = append(toAdd, addr) + } + } + + if len(toAdd) > 0 { + k.knownPeers.Add(toAdd...) + k.notifyManageLoop() + } } func (k *Kad) Pick(peer p2p.Peer) bool { @@ -1195,12 +1199,6 @@ func (k *Kad) Connected(ctx context.Context, peer p2p.Peer, forceConnection bool } func (k *Kad) onConnected(ctx context.Context, addr swarm.Address) error { - // Prevent adding self to connected peers - if addr.Equal(k.base) { - k.logger.Debug("skipping self-address in connected peers", "overlay", addr, "method", "onConnected") - return nil - } - if err := k.Announce(ctx, addr, true); err != nil { return err } From c43235ba71719c212d86da3fc4685c82a2c8b039 Mon Sep 17 00:00:00 2001 From: Ljubisa Gacevic Date: Wed, 17 Dec 2025 19:44:43 +0100 Subject: [PATCH 16/24] fix(libp2p): remove t.Parallel() from tests --- pkg/p2p/libp2p/connections_test.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pkg/p2p/libp2p/connections_test.go b/pkg/p2p/libp2p/connections_test.go index 5129b6d3682..ce1e14a4e15 100644 --- a/pkg/p2p/libp2p/connections_test.go +++ b/pkg/p2p/libp2p/connections_test.go @@ -985,8 +985,6 @@ func TestTopologyAnnounce(t *testing.T) { } func TestTopologyOverSaturated(t *testing.T) { - t.Parallel() - var ( mtx sync.Mutex ctx = context.Background() @@ -1097,8 +1095,6 @@ func TestWithDisconnectStreams(t *testing.T) { } func TestWithBlocklistStreams(t *testing.T) { - t.Parallel() - ctx := t.Context() s1, overlay1 := newService(t, 1, libp2pServiceOpts{libp2pOpts: libp2p.Options{ From 9543e61492d61665ce2eda6b497d4e17dbb819e3 Mon Sep 17 00:00:00 2001 From: Ljubisa Gacevic Date: Wed, 17 Dec 2025 20:55:35 +0100 Subject: [PATCH 17/24] fix: add unit tests for self connect --- pkg/hive/hive_test.go | 219 +++++++++++++++++++++++++ pkg/p2p/libp2p/connections_test.go | 36 ++++ pkg/topology/kademlia/kademlia_test.go | 69 ++++++++ 3 files changed, 324 insertions(+) diff --git a/pkg/hive/hive_test.go b/pkg/hive/hive_test.go index 510a807f443..ec603c8bb2b 100644 --- a/pkg/hive/hive_test.go +++ b/pkg/hive/hive_test.go @@ -446,3 +446,222 @@ func shortHex(b []byte) string { } return s } + +// TestBroadcastPeersSkipsSelf verifies that hive does not broadcast self address +// to other peers, preventing self-connection attempts. +func TestBroadcastPeersSkipsSelf(t *testing.T) { + t.Parallel() + + logger := log.Noop + statestore := mock.NewStateStore() + addressbook := ab.New(statestore) + networkID := uint64(1) + addressbookclean := ab.New(mock.NewStateStore()) + + // Create addresses + serverAddress := swarm.RandAddress(t) + clientAddress := swarm.RandAddress(t) + + // Create a peer address + peer1 := swarm.RandAddress(t) + underlay1, err := ma.NewMultiaddr("/ip4/127.0.0.1/tcp/1234") + if err != nil { + t.Fatal(err) + } + pk, err := crypto.GenerateSecp256k1Key() + if err != nil { + t.Fatal(err) + } + signer := crypto.NewDefaultSigner(pk) + overlay1, err := crypto.NewOverlayAddress(pk.PublicKey, networkID, block) + if err != nil { + t.Fatal(err) + } + bzzAddr1, err := bzz.NewAddress(signer, []ma.Multiaddr{underlay1}, overlay1, networkID, nonce) + if err != nil { + t.Fatal(err) + } + if err := addressbook.Put(bzzAddr1.Overlay, *bzzAddr1); err != nil { + t.Fatal(err) + } + + // Create self address entry in addressbook + underlayClient, err := ma.NewMultiaddr("/ip4/127.0.0.1/tcp/9999") + if err != nil { + t.Fatal(err) + } + pkClient, err := crypto.GenerateSecp256k1Key() + if err != nil { + t.Fatal(err) + } + signerClient := crypto.NewDefaultSigner(pkClient) + bzzAddrClient, err := bzz.NewAddress(signerClient, []ma.Multiaddr{underlayClient}, clientAddress, networkID, nonce) + if err != nil { + t.Fatal(err) + } + if err := addressbook.Put(clientAddress, *bzzAddrClient); err != nil { + t.Fatal(err) + } + + // Setup server + streamer := streamtest.New() + server := hive.New(streamer, addressbookclean, networkID, false, true, serverAddress, logger) + testutil.CleanupCloser(t, server) + + serverRecorder := streamtest.New( + streamtest.WithProtocols(server.Protocol()), + ) + + // Setup client + client := hive.New(serverRecorder, addressbook, networkID, false, true, clientAddress, logger) + testutil.CleanupCloser(t, client) + + // Try to broadcast: peer1, clientAddress (self), and another peer + peersIncludingSelf := []swarm.Address{bzzAddr1.Overlay, clientAddress, peer1} + + err = client.BroadcastPeers(context.Background(), serverAddress, peersIncludingSelf...) + if err != nil { + t.Fatal(err) + } + + // Get records + records, err := serverRecorder.Records(serverAddress, "hive", "1.1.0", "peers") + if err != nil { + t.Fatal(err) + } + + if len(records) == 0 { + t.Fatal("expected at least one record") + } + + // Read the messages + messages, err := readAndAssertPeersMsgs(records[0].In(), 1) + if err != nil { + t.Fatal(err) + } + + // Verify that clientAddress (self) was NOT included in broadcast + for _, peerMsg := range messages[0].Peers { + receivedOverlay := swarm.NewAddress(peerMsg.Overlay) + if receivedOverlay.Equal(clientAddress) { + t.Fatal("self address should not be broadcast to peers") + } + } + + // Verify server addressbook eventually contains only the valid peers, not self + err = spinlock.Wait(spinTimeout, func() bool { + overlays, err := addressbookclean.Overlays() + if err != nil { + t.Fatal(err) + } + // Should only have bzzAddr1, not clientAddress + for _, o := range overlays { + if o.Equal(clientAddress) { + return false // self should not be in addressbook + } + } + return true + }) + if err != nil { + t.Fatal("self address found in server addressbook") + } +} + +// TestReceivePeersSkipsSelf verifies that hive does not add self address +// when receiving peer lists from other peers. +func TestReceivePeersSkipsSelf(t *testing.T) { + t.Parallel() + + logger := log.Noop + statestore := mock.NewStateStore() + addressbook := ab.New(statestore) + networkID := uint64(1) + addressbookclean := ab.New(mock.NewStateStore()) + + // Create addresses + serverAddress := swarm.RandAddress(t) + clientAddress := swarm.RandAddress(t) + + // Create a valid peer + underlay1, err := ma.NewMultiaddr("/ip4/127.0.0.1/tcp/1234") + if err != nil { + t.Fatal(err) + } + pk1, err := crypto.GenerateSecp256k1Key() + if err != nil { + t.Fatal(err) + } + signer1 := crypto.NewDefaultSigner(pk1) + overlay1, err := crypto.NewOverlayAddress(pk1.PublicKey, networkID, block) + if err != nil { + t.Fatal(err) + } + bzzAddr1, err := bzz.NewAddress(signer1, []ma.Multiaddr{underlay1}, overlay1, networkID, nonce) + if err != nil { + t.Fatal(err) + } + if err := addressbook.Put(bzzAddr1.Overlay, *bzzAddr1); err != nil { + t.Fatal(err) + } + + // Create self address entry (serverAddress) that will be sent by client + underlayServer, err := ma.NewMultiaddr("/ip4/127.0.0.1/tcp/8888") + if err != nil { + t.Fatal(err) + } + pkServer, err := crypto.GenerateSecp256k1Key() + if err != nil { + t.Fatal(err) + } + signerServer := crypto.NewDefaultSigner(pkServer) + bzzAddrServer, err := bzz.NewAddress(signerServer, []ma.Multiaddr{underlayServer}, serverAddress, networkID, nonce) + if err != nil { + t.Fatal(err) + } + // Add server's own address to client's addressbook (so client can send it) + if err := addressbook.Put(serverAddress, *bzzAddrServer); err != nil { + t.Fatal(err) + } + + // Setup server that will receive peers including its own address + streamer := streamtest.New() + server := hive.New(streamer, addressbookclean, networkID, false, true, serverAddress, logger) + testutil.CleanupCloser(t, server) + + serverRecorder := streamtest.New( + streamtest.WithProtocols(server.Protocol()), + ) + + // Setup client + client := hive.New(serverRecorder, addressbook, networkID, false, true, clientAddress, logger) + testutil.CleanupCloser(t, client) + + // Client broadcasts: valid peer and server's own address + peersIncludingSelf := []swarm.Address{bzzAddr1.Overlay, serverAddress} + + err = client.BroadcastPeers(context.Background(), serverAddress, peersIncludingSelf...) + if err != nil { + t.Fatal(err) + } + + // Wait a bit for server to process + time.Sleep(100 * time.Millisecond) + + // Verify server's addressbook does NOT contain its own address + overlays, err := addressbookclean.Overlays() + if err != nil { + t.Fatal(err) + } + + for _, o := range overlays { + if o.Equal(serverAddress) { + t.Fatal("server should not add its own address to addressbook when received from peer") + } + } + + // Verify server does have the valid peer + _, err = addressbookclean.Get(bzzAddr1.Overlay) + if err != nil { + t.Fatalf("expected server to have valid peer in addressbook, got error: %v", err) + } +} diff --git a/pkg/p2p/libp2p/connections_test.go b/pkg/p2p/libp2p/connections_test.go index ce1e14a4e15..27ba4b7549d 100644 --- a/pkg/p2p/libp2p/connections_test.go +++ b/pkg/p2p/libp2p/connections_test.go @@ -88,6 +88,42 @@ func TestConnectDisconnect(t *testing.T) { expectPeersEventually(t, s1) } +// TestConnectSelf verifies that a service cannot connect to itself, +// preventing self-connection attempts. +func TestConnectSelf(t *testing.T) { + t.Parallel() + + ctx := t.Context() + + s1, _ := newService(t, 1, libp2pServiceOpts{libp2pOpts: libp2p.Options{ + FullNode: true, + }}) + + // Get own underlay addresses + addr := serviceUnderlayAddress(t, s1) + + // Attempt to connect to self + bzzAddr, err := s1.Connect(ctx, addr) + + // Should return an error + if err == nil { + t.Fatal("expected error when connecting to self, got nil") + } + + // Should contain "cannot connect to self" in error message + if !strings.Contains(err.Error(), "cannot connect to self") { + t.Fatalf("expected 'cannot connect to self' error, got: %v", err) + } + + // bzzAddr should be nil + if bzzAddr != nil { + t.Fatal("expected nil bzz address when connecting to self") + } + + // Verify no peers are connected + expectPeers(t, s1) +} + func TestConnectToLightPeer(t *testing.T) { t.Parallel() diff --git a/pkg/topology/kademlia/kademlia_test.go b/pkg/topology/kademlia/kademlia_test.go index 4d534ddade8..6750ebe2284 100644 --- a/pkg/topology/kademlia/kademlia_test.go +++ b/pkg/topology/kademlia/kademlia_test.go @@ -2253,3 +2253,72 @@ func generateMultipleUnderlays(t *testing.T, n int, baseUnderlay string) []ma.Mu } return underlays } + +// TestAddPeersSkipsSelf verifies that AddPeers does not add self address +// to the known peers list, preventing self-connection attempts. +func TestAddPeersSkipsSelf(t *testing.T) { + t.Parallel() + + var ( + conns int32 + base, kad, ab, _, signer = newTestKademlia(t, &conns, nil, kademlia.Options{ + ExcludeFunc: defaultExcludeFunc, + }) + ) + + if err := kad.Start(context.Background()); err != nil { + t.Fatal(err) + } + testutil.CleanupCloser(t, kad) + + // Add some regular peers first + peer1 := swarm.RandAddressAt(t, base, 1) + peer2 := swarm.RandAddressAt(t, base, 2) + + addOne(t, signer, kad, ab, peer1) + addOne(t, signer, kad, ab, peer2) + + waitCounter(t, &conns, 2) + + // Now try to add self address along with another peer + peer3 := swarm.RandAddressAt(t, base, 3) + + // Prepare address for peer3 + multiaddr, err := ma.NewMultiaddr(underlayBase + peer3.String()) + if err != nil { + t.Fatal(err) + } + bzzAddr, err := bzz.NewAddress(signer, []ma.Multiaddr{multiaddr}, peer3, 0, nil) + if err != nil { + t.Fatal(err) + } + if err := ab.Put(peer3, *bzzAddr); err != nil { + t.Fatal(err) + } + + // Try to add self (base) and peer3 together + kad.AddPeers(base, peer3) + + // Only peer3 should result in a connection attempt, not base + waitCounter(t, &conns, 1) + + // Verify we have exactly 3 connected peers (peer1, peer2, peer3), not 4 + waitPeers(t, kad, 3) + + // Verify base is not in the connected peers list + foundSelf := false + err = kad.EachConnectedPeer(func(addr swarm.Address, _ uint8) (bool, bool, error) { + if addr.Equal(base) { + foundSelf = true + return true, false, nil + } + return false, false, nil + }, topology.Select{}) + if err != nil { + t.Fatal(err) + } + + if foundSelf { + t.Fatal("self address should not be in connected peers") + } +} From 96e799ed952d5f347ee49327f334835d68599903 Mon Sep 17 00:00:00 2001 From: Ljubisa Gacevic Date: Mon, 22 Dec 2025 17:48:07 +0100 Subject: [PATCH 18/24] fix(libp2p): call Disconnect if host not connected --- .gitignore | 1 + go.mod | 2 +- go.sum | 4 ++-- pkg/p2p/libp2p/libp2p.go | 13 +++++++++++++ 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index b7b0629ab25..c94f81d64ab 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ /.idea /.vscode /tmp +/vendor # Compiled Object files, Static and Dynamic libs (Shared Objects) *.o diff --git a/go.mod b/go.mod index 604bec0dee7..d2134aa7286 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/ethereum/go-ethereum v1.15.11 github.com/ethersphere/batch-archive v0.0.4 github.com/ethersphere/go-price-oracle-abi v0.6.9 - github.com/ethersphere/go-storage-incentives-abi v0.9.4 + github.com/ethersphere/go-storage-incentives-abi v0.9.3-rc4 github.com/ethersphere/go-sw3-abi v0.6.9 github.com/ethersphere/langos v1.0.0 github.com/go-playground/validator/v10 v10.19.0 diff --git a/go.sum b/go.sum index 7b0f87f302a..a9cebe94046 100644 --- a/go.sum +++ b/go.sum @@ -240,8 +240,8 @@ github.com/ethersphere/batch-archive v0.0.4 h1:PHmwQfmUEyDJgoX2IqI/R0alQ63+aLPXf github.com/ethersphere/batch-archive v0.0.4/go.mod h1:41BPb192NoK9CYjNB8BAE1J2MtiI/5aq0Wtas5O7A7Q= github.com/ethersphere/go-price-oracle-abi v0.6.9 h1:bseen6he3PZv5GHOm+KD6s4awaFmVSD9LFx+HpB6rCU= github.com/ethersphere/go-price-oracle-abi v0.6.9/go.mod h1:sI/Qj4/zJ23/b1enzwMMv0/hLTpPNVNacEwCWjo6yBk= -github.com/ethersphere/go-storage-incentives-abi v0.9.4 h1:mSIWXQXg5OQmH10QvXMV5w0vbSibFMaRlBL37gPLTM0= -github.com/ethersphere/go-storage-incentives-abi v0.9.4/go.mod h1:SXvJVtM4sEsaSKD0jc1ClpDLw8ErPoROZDme4Wrc/Nc= +github.com/ethersphere/go-storage-incentives-abi v0.9.3-rc4 h1:YK9FpiQz29ctU5V46CuwMt+4X5Xn8FTBwy6E2v/ix8s= +github.com/ethersphere/go-storage-incentives-abi v0.9.3-rc4/go.mod h1:SXvJVtM4sEsaSKD0jc1ClpDLw8ErPoROZDme4Wrc/Nc= github.com/ethersphere/go-sw3-abi v0.6.9 h1:TnWLnYkWE5UvC17mQBdUmdkzhPhO8GcqvWy4wvd1QJQ= github.com/ethersphere/go-sw3-abi v0.6.9/go.mod h1:BmpsvJ8idQZdYEtWnvxA8POYQ8Rl/NhyCdF0zLMOOJU= github.com/ethersphere/langos v1.0.0 h1:NBtNKzXTTRSue95uOlzPN4py7Aofs0xWPzyj4AI1Vcc= diff --git a/pkg/p2p/libp2p/libp2p.go b/pkg/p2p/libp2p/libp2p.go index 06d4896c32e..ff2e143a9b2 100644 --- a/pkg/p2p/libp2p/libp2p.go +++ b/pkg/p2p/libp2p/libp2p.go @@ -239,6 +239,8 @@ func New(ctx context.Context, signer beecrypto.Signer, networkID uint64, overlay return nil, err } + // TODO: Example of using a custom rate limiter: + // rcmgr.WithConnRateLimiters(&libp2prate.Limiter{}) rm, err := rcmgr.NewResourceManager(limiter, rcmgr.WithTraceReporter(str)) if err != nil { return nil, err @@ -1219,6 +1221,12 @@ func (s *Service) NewStream(ctx context.Context, overlay swarm.Address, headers return nil, p2p.ErrPeerNotFound } + // Verify if we really have an active connection + if s.host.Network().Connectedness(peerID) != network.Connected { + _ = s.Disconnect(overlay, "registry-host mismatch in NewStream") + return nil, p2p.ErrPeerNotFound + } + streamlibp2p, err := s.newStreamForPeerID(ctx, peerID, protocolName, protocolVersion, streamName) if err != nil { return nil, fmt.Errorf("new stream for peerid: %w", err) @@ -1248,6 +1256,11 @@ func (s *Service) NewStream(ctx context.Context, overlay swarm.Address, headers func (s *Service) newStreamForPeerID(ctx context.Context, peerID libp2ppeer.ID, protocolName, protocolVersion, streamName string) (network.Stream, error) { swarmStreamName := p2p.NewSwarmStreamName(protocolName, protocolVersion, streamName) + + if s.host.Network().Connectedness(peerID) != network.Connected { + s.logger.Debug("newStreamForPeerID: host not connected to peer, this will trigger a dial", "peer_id", peerID, "protocol", swarmStreamName) + } + st, err := s.host.NewStream(ctx, peerID, protocol.ID(swarmStreamName)) if err != nil { if st != nil { From 74b8299afafd2b648622000a03061e6ad66e9134 Mon Sep 17 00:00:00 2001 From: Ljubisa Gacevic Date: Mon, 22 Dec 2025 18:14:05 +0100 Subject: [PATCH 19/24] fix(libp2p): increase limit per ip connections --- pkg/p2p/libp2p/libp2p.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pkg/p2p/libp2p/libp2p.go b/pkg/p2p/libp2p/libp2p.go index ff2e143a9b2..baaefa817ee 100644 --- a/pkg/p2p/libp2p/libp2p.go +++ b/pkg/p2p/libp2p/libp2p.go @@ -239,9 +239,14 @@ func New(ctx context.Context, signer beecrypto.Signer, networkID uint64, overlay return nil, err } + limitPerIp := rcmgr.WithLimitPerSubnet( + []rcmgr.ConnLimitPerSubnet{{PrefixLength: 32, ConnCount: 200}}, // IPv4 /32 (Single IP) -> 200 conns + []rcmgr.ConnLimitPerSubnet{{PrefixLength: 56, ConnCount: 200}}, // IPv6 /56 subnet -> 200 conns + ) + // TODO: Example of using a custom rate limiter: // rcmgr.WithConnRateLimiters(&libp2prate.Limiter{}) - rm, err := rcmgr.NewResourceManager(limiter, rcmgr.WithTraceReporter(str)) + rm, err := rcmgr.NewResourceManager(limiter, rcmgr.WithTraceReporter(str), limitPerIp) if err != nil { return nil, err } From c2012b9fbebe587287d8b9f9a6c5064898f5f58a Mon Sep 17 00:00:00 2001 From: Ljubisa Gacevic Date: Tue, 23 Dec 2025 15:09:16 +0100 Subject: [PATCH 20/24] fix(libp2p): use custom rate limiter --- pkg/p2p/libp2p/libp2p.go | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/pkg/p2p/libp2p/libp2p.go b/pkg/p2p/libp2p/libp2p.go index baaefa817ee..31eed83d2a9 100644 --- a/pkg/p2p/libp2p/libp2p.go +++ b/pkg/p2p/libp2p/libp2p.go @@ -11,6 +11,7 @@ import ( "errors" "fmt" "net" + "net/netip" "os" "path/filepath" "runtime" @@ -57,6 +58,7 @@ import ( libp2pping "github.com/libp2p/go-libp2p/p2p/protocol/ping" "github.com/libp2p/go-libp2p/p2p/transport/tcp" ws "github.com/libp2p/go-libp2p/p2p/transport/websocket" + libp2prate "github.com/libp2p/go-libp2p/x/rate" ma "github.com/multiformats/go-multiaddr" manet "github.com/multiformats/go-multiaddr/net" "github.com/multiformats/go-multistream" @@ -244,9 +246,35 @@ func New(ctx context.Context, signer beecrypto.Signer, networkID uint64, overlay []rcmgr.ConnLimitPerSubnet{{PrefixLength: 56, ConnCount: 200}}, // IPv6 /56 subnet -> 200 conns ) - // TODO: Example of using a custom rate limiter: - // rcmgr.WithConnRateLimiters(&libp2prate.Limiter{}) - rm, err := rcmgr.NewResourceManager(limiter, rcmgr.WithTraceReporter(str), limitPerIp) + // Custom rate limiter for connection attempts + // 20 peers cluster adaptation: + // Allow bursts of connection attempts (e.g. restart) but prevent DDOS. + connLimiter := &libp2prate.Limiter{ + // Allow unlimited local connections (same as default) + NetworkPrefixLimits: []libp2prate.PrefixLimit{ + {Prefix: netip.MustParsePrefix("127.0.0.0/8"), Limit: libp2prate.Limit{}}, + {Prefix: netip.MustParsePrefix("::1/128"), Limit: libp2prate.Limit{}}, + }, + GlobalLimit: libp2prate.Limit{}, // Unlimited global + SubnetRateLimiter: libp2prate.SubnetLimiter{ + IPv4SubnetLimits: []libp2prate.SubnetLimit{ + { + PrefixLength: 32, // Per IP + // Allow 10 connection attempts per second per IP, burst up to 40 + Limit: libp2prate.Limit{RPS: 10.0, Burst: 40}, + }, + }, + IPv6SubnetLimits: []libp2prate.SubnetLimit{ + { + PrefixLength: 56, // Per Subnet + Limit: libp2prate.Limit{RPS: 10.0, Burst: 40}, + }, + }, + GracePeriod: 10 * time.Second, + }, + } + + rm, err := rcmgr.NewResourceManager(limiter, rcmgr.WithTraceReporter(str), limitPerIp, rcmgr.WithConnRateLimiters(connLimiter)) if err != nil { return nil, err } @@ -645,7 +673,7 @@ func (s *Service) handleIncoming(stream network.Stream) { s.logger.Debug("stream handler: blocklisting: exists failed", "peer_address", overlay, "error", err) s.logger.Error(nil, "stream handler: internal error while connecting with peer", "peer_address", overlay) _ = handshakeStream.Reset() - _ = s.host.Network().ClosePeer(peerID) + _ = stream.Conn().Close() return } @@ -661,7 +689,7 @@ func (s *Service) handleIncoming(stream network.Stream) { if err = handshakeStream.FullClose(); err != nil { s.logger.Debug("stream handler: could not close stream", "peer_address", overlay, "error", err) s.logger.Error(nil, "stream handler: unable to handshake with peer", "peer_address", overlay) - _ = s.Disconnect(overlay, "unable to close handshake stream") + _ = stream.Conn().Close() } return } From 9a4660ec3593466f4992e1c6e3623552878abe33 Mon Sep 17 00:00:00 2001 From: Ljubisa Gacevic Date: Wed, 24 Dec 2025 18:17:22 +0100 Subject: [PATCH 21/24] fix(libp2p): close only failing connection on handshake error --- pkg/p2p/libp2p/libp2p.go | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/pkg/p2p/libp2p/libp2p.go b/pkg/p2p/libp2p/libp2p.go index 31eed83d2a9..f01d9fe6837 100644 --- a/pkg/p2p/libp2p/libp2p.go +++ b/pkg/p2p/libp2p/libp2p.go @@ -648,7 +648,7 @@ func (s *Service) handleIncoming(stream network.Stream) { s.logger.Debug("stream handler: handshake: build remote multiaddrs", "peer_id", peerID, "error", err) s.logger.Error(nil, "stream handler: handshake: build remote multiaddrs", "peer_id", peerID) _ = handshakeStream.Reset() - _ = s.host.Network().ClosePeer(peerID) + _ = stream.Conn().Close() return } @@ -662,7 +662,7 @@ func (s *Service) handleIncoming(stream network.Stream) { s.logger.Debug("stream handler: handshake: handle failed", "peer_id", peerID, "error", err) s.logger.Error(nil, "stream handler: handshake: handle failed", "peer_id", peerID) _ = handshakeStream.Reset() - _ = s.host.Network().ClosePeer(peerID) + _ = stream.Conn().Close() return } @@ -1063,7 +1063,7 @@ func (s *Service) Connect(ctx context.Context, addrs []ma.Multiaddr) (address *b peerMultiaddrs, err := s.peerMultiaddrs(ctx, peerID) if err != nil { _ = handshakeStream.Reset() - _ = s.host.Network().ClosePeer(peerID) + _ = stream.Conn().Close() return nil, fmt.Errorf("build peer multiaddrs: %w", err) } @@ -1075,13 +1075,13 @@ func (s *Service) Connect(ctx context.Context, addrs []ma.Multiaddr) (address *b ) if err != nil { _ = handshakeStream.Reset() - _ = s.host.Network().ClosePeer(info.ID) + _ = stream.Conn().Close() return nil, fmt.Errorf("handshake: %w", err) } if !i.FullNode { _ = handshakeStream.Reset() - _ = s.host.Network().ClosePeer(info.ID) + _ = stream.Conn().Close() return nil, p2p.ErrDialLightNode } @@ -1092,7 +1092,7 @@ func (s *Service) Connect(ctx context.Context, addrs []ma.Multiaddr) (address *b s.logger.Debug("blocklisting: exists failed", "peer_id", info.ID, "error", err) s.logger.Error(nil, "internal error while connecting with peer", "peer_id", info.ID) _ = handshakeStream.Reset() - _ = s.host.Network().ClosePeer(info.ID) + _ = stream.Conn().Close() return nil, err } @@ -1105,7 +1105,8 @@ func (s *Service) Connect(ctx context.Context, addrs []ma.Multiaddr) (address *b if exists := s.peers.addIfNotExists(stream.Conn(), overlay, i.FullNode); exists { if err := handshakeStream.FullClose(); err != nil { - _ = s.Disconnect(overlay, "failed closing handshake stream after connect") + // Only close the new (duplicate) connection; keep existing healthy sessions intact. + _ = stream.Conn().Close() return nil, fmt.Errorf("peer exists, full close: %w", err) } From a7892f654b4115d456cb5155f934734d058eba67 Mon Sep 17 00:00:00 2001 From: Ljubisa Gacevic Date: Wed, 24 Dec 2025 19:41:28 +0100 Subject: [PATCH 22/24] fix(libp2p): always enable websocket transport for dialing --- pkg/p2p/libp2p/libp2p.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/p2p/libp2p/libp2p.go b/pkg/p2p/libp2p/libp2p.go index f01d9fe6837..5081e70cef1 100644 --- a/pkg/p2p/libp2p/libp2p.go +++ b/pkg/p2p/libp2p/libp2p.go @@ -426,7 +426,7 @@ func New(ctx context.Context, signer beecrypto.Signer, networkID uint64, overlay if o.EnableWSS { wsOpt := ws.WithTLSConfig(certManager.TLSConfig()) transports = append(transports, libp2p.Transport(ws.New, wsOpt)) - } else if o.EnableWS { + } else { transports = append(transports, libp2p.Transport(ws.New)) } From 9bfbf8e14b59fb3899f238cdb1b9e53a4feda951 Mon Sep 17 00:00:00 2001 From: Ljubisa Gacevic Date: Mon, 29 Dec 2025 11:37:20 +0100 Subject: [PATCH 23/24] Revert "fix(libp2p): close only failing connection on handshake error" This reverts commit 9a4660ec3593466f4992e1c6e3623552878abe33. --- pkg/p2p/libp2p/libp2p.go | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/pkg/p2p/libp2p/libp2p.go b/pkg/p2p/libp2p/libp2p.go index 5081e70cef1..419cc33642f 100644 --- a/pkg/p2p/libp2p/libp2p.go +++ b/pkg/p2p/libp2p/libp2p.go @@ -648,7 +648,7 @@ func (s *Service) handleIncoming(stream network.Stream) { s.logger.Debug("stream handler: handshake: build remote multiaddrs", "peer_id", peerID, "error", err) s.logger.Error(nil, "stream handler: handshake: build remote multiaddrs", "peer_id", peerID) _ = handshakeStream.Reset() - _ = stream.Conn().Close() + _ = s.host.Network().ClosePeer(peerID) return } @@ -662,7 +662,7 @@ func (s *Service) handleIncoming(stream network.Stream) { s.logger.Debug("stream handler: handshake: handle failed", "peer_id", peerID, "error", err) s.logger.Error(nil, "stream handler: handshake: handle failed", "peer_id", peerID) _ = handshakeStream.Reset() - _ = stream.Conn().Close() + _ = s.host.Network().ClosePeer(peerID) return } @@ -1063,7 +1063,7 @@ func (s *Service) Connect(ctx context.Context, addrs []ma.Multiaddr) (address *b peerMultiaddrs, err := s.peerMultiaddrs(ctx, peerID) if err != nil { _ = handshakeStream.Reset() - _ = stream.Conn().Close() + _ = s.host.Network().ClosePeer(peerID) return nil, fmt.Errorf("build peer multiaddrs: %w", err) } @@ -1075,13 +1075,13 @@ func (s *Service) Connect(ctx context.Context, addrs []ma.Multiaddr) (address *b ) if err != nil { _ = handshakeStream.Reset() - _ = stream.Conn().Close() + _ = s.host.Network().ClosePeer(info.ID) return nil, fmt.Errorf("handshake: %w", err) } if !i.FullNode { _ = handshakeStream.Reset() - _ = stream.Conn().Close() + _ = s.host.Network().ClosePeer(info.ID) return nil, p2p.ErrDialLightNode } @@ -1092,7 +1092,7 @@ func (s *Service) Connect(ctx context.Context, addrs []ma.Multiaddr) (address *b s.logger.Debug("blocklisting: exists failed", "peer_id", info.ID, "error", err) s.logger.Error(nil, "internal error while connecting with peer", "peer_id", info.ID) _ = handshakeStream.Reset() - _ = stream.Conn().Close() + _ = s.host.Network().ClosePeer(info.ID) return nil, err } @@ -1105,8 +1105,7 @@ func (s *Service) Connect(ctx context.Context, addrs []ma.Multiaddr) (address *b if exists := s.peers.addIfNotExists(stream.Conn(), overlay, i.FullNode); exists { if err := handshakeStream.FullClose(); err != nil { - // Only close the new (duplicate) connection; keep existing healthy sessions intact. - _ = stream.Conn().Close() + _ = s.Disconnect(overlay, "failed closing handshake stream after connect") return nil, fmt.Errorf("peer exists, full close: %w", err) } From 4c2c2328273e3bbd90ebfe18361a91d015005017 Mon Sep 17 00:00:00 2001 From: Ljubisa Gacevic Date: Thu, 1 Jan 2026 11:59:50 +0100 Subject: [PATCH 24/24] fix(libp2p): enable websocket transport for dialing only when ws-enabled --- pkg/p2p/libp2p/libp2p.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/p2p/libp2p/libp2p.go b/pkg/p2p/libp2p/libp2p.go index 419cc33642f..31eed83d2a9 100644 --- a/pkg/p2p/libp2p/libp2p.go +++ b/pkg/p2p/libp2p/libp2p.go @@ -426,7 +426,7 @@ func New(ctx context.Context, signer beecrypto.Signer, networkID uint64, overlay if o.EnableWSS { wsOpt := ws.WithTLSConfig(certManager.TLSConfig()) transports = append(transports, libp2p.Transport(ws.New, wsOpt)) - } else { + } else if o.EnableWS { transports = append(transports, libp2p.Transport(ws.New)) }