Skip to content

Commit f05a92c

Browse files
committed
swarm: move AddCertHashes to swarm
1 parent 7b7c3ed commit f05a92c

File tree

5 files changed

+111
-60
lines changed

5 files changed

+111
-60
lines changed

p2p/host/basic/addrs_manager.go

Lines changed: 3 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,8 @@ import (
1212

1313
"github.com/libp2p/go-libp2p/core/event"
1414
"github.com/libp2p/go-libp2p/core/network"
15-
"github.com/libp2p/go-libp2p/core/transport"
1615
"github.com/libp2p/go-libp2p/p2p/host/basic/internal/backoff"
1716
"github.com/libp2p/go-libp2p/p2p/host/eventbus"
18-
libp2pwebrtc "github.com/libp2p/go-libp2p/p2p/transport/webrtc"
19-
libp2pwebtransport "github.com/libp2p/go-libp2p/p2p/transport/webtransport"
2017
"github.com/libp2p/go-netroute"
2118
ma "github.com/multiformats/go-multiaddr"
2219
manet "github.com/multiformats/go-multiaddr/net"
@@ -44,7 +41,7 @@ type addrsManager struct {
4441
natManager NATManager
4542
addrsFactory AddrsFactory
4643
listenAddrs func() []ma.Multiaddr
47-
transportForListening func(ma.Multiaddr) transport.Transport
44+
addCertHashes func([]ma.Multiaddr) []ma.Multiaddr
4845
observedAddrsManager observedAddrsManager
4946
interfaceAddrs *interfaceAddrsCache
5047
addrsReachabilityTracker *addrsReachabilityTracker
@@ -72,7 +69,7 @@ func newAddrsManager(
7269
natmgr NATManager,
7370
addrsFactory AddrsFactory,
7471
listenAddrs func() []ma.Multiaddr,
75-
transportForListening func(ma.Multiaddr) transport.Transport,
72+
addCertHashes func([]ma.Multiaddr) []ma.Multiaddr,
7673
observedAddrsManager observedAddrsManager,
7774
addrsUpdatedChan chan struct{},
7875
client autonatv2Client,
@@ -83,7 +80,7 @@ func newAddrsManager(
8380
as := &addrsManager{
8481
bus: bus,
8582
listenAddrs: listenAddrs,
86-
transportForListening: transportForListening,
83+
addCertHashes: addCertHashes,
8784
observedAddrsManager: observedAddrsManager,
8885
natManager: natmgr,
8986
addrsFactory: addrsFactory,
@@ -504,51 +501,6 @@ func (a *addrsManager) appendObservedAddrs(dst []ma.Multiaddr, listenAddr ma.Mul
504501
return dst
505502
}
506503

507-
func (a *addrsManager) addCertHashes(addrs []ma.Multiaddr) []ma.Multiaddr {
508-
if a.transportForListening == nil {
509-
return addrs
510-
}
511-
512-
// TODO(sukunrt): Move this to swarm.
513-
// There are two parts to determining our external address
514-
// 1. From the NAT device, or identify, or other such STUN like mechanism.
515-
// All that matters here is (internal_ip, internal_port, tcp) => (external_ip, external_port, tcp)
516-
// The rest of the address should be cut and appended to the external one.
517-
// 2. The user provides us with the address (/ip4/1.2.3.4/udp/1/webrtc-direct) and we add the certhash.
518-
// This API should be where the transports are, i.e. swarm.
519-
//
520-
// It would have been nice to remove this completely and just work with
521-
// mapping the interface thinwaist addresses (tcp, 192.168.18.18:4000 => 1.2.3.4:4577)
522-
// but that is only convenient if we're using the same port for listening on
523-
// all transports which share the same thinwaist protocol. If you listen
524-
// on 4001 for tcp, and 4002 for websocket, then it's a terrible API.
525-
type addCertHasher interface {
526-
AddCertHashes(m ma.Multiaddr) (ma.Multiaddr, bool)
527-
}
528-
529-
for i, addr := range addrs {
530-
wtOK, wtN := libp2pwebtransport.IsWebtransportMultiaddr(addr)
531-
webrtcOK, webrtcN := libp2pwebrtc.IsWebRTCDirectMultiaddr(addr)
532-
if (wtOK && wtN == 0) || (webrtcOK && webrtcN == 0) {
533-
t := a.transportForListening(addr)
534-
if t == nil {
535-
continue
536-
}
537-
tpt, ok := t.(addCertHasher)
538-
if !ok {
539-
continue
540-
}
541-
addrWithCerthash, added := tpt.AddCertHashes(addr)
542-
if !added {
543-
log.Warnf("Couldn't add certhashes to multiaddr: %s", addr)
544-
continue
545-
}
546-
addrs[i] = addrWithCerthash
547-
}
548-
}
549-
return addrs
550-
}
551-
552504
func areAddrsDifferent(prev, current []ma.Multiaddr) bool {
553505
// TODO: make the sorted nature of ma.Unique a guarantee in multiaddrs
554506
prev = ma.Unique(prev)

p2p/host/basic/addrs_manager_test.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ type addrsManagerArgs struct {
175175
AddrsFactory AddrsFactory
176176
ObservedAddrsManager observedAddrsManager
177177
ListenAddrs func() []ma.Multiaddr
178+
AddCertHashes func([]ma.Multiaddr) []ma.Multiaddr
178179
AutoNATClient autonatv2Client
179180
Bus event.Bus
180181
}
@@ -194,8 +195,15 @@ func newAddrsManagerTestCase(t *testing.T, args addrsManagerArgs) addrsManagerTe
194195
args.AddrsFactory = func(addrs []ma.Multiaddr) []ma.Multiaddr { return addrs }
195196
}
196197
addrsUpdatedChan := make(chan struct{}, 1)
198+
199+
addCertHashes := func(addrs []ma.Multiaddr) []ma.Multiaddr {
200+
return addrs
201+
}
202+
if args.AddCertHashes != nil {
203+
addCertHashes = args.AddCertHashes
204+
}
197205
am, err := newAddrsManager(
198-
eb, args.NATManager, args.AddrsFactory, args.ListenAddrs, nil, args.ObservedAddrsManager, addrsUpdatedChan, args.AutoNATClient, true, prometheus.DefaultRegisterer,
206+
eb, args.NATManager, args.AddrsFactory, args.ListenAddrs, addCertHashes, args.ObservedAddrsManager, addrsUpdatedChan, args.AutoNATClient, true, prometheus.DefaultRegisterer,
199207
)
200208
require.NoError(t, err)
201209

p2p/host/basic/basic_host.go

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import (
1818
"github.com/libp2p/go-libp2p/core/peerstore"
1919
"github.com/libp2p/go-libp2p/core/protocol"
2020
"github.com/libp2p/go-libp2p/core/record"
21-
"github.com/libp2p/go-libp2p/core/transport"
2221
"github.com/libp2p/go-libp2p/p2p/host/autonat"
2322
"github.com/libp2p/go-libp2p/p2p/host/eventbus"
2423
"github.com/libp2p/go-libp2p/p2p/host/pstoremanager"
@@ -232,12 +231,6 @@ func NewHost(n network.Network, opts *HostOpts) (*BasicHost, error) {
232231
if opts.NATManager != nil {
233232
natmgr = opts.NATManager(h.Network())
234233
}
235-
var tfl func(ma.Multiaddr) transport.Transport
236-
if s, ok := h.Network().(interface {
237-
TransportForListening(ma.Multiaddr) transport.Transport
238-
}); ok {
239-
tfl = s.TransportForListening
240-
}
241234

242235
if opts.AutoNATv2 != nil {
243236
h.autonatv2 = opts.AutoNATv2
@@ -247,12 +240,23 @@ func NewHost(n network.Network, opts *HostOpts) (*BasicHost, error) {
247240
if h.autonatv2 != nil {
248241
autonatv2Client = h.autonatv2
249242
}
243+
244+
// Create addCertHashes function with interface assertion for swarm
245+
addCertHashesFunc := func(addrs []ma.Multiaddr) []ma.Multiaddr {
246+
return addrs
247+
}
248+
if swarm, ok := h.Network().(interface {
249+
AddCertHashes(addrs []ma.Multiaddr) []ma.Multiaddr
250+
}); ok {
251+
addCertHashesFunc = swarm.AddCertHashes
252+
}
253+
250254
h.addressManager, err = newAddrsManager(
251255
h.eventbus,
252256
natmgr,
253257
addrFactory,
254258
h.Network().ListenAddresses,
255-
tfl,
259+
addCertHashesFunc,
256260
h.ids,
257261
h.addrsUpdatedChan,
258262
autonatv2Client,

p2p/net/swarm/swarm.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -961,3 +961,31 @@ func (r ResolverFromMaDNS) ResolveDNSComponent(ctx context.Context, maddr ma.Mul
961961
}
962962
return addrs, nil
963963
}
964+
965+
// AddCertHashes adds certificate hashes to relevant transport addresses, if there
966+
// are no certhashes already present on the method. It mutates `listenAddrs`.
967+
// This method is useful for adding certhashes to public addresses discovered
968+
// via identify, nat mapping, or provided by the user.
969+
func (s *Swarm) AddCertHashes(listenAddrs []ma.Multiaddr) []ma.Multiaddr {
970+
type addCertHasher interface {
971+
AddCertHashes(m ma.Multiaddr) (ma.Multiaddr, bool)
972+
}
973+
974+
for i, addr := range listenAddrs {
975+
t := s.TransportForListening(addr)
976+
if t == nil {
977+
continue
978+
}
979+
tpt, ok := t.(addCertHasher)
980+
if !ok {
981+
continue
982+
}
983+
addrWithCerthash, added := tpt.AddCertHashes(addr)
984+
if !added {
985+
log.Warnf("Couldn't add certhashes to multiaddr: %s", addr)
986+
continue
987+
}
988+
listenAddrs[i] = addrWithCerthash
989+
}
990+
return listenAddrs
991+
}

p2p/net/swarm/swarm_test.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"errors"
77
"fmt"
88
"io"
9+
"slices"
910
"strings"
1011
"sync"
1112
"testing"
@@ -567,3 +568,61 @@ func TestListenCloseCount(t *testing.T) {
567568
_, err := remainingAddrs[0].ValueForProtocol(ma.P_TCP)
568569
require.NoError(t, err, "expected the TCP address to still be present")
569570
}
571+
572+
func TestAddCertHashes(t *testing.T) {
573+
s := GenSwarm(t)
574+
575+
listenAddrs := s.ListenAddresses()
576+
splitCertHashes := func(a ma.Multiaddr) (prefix, certhashes ma.Multiaddr, ok bool) {
577+
for i, c := range a {
578+
if c.Protocol().Code == ma.P_CERTHASH {
579+
return prefix, a[i:], true
580+
}
581+
prefix = append(prefix, c)
582+
}
583+
return prefix, certhashes, false
584+
}
585+
addrWithNewIPPort := func(addr ma.Multiaddr, newIPPort ma.Multiaddr) ma.Multiaddr {
586+
a := slices.Clone(addr)
587+
a[0] = newIPPort[0]
588+
a[1] = newIPPort[1]
589+
return a
590+
}
591+
publicIPPort := []ma.Multiaddr{
592+
ma.StringCast("/ip4/1.1.1.1/udp/1"),
593+
ma.StringCast("/ip4/1.2.3.4/udp/1"),
594+
ma.StringCast("/ip6/2005::/udp/1"),
595+
}
596+
597+
certHashComponent := ma.StringCast("/certhash/uEgNmb28")
598+
for _, a := range listenAddrs {
599+
prefix, certhashes, ok := splitCertHashes(a)
600+
if !ok {
601+
continue
602+
}
603+
var publicAddrs []ma.Multiaddr
604+
for _, tc := range publicIPPort {
605+
publicAddrs = append(publicAddrs, addrWithNewIPPort(prefix, tc))
606+
}
607+
finalAddrs := s.AddCertHashes(publicAddrs)
608+
for _, a := range finalAddrs {
609+
_, certhash2, ok := splitCertHashes(a)
610+
require.True(t, ok)
611+
require.Equal(t, certhashes, certhash2)
612+
}
613+
614+
// if the addr has a certhash already, check it isn't modified
615+
publicAddrs = nil
616+
for _, tc := range publicIPPort {
617+
a := addrWithNewIPPort(prefix, tc)
618+
a = append(a, certHashComponent...)
619+
publicAddrs = append(publicAddrs, a)
620+
}
621+
finalAddrs = s.AddCertHashes(publicAddrs)
622+
for _, a := range finalAddrs {
623+
_, certhash2, ok := splitCertHashes(a)
624+
require.True(t, ok)
625+
require.Equal(t, certHashComponent, certhash2)
626+
}
627+
}
628+
}

0 commit comments

Comments
 (0)