@libp2p/peer-store 1.0.4 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,7 +5,7 @@ import { peerIdFromPeerId } from '@libp2p/peer-id'
5
5
  import { equals as uint8ArrayEquals } from 'uint8arrays/equals'
6
6
  import { CustomEvent } from '@libp2p/interfaces'
7
7
  import type { Store } from './store.js'
8
- import type { PeerStore, MetadataBook } from '@libp2p/interfaces/src/peer-store'
8
+ import type { PeerStore, MetadataBook, PeerMetadataChangeData, Peer } from '@libp2p/interfaces/peer-store'
9
9
  import type { PeerId } from '@libp2p/interfaces/peer-id'
10
10
 
11
11
  const log = logger('libp2p:peer-store:metadata-book')
@@ -31,9 +31,9 @@ export class PeerStoreMetadataBook implements MetadataBook {
31
31
  async get (peerId: PeerId) {
32
32
  peerId = peerIdFromPeerId(peerId)
33
33
 
34
- log('get await read lock')
34
+ log.trace('get await read lock')
35
35
  const release = await this.store.lock.readLock()
36
- log('get got read lock')
36
+ log.trace('get got read lock')
37
37
 
38
38
  try {
39
39
  const peer = await this.store.load(peerId)
@@ -44,7 +44,7 @@ export class PeerStoreMetadataBook implements MetadataBook {
44
44
  throw err
45
45
  }
46
46
  } finally {
47
- log('get release read lock')
47
+ log.trace('get release read lock')
48
48
  release()
49
49
  }
50
50
 
@@ -57,9 +57,9 @@ export class PeerStoreMetadataBook implements MetadataBook {
57
57
  async getValue (peerId: PeerId, key: string) {
58
58
  peerId = peerIdFromPeerId(peerId)
59
59
 
60
- log('getValue await read lock')
60
+ log.trace('getValue await read lock')
61
61
  const release = await this.store.lock.readLock()
62
- log('getValue got read lock')
62
+ log.trace('getValue got read lock')
63
63
 
64
64
  try {
65
65
  const peer = await this.store.load(peerId)
@@ -70,7 +70,7 @@ export class PeerStoreMetadataBook implements MetadataBook {
70
70
  throw err
71
71
  }
72
72
  } finally {
73
- log('getValue release write lock')
73
+ log.trace('getValue release write lock')
74
74
  release()
75
75
  }
76
76
  }
@@ -83,21 +83,35 @@ export class PeerStoreMetadataBook implements MetadataBook {
83
83
  throw errcode(new Error('valid metadata must be provided'), codes.ERR_INVALID_PARAMETERS)
84
84
  }
85
85
 
86
- log('set await write lock')
86
+ log.trace('set await write lock')
87
87
  const release = await this.store.lock.writeLock()
88
- log('set got write lock')
88
+ log.trace('set got write lock')
89
+
90
+ let peer: Peer | undefined
89
91
 
90
92
  try {
93
+ try {
94
+ peer = await this.store.load(peerId)
95
+ } catch (err: any) {
96
+ if (err.code !== codes.ERR_NOT_FOUND) {
97
+ throw err
98
+ }
99
+ }
100
+
91
101
  await this.store.mergeOrCreate(peerId, {
92
102
  metadata
93
103
  })
94
104
  } finally {
95
- log('set release write lock')
105
+ log.trace('set release write lock')
96
106
  release()
97
107
  }
98
108
 
99
- this.dispatchEvent(new CustomEvent(EVENT_NAME, {
100
- detail: { peerId, metadata }
109
+ this.dispatchEvent(new CustomEvent<PeerMetadataChangeData>(EVENT_NAME, {
110
+ detail: {
111
+ peerId,
112
+ metadata,
113
+ oldMetadata: peer == null ? new Map() : peer.metadata
114
+ }
101
115
  }))
102
116
  }
103
117
 
@@ -112,16 +126,17 @@ export class PeerStoreMetadataBook implements MetadataBook {
112
126
  throw errcode(new Error('valid key and value must be provided'), codes.ERR_INVALID_PARAMETERS)
113
127
  }
114
128
 
115
- log('setValue await write lock')
129
+ log.trace('setValue await write lock')
116
130
  const release = await this.store.lock.writeLock()
117
- log('setValue got write lock')
131
+ log.trace('setValue got write lock')
118
132
 
133
+ let peer: Peer | undefined
119
134
  let updatedPeer
120
135
 
121
136
  try {
122
137
  try {
123
- const existingPeer = await this.store.load(peerId)
124
- const existingValue = existingPeer.metadata.get(key)
138
+ peer = await this.store.load(peerId)
139
+ const existingValue = peer.metadata.get(key)
125
140
 
126
141
  if (existingValue != null && uint8ArrayEquals(value, existingValue)) {
127
142
  return
@@ -136,40 +151,54 @@ export class PeerStoreMetadataBook implements MetadataBook {
136
151
  metadata: new Map([[key, value]])
137
152
  })
138
153
  } finally {
139
- log('setValue release write lock')
154
+ log.trace('setValue release write lock')
140
155
  release()
141
156
  }
142
157
 
143
- this.dispatchEvent(new CustomEvent(EVENT_NAME, {
144
- detail: { peerId, metadata: updatedPeer.metadata }
158
+ this.dispatchEvent(new CustomEvent<PeerMetadataChangeData>(EVENT_NAME, {
159
+ detail: {
160
+ peerId,
161
+ metadata: updatedPeer.metadata,
162
+ oldMetadata: peer == null ? new Map() : peer.metadata
163
+ }
145
164
  }))
146
165
  }
147
166
 
148
167
  async delete (peerId: PeerId) {
149
168
  peerId = peerIdFromPeerId(peerId)
150
169
 
151
- log('delete await write lock')
170
+ log.trace('delete await write lock')
152
171
  const release = await this.store.lock.writeLock()
153
- log('delete got write lock')
172
+ log.trace('delete got write lock')
154
173
 
155
- let has
174
+ let peer: Peer | undefined
156
175
 
157
176
  try {
158
- has = await this.store.has(peerId)
177
+ try {
178
+ peer = await this.store.load(peerId)
179
+ } catch (err: any) {
180
+ if (err.code !== codes.ERR_NOT_FOUND) {
181
+ throw err
182
+ }
183
+ }
159
184
 
160
- if (has) {
185
+ if (peer != null) {
161
186
  await this.store.patch(peerId, {
162
187
  metadata: new Map()
163
188
  })
164
189
  }
165
190
  } finally {
166
- log('delete release write lock')
191
+ log.trace('delete release write lock')
167
192
  release()
168
193
  }
169
194
 
170
- if (has) {
171
- this.dispatchEvent(new CustomEvent(EVENT_NAME, {
172
- detail: { peerId, metadata: new Map() }
195
+ if (peer != null) {
196
+ this.dispatchEvent(new CustomEvent<PeerMetadataChangeData>(EVENT_NAME, {
197
+ detail: {
198
+ peerId,
199
+ metadata: new Map(),
200
+ oldMetadata: peer.metadata
201
+ }
173
202
  }))
174
203
  }
175
204
  }
@@ -177,14 +206,15 @@ export class PeerStoreMetadataBook implements MetadataBook {
177
206
  async deleteValue (peerId: PeerId, key: string) {
178
207
  peerId = peerIdFromPeerId(peerId)
179
208
 
180
- log('deleteValue await write lock')
209
+ log.trace('deleteValue await write lock')
181
210
  const release = await this.store.lock.writeLock()
182
- log('deleteValue got write lock')
211
+ log.trace('deleteValue got write lock')
183
212
 
184
213
  let metadata
214
+ let peer: Peer | undefined
185
215
 
186
216
  try {
187
- const peer = await this.store.load(peerId)
217
+ peer = await this.store.load(peerId)
188
218
  metadata = peer.metadata
189
219
 
190
220
  metadata.delete(key)
@@ -197,13 +227,17 @@ export class PeerStoreMetadataBook implements MetadataBook {
197
227
  throw err
198
228
  }
199
229
  } finally {
200
- log('deleteValue release write lock')
230
+ log.trace('deleteValue release write lock')
201
231
  release()
202
232
  }
203
233
 
204
234
  if (metadata != null) {
205
- this.dispatchEvent(new CustomEvent(EVENT_NAME, {
206
- detail: { peerId, metadata }
235
+ this.dispatchEvent(new CustomEvent<PeerMetadataChangeData>(EVENT_NAME, {
236
+ detail: {
237
+ peerId,
238
+ metadata,
239
+ oldMetadata: peer == null ? new Map() : peer.metadata
240
+ }
207
241
  }))
208
242
  }
209
243
  }
package/src/proto-book.ts CHANGED
@@ -2,10 +2,9 @@ import { logger } from '@libp2p/logger'
2
2
  import errcode from 'err-code'
3
3
  import { codes } from './errors.js'
4
4
  import { peerIdFromPeerId } from '@libp2p/peer-id'
5
- import { base58btc } from 'multiformats/bases/base58'
6
5
  import { CustomEvent } from '@libp2p/interfaces'
7
6
  import type { Store } from './store.js'
8
- import type { PeerStore, ProtoBook } from '@libp2p/interfaces/src/peer-store'
7
+ import type { Peer, PeerProtocolsChangeData, PeerStore, ProtoBook } from '@libp2p/interfaces/peer-store'
9
8
  import type { PeerId } from '@libp2p/interfaces/peer-id'
10
9
 
11
10
  const log = logger('libp2p:peer-store:proto-book')
@@ -26,9 +25,9 @@ export class PeerStoreProtoBook implements ProtoBook {
26
25
  }
27
26
 
28
27
  async get (peerId: PeerId) {
29
- log('get wait for read lock')
28
+ log.trace('get wait for read lock')
30
29
  const release = await this.store.lock.readLock()
31
- log('get got read lock')
30
+ log.trace('get got read lock')
32
31
 
33
32
  try {
34
33
  const peer = await this.store.load(peerId)
@@ -39,7 +38,7 @@ export class PeerStoreProtoBook implements ProtoBook {
39
38
  throw err
40
39
  }
41
40
  } finally {
42
- log('get release read lock')
41
+ log.trace('get release read lock')
43
42
  release()
44
43
  }
45
44
 
@@ -54,15 +53,16 @@ export class PeerStoreProtoBook implements ProtoBook {
54
53
  throw errcode(new Error('protocols must be provided'), codes.ERR_INVALID_PARAMETERS)
55
54
  }
56
55
 
57
- log('set await write lock')
56
+ log.trace('set await write lock')
58
57
  const release = await this.store.lock.writeLock()
59
- log('set got write lock')
58
+ log.trace('set got write lock')
60
59
 
60
+ let peer
61
61
  let updatedPeer
62
62
 
63
63
  try {
64
64
  try {
65
- const peer = await this.store.load(peerId)
65
+ peer = await this.store.load(peerId)
66
66
 
67
67
  if (new Set([
68
68
  ...protocols
@@ -79,14 +79,18 @@ export class PeerStoreProtoBook implements ProtoBook {
79
79
  protocols
80
80
  })
81
81
 
82
- log(`stored provided protocols for ${peerId.toString(base58btc)}`)
82
+ log('stored provided protocols for %p', peerId)
83
83
  } finally {
84
- log('set release write lock')
84
+ log.trace('set release write lock')
85
85
  release()
86
86
  }
87
87
 
88
- this.dispatchEvent(new CustomEvent(EVENT_NAME, {
89
- detail: { peerId, protocols: updatedPeer.protocols }
88
+ this.dispatchEvent(new CustomEvent<PeerProtocolsChangeData>(EVENT_NAME, {
89
+ detail: {
90
+ peerId,
91
+ protocols: updatedPeer.protocols,
92
+ oldProtocols: peer == null ? [] : peer.protocols
93
+ }
90
94
  }))
91
95
  }
92
96
 
@@ -98,15 +102,16 @@ export class PeerStoreProtoBook implements ProtoBook {
98
102
  throw errcode(new Error('protocols must be provided'), codes.ERR_INVALID_PARAMETERS)
99
103
  }
100
104
 
101
- log('add await write lock')
105
+ log.trace('add await write lock')
102
106
  const release = await this.store.lock.writeLock()
103
- log('add got write lock')
107
+ log.trace('add got write lock')
104
108
 
109
+ let peer: Peer | undefined
105
110
  let updatedPeer
106
111
 
107
112
  try {
108
113
  try {
109
- const peer = await this.store.load(peerId)
114
+ peer = await this.store.load(peerId)
110
115
 
111
116
  if (new Set([
112
117
  ...peer.protocols,
@@ -124,14 +129,18 @@ export class PeerStoreProtoBook implements ProtoBook {
124
129
  protocols
125
130
  })
126
131
 
127
- log(`added provided protocols for ${peerId.toString(base58btc)}`)
132
+ log('added provided protocols for %p', peerId)
128
133
  } finally {
129
- log('add release write lock')
134
+ log.trace('add release write lock')
130
135
  release()
131
136
  }
132
137
 
133
- this.dispatchEvent(new CustomEvent(EVENT_NAME, {
134
- detail: { peerId, protocols: updatedPeer.protocols }
138
+ this.dispatchEvent(new CustomEvent<PeerProtocolsChangeData>(EVENT_NAME, {
139
+ detail: {
140
+ peerId,
141
+ protocols: updatedPeer.protocols,
142
+ oldProtocols: peer == null ? [] : peer.protocols
143
+ }
135
144
  }))
136
145
  }
137
146
 
@@ -143,15 +152,16 @@ export class PeerStoreProtoBook implements ProtoBook {
143
152
  throw errcode(new Error('protocols must be provided'), codes.ERR_INVALID_PARAMETERS)
144
153
  }
145
154
 
146
- log('remove await write lock')
155
+ log.trace('remove await write lock')
147
156
  const release = await this.store.lock.writeLock()
148
- log('remove got write lock')
157
+ log.trace('remove got write lock')
149
158
 
150
- let updatedPeer
159
+ let peer: Peer | undefined
160
+ let updatedPeer: Peer
151
161
 
152
162
  try {
153
163
  try {
154
- const peer = await this.store.load(peerId)
164
+ peer = await this.store.load(peerId)
155
165
  const protocolSet = new Set(peer.protocols)
156
166
 
157
167
  for (const protocol of protocols) {
@@ -173,41 +183,51 @@ export class PeerStoreProtoBook implements ProtoBook {
173
183
  protocols
174
184
  })
175
185
  } finally {
176
- log('remove release write lock')
186
+ log.trace('remove release write lock')
177
187
  release()
178
188
  }
179
189
 
180
- this.dispatchEvent(new CustomEvent(EVENT_NAME, {
181
- detail: { peerId, protocols: updatedPeer.protocols }
190
+ this.dispatchEvent(new CustomEvent<PeerProtocolsChangeData>(EVENT_NAME, {
191
+ detail: {
192
+ peerId,
193
+ protocols: updatedPeer.protocols,
194
+ oldProtocols: peer == null ? [] : peer.protocols
195
+ }
182
196
  }))
183
197
  }
184
198
 
185
199
  async delete (peerId: PeerId) {
186
200
  peerId = peerIdFromPeerId(peerId)
187
201
 
188
- log('delete await write lock')
202
+ log.trace('delete await write lock')
189
203
  const release = await this.store.lock.writeLock()
190
- log('delete got write lock')
191
- let has
204
+ log.trace('delete got write lock')
205
+ let peer: Peer | undefined
192
206
 
193
207
  try {
194
- has = await this.store.has(peerId)
208
+ try {
209
+ peer = await this.store.load(peerId)
210
+ } catch (err: any) {
211
+ if (err.code !== codes.ERR_NOT_FOUND) {
212
+ throw err
213
+ }
214
+ }
195
215
 
196
216
  await this.store.patchOrCreate(peerId, {
197
217
  protocols: []
198
218
  })
199
- } catch (err: any) {
200
- if (err.code !== codes.ERR_NOT_FOUND) {
201
- throw err
202
- }
203
219
  } finally {
204
- log('delete release write lock')
220
+ log.trace('delete release write lock')
205
221
  release()
206
222
  }
207
223
 
208
- if (has === true) {
209
- this.dispatchEvent(new CustomEvent(EVENT_NAME, {
210
- detail: { peerId, protocols: [] }
224
+ if (peer != null) {
225
+ this.dispatchEvent(new CustomEvent<PeerProtocolsChangeData>(EVENT_NAME, {
226
+ detail: {
227
+ peerId,
228
+ protocols: [],
229
+ oldProtocols: peer.protocols
230
+ }
211
231
  }))
212
232
  }
213
233
  }
package/src/store.ts CHANGED
@@ -51,8 +51,8 @@ export class PersistentStore {
51
51
  throw errcode(new Error('peerId must be an instance of peer-id'), codes.ERR_INVALID_PARAMETERS)
52
52
  }
53
53
 
54
- const b32key = peerId.toString(base32)
55
- return new Key(`${NAMESPACE_COMMON}b${b32key}`)
54
+ const b32key = base32.encode(peerId.toBytes())
55
+ return new Key(`${NAMESPACE_COMMON}${b32key}`)
56
56
  }
57
57
 
58
58
  async has (peerId: PeerId) {
@@ -93,24 +93,25 @@ export class PersistentStore {
93
93
 
94
94
  // dedupe addresses
95
95
  const addressSet = new Set()
96
+ const addresses = peer.addresses
97
+ .filter(address => {
98
+ if (addressSet.has(address.multiaddr.toString())) {
99
+ return false
100
+ }
101
+
102
+ addressSet.add(address.multiaddr.toString())
103
+ return true
104
+ })
105
+ .sort((a, b) => {
106
+ return a.multiaddr.toString().localeCompare(b.multiaddr.toString())
107
+ })
108
+ .map(({ multiaddr, isCertified }) => ({
109
+ multiaddr: multiaddr.bytes,
110
+ isCertified
111
+ }))
96
112
 
97
113
  const buf = PeerPB.encode({
98
- addresses: peer.addresses
99
- .filter(address => {
100
- if (addressSet.has(address.multiaddr.toString())) {
101
- return false
102
- }
103
-
104
- addressSet.add(address.multiaddr.toString())
105
- return true
106
- })
107
- .sort((a, b) => {
108
- return a.multiaddr.toString().localeCompare(b.multiaddr.toString())
109
- })
110
- .map(({ multiaddr, isCertified }) => ({
111
- multiaddr: multiaddr.bytes,
112
- isCertified
113
- })),
114
+ addresses,
114
115
  protocols: peer.protocols.sort(),
115
116
  pubKey: peer.pubKey,
116
117
  metadata: [...peer.metadata.keys()].sort().map(key => ({ key, value: peer.metadata.get(key) })),
@@ -178,16 +179,19 @@ export class PersistentStore {
178
179
  async _merge (peerId: PeerId, data: Partial<Peer>, peer: Peer) {
179
180
  // if the peer has certified addresses, use those in
180
181
  // favour of the supplied versions
181
- /** @type {Map<string, boolean>} */
182
- const addresses = new Map()
182
+ const addresses = new Map<string, boolean>()
183
183
 
184
- ;(data.addresses ?? []).forEach(addr => {
184
+ peer.addresses.forEach((addr) => {
185
185
  addresses.set(addr.multiaddr.toString(), addr.isCertified)
186
186
  })
187
187
 
188
- peer.addresses.forEach(({ multiaddr, isCertified }) => {
189
- const addrStr = multiaddr.toString()
190
- addresses.set(addrStr, Boolean(addresses.has(addrStr) ?? isCertified))
188
+ ;(data.addresses ?? []).forEach(addr => {
189
+ const addrString = addr.multiaddr.toString()
190
+ const isAlreadyCertified = Boolean(addresses.get(addrString))
191
+
192
+ const isCertified = isAlreadyCertified || addr.isCertified
193
+
194
+ addresses.set(addrString, isCertified)
191
195
  })
192
196
 
193
197
  return await this.save({