Skip to content

Commit a5a33af

Browse files
authored
feat: add getInfo function to peerstore (#3099)
Adds a function to return a `PeerInfo` object - this is more lightweight than a full `Peer` object as it only contains the peer id and the listening addresses and is commonly used for exchanging peer information since it can be serialized to JSON trivially.
1 parent 9b33d20 commit a5a33af

File tree

4 files changed

+110
-5
lines changed

4 files changed

+110
-5
lines changed

packages/interface/src/peer-store.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { PublicKey } from './keys.js'
22
import type { PeerId } from './peer-id.js'
3+
import type { PeerInfo } from './peer-info.js'
34
import type { Multiaddr } from '@multiformats/multiaddr'
45

56
/**
@@ -229,6 +230,32 @@ export interface PeerStore {
229230
*/
230231
get(peerId: PeerId): Promise<Peer>
231232

233+
/**
234+
* Returns a PeerInfo object for the passed peer id. This is similar to `get`
235+
* except the returned value contains fewer fields and is often used to
236+
* exchange peer information with other systems.
237+
*
238+
* The returned object can be passed to `JSON.stringify` without any
239+
* additional processing.
240+
*
241+
* @see https://docs.libp2p.io/concepts/fundamentals/peers/#peer-info
242+
*
243+
* @example
244+
*
245+
* ```TypeScript
246+
* const peerInfo = await peerStore.getInfo(peerId)
247+
*
248+
* console.info(JSON.stringify(peerInfo))
249+
* // {
250+
* // id: 'peerId'
251+
* // multiaddrs: [
252+
* // '...'
253+
* // ]
254+
* // }
255+
* ```
256+
*/
257+
getInfo (peerId: PeerId): Promise<PeerInfo>
258+
232259
/**
233260
* Adds a peer to the peer store, overwriting any existing data
234261
*

packages/peer-store/src/index.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { peerIdFromCID } from '@libp2p/peer-id'
88
import { RecordEnvelope, PeerRecord } from '@libp2p/peer-record'
99
import all from 'it-all'
1010
import { PersistentStore, type PeerUpdate } from './store.js'
11-
import type { ComponentLogger, Libp2pEvents, Logger, TypedEventTarget, PeerId, PeerStore, Peer, PeerData, PeerQuery } from '@libp2p/interface'
11+
import type { ComponentLogger, Libp2pEvents, Logger, TypedEventTarget, PeerId, PeerStore, Peer, PeerData, PeerQuery, PeerInfo } from '@libp2p/interface'
1212
import type { Multiaddr } from '@multiformats/multiaddr'
1313
import type { Datastore } from 'interface-datastore'
1414

@@ -139,6 +139,15 @@ class PersistentPeerStore implements PeerStore {
139139
}
140140
}
141141

142+
async getInfo (peerId: PeerId): Promise<PeerInfo> {
143+
const peer = await this.get(peerId)
144+
145+
return {
146+
id: peer.id,
147+
multiaddrs: peer.addresses.map(({ multiaddr }) => multiaddr)
148+
}
149+
}
150+
142151
async save (id: PeerId, data: PeerData): Promise<Peer> {
143152
this.log.trace('save await write lock')
144153
const release = await this.store.lock.writeLock()

packages/peer-store/src/utils/dedupe-addresses.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,17 @@ export async function dedupeFilterAndSortAddresses (peerId: PeerId, filter: Addr
4242
.sort((a, b) => {
4343
return a.multiaddr.toString().localeCompare(b.multiaddr.toString())
4444
})
45-
.map(({ isCertified, multiaddr }) => ({
46-
isCertified,
47-
multiaddr: multiaddr.bytes
48-
}))
45+
.map(({ isCertified, multiaddr: ma }) => {
46+
// strip the trailing peerId if it is present
47+
const addrPeer = ma.getPeerId()
48+
49+
if (peerId.equals(addrPeer)) {
50+
ma = ma.decapsulate(multiaddr(`/p2p/${peerId}`))
51+
}
52+
53+
return {
54+
isCertified,
55+
multiaddr: ma.bytes
56+
}
57+
})
4958
}

packages/peer-store/test/index.spec.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,4 +495,64 @@ describe('PersistentPeerStore', () => {
495495
}
496496
})
497497
})
498+
499+
it('should return peerInfo', async () => {
500+
const peerStore = persistentPeerStore(components, {
501+
maxAddressAge: 50,
502+
maxPeerAge: 200
503+
})
504+
505+
await peerStore.save(otherPeerId, {
506+
multiaddrs: [
507+
multiaddr('/ip4/123.123.123.123/tcp/1234')
508+
]
509+
})
510+
511+
await expect(peerStore.getInfo(otherPeerId)).to.eventually.deep.equal({
512+
id: otherPeerId,
513+
multiaddrs: [
514+
multiaddr('/ip4/123.123.123.123/tcp/1234')
515+
]
516+
})
517+
})
518+
519+
it('should not include peer id in multiaddrs in returned peerInfo', async () => {
520+
const peerStore = persistentPeerStore(components, {
521+
maxAddressAge: 50,
522+
maxPeerAge: 200
523+
})
524+
525+
await peerStore.save(otherPeerId, {
526+
multiaddrs: [
527+
multiaddr(`/ip4/123.123.123.123/tcp/1234/p2p/${otherPeerId}`)
528+
]
529+
})
530+
531+
await expect(peerStore.getInfo(otherPeerId)).to.eventually.deep.equal({
532+
id: otherPeerId,
533+
multiaddrs: [
534+
multiaddr('/ip4/123.123.123.123/tcp/1234')
535+
]
536+
})
537+
})
538+
539+
it('should serialize peerInfo', async () => {
540+
const peerStore = persistentPeerStore(components, {
541+
maxAddressAge: 50,
542+
maxPeerAge: 200
543+
})
544+
545+
await peerStore.save(otherPeerId, {
546+
multiaddrs: [
547+
multiaddr(`/ip4/123.123.123.123/tcp/1234/p2p/${otherPeerId}`)
548+
]
549+
})
550+
551+
expect(JSON.parse(JSON.stringify(await peerStore.getInfo(otherPeerId)))).to.deep.equal({
552+
id: otherPeerId.toString(),
553+
multiaddrs: [
554+
'/ip4/123.123.123.123/tcp/1234'
555+
]
556+
})
557+
})
498558
})

0 commit comments

Comments
 (0)