@helia/utils 2.5.2 → 3.0.0-3a1dd561

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