Skip to content

Commit ecab374

Browse files
committed
add method UpdateHostAddrs to peerstore
1 parent 4fb69b6 commit ecab374

File tree

7 files changed

+106
-88
lines changed

7 files changed

+106
-88
lines changed

core/peerstore/peerstore.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ type Peerstore interface {
7070
// RemovePeer removes all the peer related information except its addresses. To remove the
7171
// addresses use `AddrBook.ClearAddrs` or set the address ttls to 0.
7272
RemovePeer(peer.ID)
73+
74+
// UpdateHostAddrs updates the addresses of the host in the peerstore. It also adds the signed
75+
// peer record for the host if there's a private key available for the host in the KeyBook.
76+
// This method should only be used to update the addresses of the Host that owns the peerstore.
77+
UpdateHostAddrs(hostID peer.ID, currentAddrs, removedAddrs, peerRecordAddrs []ma.Multiaddr) error
7378
}
7479

7580
// PeerMetadata can handle values of any type. Serializing values is

p2p/host/basic/addrs_manager.go

Lines changed: 14 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import (
1111
"sync/atomic"
1212
"time"
1313

14-
"github.com/libp2p/go-libp2p/core/crypto"
1514
"github.com/libp2p/go-libp2p/core/event"
1615
"github.com/libp2p/go-libp2p/core/network"
1716
"github.com/libp2p/go-libp2p/core/peer"
@@ -32,11 +31,6 @@ var addrChangeTickrInterval = 5 * time.Second
3231

3332
const maxPeerRecordSize = 8 * 1024 // 8k to be compatible with identify's limit
3433

35-
// addrStore is a minimal interface for storing peer addresses
36-
type addrStore interface {
37-
SetAddrs(peer.ID, []ma.Multiaddr, time.Duration)
38-
}
39-
4034
// ObservedAddrsManager maps our local listen addrs to externally observed addrs.
4135
type ObservedAddrsManager interface {
4236
Addrs(minObservers int) []ma.Multiaddr
@@ -74,10 +68,8 @@ type addrsManager struct {
7468
addrsMx sync.RWMutex
7569
currentAddrs hostAddrs
7670

77-
signKey crypto.PrivKey
78-
addrStore addrStore
79-
signedRecordStore peerstore.CertifiedAddrBook
80-
hostID peer.ID
71+
peerstore peerstore.Peerstore
72+
hostID peer.ID
8173

8274
wg sync.WaitGroup
8375
ctx context.Context
@@ -94,9 +86,7 @@ func newAddrsManager(
9486
client autonatv2Client,
9587
enableMetrics bool,
9688
registerer prometheus.Registerer,
97-
disableSignedPeerRecord bool,
98-
signKey crypto.PrivKey,
99-
addrStore addrStore,
89+
pstore peerstore.Peerstore,
10090
hostID peer.ID,
10191
) (*addrsManager, error) {
10292
ctx, cancel := context.WithCancel(context.Background())
@@ -110,23 +100,14 @@ func newAddrsManager(
110100
triggerAddrsUpdateChan: make(chan chan struct{}, 1),
111101
triggerReachabilityUpdate: make(chan struct{}, 1),
112102
interfaceAddrs: &interfaceAddrsCache{},
113-
signKey: signKey,
114-
addrStore: addrStore,
103+
peerstore: pstore,
115104
hostID: hostID,
116105
ctx: ctx,
117106
ctxCancel: cancel,
118107
}
119108
unknownReachability := network.ReachabilityUnknown
120109
as.hostReachability.Store(&unknownReachability)
121110

122-
if !disableSignedPeerRecord {
123-
var ok bool
124-
as.signedRecordStore, ok = as.addrStore.(peerstore.CertifiedAddrBook)
125-
if !ok {
126-
return nil, errors.New("peerstore doesn't implement CertifiedAddrBook interface")
127-
}
128-
}
129-
130111
if client != nil {
131112
var metricsTracker MetricsTracker
132113
if enableMetrics {
@@ -347,26 +328,10 @@ func (a *addrsManager) updateAddrs(prevHostAddrs hostAddrs, relayAddrs []ma.Mult
347328

348329
// updatePeerStore updates the peer store for the host
349330
func (a *addrsManager) updatePeerStore(currentAddrs []ma.Multiaddr, removedAddrs []ma.Multiaddr) {
350-
// update host addresses in the peer store
351-
a.addrStore.SetAddrs(a.hostID, currentAddrs, peerstore.PermanentAddrTTL)
352-
a.addrStore.SetAddrs(a.hostID, removedAddrs, 0)
353-
354-
var sr *record.Envelope
355-
// Our addresses have changed.
356-
// store the signed peer record in the peer store.
357-
if a.signedRecordStore != nil {
358-
var err error
359-
// add signed peer record to the event
360-
// in case of an error drop this event.
361-
sr, err = a.makeSignedPeerRecord(currentAddrs)
362-
if err != nil {
363-
log.Error("error creating a signed peer record from the set of current addresses", "err", err)
364-
return
365-
}
366-
if _, err := a.signedRecordStore.ConsumePeerRecord(sr, peerstore.PermanentAddrTTL); err != nil {
367-
log.Error("failed to persist signed peer record in peer store", "err", err)
368-
return
369-
}
331+
peerRecordAddrs := trimHostAddrList(currentAddrs, maxPeerRecordSize-1024) // 1024 B of buffer for things other than addrs in peerstore
332+
err := a.peerstore.UpdateHostAddrs(a.hostID, currentAddrs, removedAddrs, peerRecordAddrs)
333+
if err != nil {
334+
log.Error("error updating peer store", "err", err)
370335
}
371336
}
372337

@@ -378,7 +343,7 @@ func (a *addrsManager) notifyAddrsUpdated(emitter event.Emitter, localAddrsEmitt
378343
}
379344
}
380345
if areAddrsDifferent(previous.addrs, current.addrs) {
381-
log.Debug("host addresses updated", "addrs", current.localAddrs)
346+
log.Debug("host addresses updated", "addrs", current.addrs)
382347
a.emitLocalAddrsUpdated(localAddrsEmitter, current.addrs, previous.addrs)
383348
}
384349

@@ -562,30 +527,6 @@ func (a *addrsManager) appendObservedAddrs(dst []ma.Multiaddr, listenAddrs, ifac
562527
return dst
563528
}
564529

565-
// makeSignedPeerRecord creates a signed peer record for the given addresses
566-
func (a *addrsManager) makeSignedPeerRecord(addrs []ma.Multiaddr) (*record.Envelope, error) {
567-
if a.signKey == nil {
568-
return nil, errors.New("signKey is nil")
569-
}
570-
// Limit the length of currentAddrs to ensure that our signed peer records aren't rejected
571-
peerRecordSize := 64 // HostID
572-
k, err := a.signKey.Raw()
573-
var nk int
574-
if err == nil {
575-
nk = len(k)
576-
} else {
577-
nk = 1024 // In case of error, use a large enough value.
578-
}
579-
peerRecordSize += 2 * nk // 1 for signature, 1 for public key
580-
// we want the final address list to be small for keeping the signed peer record in size
581-
addrs = trimHostAddrList(addrs, maxPeerRecordSize-peerRecordSize-256) // 256 B of buffer
582-
rec := peer.PeerRecordFromAddrInfo(peer.AddrInfo{
583-
ID: a.hostID,
584-
Addrs: addrs,
585-
})
586-
return record.Seal(rec, a.signKey)
587-
}
588-
589530
// emitLocalAddrsUpdated emits an EvtLocalAddressesUpdated event and updates the addresses in the peerstore.
590531
func (a *addrsManager) emitLocalAddrsUpdated(emitter event.Emitter, currentAddrs []ma.Multiaddr, lastAddrs []ma.Multiaddr) {
591532
added, maintained, removed := diffAddrs(lastAddrs, currentAddrs)
@@ -594,8 +535,11 @@ func (a *addrsManager) emitLocalAddrsUpdated(emitter event.Emitter, currentAddrs
594535
}
595536

596537
var sr *record.Envelope
597-
if a.signedRecordStore != nil {
598-
sr = a.signedRecordStore.GetPeerRecord(a.hostID)
538+
if a.peerstore != nil {
539+
ca, ok := a.peerstore.(peerstore.CertifiedAddrBook)
540+
if ok {
541+
sr = ca.GetPeerRecord(a.hostID)
542+
}
599543
}
600544

601545
evt := &event.EvtLocalAddressesUpdated{

p2p/host/basic/addrs_manager_test.go

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,10 @@ func (m *mockObservedAddrs) AddrsFor(local ma.Multiaddr) []ma.Multiaddr { return
5757

5858
var _ ObservedAddrsManager = &mockObservedAddrs{}
5959

60-
type addrStoreArgs struct {
61-
AddrStore addrStore
62-
SignKey crypto.PrivKey
63-
HostID peer.ID
64-
DisableSignedPeerRecord bool
60+
type peerstoreArgs struct {
61+
Peerstore peerstore.Peerstore
62+
HostID peer.ID
63+
SignKey crypto.PrivKey
6564
}
6665

6766
type addrsManagerArgs struct {
@@ -72,7 +71,7 @@ type addrsManagerArgs struct {
7271
AddCertHashes func([]ma.Multiaddr) []ma.Multiaddr
7372
AutoNATClient autonatv2Client
7473
Bus event.Bus
75-
AddrStoreArgs addrStoreArgs
74+
PeerstoreArgs peerstoreArgs
7675
}
7776

7877
type addrsManagerTestCase struct {
@@ -96,14 +95,14 @@ func newAddrsManagerTestCase(tb testing.TB, args addrsManagerArgs) addrsManagerT
9695
if args.AddCertHashes != nil {
9796
addCertHashes = args.AddCertHashes
9897
}
99-
signKey := args.AddrStoreArgs.SignKey
100-
addrStore := args.AddrStoreArgs.AddrStore
101-
pid := args.AddrStoreArgs.HostID
102-
if args.AddrStoreArgs == (addrStoreArgs{}) {
98+
peerstore := args.PeerstoreArgs.Peerstore
99+
pid := args.PeerstoreArgs.HostID
100+
signKey := args.PeerstoreArgs.SignKey
101+
if peerstore == nil {
103102
var err error
104103
signKey, _, err = crypto.GenerateEd25519Key(rand.Reader)
105104
require.NoError(tb, err)
106-
addrStore, err = pstoremem.NewPeerstore()
105+
peerstore, err = pstoremem.NewPeerstore()
107106
require.NoError(tb, err)
108107
pid, err = peer.IDFromPrivateKey(signKey)
109108
require.NoError(tb, err)
@@ -118,9 +117,7 @@ func newAddrsManagerTestCase(tb testing.TB, args addrsManagerArgs) addrsManagerT
118117
args.AutoNATClient,
119118
true,
120119
prometheus.DefaultRegisterer,
121-
false,
122-
signKey,
123-
addrStore,
120+
peerstore,
124121
pid,
125122
)
126123
require.NoError(tb, err)
@@ -456,6 +453,7 @@ func TestAddrsManagerPeerstoreUpdated(t *testing.T) {
456453
require.NoError(t, err)
457454
pid, err := peer.IDFromPrivateKey(signKey)
458455
require.NoError(t, err)
456+
require.NoError(t, pstore.AddPrivKey(pid, signKey))
459457

460458
var update atomic.Bool
461459
am := newAddrsManagerTestCase(t, addrsManagerArgs{
@@ -466,15 +464,16 @@ func TestAddrsManagerPeerstoreUpdated(t *testing.T) {
466464
}
467465
return []ma.Multiaddr{quic2}
468466
},
469-
AddrStoreArgs: addrStoreArgs{
470-
AddrStore: pstore,
467+
PeerstoreArgs: peerstoreArgs{
468+
Peerstore: pstore,
471469
HostID: pid,
472470
SignKey: signKey,
473471
},
474472
})
475473
defer am.Close()
476474
matest.AssertEqualMultiaddrs(t, []ma.Multiaddr{quic1}, pstore.Addrs(pid))
477475
ev := cab.GetPeerRecord(pid)
476+
require.NotNil(t, ev)
478477
pr := peerRecordFromEnvelope(t, ev)
479478
require.Equal(t, pr.Addrs, []ma.Multiaddr{quic1})
480479
update.Store(true)

p2p/host/basic/basic_host.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,8 +237,6 @@ func NewHost(n network.Network, opts *HostOpts) (*BasicHost, error) {
237237
autonatv2Client,
238238
opts.EnableMetrics,
239239
opts.PrometheusRegisterer,
240-
opts.DisableSignedPeerRecord,
241-
h.Peerstore().PrivKey(h.ID()),
242240
h.Peerstore(),
243241
h.ID(),
244242
)

p2p/host/peerstore/pstoreds/peerstore.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@ import (
88

99
"github.com/libp2p/go-libp2p/core/peer"
1010
"github.com/libp2p/go-libp2p/core/peerstore"
11+
"github.com/libp2p/go-libp2p/core/record"
1112
pstore "github.com/libp2p/go-libp2p/p2p/host/peerstore"
1213

1314
ds "github.com/ipfs/go-datastore"
1415
"github.com/ipfs/go-datastore/query"
1516
"github.com/multiformats/go-base32"
17+
ma "github.com/multiformats/go-multiaddr"
1618
)
1719

1820
// Configuration object for the peerstore.
@@ -177,6 +179,33 @@ func (ps *pstoreds) PeerInfo(p peer.ID) peer.AddrInfo {
177179
}
178180
}
179181

182+
func (ps *pstoreds) UpdateHostAddrs(hostID peer.ID, currentAddrs, removedAddrs, peerRecordAddrs []ma.Multiaddr) error {
183+
// update host addresses in the peer store
184+
ps.dsAddrBook.SetAddrs(hostID, currentAddrs, peerstore.PermanentAddrTTL)
185+
ps.dsAddrBook.SetAddrs(hostID, removedAddrs, 0)
186+
187+
signKey := ps.dsKeyBook.PrivKey(hostID)
188+
if signKey == nil {
189+
log.Debug("no sign key found for host", "host", hostID)
190+
// don't return an error here. It's fine to not have a signed peer record.
191+
return nil
192+
}
193+
194+
pr := peer.PeerRecordFromAddrInfo(peer.AddrInfo{
195+
ID: hostID,
196+
Addrs: peerRecordAddrs,
197+
})
198+
rec, err := record.Seal(pr, signKey)
199+
if err != nil {
200+
return fmt.Errorf("error sealing peer record: %s", err)
201+
}
202+
_, err = ps.dsAddrBook.ConsumePeerRecord(rec, peerstore.PermanentAddrTTL)
203+
if err != nil {
204+
return fmt.Errorf("error consuming peer record: %s", err)
205+
}
206+
return nil
207+
}
208+
180209
// RemovePeer removes entries associated with a peer from:
181210
// * the KeyBook
182211
// * the ProtoBook

p2p/host/peerstore/pstoremem/peerstore.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ import (
66

77
"github.com/libp2p/go-libp2p/core/peer"
88
"github.com/libp2p/go-libp2p/core/peerstore"
9+
"github.com/libp2p/go-libp2p/core/record"
910
pstore "github.com/libp2p/go-libp2p/p2p/host/peerstore"
11+
ma "github.com/multiformats/go-multiaddr"
1012
)
1113

1214
type pstoremem struct {
@@ -98,6 +100,33 @@ func (ps *pstoremem) PeerInfo(p peer.ID) peer.AddrInfo {
98100
}
99101
}
100102

103+
func (ps *pstoremem) UpdateHostAddrs(hostID peer.ID, currentAddrs, removedAddrs, peerRecordAddrs []ma.Multiaddr) error {
104+
// update host addresses in the peer store
105+
ps.memoryAddrBook.SetAddrs(hostID, currentAddrs, peerstore.PermanentAddrTTL)
106+
ps.memoryAddrBook.SetAddrs(hostID, removedAddrs, 0)
107+
108+
signKey := ps.memoryKeyBook.PrivKey(hostID)
109+
if signKey == nil {
110+
log.Debug("no sign key found for host", "host", hostID)
111+
// don't return an error here. It's fine to not have a signed peer record.
112+
return nil
113+
}
114+
115+
pr := peer.PeerRecordFromAddrInfo(peer.AddrInfo{
116+
ID: hostID,
117+
Addrs: peerRecordAddrs,
118+
})
119+
rec, err := record.Seal(pr, signKey)
120+
if err != nil {
121+
return fmt.Errorf("error sealing peer record: %s", err)
122+
}
123+
_, err = ps.memoryAddrBook.ConsumePeerRecord(rec, peerstore.PermanentAddrTTL)
124+
if err != nil {
125+
return fmt.Errorf("error consuming peer record: %s", err)
126+
}
127+
return nil
128+
}
129+
101130
// RemovePeer removes entries associated with a peer from:
102131
// * the KeyBook
103132
// * the ProtoBook

p2p/host/pstoremanager/mock_peerstore_test.go

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)