Skip to content

Commit 1f8f634

Browse files
authored
feat!: update to [email protected] (#504)
* feat!: update to [email protected] Incorporates API changes from the upcoming [email protected] release. BREAKING CHANGE: Can only be used with [email protected] or later * chore: remove CodeError * chore: update deps * chore: fix linting
1 parent 9e57215 commit 1f8f634

20 files changed

+5320
-7331
lines changed

package-lock.json

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

package.json

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -73,44 +73,44 @@
7373
},
7474
"homepage": "https://github.com/ChainSafe/js-libp2p-gossipsub#readme",
7575
"dependencies": {
76-
"@libp2p/crypto": "^4.0.1",
77-
"@libp2p/interface": "^1.5.0",
78-
"@libp2p/interface-internal": "^1.0.7",
79-
"@libp2p/peer-id": "^4.0.5",
80-
"@libp2p/pubsub": "^9.0.8",
76+
"@libp2p/crypto": "^5.0.0",
77+
"@libp2p/interface": "^2.0.0",
78+
"@libp2p/interface-internal": "^2.0.0",
79+
"@libp2p/peer-id": "^5.0.0",
80+
"@libp2p/pubsub": "^10.0.0",
8181
"@multiformats/multiaddr": "^12.1.14",
8282
"denque": "^2.1.0",
8383
"it-length-prefixed": "^9.0.4",
8484
"it-pipe": "^3.0.1",
8585
"it-pushable": "^3.2.3",
8686
"multiformats": "^13.0.1",
87-
"protons-runtime": "5.4.0",
87+
"protons-runtime": "^5.5.0",
8888
"uint8arraylist": "^2.4.8",
8989
"uint8arrays": "^5.0.1"
9090
},
9191
"devDependencies": {
9292
"@chainsafe/as-sha256": "^0.4.1",
9393
"@dapplion/benchmark": "^0.2.4",
94-
"@libp2p/floodsub": "^9.0.9",
95-
"@libp2p/interface-compliance-tests": "^5.2.0",
96-
"@libp2p/logger": "^4.0.5",
97-
"@libp2p/peer-id-factory": "^4.0.5",
98-
"@libp2p/peer-store": "^10.0.8",
94+
"@libp2p/floodsub": "^10.0.0",
95+
"@libp2p/interface-compliance-tests": "^6.0.0",
96+
"@libp2p/logger": "^5.0.0",
97+
"@libp2p/peer-store": "^11.0.0",
9998
"@types/node": "^20.11.6",
99+
"@types/sinon": "^17.0.3",
100100
"abortable-iterator": "^5.1.0",
101-
"aegir": "^42.2.2",
102-
"datastore-core": "^9.2.7",
101+
"aegir": "^44.1.1",
102+
"datastore-core": "^10.0.0",
103103
"delay": "^6.0.0",
104-
"mkdirp": "^3.0.1",
105104
"it-all": "^3.0.6",
105+
"mkdirp": "^3.0.1",
106106
"p-defer": "^4.0.0",
107107
"p-event": "^6.0.0",
108108
"p-retry": "^6.2.0",
109109
"p-wait-for": "^5.0.2",
110110
"protons": "^7.5.0",
111-
"sinon": "^17.0.1",
112-
"time-cache": "^0.3.0",
113-
"ts-sinon": "^2.0.2"
111+
"sinon": "^18.0.1",
112+
"sinon-ts": "^2.0.0",
113+
"time-cache": "^0.3.0"
114114
},
115115
"engines": {
116116
"npm": ">=8.7.0"

src/errors.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
export class InvalidPeerScoreParamsError extends Error {
2+
static name = 'InvalidPeerScoreParamsError'
3+
4+
constructor (message = 'Invalid peer score params') {
5+
super(message)
6+
this.name = 'InvalidPeerScoreParamsError'
7+
}
8+
}
9+
10+
export class InvalidPeerScoreThresholdsError extends Error {
11+
static name = 'InvalidPeerScoreThresholdsError'
12+
13+
constructor (message = 'Invalid peer score thresholds') {
14+
super(message)
15+
this.name = 'InvalidPeerScoreThresholdsError'
16+
}
17+
}

src/index.ts

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import { TypedEventEmitter, StrictSign, StrictNoSign, TopicValidatorResult, serviceCapabilities, serviceDependencies } from '@libp2p/interface'
2-
import { peerIdFromBytes, peerIdFromString } from '@libp2p/peer-id'
2+
import { peerIdFromMultihash, peerIdFromString } from '@libp2p/peer-id'
33
import { encode } from 'it-length-prefixed'
44
import { pipe } from 'it-pipe'
55
import { pushable } from 'it-pushable'
6+
import * as Digest from 'multiformats/hashes/digest'
67
import * as constants from './constants.js'
78
import {
89
ACCEPT_FROM_WHITELIST_DURATION_MS,
@@ -73,7 +74,8 @@ import type {
7374
TopicValidatorFn,
7475
Logger,
7576
ComponentLogger,
76-
Topology
77+
Topology,
78+
PrivateKey
7779
} from '@libp2p/interface'
7880
import type { ConnectionManager, IncomingStreamData, Registrar } from '@libp2p/interface-internal'
7981
import type { Multiaddr } from '@multiformats/multiaddr'
@@ -166,13 +168,13 @@ export interface GossipsubOpts extends GossipsubOptsSpec, PubSubInit {
166168
maxOutboundStreams?: number
167169

168170
/**
169-
* Pass true to run on transient connections - data or time-limited
171+
* Pass true to run on limited connections - data or time-limited
170172
* connections that may be closed at any time such as circuit relay
171173
* connections.
172174
*
173175
* @default false
174176
*/
175-
runOnTransientConnection?: boolean
177+
runOnLimitedConnection?: boolean
176178

177179
/**
178180
* Specify max buffer size in bytes for OutboundStream.
@@ -259,6 +261,7 @@ interface AcceptFromWhitelistEntry {
259261
}
260262

261263
export interface GossipSubComponents {
264+
privateKey: PrivateKey
262265
peerId: PeerId
263266
peerStore: PeerStore
264267
registrar: Registrar
@@ -420,7 +423,7 @@ export class GossipSub extends TypedEventEmitter<GossipsubEvents> implements Pub
420423
private status: GossipStatus = { code: GossipStatusCode.stopped }
421424
private readonly maxInboundStreams?: number
422425
private readonly maxOutboundStreams?: number
423-
private readonly runOnTransientConnection?: boolean
426+
private readonly runOnLimitedConnection?: boolean
424427
private readonly allowedTopics: Set<TopicStr> | null
425428

426429
private heartbeatTimer: {
@@ -554,7 +557,7 @@ export class GossipSub extends TypedEventEmitter<GossipsubEvents> implements Pub
554557

555558
this.maxInboundStreams = options.maxInboundStreams
556559
this.maxOutboundStreams = options.maxOutboundStreams
557-
this.runOnTransientConnection = options.runOnTransientConnection
560+
this.runOnLimitedConnection = options.runOnLimitedConnection
558561

559562
this.allowedTopics = (opts.allowedTopics != null) ? new Set(opts.allowedTopics) : null
560563
}
@@ -591,7 +594,7 @@ export class GossipSub extends TypedEventEmitter<GossipsubEvents> implements Pub
591594

592595
this.log('starting')
593596

594-
this.publishConfig = await getPublishConfigFromPeerId(this.globalSignaturePolicy, this.components.peerId)
597+
this.publishConfig = getPublishConfigFromPeerId(this.globalSignaturePolicy, this.components.peerId, this.components.privateKey)
595598

596599
// Create the outbound inflight queue
597600
// This ensures that outbound stream creation happens sequentially
@@ -619,7 +622,7 @@ export class GossipSub extends TypedEventEmitter<GossipsubEvents> implements Pub
619622
registrar.handle(multicodec, this.onIncomingStream.bind(this), {
620623
maxInboundStreams: this.maxInboundStreams,
621624
maxOutboundStreams: this.maxOutboundStreams,
622-
runOnTransientConnection: this.runOnTransientConnection
625+
runOnLimitedConnection: this.runOnLimitedConnection
623626
})
624627
)
625628
)
@@ -646,7 +649,7 @@ export class GossipSub extends TypedEventEmitter<GossipsubEvents> implements Pub
646649
const topology: Topology = {
647650
onConnect: this.onPeerConnected.bind(this),
648651
onDisconnect: this.onPeerDisconnected.bind(this),
649-
notifyOnTransient: this.runOnTransientConnection
652+
notifyOnLimitedConnection: this.runOnLimitedConnection
650653
}
651654
const registrarTopologyIds = await Promise.all(
652655
this.multicodecs.map(async (multicodec) => registrar.register(multicodec, topology))
@@ -817,7 +820,7 @@ export class GossipSub extends TypedEventEmitter<GossipsubEvents> implements Pub
817820
try {
818821
const stream = new OutboundStream(
819822
await connection.newStream(this.multicodecs, {
820-
runOnTransientConnection: this.runOnTransientConnection
823+
runOnLimitedConnection: this.runOnLimitedConnection
821824
}),
822825
(e) => { this.log.error('outbound pipe error', e) },
823826
{ maxBufferSize: this.opts.maxOutboundBufferSize }
@@ -1778,7 +1781,7 @@ export class GossipSub extends TypedEventEmitter<GossipsubEvents> implements Pub
17781781
return
17791782
}
17801783

1781-
const peer = peerIdFromBytes(pi.peerID)
1784+
const peer = peerIdFromMultihash(Digest.decode(pi.peerID))
17821785
const p = peer.toString()
17831786

17841787
if (this.peers.has(p)) {
@@ -1895,7 +1898,7 @@ export class GossipSub extends TypedEventEmitter<GossipsubEvents> implements Pub
18951898

18961899
// remove explicit peers, peers with negative scores, and backoffed peers
18971900
fanoutPeers.forEach((id) => {
1898-
if (!this.direct.has(id) && this.score.score(id) >= 0 && ((backoff == null) || !backoff.has(id))) {
1901+
if (!this.direct.has(id) && this.score.score(id) >= 0 && backoff?.has(id) !== true) {
18991902
toAdd.add(id)
19001903
}
19011904
})
@@ -1911,7 +1914,7 @@ export class GossipSub extends TypedEventEmitter<GossipsubEvents> implements Pub
19111914
this.opts.D,
19121915
(id: PeerIdStr): boolean =>
19131916
// filter direct peers and peers with negative score
1914-
!toAdd.has(id) && !this.direct.has(id) && this.score.score(id) >= 0 && ((backoff == null) || !backoff.has(id))
1917+
!toAdd.has(id) && !this.direct.has(id) && this.score.score(id) >= 0 && backoff?.has(id) !== true
19151918
)
19161919

19171920
newPeers.forEach((peer) => {
@@ -2610,13 +2613,13 @@ export class GossipSub extends TypedEventEmitter<GossipsubEvents> implements Pub
26102613
try {
26112614
peerInfo = await this.components.peerStore.get(id)
26122615
} catch (err: any) {
2613-
if (err.code !== 'ERR_NOT_FOUND') {
2616+
if (err.name !== 'NotFoundError') {
26142617
throw err
26152618
}
26162619
}
26172620

26182621
return {
2619-
peerID: id.toBytes(),
2622+
peerID: id.toMultihash().bytes,
26202623
signedPeerRecord: peerInfo?.peerRecordEnvelope
26212624
}
26222625
})
@@ -2741,7 +2744,7 @@ export class GossipSub extends TypedEventEmitter<GossipsubEvents> implements Pub
27412744
!this.direct.has(id)
27422745
) {
27432746
const score = getScore(id)
2744-
if (((backoff == null) || !backoff.has(id)) && score >= 0) candidateMeshPeers.add(id)
2747+
if (backoff?.has(id) !== true && score >= 0) candidateMeshPeers.add(id)
27452748
// instead of having to find gossip peers after heartbeat which require another loop
27462749
// we prepare peers to gossip in a topic within heartbeat to improve performance
27472750
if (score >= this.opts.scoreThresholds.gossipThreshold) peersToGossip.add(id)

src/message/rpc.ts

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */
55
/* eslint-disable @typescript-eslint/no-empty-interface */
66

7-
import { type Codec, CodeError, decodeMessage, type DecodeOptions, encodeMessage, message } from 'protons-runtime'
7+
import { type Codec, decodeMessage, type DecodeOptions, encodeMessage, MaxLengthError, message } from 'protons-runtime'
88
import type { Uint8ArrayList } from 'uint8arraylist'
99

1010
export interface RPC {
@@ -256,34 +256,42 @@ export namespace RPC {
256256
switch (tag >>> 3) {
257257
case 1: {
258258
if (opts.limits?.ihave != null && obj.ihave.length === opts.limits.ihave) {
259-
throw new CodeError('decode error - map field "ihave" had too many elements', 'ERR_MAX_LENGTH')
259+
throw new MaxLengthError('Decode error - map field "ihave" had too many elements')
260260
}
261261

262-
obj.ihave.push(RPC.ControlIHave.codec().decode(reader, reader.uint32()))
262+
obj.ihave.push(RPC.ControlIHave.codec().decode(reader, reader.uint32(), {
263+
limits: opts.limits?.ihave$
264+
}))
263265
break
264266
}
265267
case 2: {
266268
if (opts.limits?.iwant != null && obj.iwant.length === opts.limits.iwant) {
267-
throw new CodeError('decode error - map field "iwant" had too many elements', 'ERR_MAX_LENGTH')
269+
throw new MaxLengthError('Decode error - map field "iwant" had too many elements')
268270
}
269271

270-
obj.iwant.push(RPC.ControlIWant.codec().decode(reader, reader.uint32()))
272+
obj.iwant.push(RPC.ControlIWant.codec().decode(reader, reader.uint32(), {
273+
limits: opts.limits?.iwant$
274+
}))
271275
break
272276
}
273277
case 3: {
274278
if (opts.limits?.graft != null && obj.graft.length === opts.limits.graft) {
275-
throw new CodeError('decode error - map field "graft" had too many elements', 'ERR_MAX_LENGTH')
279+
throw new MaxLengthError('Decode error - map field "graft" had too many elements')
276280
}
277281

278-
obj.graft.push(RPC.ControlGraft.codec().decode(reader, reader.uint32()))
282+
obj.graft.push(RPC.ControlGraft.codec().decode(reader, reader.uint32(), {
283+
limits: opts.limits?.graft$
284+
}))
279285
break
280286
}
281287
case 4: {
282288
if (opts.limits?.prune != null && obj.prune.length === opts.limits.prune) {
283-
throw new CodeError('decode error - map field "prune" had too many elements', 'ERR_MAX_LENGTH')
289+
throw new MaxLengthError('Decode error - map field "prune" had too many elements')
284290
}
285291

286-
obj.prune.push(RPC.ControlPrune.codec().decode(reader, reader.uint32()))
292+
obj.prune.push(RPC.ControlPrune.codec().decode(reader, reader.uint32(), {
293+
limits: opts.limits?.prune$
294+
}))
287295
break
288296
}
289297
default: {
@@ -356,7 +364,7 @@ export namespace RPC {
356364
}
357365
case 2: {
358366
if (opts.limits?.messageIDs != null && obj.messageIDs.length === opts.limits.messageIDs) {
359-
throw new CodeError('decode error - map field "messageIDs" had too many elements', 'ERR_MAX_LENGTH')
367+
throw new MaxLengthError('Decode error - map field "messageIDs" had too many elements')
360368
}
361369

362370
obj.messageIDs.push(reader.bytes())
@@ -422,7 +430,7 @@ export namespace RPC {
422430
switch (tag >>> 3) {
423431
case 1: {
424432
if (opts.limits?.messageIDs != null && obj.messageIDs.length === opts.limits.messageIDs) {
425-
throw new CodeError('decode error - map field "messageIDs" had too many elements', 'ERR_MAX_LENGTH')
433+
throw new MaxLengthError('Decode error - map field "messageIDs" had too many elements')
426434
}
427435

428436
obj.messageIDs.push(reader.bytes())
@@ -562,10 +570,12 @@ export namespace RPC {
562570
}
563571
case 2: {
564572
if (opts.limits?.peers != null && obj.peers.length === opts.limits.peers) {
565-
throw new CodeError('decode error - map field "peers" had too many elements', 'ERR_MAX_LENGTH')
573+
throw new MaxLengthError('Decode error - map field "peers" had too many elements')
566574
}
567575

568-
obj.peers.push(RPC.PeerInfo.codec().decode(reader, reader.uint32()))
576+
obj.peers.push(RPC.PeerInfo.codec().decode(reader, reader.uint32(), {
577+
limits: opts.limits?.peers$
578+
}))
569579
break
570580
}
571581
case 3: {
@@ -708,22 +718,28 @@ export namespace RPC {
708718
switch (tag >>> 3) {
709719
case 1: {
710720
if (opts.limits?.subscriptions != null && obj.subscriptions.length === opts.limits.subscriptions) {
711-
throw new CodeError('decode error - map field "subscriptions" had too many elements', 'ERR_MAX_LENGTH')
721+
throw new MaxLengthError('Decode error - map field "subscriptions" had too many elements')
712722
}
713723

714-
obj.subscriptions.push(RPC.SubOpts.codec().decode(reader, reader.uint32()))
724+
obj.subscriptions.push(RPC.SubOpts.codec().decode(reader, reader.uint32(), {
725+
limits: opts.limits?.subscriptions$
726+
}))
715727
break
716728
}
717729
case 2: {
718730
if (opts.limits?.messages != null && obj.messages.length === opts.limits.messages) {
719-
throw new CodeError('decode error - map field "messages" had too many elements', 'ERR_MAX_LENGTH')
731+
throw new MaxLengthError('Decode error - map field "messages" had too many elements')
720732
}
721733

722-
obj.messages.push(RPC.Message.codec().decode(reader, reader.uint32()))
734+
obj.messages.push(RPC.Message.codec().decode(reader, reader.uint32(), {
735+
limits: opts.limits?.messages$
736+
}))
723737
break
724738
}
725739
case 3: {
726-
obj.control = RPC.ControlMessage.codec().decode(reader, reader.uint32())
740+
obj.control = RPC.ControlMessage.codec().decode(reader, reader.uint32(), {
741+
limits: opts.limits?.control
742+
})
727743
break
728744
}
729745
default: {

src/score/constants.ts

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

0 commit comments

Comments
 (0)