Skip to content

Commit 1c77705

Browse files
chore: apply suggestions from code review
Co-Authored-By: Jacob Heun <jacobheun@gmail.com>
1 parent 9abc2d3 commit 1c77705

File tree

5 files changed

+175
-118
lines changed

5 files changed

+175
-118
lines changed

src/index.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -181,10 +181,10 @@ class Libp2p extends EventEmitter {
181181

182182
// Once we start, emit and dial any peers we may have already discovered
183183
this.state.on('STARTED', () => {
184-
this.peerStore.getAllArray().forEach((peerInfo) => {
184+
for (const peerInfo of this.peerStore.peers) {
185185
this.emit('peer:discovery', peerInfo)
186186
this._maybeConnect(peerInfo)
187-
})
187+
}
188188
})
189189

190190
this._peerDiscovered = this._peerDiscovered.bind(this)
@@ -279,17 +279,19 @@ class Libp2p extends EventEmitter {
279279
connection = await this.dialer.connectToPeer(peer, options)
280280
}
281281

282+
const peerInfo = getPeerInfo(connection.remotePeer)
283+
282284
// If a protocol was provided, create a new stream
283285
if (protocols) {
284286
const stream = await connection.newStream(protocols)
285-
const peerInfo = getPeerInfo(connection.remotePeer)
286287

287288
peerInfo.protocols.add(stream.protocol)
288289
this.peerStore.put(peerInfo)
289290

290291
return stream
291292
}
292293

294+
this.peerStore.put(peerInfo)
293295
return connection
294296
}
295297

src/peer-store/index.js

Lines changed: 40 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ const assert = require('assert')
44
const debug = require('debug')
55
const log = debug('libp2p:peer-store')
66
log.error = debug('libp2p:peer-store:error')
7-
const errCode = require('err-code')
87

98
const { EventEmitter } = require('events')
109

@@ -60,12 +59,37 @@ class PeerStore extends EventEmitter {
6059
add (peerInfo) {
6160
assert(PeerInfo.isPeerInfo(peerInfo), 'peerInfo must be an instance of peer-info')
6261

63-
this.peers.set(peerInfo.id.toB58String(), peerInfo)
62+
// Create new instance and add values to it
63+
const newPeerInfo = new PeerInfo(peerInfo.id)
64+
65+
peerInfo.multiaddrs.forEach((ma) => newPeerInfo.multiaddrs.add(ma))
66+
peerInfo.protocols.forEach((p) => newPeerInfo.protocols.add(p))
67+
68+
const connectedMa = peerInfo.isConnected()
69+
connectedMa && newPeerInfo.connect(connectedMa)
70+
71+
const peerProxy = new Proxy(newPeerInfo, {
72+
set: (obj, prop, value) => {
73+
if (prop === 'multiaddrs') {
74+
this.emit('change:multiaddrs', {
75+
peerInfo: obj,
76+
multiaddrs: value.toArray()
77+
})
78+
} else if (prop === 'protocols') {
79+
this.emit('change:protocols', {
80+
peerInfo: obj,
81+
protocols: Array.from(value)
82+
})
83+
}
84+
return true
85+
}
86+
})
87+
88+
this.peers.set(peerInfo.id.toB58String(), peerProxy)
6489
}
6590

6691
/**
6792
* Updates an already known peer.
68-
* If already exist, updates ids info if outdated.
6993
* @param {PeerInfo} peerInfo
7094
*/
7195
update (peerInfo) {
@@ -81,24 +105,22 @@ class PeerStore extends EventEmitter {
81105

82106
// Verify new multiaddrs
83107
// TODO: better track added and removed multiaddrs
84-
if (peerInfo.multiaddrs.size || recorded.multiaddrs.size) {
85-
recorded.multiaddrs = peerInfo.multiaddrs
108+
const multiaddrsIntersection = [
109+
...recorded.multiaddrs.toArray()
110+
].filter((m) => peerInfo.multiaddrs.has(m))
86111

87-
this.emit('change:multiaddrs', {
88-
peerInfo: recorded,
89-
multiaddrs: Array.from(recorded.multiaddrs)
90-
})
112+
if (multiaddrsIntersection.length !== peerInfo.multiaddrs.size) {
113+
recorded.multiaddrs = peerInfo.multiaddrs
91114
}
92115

93116
// Update protocols
94117
// TODO: better track added and removed protocols
95-
if (peerInfo.protocols.size || recorded.protocols.size) {
96-
recorded.protocols = new Set(peerInfo.protocols)
118+
const protocolsIntersection = new Set(
119+
[...recorded.protocols].filter((p) => peerInfo.protocols.has(p))
120+
)
97121

98-
this.emit('change:protocols', {
99-
peerInfo: recorded,
100-
protocols: Array.from(recorded.protocols)
101-
})
122+
if (protocolsIntersection.size !== peerInfo.protocols.size) {
123+
recorded.protocols = peerInfo.protocols
102124
}
103125

104126
// Add the public key if missing
@@ -119,19 +141,11 @@ class PeerStore extends EventEmitter {
119141
return peerInfo
120142
}
121143

122-
throw errCode(new Error('PeerInfo was not found'), 'ERR_NO_PEER_INFO')
123-
}
124-
125-
/**
126-
* Get an array with all peers known.
127-
* @returns {Array<PeerInfo>}
128-
*/
129-
getAllArray () {
130-
return Array.from(this.peers.values())
144+
return undefined
131145
}
132146

133147
/**
134-
* Remove the info of the peer with the given id.
148+
* Removes the Peer with the matching `peerId` from the PeerStore
135149
* @param {string} peerId b58str id
136150
* @returns {boolean} true if found and removed
137151
*/
@@ -140,7 +154,7 @@ class PeerStore extends EventEmitter {
140154
}
141155

142156
/**
143-
* Replace the info stored of the given peer.
157+
* Completely replaces the existing peers metadata with the given `peerInfo`
144158
* @param {PeerInfo} peerInfo
145159
* @returns {void}
146160
*/

test/peer-store/peer-store.node.js

Lines changed: 0 additions & 68 deletions
This file was deleted.

test/peer-store/peer-store.spec.js

Lines changed: 80 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,18 @@ const { expect } = chai
77
const sinon = require('sinon')
88

99
const pDefer = require('p-defer')
10+
const mergeOptions = require('merge-options')
11+
12+
const Libp2p = require('../../src')
1013
const PeerStore = require('../../src/peer-store')
1114
const multiaddr = require('multiaddr')
1215

13-
const addr = multiaddr('/ip4/127.0.0.1/tcp/8000')
16+
const baseOptions = require('../utils/base-options')
1417
const peerUtils = require('../utils/creators/peer')
18+
const mockConnection = require('../utils/mockConnection')
19+
20+
const addr = multiaddr('/ip4/127.0.0.1/tcp/8000')
21+
const listenAddr = multiaddr('/ip4/127.0.0.1/tcp/0')
1522

1623
describe('peer-store', () => {
1724
let peerStore
@@ -75,49 +82,55 @@ describe('peer-store', () => {
7582

7683
it('should emit the "change:multiaddrs" event when a peer has new multiaddrs', async () => {
7784
const defer = pDefer()
78-
const [peerInfo] = await peerUtils.createPeerInfo(1)
85+
const [createdPeerInfo] = await peerUtils.createPeerInfo(1)
7986

8087
// Put the peer in the store
81-
peerStore.put(peerInfo)
88+
peerStore.put(createdPeerInfo)
8289

8390
// When updating, "change:multiaddrs" event must not be emitted
8491
peerStore.on('change:multiaddrs', ({ peerInfo, multiaddrs }) => {
8592
expect(peerInfo).to.exist()
93+
expect(peerInfo.id).to.eql(createdPeerInfo.id)
94+
expect(peerInfo.protocols).to.eql(createdPeerInfo.protocols)
8695
expect(multiaddrs).to.exist()
96+
expect(multiaddrs).to.eql(createdPeerInfo.multiaddrs.toArray())
8797
defer.resolve()
8898
})
8999
// If no protocols change, the event should not be emitted
90100
peerStore.on('change:protocols', () => {
91101
throw new Error('should not emit change:protocols')
92102
})
93103

94-
peerInfo.multiaddrs.add(addr)
95-
peerStore.put(peerInfo)
104+
createdPeerInfo.multiaddrs.add(addr)
105+
peerStore.put(createdPeerInfo)
96106

97107
// Wait for peerStore to emit the event
98108
await defer.promise
99109
})
100110

101111
it('should emit the "change:protocols" event when a peer has new protocols', async () => {
102112
const defer = pDefer()
103-
const [peerInfo] = await peerUtils.createPeerInfo(1)
113+
const [createdPeerInfo] = await peerUtils.createPeerInfo(1)
104114

105115
// Put the peer in the store
106-
peerStore.put(peerInfo)
116+
peerStore.put(createdPeerInfo)
107117

108118
// If no multiaddrs change, the event should not be emitted
109119
peerStore.on('change:multiaddrs', () => {
110120
throw new Error('should not emit change:multiaddrs')
111121
})
112-
// When updating, "change:protocols" event must not be emitted
122+
// When updating, "change:protocols" event must be emitted
113123
peerStore.on('change:protocols', ({ peerInfo, protocols }) => {
114124
expect(peerInfo).to.exist()
125+
expect(peerInfo.id).to.eql(createdPeerInfo.id)
126+
expect(peerInfo.multiaddrs).to.eql(createdPeerInfo.multiaddrs)
115127
expect(protocols).to.exist()
128+
expect(protocols).to.eql(Array.from(createdPeerInfo.protocols))
116129
defer.resolve()
117130
})
118131

119-
peerInfo.protocols.add('/new-protocol/1.0.0')
120-
peerStore.put(peerInfo)
132+
createdPeerInfo.protocols.add('/new-protocol/1.0.0')
133+
peerStore.put(createdPeerInfo)
121134

122135
// Wait for peerStore to emit the event
123136
await defer.promise
@@ -127,19 +140,17 @@ describe('peer-store', () => {
127140
const [peerInfo] = await peerUtils.createPeerInfo(1)
128141
const id = peerInfo.id.toB58String()
129142

130-
try {
131-
peerStore.get(id)
132-
throw new Error('peer should not exist in store')
133-
} catch (err) {
134-
expect(err).to.exist()
135-
expect(err.code).to.eql('ERR_NO_PEER_INFO')
136-
}
143+
let retrievedPeer = peerStore.get(id)
144+
expect(retrievedPeer).to.not.exist()
137145

138146
// Put the peer in the store
139147
peerStore.put(peerInfo)
140148

141-
const retrievedPeer = peerStore.get(id)
149+
retrievedPeer = peerStore.get(id)
142150
expect(retrievedPeer).to.exist()
151+
expect(retrievedPeer.id).to.equal(peerInfo.id)
152+
expect(retrievedPeer.multiaddrs).to.eql(peerInfo.multiaddrs)
153+
expect(retrievedPeer.protocols).to.eql(peerInfo.protocols)
143154
})
144155

145156
it('should be able to remove a peer from store through its b58str id', async () => {
@@ -151,11 +162,59 @@ describe('peer-store', () => {
151162

152163
// Put the peer in the store
153164
peerStore.put(peerInfo)
154-
155-
const peers = peerStore.getAllArray()
156-
expect(peers).to.have.lengthOf(1)
165+
expect(peerStore.peers.size).to.equal(1)
157166

158167
removed = peerStore.remove(id)
159168
expect(removed).to.eql(true)
169+
expect(peerStore.peers.size).to.equal(0)
160170
})
161171
})
172+
173+
describe('peer-store on dial', () => {
174+
let peerInfo
175+
let remotePeerInfo
176+
let libp2p
177+
let remoteLibp2p
178+
179+
before(async () => {
180+
[peerInfo, remotePeerInfo] = await peerUtils.createPeerInfoFromFixture(2)
181+
remoteLibp2p = new Libp2p(mergeOptions(baseOptions, {
182+
peerInfo: remotePeerInfo
183+
}))
184+
})
185+
186+
after(async () => {
187+
sinon.restore()
188+
await remoteLibp2p.stop()
189+
libp2p && await libp2p.stop()
190+
})
191+
192+
it('should put the remote peerInfo after dial and emit event', async () => {
193+
const remoteId = remotePeerInfo.id.toB58String()
194+
195+
libp2p = new Libp2p(mergeOptions(baseOptions, {
196+
peerInfo
197+
}))
198+
199+
sinon.spy(libp2p.peerStore, 'put')
200+
sinon.spy(libp2p.peerStore, 'add')
201+
sinon.spy(libp2p.peerStore, 'update')
202+
sinon.stub(libp2p.dialer, 'connectToMultiaddr').returns(mockConnection({
203+
remotePeer: remotePeerInfo.id
204+
}))
205+
206+
const connection = await libp2p.dial(listenAddr)
207+
await connection.close()
208+
209+
expect(libp2p.peerStore.put.callCount).to.equal(1)
210+
expect(libp2p.peerStore.add.callCount).to.equal(1)
211+
expect(libp2p.peerStore.update.callCount).to.equal(0)
212+
213+
const storedPeer = libp2p.peerStore.get(remoteId)
214+
expect(storedPeer).to.exist()
215+
})
216+
})
217+
218+
describe('peer-store on discovery', () => {
219+
// TODO: implement with discovery
220+
})

0 commit comments

Comments
 (0)