@helia/bitswap 3.2.3-f6cc7640 → 4.0.0
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.
- package/dist/index.min.js +12 -1
- package/dist/index.min.js.map +4 -4
- package/dist/src/block-broker.d.ts +27 -0
- package/dist/src/block-broker.d.ts.map +1 -0
- package/dist/src/block-broker.js +91 -0
- package/dist/src/block-broker.js.map +1 -0
- package/dist/src/index.d.ts +8 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +19 -4
- package/dist/src/index.js.map +1 -1
- package/dist/src/network.d.ts +2 -2
- package/dist/src/network.d.ts.map +1 -1
- package/dist/src/network.js +19 -23
- package/dist/src/network.js.map +1 -1
- package/dist/src/session.d.ts +4 -4
- package/dist/src/session.d.ts.map +1 -1
- package/dist/src/session.js +9 -7
- package/dist/src/session.js.map +1 -1
- package/dist/typedoc-urls.json +29 -0
- package/package.json +15 -14
- package/src/block-broker.ts +119 -0
- package/src/index.ts +26 -5
- package/src/network.ts +27 -31
- package/src/session.ts +13 -11
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { isPeerId } from '@libp2p/interface'
|
|
2
|
+
import { CustomProgressEvent } from 'progress-events'
|
|
3
|
+
import { Bitswap } from './bitswap.ts'
|
|
4
|
+
import type { BitswapOptions, BitswapWantBlockProgressEvents, BitswapNotifyProgressEvents } from './index.ts'
|
|
5
|
+
import type { BlockAnnounceOptions, BlockBroker, BlockRetrievalOptions, CreateSessionOptions, Routing, HasherLoader, SessionBlockBroker, BlockBrokerConnectProgressEvent, BlockBrokerConnectedProgressEvent, BlockBrokerRequestBlockProgressEvent, BlockBrokerReceiveBlockProgressEvent } from '@helia/interface'
|
|
6
|
+
import type { Libp2p, Startable, ComponentLogger } from '@libp2p/interface'
|
|
7
|
+
import type { Blockstore } from 'interface-blockstore'
|
|
8
|
+
import type { CID } from 'multiformats/cid'
|
|
9
|
+
|
|
10
|
+
export interface BitswapBlockBrokerComponents {
|
|
11
|
+
libp2p: Libp2p
|
|
12
|
+
blockstore: Blockstore
|
|
13
|
+
routing: Routing
|
|
14
|
+
logger: ComponentLogger
|
|
15
|
+
getHasher: HasherLoader
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface BitswapBlockBrokerInit extends BitswapOptions {
|
|
19
|
+
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export class BitswapBlockBroker implements BlockBroker<BitswapWantBlockProgressEvents, BitswapNotifyProgressEvents>, Startable {
|
|
23
|
+
public readonly name = 'bitswap'
|
|
24
|
+
private readonly bitswap: Bitswap
|
|
25
|
+
private started: boolean
|
|
26
|
+
|
|
27
|
+
constructor (components: BitswapBlockBrokerComponents, init: BitswapBlockBrokerInit = {}) {
|
|
28
|
+
this.bitswap = new Bitswap(components, init)
|
|
29
|
+
this.started = false
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
isStarted (): boolean {
|
|
33
|
+
return this.started
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async start (): Promise<void> {
|
|
37
|
+
await this.bitswap.start()
|
|
38
|
+
this.started = true
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async stop (): Promise<void> {
|
|
42
|
+
await this.bitswap.stop()
|
|
43
|
+
this.started = false
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async announce (cid: CID, options?: BlockAnnounceOptions<BitswapNotifyProgressEvents>): Promise<void> {
|
|
47
|
+
await this.bitswap.notify(cid, options)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async retrieve (cid: CID, options: BlockRetrievalOptions<BitswapWantBlockProgressEvents> = {}): Promise<Uint8Array> {
|
|
51
|
+
return this.bitswap.want(cid, {
|
|
52
|
+
...options,
|
|
53
|
+
onProgress: function bitswapBlockBrokerRetrieveCallback (evt) {
|
|
54
|
+
if (options?.onProgress == null) {
|
|
55
|
+
return
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
options.onProgress(evt)
|
|
59
|
+
|
|
60
|
+
if (evt.type === 'connection:open') {
|
|
61
|
+
if (!isPeerId(evt.detail)) {
|
|
62
|
+
// should not happen as bitswap impl only sends wantlist to
|
|
63
|
+
// connected peers so we always have a peer id
|
|
64
|
+
return
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
options.onProgress(new CustomProgressEvent<BlockBrokerConnectProgressEvent>('helia:block-broker:connect', {
|
|
68
|
+
broker: 'bitswap',
|
|
69
|
+
type: 'connect',
|
|
70
|
+
provider: evt.detail.toCID(),
|
|
71
|
+
cid
|
|
72
|
+
}))
|
|
73
|
+
} else if (evt.type === 'connection:opened') {
|
|
74
|
+
options.onProgress(new CustomProgressEvent<BlockBrokerConnectedProgressEvent>('helia:block-broker:connected', {
|
|
75
|
+
broker: 'bitswap',
|
|
76
|
+
type: 'connected',
|
|
77
|
+
provider: evt.detail.remotePeer.toCID(),
|
|
78
|
+
address: evt.detail.remoteAddr,
|
|
79
|
+
cid
|
|
80
|
+
}))
|
|
81
|
+
} else if (evt.type === 'bitswap:send-wantlist') {
|
|
82
|
+
options.onProgress(new CustomProgressEvent<BlockBrokerRequestBlockProgressEvent>('helia:block-broker:request-block', {
|
|
83
|
+
broker: 'bitswap',
|
|
84
|
+
type: 'request-block',
|
|
85
|
+
provider: evt.detail.toCID(),
|
|
86
|
+
cid
|
|
87
|
+
}))
|
|
88
|
+
} else if (evt.type === 'bitswap:block') {
|
|
89
|
+
options.onProgress(new CustomProgressEvent<BlockBrokerReceiveBlockProgressEvent>('helia:block-broker:receive-block', {
|
|
90
|
+
broker: 'bitswap',
|
|
91
|
+
type: 'receive-block',
|
|
92
|
+
provider: evt.detail.sender.toCID(),
|
|
93
|
+
cid
|
|
94
|
+
}))
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
})
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
createSession (options?: CreateSessionOptions<BitswapWantBlockProgressEvents>): SessionBlockBroker<BitswapWantBlockProgressEvents, BitswapNotifyProgressEvents> {
|
|
101
|
+
const session = this.bitswap.createSession(options)
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
name: 'bitswap-session',
|
|
105
|
+
|
|
106
|
+
addPeer: async (peer, options) => {
|
|
107
|
+
await session.addPeer(peer, options)
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
announce: async (cid, options) => {
|
|
111
|
+
await this.bitswap.notify(cid, options)
|
|
112
|
+
},
|
|
113
|
+
|
|
114
|
+
retrieve: async (cid, options) => {
|
|
115
|
+
return session.retrieve(cid, options)
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -6,11 +6,14 @@
|
|
|
6
6
|
* It supersedes the older [ipfs-bitswap](https://www.npmjs.com/package/ipfs-bitswap) module with the aim of being smaller, faster, better integrated with libp2p/helia, having fewer dependencies and using standard JavaScript instead of Node.js APIs.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import {
|
|
9
|
+
import { start } from '@libp2p/interface'
|
|
10
|
+
import { BitswapBlockBroker } from './block-broker.ts'
|
|
11
|
+
import type { BitswapBlockBrokerInit } from './block-broker.ts'
|
|
10
12
|
import type { BitswapNetworkNotifyProgressEvents, BitswapNetworkWantProgressEvents, BitswapNetworkProgressEvents } from './network.ts'
|
|
11
13
|
import type { WantType } from './pb/message.ts'
|
|
12
|
-
import type { BlockBrokerGetBlockProgressEvents, CreateSessionOptions, HasherLoader, ProviderOptions, SessionBlockBroker } from '@helia/interface'
|
|
13
|
-
import type { Routing } from '@helia/interface
|
|
14
|
+
import type { BlockBrokerGetBlockProgressEvents, CreateSessionOptions, HasherLoader, HeliaMixin, ProviderOptions, SessionBlockBroker } from '@helia/interface'
|
|
15
|
+
import type { Routing } from '@helia/interface'
|
|
16
|
+
import type { HeliaWithLibp2p } from '@helia/libp2p'
|
|
14
17
|
import type { Libp2p, AbortOptions, Startable, ComponentLogger, Metrics, PeerId } from '@libp2p/interface'
|
|
15
18
|
import type { Blockstore } from 'interface-blockstore'
|
|
16
19
|
import type { CID } from 'multiformats/cid'
|
|
@@ -34,6 +37,7 @@ export type { BitswapNetworkWantProgressEvents }
|
|
|
34
37
|
export type { BitswapNetworkProgressEvents }
|
|
35
38
|
export type { WantType }
|
|
36
39
|
export type { BitswapProvider } from './network.ts'
|
|
40
|
+
export type { BitswapBlockBrokerInit } from './block-broker.ts'
|
|
37
41
|
|
|
38
42
|
export type WantStatus = 'want' | 'sending' | 'sent'
|
|
39
43
|
|
|
@@ -227,6 +231,23 @@ export interface BitswapOptions {
|
|
|
227
231
|
maxWantlistSize?: number
|
|
228
232
|
}
|
|
229
233
|
|
|
230
|
-
|
|
231
|
-
|
|
234
|
+
/**
|
|
235
|
+
* Return a Helia node augmented with a libp2p instance
|
|
236
|
+
*/
|
|
237
|
+
export function withBitswap (helia: HeliaWithLibp2p, options: BitswapBlockBrokerInit = {}): HeliaWithLibp2p {
|
|
238
|
+
const mixin: HeliaMixin<HeliaWithLibp2p> = {
|
|
239
|
+
name: 'bitswap',
|
|
240
|
+
start: async (helia) => {
|
|
241
|
+
if (helia.status === 'starting' && !helia.hasBlockBroker('bitswap')) {
|
|
242
|
+
const broker = new BitswapBlockBroker(helia, options)
|
|
243
|
+
await start(broker)
|
|
244
|
+
|
|
245
|
+
helia.addBlockBroker(broker)
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
helia.addMixin(mixin)
|
|
251
|
+
|
|
252
|
+
return helia
|
|
232
253
|
}
|
package/src/network.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isCID } from '@helia/utils'
|
|
2
|
+
import { InvalidParametersError, NotStartedError, TimeoutError, TypedEventEmitter, isPeerId, setMaxListeners } from '@libp2p/interface'
|
|
3
|
+
import { peerIdFromCID } from '@libp2p/peer-id'
|
|
2
4
|
import { PeerQueue } from '@libp2p/utils'
|
|
5
|
+
import { isMultiaddr } from '@multiformats/multiaddr'
|
|
3
6
|
import drain from 'it-drain'
|
|
4
7
|
import * as lp from 'it-length-prefixed'
|
|
5
8
|
import map from 'it-map'
|
|
@@ -7,7 +10,6 @@ import { pushable } from 'it-pushable'
|
|
|
7
10
|
import take from 'it-take'
|
|
8
11
|
import { CID } from 'multiformats/cid'
|
|
9
12
|
import { CustomProgressEvent } from 'progress-events'
|
|
10
|
-
import { raceEvent } from 'race-event'
|
|
11
13
|
import { BITSWAP_120, DEFAULT_MAX_INBOUND_STREAMS, DEFAULT_MAX_INCOMING_MESSAGE_SIZE, DEFAULT_MAX_OUTBOUND_STREAMS, DEFAULT_MAX_OUTGOING_MESSAGE_SIZE, DEFAULT_MAX_PROVIDERS_PER_REQUEST, DEFAULT_MESSAGE_RECEIVE_TIMEOUT, DEFAULT_MESSAGE_SEND_CONCURRENCY, DEFAULT_MESSAGE_SEND_TIMEOUT, DEFAULT_RUN_ON_TRANSIENT_CONNECTIONS } from './constants.ts'
|
|
12
14
|
import { BitswapMessage } from './pb/message.ts'
|
|
13
15
|
import { mergeMessages } from './utils/merge-messages.ts'
|
|
@@ -16,8 +18,8 @@ import type { WantOptions } from './bitswap.ts'
|
|
|
16
18
|
import type { Block } from './pb/message.ts'
|
|
17
19
|
import type { QueuedBitswapMessage } from './utils/bitswap-message.ts'
|
|
18
20
|
import type { BlockBrokerGetBlockProgressEvents } from '@helia/interface'
|
|
19
|
-
import type { Provider, Routing, RoutingFindProvidersProgressEvents } from '@helia/interface
|
|
20
|
-
import type { Libp2p, AbortOptions, Connection, PeerId, Topology, ComponentLogger,
|
|
21
|
+
import type { Provider, Routing, RoutingFindProvidersProgressEvents } from '@helia/interface'
|
|
22
|
+
import type { Libp2p, AbortOptions, Connection, PeerId, Topology, ComponentLogger, Counter, Metrics, Stream, OpenConnectionProgressEvents, NewStreamProgressEvents } from '@libp2p/interface'
|
|
21
23
|
import type { Logger } from '@libp2p/logger'
|
|
22
24
|
import type { PeerQueueJobOptions } from '@libp2p/utils'
|
|
23
25
|
import type { Multiaddr } from '@multiformats/multiaddr'
|
|
@@ -102,6 +104,22 @@ interface SendMessageJobOptions extends AbortOptions, ProgressOptions<BitswapNet
|
|
|
102
104
|
message: QueuedBitswapMessage
|
|
103
105
|
}
|
|
104
106
|
|
|
107
|
+
function toDialable (peer: CID | PeerId | Multiaddr | Multiaddr[]): PeerId | Multiaddr | Multiaddr[] {
|
|
108
|
+
if (isPeerId(peer)) {
|
|
109
|
+
return peer
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (isCID(peer)) {
|
|
113
|
+
return peerIdFromCID(peer)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (isMultiaddr(peer) || Array.isArray(peer)) {
|
|
117
|
+
return peer
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
throw new InvalidParametersError(`Peer ${peer} was not a CID, a Multiaddr or a Multiaddr[]`)
|
|
121
|
+
}
|
|
122
|
+
|
|
105
123
|
export class Network extends TypedEventEmitter<NetworkEvents> {
|
|
106
124
|
private readonly log: Logger
|
|
107
125
|
private readonly libp2p: Libp2p
|
|
@@ -236,7 +254,6 @@ export class Network extends TypedEventEmitter<NetworkEvents> {
|
|
|
236
254
|
const input = pushable<Uint8Array | Uint8ArrayList>()
|
|
237
255
|
|
|
238
256
|
stream.addEventListener('message', (evt) => {
|
|
239
|
-
// @ts-expect-error libp2p needs dep updates
|
|
240
257
|
input.push(evt.data)
|
|
241
258
|
})
|
|
242
259
|
stream.addEventListener('remoteCloseWrite', () => {
|
|
@@ -316,7 +333,7 @@ export class Network extends TypedEventEmitter<NetworkEvents> {
|
|
|
316
333
|
// connect to initial session providers if supplied
|
|
317
334
|
if (options?.providers != null) {
|
|
318
335
|
await Promise.all(
|
|
319
|
-
options.providers.map(async prov => this.connectTo(prov)
|
|
336
|
+
options.providers.map(async prov => this.connectTo(prov, options)
|
|
320
337
|
.catch(err => {
|
|
321
338
|
this.log.error('could not connect to supplied provider - %e', err)
|
|
322
339
|
}))
|
|
@@ -371,7 +388,6 @@ export class Network extends TypedEventEmitter<NetworkEvents> {
|
|
|
371
388
|
|
|
372
389
|
try {
|
|
373
390
|
for (const buf of splitMessage(message, this.maxOutgoingMessageSize)) {
|
|
374
|
-
// @ts-expect-error libp2p needs dep updates
|
|
375
391
|
if (!stream.send(lp.encode.single(buf))) {
|
|
376
392
|
await stream.onDrain(options)
|
|
377
393
|
}
|
|
@@ -399,36 +415,16 @@ export class Network extends TypedEventEmitter<NetworkEvents> {
|
|
|
399
415
|
/**
|
|
400
416
|
* Connects to another peer
|
|
401
417
|
*/
|
|
402
|
-
async connectTo (peer: PeerId | Multiaddr | Multiaddr[], options?: AbortOptions & ProgressOptions<BitswapNetworkProgressEvents>): Promise<Connection> {
|
|
418
|
+
async connectTo (peer: CID | PeerId | Multiaddr | Multiaddr[], options?: AbortOptions & ProgressOptions<BitswapNetworkProgressEvents>): Promise<Connection> {
|
|
403
419
|
if (!this.running) {
|
|
404
420
|
throw new NotStartedError('Network isn\'t running')
|
|
405
421
|
}
|
|
406
422
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
// dial and wait for identify - this is to avoid opening a protocol stream
|
|
410
|
-
// that we are not going to use but depends on the remote node running the
|
|
411
|
-
// identify protocol
|
|
412
|
-
const [
|
|
413
|
-
connection
|
|
414
|
-
] = await Promise.all([
|
|
415
|
-
this.libp2p.dial(peer, options),
|
|
416
|
-
raceEvent(this.libp2p, 'peer:identify', options?.signal, {
|
|
417
|
-
filter: (evt: CustomEvent<IdentifyResult>): boolean => {
|
|
418
|
-
if (!evt.detail.peerId.equals(peer)) {
|
|
419
|
-
return false
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
if (evt.detail.protocols.includes(BITSWAP_120)) {
|
|
423
|
-
return true
|
|
424
|
-
}
|
|
423
|
+
peer = toDialable(peer)
|
|
425
424
|
|
|
426
|
-
|
|
427
|
-
}
|
|
428
|
-
})
|
|
429
|
-
])
|
|
425
|
+
options?.onProgress?.(new CustomProgressEvent<PeerId | Multiaddr | Multiaddr[]>('bitswap:dial', peer))
|
|
430
426
|
|
|
431
|
-
return
|
|
427
|
+
return this.libp2p.dial(peer, options)
|
|
432
428
|
}
|
|
433
429
|
|
|
434
430
|
_updateSentStats (blocks: Map<string, Block>): void {
|
package/src/session.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { AbstractSession } from '@helia/utils'
|
|
2
|
-
import {
|
|
1
|
+
import { AbstractSession, isCID } from '@helia/utils'
|
|
2
|
+
import { peerIdFromCID } from '@libp2p/peer-id'
|
|
3
|
+
import { CID } from 'multiformats/cid'
|
|
3
4
|
import { CustomProgressEvent } from 'progress-events'
|
|
4
5
|
import type { BitswapProvider, BitswapWantProgressEvents } from './index.ts'
|
|
5
6
|
import type { Network } from './network.ts'
|
|
6
7
|
import type { WantList } from './want-list.ts'
|
|
7
8
|
import type { BlockRetrievalOptions, CreateSessionOptions } from '@helia/interface'
|
|
8
|
-
import type { ComponentLogger, Libp2p,
|
|
9
|
+
import type { ComponentLogger, Libp2p, AbortOptions } from '@libp2p/interface'
|
|
9
10
|
import type { Multiaddr } from '@multiformats/multiaddr'
|
|
10
|
-
import type { CID } from 'multiformats/cid'
|
|
11
11
|
|
|
12
12
|
export interface BitswapSessionComponents {
|
|
13
13
|
network: Network
|
|
@@ -17,7 +17,7 @@ export interface BitswapSessionComponents {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
interface ProviderPeer {
|
|
20
|
-
peerId:
|
|
20
|
+
peerId: CID
|
|
21
21
|
routing: string
|
|
22
22
|
toString(): string
|
|
23
23
|
}
|
|
@@ -40,9 +40,11 @@ class BitswapSession extends AbstractSession<ProviderPeer, BitswapWantProgressEv
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
async queryProvider (cid: CID, provider: ProviderPeer, options: AbortOptions): Promise<Uint8Array> {
|
|
43
|
-
|
|
43
|
+
const peerId = peerIdFromCID(provider.peerId)
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
this.log('sending WANT-BLOCK for %c to %p', cid, peerId)
|
|
46
|
+
|
|
47
|
+
const result = await this.wantList.wantSessionBlock(cid, peerId, options)
|
|
46
48
|
|
|
47
49
|
this.log('%p %s %c', provider, result.has ? 'has' : 'does not have', cid)
|
|
48
50
|
|
|
@@ -68,15 +70,15 @@ class BitswapSession extends AbstractSession<ProviderPeer, BitswapWantProgressEv
|
|
|
68
70
|
}
|
|
69
71
|
|
|
70
72
|
toFilterKey (provider: ProviderPeer): Uint8Array | string {
|
|
71
|
-
return provider.peerId.
|
|
73
|
+
return provider.peerId.multihash.bytes
|
|
72
74
|
}
|
|
73
75
|
|
|
74
76
|
equals (providerA: ProviderPeer, providerB: ProviderPeer): boolean {
|
|
75
77
|
return providerA.peerId.equals(providerB.peerId)
|
|
76
78
|
}
|
|
77
79
|
|
|
78
|
-
async convertToProvider (provider:
|
|
79
|
-
if (
|
|
80
|
+
async convertToProvider (provider: CID | Multiaddr | Multiaddr[], routing: string, options?: AbortOptions): Promise<ProviderPeer | undefined> {
|
|
81
|
+
if (isCID(provider)) {
|
|
80
82
|
return {
|
|
81
83
|
peerId: provider,
|
|
82
84
|
routing,
|
|
@@ -92,7 +94,7 @@ class BitswapSession extends AbstractSession<ProviderPeer, BitswapWantProgressEv
|
|
|
92
94
|
const connection = await this.libp2p.dial(provider, options)
|
|
93
95
|
|
|
94
96
|
return {
|
|
95
|
-
peerId: connection.remotePeer,
|
|
97
|
+
peerId: connection.remotePeer.toCID(),
|
|
96
98
|
routing,
|
|
97
99
|
toString: () => `Bitswap(${connection.remotePeer})`
|
|
98
100
|
}
|