@helia/utils 2.5.2-1361bfa5 → 2.5.2-16d805e1

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.
Files changed (77) hide show
  1. package/dist/index.min.js +1 -22
  2. package/dist/index.min.js.map +4 -4
  3. package/dist/src/index.d.ts +5 -171
  4. package/dist/src/index.d.ts.map +1 -1
  5. package/dist/src/index.js +5 -162
  6. package/dist/src/index.js.map +1 -1
  7. package/dist/src/is-cid.d.ts.map +1 -0
  8. package/dist/src/is-cid.js.map +1 -0
  9. package/dist/src/is-promise.d.ts.map +1 -0
  10. package/dist/src/is-promise.js.map +1 -0
  11. package/package.json +7 -24
  12. package/src/index.ts +5 -368
  13. package/dist/src/pins.d.ts +0 -21
  14. package/dist/src/pins.d.ts.map +0 -1
  15. package/dist/src/pins.js +0 -141
  16. package/dist/src/pins.js.map +0 -1
  17. package/dist/src/routing.d.ts +0 -51
  18. package/dist/src/routing.d.ts.map +0 -1
  19. package/dist/src/routing.js +0 -311
  20. package/dist/src/routing.js.map +0 -1
  21. package/dist/src/storage.d.ts +0 -62
  22. package/dist/src/storage.d.ts.map +0 -1
  23. package/dist/src/storage.js +0 -159
  24. package/dist/src/storage.js.map +0 -1
  25. package/dist/src/utils/constants.d.ts +0 -4
  26. package/dist/src/utils/constants.d.ts.map +0 -1
  27. package/dist/src/utils/constants.js +0 -4
  28. package/dist/src/utils/constants.js.map +0 -1
  29. package/dist/src/utils/datastore-version.d.ts +0 -3
  30. package/dist/src/utils/datastore-version.d.ts.map +0 -1
  31. package/dist/src/utils/datastore-version.js +0 -20
  32. package/dist/src/utils/datastore-version.js.map +0 -1
  33. package/dist/src/utils/get-codec.d.ts +0 -4
  34. package/dist/src/utils/get-codec.d.ts.map +0 -1
  35. package/dist/src/utils/get-codec.js +0 -37
  36. package/dist/src/utils/get-codec.js.map +0 -1
  37. package/dist/src/utils/get-crypto.d.ts +0 -4
  38. package/dist/src/utils/get-crypto.d.ts.map +0 -1
  39. package/dist/src/utils/get-crypto.js +0 -35
  40. package/dist/src/utils/get-crypto.js.map +0 -1
  41. package/dist/src/utils/get-hasher.d.ts +0 -4
  42. package/dist/src/utils/get-hasher.d.ts.map +0 -1
  43. package/dist/src/utils/get-hasher.js +0 -32
  44. package/dist/src/utils/get-hasher.js.map +0 -1
  45. package/dist/src/utils/is-cid.d.ts.map +0 -1
  46. package/dist/src/utils/is-cid.js.map +0 -1
  47. package/dist/src/utils/is-promise.d.ts.map +0 -1
  48. package/dist/src/utils/is-promise.js.map +0 -1
  49. package/dist/src/utils/networked-storage.d.ts +0 -28
  50. package/dist/src/utils/networked-storage.d.ts.map +0 -1
  51. package/dist/src/utils/networked-storage.js +0 -52
  52. package/dist/src/utils/networked-storage.js.map +0 -1
  53. package/dist/src/utils/session-storage.d.ts +0 -47
  54. package/dist/src/utils/session-storage.d.ts.map +0 -1
  55. package/dist/src/utils/session-storage.js +0 -148
  56. package/dist/src/utils/session-storage.js.map +0 -1
  57. package/dist/src/utils/storage.d.ts +0 -55
  58. package/dist/src/utils/storage.d.ts.map +0 -1
  59. package/dist/src/utils/storage.js +0 -225
  60. package/dist/src/utils/storage.js.map +0 -1
  61. package/src/pins.ts +0 -209
  62. package/src/routing.ts +0 -389
  63. package/src/storage.ts +0 -194
  64. package/src/utils/constants.ts +0 -3
  65. package/src/utils/datastore-version.ts +0 -25
  66. package/src/utils/get-codec.ts +0 -45
  67. package/src/utils/get-crypto.ts +0 -44
  68. package/src/utils/get-hasher.ts +0 -40
  69. package/src/utils/networked-storage.ts +0 -74
  70. package/src/utils/session-storage.ts +0 -174
  71. package/src/utils/storage.ts +0 -294
  72. /package/dist/src/{utils/is-cid.d.ts → is-cid.d.ts} +0 -0
  73. /package/dist/src/{utils/is-cid.js → is-cid.js} +0 -0
  74. /package/dist/src/{utils/is-promise.d.ts → is-promise.d.ts} +0 -0
  75. /package/dist/src/{utils/is-promise.js → is-promise.js} +0 -0
  76. /package/src/{utils/is-cid.ts → is-cid.ts} +0 -0
  77. /package/src/{utils/is-promise.ts → is-promise.ts} +0 -0
@@ -1,40 +0,0 @@
1
- import { UnknownHashAlgorithmError } from '@helia/interface'
2
- import { identity } from 'multiformats/hashes/identity'
3
- import { sha256, sha512 } from 'multiformats/hashes/sha2'
4
- import { isPromise } from './is-promise.ts'
5
- import type { HasherLoader } from '@helia/interface'
6
- import type { MultihashHasher } from 'multiformats/hashes/interface'
7
-
8
- export function getHasher (initialHashers: MultihashHasher[] = [], loadHasher?: HasherLoader): HasherLoader {
9
- const hashers: Record<number, MultihashHasher> = {
10
- [sha256.code]: sha256,
11
- [sha512.code]: sha512,
12
- [identity.code]: identity
13
- }
14
-
15
- initialHashers.forEach(hasher => {
16
- hashers[hasher.code] = hasher
17
- })
18
-
19
- return async (code) => {
20
- let hasher = hashers[code]
21
-
22
- if (hasher == null && loadHasher != null) {
23
- const res = loadHasher(code)
24
-
25
- if (isPromise(res)) {
26
- hasher = await res
27
- } else {
28
- hasher = res
29
- }
30
-
31
- hashers[hasher.code] = hasher
32
- }
33
-
34
- if (hasher != null) {
35
- return hasher
36
- }
37
-
38
- throw new UnknownHashAlgorithmError(`No hasher configured for multihash code 0x${code.toString(16)}, please configure one. You can look up which hash this is at https://github.com/multiformats/multicodec/blob/master/table.csv`)
39
- }
40
- }
@@ -1,74 +0,0 @@
1
- import { start, stop } from '@libp2p/interface'
2
- import { InvalidConfigurationError } from '../errors.ts'
3
- import { SessionStorage } from './session-storage.ts'
4
- import { Storage } from './storage.ts'
5
- import type { StorageComponents, StorageInit } from './storage.ts'
6
- import type { BlockBroker, Blocks, CreateSessionOptions, SessionBlockstore } from '@helia/interface'
7
- import type { Startable } from '@libp2p/interface'
8
- import type { AbortOptions } from 'abort-error'
9
- import type { Blockstore } from 'interface-blockstore'
10
- import type { CID } from 'multiformats/cid'
11
-
12
- export interface GetOptions extends AbortOptions {
13
- progress?(evt: Event): void
14
- }
15
-
16
- export type NetworkedStorageComponents = StorageComponents<BlockBroker>
17
-
18
- /**
19
- * Networked storage wraps a regular blockstore - when getting blocks if the
20
- * blocks are not present, the configured BlockBrokers will be used to fetch them.
21
- */
22
- export class NetworkedStorage extends Storage<BlockBroker> implements Blocks, Startable {
23
- private started: boolean
24
-
25
- /**
26
- * Create a new BlockStorage
27
- */
28
- constructor (components: NetworkedStorageComponents, init: StorageInit = {}) {
29
- super(components, init)
30
-
31
- this.started = false
32
- }
33
-
34
- isStarted (): boolean {
35
- return this.started
36
- }
37
-
38
- async start (): Promise<void> {
39
- await start(this.child, ...this.blockBrokers)
40
- this.started = true
41
- }
42
-
43
- async stop (): Promise<void> {
44
- await stop(this.child, ...this.blockBrokers)
45
- this.started = false
46
- }
47
-
48
- unwrap (): Blockstore {
49
- return this.child
50
- }
51
-
52
- createSession (root: CID, options?: CreateSessionOptions): SessionBlockstore {
53
- if (this.blockBrokers.length === 0) {
54
- throw new InvalidConfigurationError('No block brokers configured')
55
- }
56
-
57
- const blockBrokers = this.blockBrokers
58
- .map(broker => broker.createSession?.(options))
59
- .filter(broker => broker != null)
60
-
61
- if (blockBrokers.length === 0) {
62
- throw new InvalidConfigurationError(`No configured block brokers support sessions - tried ${this.blockBrokers.map(b => b.name).join(', ')}`)
63
- }
64
-
65
- return new SessionStorage({
66
- blockstore: this.child,
67
- blockBrokers,
68
- getHasher: this.getHasher,
69
- logger: this.logger
70
- }, {
71
- root
72
- })
73
- }
74
- }
@@ -1,174 +0,0 @@
1
- import { setMaxListeners } from '@libp2p/interface'
2
- import { anySignal } from 'any-signal'
3
- import { Storage } from './storage.ts'
4
- import type { StorageComponents } from './storage.ts'
5
- import type { Pair, DeleteManyBlocksProgressEvents, DeleteBlockProgressEvents, GetBlockProgressEvents, GetManyBlocksProgressEvents, PutManyBlocksProgressEvents, PutBlockProgressEvents, GetAllBlocksProgressEvents, GetOfflineOptions, SessionBlockstore, SessionBlockBroker } from '@helia/interface'
6
- import type { AbortOptions } from '@libp2p/interface'
7
- import type { Multiaddr } from '@multiformats/multiaddr'
8
- import type { InputPair } from 'interface-blockstore'
9
- import type { CID } from 'multiformats/cid'
10
- import type { ProgressOptions } from 'progress-events'
11
-
12
- export interface SessionStorageInit {
13
- root: CID
14
- }
15
-
16
- /**
17
- * Storage subclass that can cancel any ongoing operation at any point.
18
- */
19
- export class SessionStorage extends Storage<SessionBlockBroker> implements SessionBlockstore {
20
- private readonly closeController: AbortController
21
-
22
- constructor (components: StorageComponents<SessionBlockBroker>, init: SessionStorageInit) {
23
- super(components)
24
-
25
- // because brokers are allowed to continue searching for providers after the
26
- // session has been created, we need a way to tell them that the user has
27
- // finished using the session any in-flight requests should be cancelled
28
- this.closeController = new AbortController()
29
- setMaxListeners(Infinity, this.closeController.signal)
30
-
31
- this.log = components.logger.forComponent(`helia:session-storage:${init.root}`)
32
- }
33
-
34
- close (): void {
35
- this.closeController.abort()
36
- }
37
-
38
- async addPeer (peer: CID | Multiaddr | Multiaddr[], options?: AbortOptions): Promise<void> {
39
- await Promise.all(
40
- this.blockBrokers
41
- .map(broker => broker.addPeer(peer, options))
42
- )
43
- }
44
-
45
- /**
46
- * Put a block to the underlying datastore
47
- */
48
- async put (cid: CID, block: Uint8Array, options: AbortOptions & ProgressOptions<PutBlockProgressEvents> = {}): Promise<CID> {
49
- const signal = anySignal([this.closeController.signal, options.signal])
50
- setMaxListeners(Infinity, signal)
51
-
52
- try {
53
- return await super.put(cid, block, {
54
- ...options,
55
- signal
56
- })
57
- } finally {
58
- signal.clear()
59
- }
60
- }
61
-
62
- /**
63
- * Put a multiple blocks to the underlying datastore
64
- */
65
- async * putMany (blocks: Iterable<InputPair> | AsyncIterable<InputPair>, options: AbortOptions & ProgressOptions<PutManyBlocksProgressEvents> = {}): AsyncGenerator<CID> {
66
- const signal = anySignal([this.closeController.signal, options.signal])
67
- setMaxListeners(Infinity, signal)
68
-
69
- try {
70
- yield * super.putMany(blocks, {
71
- ...options,
72
- signal
73
- })
74
- } finally {
75
- signal.clear()
76
- }
77
- }
78
-
79
- /**
80
- * Get a block by cid
81
- */
82
- async * get (cid: CID, options: GetOfflineOptions & AbortOptions & ProgressOptions<GetBlockProgressEvents> = {}): AsyncGenerator<Uint8Array> {
83
- const signal = anySignal([this.closeController.signal, options.signal])
84
- setMaxListeners(Infinity, signal)
85
-
86
- try {
87
- yield * super.get(cid, {
88
- ...options,
89
- signal
90
- })
91
- } finally {
92
- signal.clear()
93
- }
94
- }
95
-
96
- /**
97
- * Get multiple blocks back from an (async) iterable of cids
98
- */
99
- async * getMany (cids: Iterable<CID> | AsyncIterable<CID>, options: GetOfflineOptions & AbortOptions & ProgressOptions<GetManyBlocksProgressEvents> = {}): AsyncGenerator<Pair> {
100
- const signal = anySignal([this.closeController.signal, options.signal])
101
- setMaxListeners(Infinity, signal)
102
-
103
- try {
104
- yield * super.getMany(cids, {
105
- ...options,
106
- signal
107
- })
108
- } finally {
109
- signal.clear()
110
- }
111
- }
112
-
113
- /**
114
- * Delete a block from the blockstore
115
- */
116
- async delete (cid: CID, options: AbortOptions & ProgressOptions<DeleteBlockProgressEvents> = {}): Promise<void> {
117
- const signal = anySignal([this.closeController.signal, options.signal])
118
- setMaxListeners(Infinity, signal)
119
-
120
- try {
121
- await super.delete(cid, {
122
- ...options,
123
- signal
124
- })
125
- } finally {
126
- signal.clear()
127
- }
128
- }
129
-
130
- /**
131
- * Delete multiple blocks from the blockstore
132
- */
133
- async * deleteMany (cids: Iterable<CID> | AsyncIterable<CID>, options: AbortOptions & ProgressOptions<DeleteManyBlocksProgressEvents> = {}): AsyncGenerator<CID> {
134
- const signal = anySignal([this.closeController.signal, options.signal])
135
- setMaxListeners(Infinity, signal)
136
-
137
- try {
138
- yield * super.deleteMany(cids, {
139
- ...options,
140
- signal
141
- })
142
- } finally {
143
- signal.clear()
144
- }
145
- }
146
-
147
- async has (cid: CID, options: AbortOptions = {}): Promise<boolean> {
148
- const signal = anySignal([this.closeController.signal, options.signal])
149
- setMaxListeners(Infinity, signal)
150
-
151
- try {
152
- return await super.has(cid, {
153
- ...options,
154
- signal
155
- })
156
- } finally {
157
- signal.clear()
158
- }
159
- }
160
-
161
- async * getAll (options: AbortOptions & ProgressOptions<GetAllBlocksProgressEvents> = {}): AsyncGenerator<Pair> {
162
- const signal = anySignal([this.closeController.signal, options.signal])
163
- setMaxListeners(Infinity, signal)
164
-
165
- try {
166
- yield * super.getAll({
167
- ...options,
168
- signal
169
- })
170
- } finally {
171
- signal.clear()
172
- }
173
- }
174
- }
@@ -1,294 +0,0 @@
1
- import { InvalidMultihashError, InvalidParametersError, setMaxListeners } from '@libp2p/interface'
2
- import { anySignal } from 'any-signal'
3
- import { IdentityBlockstore } from 'blockstore-core/identity'
4
- import filter from 'it-filter'
5
- import forEach from 'it-foreach'
6
- import { CustomProgressEvent } from 'progress-events'
7
- import { equals as uint8ArrayEquals } from 'uint8arrays/equals'
8
- import { BlockNotFoundWhileOfflineError, InvalidConfigurationError, LoadBlockFailedError } from '../errors.ts'
9
- import { isPromise } from './is-promise.ts'
10
- import type { HasherLoader } from '@helia/interface'
11
- import type { BlockBroker, Pair, DeleteManyBlocksProgressEvents, DeleteBlockProgressEvents, GetBlockProgressEvents, GetManyBlocksProgressEvents, PutManyBlocksProgressEvents, PutBlockProgressEvents, GetAllBlocksProgressEvents, GetOfflineOptions, BlockRetrievalOptions } from '@helia/interface'
12
- import type { AbortOptions, ComponentLogger, Logger, LoggerOptions } from '@libp2p/interface'
13
- import type { Blockstore, InputPair } from 'interface-blockstore'
14
- import type { CID } from 'multiformats/cid'
15
- import type { MultihashDigest, MultihashHasher } from 'multiformats/hashes/interface'
16
- import type { ProgressEvent, ProgressOptions } from 'progress-events'
17
-
18
- export interface StorageComponents<Broker extends BlockBroker<ProgressEvent<any, any>, ProgressEvent<any, any>>> {
19
- blockstore: Blockstore
20
- logger: ComponentLogger
21
- blockBrokers: Broker[]
22
- getHasher: HasherLoader
23
- }
24
-
25
- export interface StorageInit {
26
- maxIdentityHashDigestLength?: number
27
- }
28
-
29
- const DEFAULT_MAX_IDENTITY_HASH_DIGEST_LENGTH = 128
30
-
31
- export class Storage <Broker extends BlockBroker<ProgressEvent<any, any>, ProgressEvent<any, any>>> implements Blockstore {
32
- protected readonly child: Blockstore
33
- protected readonly getHasher: HasherLoader
34
- protected log: Logger
35
- protected readonly logger: ComponentLogger
36
- protected readonly blockBrokers: Broker[]
37
-
38
- /**
39
- * Create a new BlockStorage
40
- */
41
- constructor (components: StorageComponents<Broker>, init: StorageInit = {}) {
42
- this.log = components.logger.forComponent('helia:networked-storage')
43
- this.logger = components.logger
44
- this.blockBrokers = components.blockBrokers
45
- this.child = new IdentityBlockstore(components.blockstore, {
46
- maxDigestLength: init.maxIdentityHashDigestLength ?? DEFAULT_MAX_IDENTITY_HASH_DIGEST_LENGTH
47
- })
48
- this.getHasher = components.getHasher
49
- }
50
-
51
- /**
52
- * Put a block to the underlying datastore
53
- */
54
- async put (cid: CID, block: Uint8Array, options: AbortOptions & ProgressOptions<PutBlockProgressEvents> = {}): Promise<CID> {
55
- if (await this.child.has(cid, options)) {
56
- options.onProgress?.(new CustomProgressEvent<CID>('blocks:put:duplicate', cid))
57
- return cid
58
- }
59
-
60
- options.onProgress?.(new CustomProgressEvent<CID>('blocks:put:providers:notify', cid))
61
-
62
- await Promise.all(
63
- this.blockBrokers.map(async broker => broker.announce?.(cid, options))
64
- )
65
-
66
- options.onProgress?.(new CustomProgressEvent<CID>('blocks:put:blockstore:put', cid))
67
-
68
- return this.child.put(cid, block, options)
69
- }
70
-
71
- /**
72
- * Put a multiple blocks to the underlying datastore
73
- */
74
- async * putMany (blocks: Iterable<InputPair> | AsyncIterable<InputPair>, options: AbortOptions & ProgressOptions<PutManyBlocksProgressEvents> = {}): AsyncGenerator<CID> {
75
- const missingBlocks = filter(blocks, async ({ cid }): Promise<boolean> => {
76
- const has = await this.child.has(cid, options)
77
-
78
- if (has) {
79
- options.onProgress?.(new CustomProgressEvent<CID>('blocks:put-many:duplicate', cid))
80
- }
81
-
82
- return !has
83
- })
84
-
85
- const notifyEach = forEach(missingBlocks, async ({ cid }): Promise<void> => {
86
- options.onProgress?.(new CustomProgressEvent<CID>('blocks:put-many:providers:notify', cid))
87
- await Promise.all(
88
- this.blockBrokers.map(async broker => broker.announce?.(cid, options))
89
- )
90
- })
91
-
92
- options.onProgress?.(new CustomProgressEvent('blocks:put-many:blockstore:put-many'))
93
- yield * this.child.putMany(notifyEach, options)
94
- }
95
-
96
- /**
97
- * Get a block by cid
98
- */
99
- async * get (cid: CID, options: GetOfflineOptions & AbortOptions & ProgressOptions<GetBlockProgressEvents> = {}): AsyncGenerator<Uint8Array> {
100
- const has = await this.child.has(cid, options)
101
- const offline = options.offline === true
102
-
103
- if (!has) {
104
- if (offline) {
105
- throw new BlockNotFoundWhileOfflineError('The block was present in the blockstore and the node is running offline so cannot fetch it')
106
- }
107
-
108
- const hasher = await this.getHasher(cid.multihash.code)
109
- options?.signal?.throwIfAborted()
110
-
111
- // we do not have the block locally, get it from a block provider
112
-
113
- options.onProgress?.(new CustomProgressEvent<CID>('blocks:get:providers:get', cid))
114
- const block = await raceBlockRetrievers(cid, this.blockBrokers, hasher, {
115
- ...options,
116
- log: this.log
117
- })
118
- options.onProgress?.(new CustomProgressEvent<CID>('blocks:get:blockstore:put', cid))
119
- await this.child.put(cid, block, options)
120
-
121
- // notify other block providers of the new block
122
- options.onProgress?.(new CustomProgressEvent<CID>('blocks:get:providers:notify', cid))
123
- await Promise.all(
124
- this.blockBrokers.map(async broker => broker.announce?.(cid, options))
125
- )
126
-
127
- yield block
128
- return
129
- }
130
-
131
- options.onProgress?.(new CustomProgressEvent<CID>('blocks:get:blockstore:get', cid))
132
-
133
- yield * this.child.get(cid, options)
134
- }
135
-
136
- /**
137
- * Get multiple blocks back from an (async) iterable of cids
138
- */
139
- async * getMany (cids: Iterable<CID> | AsyncIterable<CID>, options: GetOfflineOptions & AbortOptions & ProgressOptions<GetManyBlocksProgressEvents> = {}): AsyncGenerator<Pair> {
140
- options.onProgress?.(new CustomProgressEvent('blocks:get-many:blockstore:get-many'))
141
-
142
- yield * this.child.getMany(forEach(cids, async (cid): Promise<void> => {
143
- const has = await this.child.has(cid, options)
144
- const offline = options.offline === true
145
-
146
- if (!has) {
147
- if (offline) {
148
- throw new BlockNotFoundWhileOfflineError('The block was present in the blockstore and the node is running offline so cannot fetch it')
149
- }
150
-
151
- const hasher = await this.getHasher(cid.multihash.code)
152
- options?.signal?.throwIfAborted()
153
-
154
- // we do not have the block locally, get it from a block provider
155
- options.onProgress?.(new CustomProgressEvent<CID>('blocks:get-many:providers:get', cid))
156
- const block = await raceBlockRetrievers(cid, this.blockBrokers, hasher, {
157
- ...options,
158
- log: this.log
159
- })
160
- options.onProgress?.(new CustomProgressEvent<CID>('blocks:get-many:blockstore:put', cid))
161
- await this.child.put(cid, block, options)
162
-
163
- // notify other block providers of the new block
164
- options.onProgress?.(new CustomProgressEvent<CID>('blocks:get-many:providers:notify', cid))
165
- await Promise.all(
166
- this.blockBrokers.map(async broker => broker.announce?.(cid, options))
167
- )
168
- }
169
- }))
170
- }
171
-
172
- /**
173
- * Delete a block from the blockstore
174
- */
175
- async delete (cid: CID, options: AbortOptions & ProgressOptions<DeleteBlockProgressEvents> = {}): Promise<void> {
176
- options.onProgress?.(new CustomProgressEvent<CID>('blocks:delete:blockstore:delete', cid))
177
-
178
- await this.child.delete(cid, options)
179
- }
180
-
181
- /**
182
- * Delete multiple blocks from the blockstore
183
- */
184
- async * deleteMany (cids: Iterable<CID> | AsyncIterable<CID>, options: AbortOptions & ProgressOptions<DeleteManyBlocksProgressEvents> = {}): AsyncGenerator<CID> {
185
- options.onProgress?.(new CustomProgressEvent('blocks:delete-many:blockstore:delete-many'))
186
- yield * this.child.deleteMany((async function * (): AsyncGenerator<CID> {
187
- for await (const cid of cids) {
188
- yield cid
189
- }
190
- }()), options)
191
- }
192
-
193
- async has (cid: CID, options: AbortOptions = {}): Promise<boolean> {
194
- return this.child.has(cid, options)
195
- }
196
-
197
- async * getAll (options: AbortOptions & ProgressOptions<GetAllBlocksProgressEvents> = {}): AsyncGenerator<Pair> {
198
- options.onProgress?.(new CustomProgressEvent('blocks:get-all:blockstore:get-many'))
199
- yield * this.child.getAll(options)
200
- }
201
- }
202
-
203
- /**
204
- * Race block providers cancelling any pending requests once the block has been
205
- * found.
206
- */
207
- async function raceBlockRetrievers (cid: CID, blockBrokers: BlockBroker[], hasher: MultihashHasher, options: AbortOptions & LoggerOptions): Promise<Uint8Array> {
208
- const validateFn = getCidBlockVerifierFunction(cid, hasher)
209
-
210
- const controller = new AbortController()
211
- const signal = anySignal([controller.signal, options.signal])
212
- setMaxListeners(Infinity, controller.signal, signal)
213
-
214
- const retrievers: Array<Required<Pick<BlockBroker, 'name' | 'retrieve'>>> = []
215
-
216
- for (const broker of blockBrokers) {
217
- if (isRetrievingBlockBroker(broker)) {
218
- retrievers.push(broker)
219
- }
220
- }
221
-
222
- if (retrievers.length === 0) {
223
- throw new InvalidConfigurationError(`No block brokers capable of retrieving blocks are configured, the CID ${cid} cannot be fetched from the network`)
224
- }
225
-
226
- try {
227
- return await Promise.any(
228
- retrievers
229
- .map(async retriever => {
230
- try {
231
- let blocksWereValidated = false
232
- const block = await retriever.retrieve(cid, {
233
- ...options,
234
- signal,
235
- validateFn: async (block: Uint8Array): Promise<void> => {
236
- await validateFn(block)
237
- options.signal?.throwIfAborted()
238
- blocksWereValidated = true
239
- }
240
- })
241
-
242
- if (!blocksWereValidated) {
243
- // the blockBroker either did not throw an error when attempting to validate the block
244
- // or did not call the validateFn at all. We should validate the block ourselves
245
- await validateFn(block)
246
- options.signal?.throwIfAborted()
247
- }
248
-
249
- return block
250
- } catch (err) {
251
- options.log.error('could not retrieve verified block for %c from %s - %e', cid, retriever.name, err)
252
- throw err
253
- }
254
- })
255
- )
256
- } catch (err: any) {
257
- throw new LoadBlockFailedError(err.errors, `Failed to load block for ${cid}`)
258
- } finally {
259
- // we have the block from the fastest block retriever, abort any still
260
- // in-flight retrieve attempts
261
- controller.abort()
262
- signal.clear()
263
- }
264
- }
265
-
266
- function isRetrievingBlockBroker (broker: BlockBroker): broker is Required<Pick<BlockBroker, 'name' | 'retrieve'>> {
267
- return typeof broker.retrieve === 'function'
268
- }
269
-
270
- export const getCidBlockVerifierFunction = (cid: CID, hasher: MultihashHasher): Required<BlockRetrievalOptions>['validateFn'] => {
271
- if (hasher == null) {
272
- throw new InvalidParametersError(`No hasher configured for multihash code 0x${cid.multihash.code.toString(16)}, please configure one. You can look up which hash this is at https://github.com/multiformats/multicodec/blob/master/table.csv`)
273
- }
274
-
275
- return async (block: Uint8Array): Promise<void> => {
276
- // verify block
277
- let hash: MultihashDigest<number>
278
- const res = hasher.digest(block, {
279
- // support truncated hashes where they are truncated
280
- truncate: cid.multihash.digest.byteLength
281
- })
282
-
283
- if (isPromise(res)) {
284
- hash = await res
285
- } else {
286
- hash = res
287
- }
288
-
289
- if (!uint8ArrayEquals(hash.digest, cid.multihash.digest)) {
290
- // if a hash mismatch occurs for a TrustlessGatewayBlockBroker, we should try another gateway
291
- throw new InvalidMultihashError('Hash of downloaded block did not match multihash from passed CID')
292
- }
293
- }
294
- }
File without changes
File without changes
File without changes
File without changes
File without changes