@aztec/blob-client 0.0.1-commit.fcb71a6 → 0.0.1-commit.ff7989d6c
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/README.md +1 -1
- package/dest/archive/config.js +1 -1
- package/dest/archive/instrumentation.d.ts +1 -1
- package/dest/archive/instrumentation.d.ts.map +1 -1
- package/dest/archive/instrumentation.js +13 -13
- package/dest/blobstore/blob_store_test_suite.js +9 -9
- package/dest/client/http.d.ts +3 -1
- package/dest/client/http.d.ts.map +1 -1
- package/dest/client/http.js +11 -8
- package/dest/client/interface.d.ts +3 -1
- package/dest/client/interface.d.ts.map +1 -1
- package/dest/client/local.d.ts +3 -1
- package/dest/client/local.d.ts.map +1 -1
- package/dest/client/local.js +3 -0
- package/dest/client/tests.js +3 -3
- package/package.json +8 -8
- package/src/archive/config.ts +1 -1
- package/src/archive/instrumentation.ts +22 -13
- package/src/blobstore/blob_store_test_suite.ts +9 -9
- package/src/client/http.ts +18 -9
- package/src/client/interface.ts +2 -0
- package/src/client/local.ts +5 -0
- package/src/client/tests.ts +2 -2
package/README.md
CHANGED
|
@@ -31,7 +31,7 @@ URL for uploading blobs to a file store.
|
|
|
31
31
|
**L1 Consensus Host URLs** (`L1_CONSENSUS_HOST_URLS`):
|
|
32
32
|
Beacon node URLs for fetching recent blobs directly from L1.
|
|
33
33
|
|
|
34
|
-
**Archive API URL** (`
|
|
34
|
+
**Archive API URL** (`BLOB_ARCHIVE_API_URL`):
|
|
35
35
|
Blobscan or similar archive API for historical blob data.
|
|
36
36
|
|
|
37
37
|
### File Store Connectivity Testing
|
package/dest/archive/config.js
CHANGED
|
@@ -2,7 +2,7 @@ import { l1ReaderConfigMappings } from '@aztec/ethereum/l1-reader';
|
|
|
2
2
|
import { pickConfigMappings } from '@aztec/foundation/config';
|
|
3
3
|
export const blobArchiveApiConfigMappings = {
|
|
4
4
|
archiveApiUrl: {
|
|
5
|
-
env: '
|
|
5
|
+
env: 'BLOB_ARCHIVE_API_URL',
|
|
6
6
|
description: 'The URL of the archive API'
|
|
7
7
|
},
|
|
8
8
|
...pickConfigMappings(l1ReaderConfigMappings, [
|
|
@@ -8,4 +8,4 @@ export declare class BlobArchiveClientInstrumentation {
|
|
|
8
8
|
incRequest(type: 'blocks' | 'blobs', status: number): void;
|
|
9
9
|
incRetrievedBlobs(count: number): void;
|
|
10
10
|
}
|
|
11
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
11
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5zdHJ1bWVudGF0aW9uLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYXJjaGl2ZS9pbnN0cnVtZW50YXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUdMLEtBQUssZUFBZSxFQUdyQixNQUFNLHlCQUF5QixDQUFDO0FBRWpDLHFCQUFhLGdDQUFnQztJQU96QyxPQUFPLENBQUMsUUFBUTtJQU5sQixPQUFPLENBQUMsbUJBQW1CLENBQWdCO0lBQzNDLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBZ0I7SUFDMUMsT0FBTyxDQUFDLGNBQWMsQ0FBZ0I7SUFFdEMsWUFDRSxNQUFNLEVBQUUsZUFBZSxFQUNmLFFBQVEsRUFBRSxNQUFNLEVBQ3hCLElBQUksRUFBRSxNQUFNLEVBb0JiO0lBRUQsVUFBVSxDQUFDLElBQUksRUFBRSxRQUFRLEdBQUcsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLFFBTWxEO0lBRUQsaUJBQWlCLENBQUMsS0FBSyxFQUFFLE1BQU0sUUFFOUI7Q0FDRiJ9
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instrumentation.d.ts","sourceRoot":"","sources":["../../src/archive/instrumentation.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"instrumentation.d.ts","sourceRoot":"","sources":["../../src/archive/instrumentation.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,eAAe,EAGrB,MAAM,yBAAyB,CAAC;AAEjC,qBAAa,gCAAgC;IAOzC,OAAO,CAAC,QAAQ;IANlB,OAAO,CAAC,mBAAmB,CAAgB;IAC3C,OAAO,CAAC,kBAAkB,CAAgB;IAC1C,OAAO,CAAC,cAAc,CAAgB;IAEtC,YACE,MAAM,EAAE,eAAe,EACf,QAAQ,EAAE,MAAM,EACxB,IAAI,EAAE,MAAM,EAoBb;IAED,UAAU,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,EAAE,MAAM,EAAE,MAAM,QAMlD;IAED,iBAAiB,CAAC,KAAK,EAAE,MAAM,QAE9B;CACF"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Attributes, Metrics,
|
|
1
|
+
import { Attributes, Metrics, createUpDownCounterWithDefault } from '@aztec/telemetry-client';
|
|
2
2
|
export class BlobArchiveClientInstrumentation {
|
|
3
3
|
httpHost;
|
|
4
4
|
blockRequestCounter;
|
|
@@ -7,18 +7,18 @@ export class BlobArchiveClientInstrumentation {
|
|
|
7
7
|
constructor(client, httpHost, name){
|
|
8
8
|
this.httpHost = httpHost;
|
|
9
9
|
const meter = client.getMeter(name);
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
10
|
+
const requestAttrs = {
|
|
11
|
+
[Attributes.HTTP_RESPONSE_STATUS_CODE]: [
|
|
12
|
+
200,
|
|
13
|
+
404
|
|
14
|
+
],
|
|
15
|
+
[Attributes.HTTP_REQUEST_HOST]: [
|
|
16
|
+
httpHost
|
|
17
|
+
]
|
|
18
|
+
};
|
|
19
|
+
this.blockRequestCounter = createUpDownCounterWithDefault(meter, Metrics.BLOB_SINK_ARCHIVE_BLOCK_REQUEST_COUNT, requestAttrs);
|
|
20
|
+
this.blobRequestCounter = createUpDownCounterWithDefault(meter, Metrics.BLOB_SINK_ARCHIVE_BLOB_REQUEST_COUNT, requestAttrs);
|
|
21
|
+
this.retrievedBlobs = createUpDownCounterWithDefault(meter, Metrics.BLOB_SINK_ARCHIVE_BLOB_COUNT);
|
|
22
22
|
}
|
|
23
23
|
incRequest(type, status) {
|
|
24
24
|
const counter = type === 'blocks' ? this.blockRequestCounter : this.blobRequestCounter;
|
|
@@ -12,7 +12,7 @@ export function describeBlobStore(getBlobStore) {
|
|
|
12
12
|
Fr.random(),
|
|
13
13
|
Fr.random()
|
|
14
14
|
];
|
|
15
|
-
const blob = Blob.fromFields(testFields);
|
|
15
|
+
const blob = await Blob.fromFields(testFields);
|
|
16
16
|
const blobHash = blob.getEthVersionedBlobHash();
|
|
17
17
|
// Store the blob
|
|
18
18
|
await blobStore.addBlobs([
|
|
@@ -28,11 +28,11 @@ export function describeBlobStore(getBlobStore) {
|
|
|
28
28
|
});
|
|
29
29
|
it('should handle multiple blobs stored and retrieved by their hashes', async ()=>{
|
|
30
30
|
// Create two different blobs
|
|
31
|
-
const blob1 = Blob.fromFields([
|
|
31
|
+
const blob1 = await Blob.fromFields([
|
|
32
32
|
Fr.random(),
|
|
33
33
|
Fr.random()
|
|
34
34
|
]);
|
|
35
|
-
const blob2 = Blob.fromFields([
|
|
35
|
+
const blob2 = await Blob.fromFields([
|
|
36
36
|
Fr.random(),
|
|
37
37
|
Fr.random(),
|
|
38
38
|
Fr.random()
|
|
@@ -64,13 +64,13 @@ export function describeBlobStore(getBlobStore) {
|
|
|
64
64
|
});
|
|
65
65
|
it('should handle retrieving subset of stored blobs', async ()=>{
|
|
66
66
|
// Store multiple blobs
|
|
67
|
-
const blob1 = Blob.fromFields([
|
|
67
|
+
const blob1 = await Blob.fromFields([
|
|
68
68
|
Fr.random()
|
|
69
69
|
]);
|
|
70
|
-
const blob2 = Blob.fromFields([
|
|
70
|
+
const blob2 = await Blob.fromFields([
|
|
71
71
|
Fr.random()
|
|
72
72
|
]);
|
|
73
|
-
const blob3 = Blob.fromFields([
|
|
73
|
+
const blob3 = await Blob.fromFields([
|
|
74
74
|
Fr.random()
|
|
75
75
|
]);
|
|
76
76
|
await blobStore.addBlobs([
|
|
@@ -90,7 +90,7 @@ export function describeBlobStore(getBlobStore) {
|
|
|
90
90
|
expect(retrievedBlobs[1]).toEqual(blob3);
|
|
91
91
|
});
|
|
92
92
|
it('should handle duplicate blob hashes in request', async ()=>{
|
|
93
|
-
const blob = Blob.fromFields([
|
|
93
|
+
const blob = await Blob.fromFields([
|
|
94
94
|
Fr.random()
|
|
95
95
|
]);
|
|
96
96
|
const blobHash = blob.getEthVersionedBlobHash();
|
|
@@ -112,8 +112,8 @@ export function describeBlobStore(getBlobStore) {
|
|
|
112
112
|
Fr.random(),
|
|
113
113
|
Fr.random()
|
|
114
114
|
];
|
|
115
|
-
const blob1 = Blob.fromFields(fields);
|
|
116
|
-
const blob2 = Blob.fromFields(fields);
|
|
115
|
+
const blob1 = await Blob.fromFields(fields);
|
|
116
|
+
const blob2 = await Blob.fromFields(fields);
|
|
117
117
|
const blobHash = blob1.getEthVersionedBlobHash();
|
|
118
118
|
// Store first blob
|
|
119
119
|
await blobStore.addBlobs([
|
package/dest/client/http.d.ts
CHANGED
|
@@ -60,6 +60,8 @@ export declare class HttpBlobClient implements BlobClientInterface {
|
|
|
60
60
|
private getSlotNumber;
|
|
61
61
|
/** @internal - exposed for testing */
|
|
62
62
|
getArchiveClient(): BlobArchiveClient | undefined;
|
|
63
|
+
/** Returns true if this client can upload blobs to filestore. */
|
|
64
|
+
canUpload(): boolean;
|
|
63
65
|
/**
|
|
64
66
|
* Start the blob client.
|
|
65
67
|
* Uploads the initial healthcheck file (awaited) and starts periodic uploads.
|
|
@@ -74,4 +76,4 @@ export declare class HttpBlobClient implements BlobClientInterface {
|
|
|
74
76
|
*/
|
|
75
77
|
stop(): void;
|
|
76
78
|
}
|
|
77
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
79
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaHR0cC5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NsaWVudC9odHRwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxJQUFJLEVBQUUsS0FBSyxRQUFRLEVBQStCLE1BQU0saUJBQWlCLENBQUM7QUFFbkYsT0FBTyxFQUFFLEtBQUssTUFBTSxFQUFnQixNQUFNLHVCQUF1QixDQUFDO0FBT2xFLE9BQU8sS0FBSyxFQUFFLGlCQUFpQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDakUsT0FBTyxLQUFLLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSx1Q0FBdUMsQ0FBQztBQUVqRixPQUFPLEVBQUUsS0FBSyxnQkFBZ0IsRUFBOEIsTUFBTSxhQUFhLENBQUM7QUFDaEYsT0FBTyxLQUFLLEVBQUUsbUJBQW1CLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUVqRixxQkFBYSxjQUFlLFlBQVcsbUJBQW1CO0lBYXRELE9BQU8sQ0FBQyxRQUFRLENBQUMsSUFBSTtJQVp2QixTQUFTLENBQUMsUUFBUSxDQUFDLEdBQUcsRUFBRSxNQUFNLENBQUM7SUFDL0IsU0FBUyxDQUFDLFFBQVEsQ0FBQyxNQUFNLEVBQUUsZ0JBQWdCLENBQUM7SUFDNUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxhQUFhLEVBQUUsaUJBQWlCLEdBQUcsU0FBUyxDQUFDO0lBQ2hFLFNBQVMsQ0FBQyxRQUFRLENBQUMsS0FBSyxFQUFFLE9BQU8sS0FBSyxDQUFDO0lBQ3ZDLFNBQVMsQ0FBQyxRQUFRLENBQUMsZ0JBQWdCLEVBQUUsbUJBQW1CLEVBQUUsQ0FBQztJQUMzRCxTQUFTLENBQUMsUUFBUSxDQUFDLHFCQUFxQixFQUFFLG1CQUFtQixHQUFHLFNBQVMsQ0FBQztJQUUxRSxPQUFPLENBQUMsUUFBUSxDQUFTO0lBQ3pCLE9BQU8sQ0FBQywyQkFBMkIsQ0FBQyxDQUFpQjtJQUVyRCxZQUNFLE1BQU0sQ0FBQyxFQUFFLGdCQUFnQixFQUNSLElBQUksR0FBRTtRQUNyQixNQUFNLENBQUMsRUFBRSxNQUFNLENBQUM7UUFDaEIsYUFBYSxDQUFDLEVBQUUsaUJBQWlCLENBQUM7UUFDbEMsZ0JBQWdCLENBQUMsRUFBRSxtQkFBbUIsRUFBRSxDQUFDO1FBQ3pDLHFCQUFxQixDQUFDLEVBQUUsbUJBQW1CLENBQUM7UUFDNUMseUVBQXlFO1FBQ3pFLGNBQWMsQ0FBQyxFQUFFLENBQUMsS0FBSyxFQUFFLElBQUksRUFBRSxLQUFLLElBQUksQ0FBQztLQUNyQyxFQXdCUDtJQUVEOzs7T0FHRztJQUNILE9BQU8sQ0FBQyxzQkFBc0I7SUFVOUI7Ozs7O09BS0c7SUFDSSxXQUFXLENBQUMsS0FBSyxFQUFFLE9BQU8sR0FBRyxJQUFJLENBR3ZDO0lBRVksV0FBVyxrQkFvRXZCO0lBRVksb0JBQW9CLENBQUMsS0FBSyxFQUFFLElBQUksRUFBRSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FtQmpFO0lBRUQ7Ozs7Ozs7Ozs7Ozs7O09BY0c7SUFDVSxjQUFjLENBQ3pCLFNBQVMsRUFBRSxLQUFLLE1BQU0sRUFBRSxFQUN4QixVQUFVLEVBQUUsTUFBTSxFQUFFLEVBQ3BCLElBQUksQ0FBQyxFQUFFLHFCQUFxQixHQUMzQixPQUFPLENBQUMsSUFBSSxFQUFFLENBQUMsQ0E2SWpCO1lBUWEsYUFBYTtJQXNDZCxrQkFBa0IsQ0FDN0IsT0FBTyxFQUFFLE1BQU0sRUFDZixlQUFlLEVBQUUsTUFBTSxHQUFHLE1BQU0sRUFDaEMsVUFBVSxHQUFFLE1BQU0sRUFBTyxFQUN6QixvQkFBb0IsQ0FBQyxFQUFFLE1BQU0sR0FDNUIsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDLENBR2pCO0lBRVksZ0JBQWdCLENBQzNCLE9BQU8sRUFBRSxNQUFNLEVBQ2YsZUFBZSxFQUFFLE1BQU0sR0FBRyxNQUFNLEVBQ2hDLG9CQUFvQixDQUFDLEVBQUUsTUFBTSxHQUM1QixPQUFPLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FzQ3JCO0lBRUQsT0FBTyxDQUFDLGlCQUFpQjtZQVlYLG1CQUFtQjtZQW1DbkIsYUFBYTtJQTZEM0Isc0NBQXNDO0lBQy9CLGdCQUFnQixJQUFJLGlCQUFpQixHQUFHLFNBQVMsQ0FFdkQ7SUFFRCxpRUFBaUU7SUFDMUQsU0FBUyxJQUFJLE9BQU8sQ0FFMUI7SUFFRDs7O09BR0c7SUFDVSxLQUFLLElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxDQVNsQztJQUVEOztPQUVHO0lBQ0gsT0FBTyxDQUFDLDhCQUE4QjtJQVd0Qzs7T0FFRztJQUNJLElBQUksSUFBSSxJQUFJLENBS2xCO0NBQ0YifQ==
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/client/http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,KAAK,QAAQ,EAA+B,MAAM,iBAAiB,CAAC;AAEnF,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,uBAAuB,CAAC;AAOlE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uCAAuC,CAAC;AAEjF,OAAO,EAAE,KAAK,gBAAgB,EAA8B,MAAM,aAAa,CAAC;AAChF,OAAO,KAAK,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAEjF,qBAAa,cAAe,YAAW,mBAAmB;IAatD,OAAO,CAAC,QAAQ,CAAC,IAAI;IAZvB,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAC/B,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAC5C,SAAS,CAAC,QAAQ,CAAC,aAAa,EAAE,iBAAiB,GAAG,SAAS,CAAC;IAChE,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,KAAK,CAAC;IACvC,SAAS,CAAC,QAAQ,CAAC,gBAAgB,EAAE,mBAAmB,EAAE,CAAC;IAC3D,SAAS,CAAC,QAAQ,CAAC,qBAAqB,EAAE,mBAAmB,GAAG,SAAS,CAAC;IAE1E,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,2BAA2B,CAAC,CAAiB;IAErD,YACE,MAAM,CAAC,EAAE,gBAAgB,EACR,IAAI,GAAE;QACrB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,aAAa,CAAC,EAAE,iBAAiB,CAAC;QAClC,gBAAgB,CAAC,EAAE,mBAAmB,EAAE,CAAC;QACzC,qBAAqB,CAAC,EAAE,mBAAmB,CAAC;QAC5C,yEAAyE;QACzE,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;KACrC,EAwBP;IAED;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IAU9B;;;;;OAKG;IACI,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAGvC;IAEY,WAAW,kBAoEvB;IAEY,oBAAoB,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAmBjE;IAED;;;;;;;;;;;;;;OAcG;IACU,cAAc,CACzB,SAAS,EAAE,KAAK,MAAM,EAAE,EACxB,UAAU,EAAE,MAAM,EAAE,EACpB,IAAI,CAAC,EAAE,qBAAqB,GAC3B,OAAO,CAAC,IAAI,EAAE,CAAC,CA6IjB;YAQa,aAAa;IAsCd,kBAAkB,CAC7B,OAAO,EAAE,MAAM,EACf,eAAe,EAAE,MAAM,GAAG,MAAM,EAChC,UAAU,GAAE,MAAM,EAAO,EACzB,oBAAoB,CAAC,EAAE,MAAM,GAC5B,OAAO,CAAC,IAAI,EAAE,CAAC,CAGjB;IAEY,gBAAgB,CAC3B,OAAO,EAAE,MAAM,EACf,eAAe,EAAE,MAAM,GAAG,MAAM,EAChC,oBAAoB,CAAC,EAAE,MAAM,GAC5B,OAAO,CAAC,QAAQ,EAAE,CAAC,CAsCrB;IAED,OAAO,CAAC,iBAAiB;YAYX,mBAAmB;YAmCnB,aAAa;IA6D3B,sCAAsC;IAC/B,gBAAgB,IAAI,iBAAiB,GAAG,SAAS,CAEvD;IAED;;;OAGG;IACU,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CASlC;IAED;;OAEG;IACH,OAAO,CAAC,8BAA8B;IAWtC;;OAEG;IACI,IAAI,IAAI,IAAI,CAKlB;CACF"}
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/client/http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,KAAK,QAAQ,EAA+B,MAAM,iBAAiB,CAAC;AAEnF,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,uBAAuB,CAAC;AAOlE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uCAAuC,CAAC;AAEjF,OAAO,EAAE,KAAK,gBAAgB,EAA8B,MAAM,aAAa,CAAC;AAChF,OAAO,KAAK,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAEjF,qBAAa,cAAe,YAAW,mBAAmB;IAatD,OAAO,CAAC,QAAQ,CAAC,IAAI;IAZvB,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAC/B,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAC5C,SAAS,CAAC,QAAQ,CAAC,aAAa,EAAE,iBAAiB,GAAG,SAAS,CAAC;IAChE,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,KAAK,CAAC;IACvC,SAAS,CAAC,QAAQ,CAAC,gBAAgB,EAAE,mBAAmB,EAAE,CAAC;IAC3D,SAAS,CAAC,QAAQ,CAAC,qBAAqB,EAAE,mBAAmB,GAAG,SAAS,CAAC;IAE1E,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,2BAA2B,CAAC,CAAiB;IAErD,YACE,MAAM,CAAC,EAAE,gBAAgB,EACR,IAAI,GAAE;QACrB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,aAAa,CAAC,EAAE,iBAAiB,CAAC;QAClC,gBAAgB,CAAC,EAAE,mBAAmB,EAAE,CAAC;QACzC,qBAAqB,CAAC,EAAE,mBAAmB,CAAC;QAC5C,yEAAyE;QACzE,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;KACrC,EAwBP;IAED;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IAU9B;;;;;OAKG;IACI,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAGvC;IAEY,WAAW,kBAoEvB;IAEY,oBAAoB,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAmBjE;IAED;;;;;;;;;;;;;;OAcG;IACU,cAAc,CACzB,SAAS,EAAE,KAAK,MAAM,EAAE,EACxB,UAAU,EAAE,MAAM,EAAE,EACpB,IAAI,CAAC,EAAE,qBAAqB,GAC3B,OAAO,CAAC,IAAI,EAAE,CAAC,CA6IjB;YAQa,aAAa;IAsCd,kBAAkB,CAC7B,OAAO,EAAE,MAAM,EACf,eAAe,EAAE,MAAM,GAAG,MAAM,EAChC,UAAU,GAAE,MAAM,EAAO,EACzB,oBAAoB,CAAC,EAAE,MAAM,GAC5B,OAAO,CAAC,IAAI,EAAE,CAAC,CAGjB;IAEY,gBAAgB,CAC3B,OAAO,EAAE,MAAM,EACf,eAAe,EAAE,MAAM,GAAG,MAAM,EAChC,oBAAoB,CAAC,EAAE,MAAM,GAC5B,OAAO,CAAC,QAAQ,EAAE,CAAC,CAsCrB;IAED,OAAO,CAAC,iBAAiB;YAYX,mBAAmB;YAmCnB,aAAa;IA6D3B,sCAAsC;IAC/B,gBAAgB,IAAI,iBAAiB,GAAG,SAAS,CAEvD;IAED,iEAAiE;IAC1D,SAAS,IAAI,OAAO,CAE1B;IAED;;;OAGG;IACU,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CASlC;IAED;;OAEG;IACH,OAAO,CAAC,8BAA8B;IAWtC;;OAEG;IACI,IAAI,IAAI,IAAI,CAKlB;CACF"}
|
package/dest/client/http.js
CHANGED
|
@@ -183,8 +183,8 @@ export class HttpBlobClient {
|
|
|
183
183
|
// Return the result, ignoring any undefined ones
|
|
184
184
|
const getFilledBlobs = ()=>resultBlobs.filter((b)=>b !== undefined);
|
|
185
185
|
// Helper to fill in results from fetched blobs
|
|
186
|
-
const fillResults = (fetchedBlobs)=>{
|
|
187
|
-
const blobs = processFetchedBlobs(fetchedBlobs, blobHashes, this.log);
|
|
186
|
+
const fillResults = async (fetchedBlobs)=>{
|
|
187
|
+
const blobs = await processFetchedBlobs(fetchedBlobs, blobHashes, this.log);
|
|
188
188
|
// Fill in any missing positions with matching blobs
|
|
189
189
|
for(let i = 0; i < blobHashes.length; i++){
|
|
190
190
|
if (resultBlobs[i] === undefined) {
|
|
@@ -236,7 +236,7 @@ export class HttpBlobClient {
|
|
|
236
236
|
...ctx
|
|
237
237
|
});
|
|
238
238
|
const blobs = await this.getBlobsFromHost(l1ConsensusHostUrl, slotNumber, l1ConsensusHostIndex);
|
|
239
|
-
const result = fillResults(blobs);
|
|
239
|
+
const result = await fillResults(blobs);
|
|
240
240
|
this.log.debug(`Got ${blobs.length} blobs from consensus host (total: ${result.length}/${blobHashes.length})`, {
|
|
241
241
|
slotNumber,
|
|
242
242
|
l1ConsensusHostUrl,
|
|
@@ -279,7 +279,7 @@ export class HttpBlobClient {
|
|
|
279
279
|
this.log.debug('No blobs found from archive client', archiveCtx);
|
|
280
280
|
} else {
|
|
281
281
|
this.log.trace(`Got ${allBlobs.length} blobs from archive client before filtering`, archiveCtx);
|
|
282
|
-
const result = fillResults(allBlobs);
|
|
282
|
+
const result = await fillResults(allBlobs);
|
|
283
283
|
this.log.debug(`Got ${allBlobs.length} blobs from archive client (total: ${result.length}/${blobHashes.length})`, archiveCtx);
|
|
284
284
|
if (result.length === blobHashes.length) {
|
|
285
285
|
return returnWithCallback(result);
|
|
@@ -320,7 +320,7 @@ export class HttpBlobClient {
|
|
|
320
320
|
});
|
|
321
321
|
const blobs = await client.getBlobsByHashes(blobHashStrings);
|
|
322
322
|
if (blobs.length > 0) {
|
|
323
|
-
const result = fillResults(blobs);
|
|
323
|
+
const result = await fillResults(blobs);
|
|
324
324
|
this.log.debug(`Got ${blobs.length} blobs from filestore (total: ${result.length}/${ctx.blobHashes.length})`, {
|
|
325
325
|
url: client.getBaseUrl(),
|
|
326
326
|
...ctx
|
|
@@ -335,7 +335,7 @@ export class HttpBlobClient {
|
|
|
335
335
|
}
|
|
336
336
|
async getBlobSidecarFrom(hostUrl, blockHashOrSlot, blobHashes = [], l1ConsensusHostIndex) {
|
|
337
337
|
const blobs = await this.getBlobsFromHost(hostUrl, blockHashOrSlot, l1ConsensusHostIndex);
|
|
338
|
-
return processFetchedBlobs(blobs, blobHashes, this.log).filter((b)=>b !== undefined);
|
|
338
|
+
return (await processFetchedBlobs(blobs, blobHashes, this.log)).filter((b)=>b !== undefined);
|
|
339
339
|
}
|
|
340
340
|
async getBlobsFromHost(hostUrl, blockHashOrSlot, l1ConsensusHostIndex) {
|
|
341
341
|
try {
|
|
@@ -476,6 +476,9 @@ export class HttpBlobClient {
|
|
|
476
476
|
/** @internal - exposed for testing */ getArchiveClient() {
|
|
477
477
|
return this.archiveClient;
|
|
478
478
|
}
|
|
479
|
+
/** Returns true if this client can upload blobs to filestore. */ canUpload() {
|
|
480
|
+
return this.fileStoreUploadClient !== undefined;
|
|
481
|
+
}
|
|
479
482
|
/**
|
|
480
483
|
* Start the blob client.
|
|
481
484
|
* Uploads the initial healthcheck file (awaited) and starts periodic uploads.
|
|
@@ -527,7 +530,7 @@ function parseBlobJson(data) {
|
|
|
527
530
|
}
|
|
528
531
|
// Returns an array that maps each blob hash to the corresponding blob, or undefined if the blob is not found
|
|
529
532
|
// or the data does not match the commitment.
|
|
530
|
-
function processFetchedBlobs(blobs, blobHashes, logger) {
|
|
533
|
+
async function processFetchedBlobs(blobs, blobHashes, logger) {
|
|
531
534
|
const requestedBlobHashes = new Set(blobHashes.map(bufferToHex));
|
|
532
535
|
const hashToBlob = new Map();
|
|
533
536
|
for (const blobJson of blobs){
|
|
@@ -536,7 +539,7 @@ function processFetchedBlobs(blobs, blobHashes, logger) {
|
|
|
536
539
|
continue;
|
|
537
540
|
}
|
|
538
541
|
try {
|
|
539
|
-
const blob = Blob.fromJson(blobJson);
|
|
542
|
+
const blob = await Blob.fromJson(blobJson);
|
|
540
543
|
hashToBlob.set(hashHex, blob);
|
|
541
544
|
} catch (err) {
|
|
542
545
|
// If the above throws, it's likely that the blob commitment does not match the hash of the blob data.
|
|
@@ -22,5 +22,7 @@ export interface BlobClientInterface {
|
|
|
22
22
|
testSources(): Promise<void>;
|
|
23
23
|
/** Stops the blob client, clearing any periodic tasks. */
|
|
24
24
|
stop?(): void;
|
|
25
|
+
/** Returns true if this client can upload blobs to filestore. */
|
|
26
|
+
canUpload(): boolean;
|
|
25
27
|
}
|
|
26
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
28
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZXJmYWNlLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY2xpZW50L2ludGVyZmFjZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxJQUFJLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUU1Qzs7R0FFRztBQUNILE1BQU0sV0FBVyxxQkFBcUI7SUFDcEM7Ozs7O09BS0c7SUFDSCxnQkFBZ0IsQ0FBQyxFQUFFLE9BQU8sQ0FBQztDQUM1QjtBQUVELE1BQU0sV0FBVyxtQkFBbUI7SUFDbEMsMEVBQTBFO0lBQzFFLG9CQUFvQixDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDdEQscUVBQXFFO0lBQ3JFLGNBQWMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLFVBQVUsQ0FBQyxFQUFFLE1BQU0sRUFBRSxFQUFFLElBQUksQ0FBQyxFQUFFLHFCQUFxQixHQUFHLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQ3RHLDZFQUE2RTtJQUM3RSxLQUFLLENBQUMsSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDeEIsb0ZBQW9GO0lBQ3BGLFdBQVcsSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDN0IsMERBQTBEO0lBQzFELElBQUksQ0FBQyxJQUFJLElBQUksQ0FBQztJQUNkLGlFQUFpRTtJQUNqRSxTQUFTLElBQUksT0FBTyxDQUFDO0NBQ3RCIn0=
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../src/client/interface.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAE5C;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,mBAAmB;IAClC,0EAA0E;IAC1E,oBAAoB,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACtD,qEAAqE;IACrE,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,EAAE,IAAI,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IACtG,6EAA6E;IAC7E,KAAK,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACxB,oFAAoF;IACpF,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,0DAA0D;IAC1D,IAAI,CAAC,IAAI,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../src/client/interface.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAE5C;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,mBAAmB;IAClC,0EAA0E;IAC1E,oBAAoB,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACtD,qEAAqE;IACrE,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,EAAE,IAAI,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IACtG,6EAA6E;IAC7E,KAAK,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACxB,oFAAoF;IACpF,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,0DAA0D;IAC1D,IAAI,CAAC,IAAI,IAAI,CAAC;IACd,iEAAiE;IACjE,SAAS,IAAI,OAAO,CAAC;CACtB"}
|
package/dest/client/local.d.ts
CHANGED
|
@@ -7,5 +7,7 @@ export declare class LocalBlobClient implements BlobClientInterface {
|
|
|
7
7
|
testSources(): Promise<void>;
|
|
8
8
|
sendBlobsToFilestore(blobs: Blob[]): Promise<boolean>;
|
|
9
9
|
getBlobSidecar(_blockId: string, blobHashes: Buffer[], _opts?: GetBlobSidecarOptions): Promise<Blob[]>;
|
|
10
|
+
/** Returns true if this client can upload blobs. Always true for local client. */
|
|
11
|
+
canUpload(): boolean;
|
|
10
12
|
}
|
|
11
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
13
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9jYWwuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jbGllbnQvbG9jYWwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLEVBQUUsSUFBSSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFFNUMsT0FBTyxLQUFLLEVBQUUsU0FBUyxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDdkQsT0FBTyxLQUFLLEVBQUUsbUJBQW1CLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUVqRixxQkFBYSxlQUFnQixZQUFXLG1CQUFtQjtJQUN6RCxPQUFPLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBWTtJQUV0QyxZQUFZLFNBQVMsRUFBRSxTQUFTLEVBRS9CO0lBRU0sV0FBVyxJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FFbEM7SUFFWSxvQkFBb0IsQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUdqRTtJQUVNLGNBQWMsQ0FBQyxRQUFRLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsRUFBRSxLQUFLLENBQUMsRUFBRSxxQkFBcUIsR0FBRyxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FFNUc7SUFFRCxrRkFBa0Y7SUFDM0UsU0FBUyxJQUFJLE9BQU8sQ0FFMUI7Q0FDRiJ9
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local.d.ts","sourceRoot":"","sources":["../../src/client/local.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,KAAK,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAEjF,qBAAa,eAAgB,YAAW,mBAAmB;IACzD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAY;IAEtC,YAAY,SAAS,EAAE,SAAS,EAE/B;IAEM,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAElC;IAEY,oBAAoB,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAGjE;IAEM,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,KAAK,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAE5G;CACF"}
|
|
1
|
+
{"version":3,"file":"local.d.ts","sourceRoot":"","sources":["../../src/client/local.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,KAAK,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAEjF,qBAAa,eAAgB,YAAW,mBAAmB;IACzD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAY;IAEtC,YAAY,SAAS,EAAE,SAAS,EAE/B;IAEM,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAElC;IAEY,oBAAoB,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAGjE;IAEM,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,KAAK,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAE5G;IAED,kFAAkF;IAC3E,SAAS,IAAI,OAAO,CAE1B;CACF"}
|
package/dest/client/local.js
CHANGED
|
@@ -13,4 +13,7 @@ export class LocalBlobClient {
|
|
|
13
13
|
getBlobSidecar(_blockId, blobHashes, _opts) {
|
|
14
14
|
return this.blobStore.getBlobsByHashes(blobHashes);
|
|
15
15
|
}
|
|
16
|
+
/** Returns true if this client can upload blobs. Always true for local client. */ canUpload() {
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
16
19
|
}
|
package/dest/client/tests.js
CHANGED
|
@@ -17,7 +17,7 @@ import { makeRandomBlob } from '@aztec/blob-lib/testing';
|
|
|
17
17
|
await cleanup();
|
|
18
18
|
});
|
|
19
19
|
it('should send and retrieve blobs by hash', async ()=>{
|
|
20
|
-
const blob = makeRandomBlob(5);
|
|
20
|
+
const blob = await makeRandomBlob(5);
|
|
21
21
|
const blobHash = blob.getEthVersionedBlobHash();
|
|
22
22
|
await client.sendBlobsToFilestore([
|
|
23
23
|
blob
|
|
@@ -29,9 +29,9 @@ import { makeRandomBlob } from '@aztec/blob-lib/testing';
|
|
|
29
29
|
expect(retrievedBlobs[0]).toEqual(blob);
|
|
30
30
|
});
|
|
31
31
|
it('should handle multiple blobs', async ()=>{
|
|
32
|
-
const blobs = Array.from({
|
|
32
|
+
const blobs = await Promise.all(Array.from({
|
|
33
33
|
length: 3
|
|
34
|
-
}, ()=>makeRandomBlob(7));
|
|
34
|
+
}, ()=>makeRandomBlob(7)));
|
|
35
35
|
const blobHashes = blobs.map((blob)=>blob.getEthVersionedBlobHash());
|
|
36
36
|
await client.sendBlobsToFilestore(blobs);
|
|
37
37
|
const retrievedBlobs = await client.getBlobSidecar(blockId, blobHashes);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/blob-client",
|
|
3
|
-
"version": "0.0.1-commit.
|
|
3
|
+
"version": "0.0.1-commit.ff7989d6c",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": "./dest/client/bin/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -56,12 +56,12 @@
|
|
|
56
56
|
]
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
|
-
"@aztec/blob-lib": "0.0.1-commit.
|
|
60
|
-
"@aztec/ethereum": "0.0.1-commit.
|
|
61
|
-
"@aztec/foundation": "0.0.1-commit.
|
|
62
|
-
"@aztec/kv-store": "0.0.1-commit.
|
|
63
|
-
"@aztec/stdlib": "0.0.1-commit.
|
|
64
|
-
"@aztec/telemetry-client": "0.0.1-commit.
|
|
59
|
+
"@aztec/blob-lib": "0.0.1-commit.ff7989d6c",
|
|
60
|
+
"@aztec/ethereum": "0.0.1-commit.ff7989d6c",
|
|
61
|
+
"@aztec/foundation": "0.0.1-commit.ff7989d6c",
|
|
62
|
+
"@aztec/kv-store": "0.0.1-commit.ff7989d6c",
|
|
63
|
+
"@aztec/stdlib": "0.0.1-commit.ff7989d6c",
|
|
64
|
+
"@aztec/telemetry-client": "0.0.1-commit.ff7989d6c",
|
|
65
65
|
"express": "^4.21.2",
|
|
66
66
|
"snappy": "^7.2.2",
|
|
67
67
|
"source-map-support": "^0.5.21",
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
"@types/node": "^22.15.17",
|
|
76
76
|
"@types/source-map-support": "^0.5.10",
|
|
77
77
|
"@types/supertest": "^6.0.2",
|
|
78
|
-
"@typescript/native-preview": "7.0.0-dev.
|
|
78
|
+
"@typescript/native-preview": "7.0.0-dev.20260113.1",
|
|
79
79
|
"jest": "^30.0.0",
|
|
80
80
|
"jest-mock-extended": "^4.0.0",
|
|
81
81
|
"supertest": "^7.0.0",
|
package/src/archive/config.ts
CHANGED
|
@@ -7,7 +7,7 @@ export type BlobArchiveApiConfig = {
|
|
|
7
7
|
|
|
8
8
|
export const blobArchiveApiConfigMappings: ConfigMappingsType<BlobArchiveApiConfig> = {
|
|
9
9
|
archiveApiUrl: {
|
|
10
|
-
env: '
|
|
10
|
+
env: 'BLOB_ARCHIVE_API_URL',
|
|
11
11
|
description: 'The URL of the archive API',
|
|
12
12
|
},
|
|
13
13
|
...pickConfigMappings(l1ReaderConfigMappings, ['l1ChainId']),
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
Attributes,
|
|
3
|
+
Metrics,
|
|
4
|
+
type TelemetryClient,
|
|
5
|
+
type UpDownCounter,
|
|
6
|
+
createUpDownCounterWithDefault,
|
|
7
|
+
} from '@aztec/telemetry-client';
|
|
2
8
|
|
|
3
9
|
export class BlobArchiveClientInstrumentation {
|
|
4
10
|
private blockRequestCounter: UpDownCounter;
|
|
@@ -11,20 +17,23 @@ export class BlobArchiveClientInstrumentation {
|
|
|
11
17
|
name: string,
|
|
12
18
|
) {
|
|
13
19
|
const meter = client.getMeter(name);
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
20
|
+
const requestAttrs = {
|
|
21
|
+
[Attributes.HTTP_RESPONSE_STATUS_CODE]: [200, 404],
|
|
22
|
+
[Attributes.HTTP_REQUEST_HOST]: [httpHost],
|
|
23
|
+
};
|
|
24
|
+
this.blockRequestCounter = createUpDownCounterWithDefault(
|
|
25
|
+
meter,
|
|
26
|
+
Metrics.BLOB_SINK_ARCHIVE_BLOCK_REQUEST_COUNT,
|
|
27
|
+
requestAttrs,
|
|
28
|
+
);
|
|
18
29
|
|
|
19
|
-
this.blobRequestCounter =
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
30
|
+
this.blobRequestCounter = createUpDownCounterWithDefault(
|
|
31
|
+
meter,
|
|
32
|
+
Metrics.BLOB_SINK_ARCHIVE_BLOB_REQUEST_COUNT,
|
|
33
|
+
requestAttrs,
|
|
34
|
+
);
|
|
23
35
|
|
|
24
|
-
this.retrievedBlobs = meter
|
|
25
|
-
description: 'Number of blobs retrieved from the blob archive',
|
|
26
|
-
valueType: ValueType.INT,
|
|
27
|
-
});
|
|
36
|
+
this.retrievedBlobs = createUpDownCounterWithDefault(meter, Metrics.BLOB_SINK_ARCHIVE_BLOB_COUNT);
|
|
28
37
|
}
|
|
29
38
|
|
|
30
39
|
incRequest(type: 'blocks' | 'blobs', status: number) {
|
|
@@ -13,7 +13,7 @@ export function describeBlobStore(getBlobStore: () => Promise<BlobStore>) {
|
|
|
13
13
|
it('should store and retrieve a blob by hash', async () => {
|
|
14
14
|
// Create a test blob with random fields
|
|
15
15
|
const testFields = [Fr.random(), Fr.random(), Fr.random()];
|
|
16
|
-
const blob = Blob.fromFields(testFields);
|
|
16
|
+
const blob = await Blob.fromFields(testFields);
|
|
17
17
|
const blobHash = blob.getEthVersionedBlobHash();
|
|
18
18
|
|
|
19
19
|
// Store the blob
|
|
@@ -29,8 +29,8 @@ export function describeBlobStore(getBlobStore: () => Promise<BlobStore>) {
|
|
|
29
29
|
|
|
30
30
|
it('should handle multiple blobs stored and retrieved by their hashes', async () => {
|
|
31
31
|
// Create two different blobs
|
|
32
|
-
const blob1 = Blob.fromFields([Fr.random(), Fr.random()]);
|
|
33
|
-
const blob2 = Blob.fromFields([Fr.random(), Fr.random(), Fr.random()]);
|
|
32
|
+
const blob1 = await Blob.fromFields([Fr.random(), Fr.random()]);
|
|
33
|
+
const blob2 = await Blob.fromFields([Fr.random(), Fr.random(), Fr.random()]);
|
|
34
34
|
|
|
35
35
|
const blobHash1 = blob1.getEthVersionedBlobHash();
|
|
36
36
|
const blobHash2 = blob2.getEthVersionedBlobHash();
|
|
@@ -57,9 +57,9 @@ export function describeBlobStore(getBlobStore: () => Promise<BlobStore>) {
|
|
|
57
57
|
|
|
58
58
|
it('should handle retrieving subset of stored blobs', async () => {
|
|
59
59
|
// Store multiple blobs
|
|
60
|
-
const blob1 = Blob.fromFields([Fr.random()]);
|
|
61
|
-
const blob2 = Blob.fromFields([Fr.random()]);
|
|
62
|
-
const blob3 = Blob.fromFields([Fr.random()]);
|
|
60
|
+
const blob1 = await Blob.fromFields([Fr.random()]);
|
|
61
|
+
const blob2 = await Blob.fromFields([Fr.random()]);
|
|
62
|
+
const blob3 = await Blob.fromFields([Fr.random()]);
|
|
63
63
|
|
|
64
64
|
await blobStore.addBlobs([blob1, blob2, blob3]);
|
|
65
65
|
|
|
@@ -75,7 +75,7 @@ export function describeBlobStore(getBlobStore: () => Promise<BlobStore>) {
|
|
|
75
75
|
});
|
|
76
76
|
|
|
77
77
|
it('should handle duplicate blob hashes in request', async () => {
|
|
78
|
-
const blob = Blob.fromFields([Fr.random()]);
|
|
78
|
+
const blob = await Blob.fromFields([Fr.random()]);
|
|
79
79
|
const blobHash = blob.getEthVersionedBlobHash();
|
|
80
80
|
|
|
81
81
|
await blobStore.addBlobs([blob]);
|
|
@@ -91,8 +91,8 @@ export function describeBlobStore(getBlobStore: () => Promise<BlobStore>) {
|
|
|
91
91
|
it('should overwrite blob when storing with same hash', async () => {
|
|
92
92
|
// Create two blobs that will have the same hash (same content)
|
|
93
93
|
const fields = [Fr.random(), Fr.random()];
|
|
94
|
-
const blob1 = Blob.fromFields(fields);
|
|
95
|
-
const blob2 = Blob.fromFields(fields);
|
|
94
|
+
const blob1 = await Blob.fromFields(fields);
|
|
95
|
+
const blob2 = await Blob.fromFields(fields);
|
|
96
96
|
|
|
97
97
|
const blobHash = blob1.getEthVersionedBlobHash();
|
|
98
98
|
|
package/src/client/http.ts
CHANGED
|
@@ -215,8 +215,8 @@ export class HttpBlobClient implements BlobClientInterface {
|
|
|
215
215
|
const getFilledBlobs = (): Blob[] => resultBlobs.filter((b): b is Blob => b !== undefined);
|
|
216
216
|
|
|
217
217
|
// Helper to fill in results from fetched blobs
|
|
218
|
-
const fillResults = (fetchedBlobs: BlobJson[]): Blob[] => {
|
|
219
|
-
const blobs = processFetchedBlobs(fetchedBlobs, blobHashes, this.log);
|
|
218
|
+
const fillResults = async (fetchedBlobs: BlobJson[]): Promise<Blob[]> => {
|
|
219
|
+
const blobs = await processFetchedBlobs(fetchedBlobs, blobHashes, this.log);
|
|
220
220
|
// Fill in any missing positions with matching blobs
|
|
221
221
|
for (let i = 0; i < blobHashes.length; i++) {
|
|
222
222
|
if (resultBlobs[i] === undefined) {
|
|
@@ -269,7 +269,7 @@ export class HttpBlobClient implements BlobClientInterface {
|
|
|
269
269
|
...ctx,
|
|
270
270
|
});
|
|
271
271
|
const blobs = await this.getBlobsFromHost(l1ConsensusHostUrl, slotNumber, l1ConsensusHostIndex);
|
|
272
|
-
const result = fillResults(blobs);
|
|
272
|
+
const result = await fillResults(blobs);
|
|
273
273
|
this.log.debug(
|
|
274
274
|
`Got ${blobs.length} blobs from consensus host (total: ${result.length}/${blobHashes.length})`,
|
|
275
275
|
{ slotNumber, l1ConsensusHostUrl, ...ctx },
|
|
@@ -312,7 +312,7 @@ export class HttpBlobClient implements BlobClientInterface {
|
|
|
312
312
|
this.log.debug('No blobs found from archive client', archiveCtx);
|
|
313
313
|
} else {
|
|
314
314
|
this.log.trace(`Got ${allBlobs.length} blobs from archive client before filtering`, archiveCtx);
|
|
315
|
-
const result = fillResults(allBlobs);
|
|
315
|
+
const result = await fillResults(allBlobs);
|
|
316
316
|
this.log.debug(
|
|
317
317
|
`Got ${allBlobs.length} blobs from archive client (total: ${result.length}/${blobHashes.length})`,
|
|
318
318
|
archiveCtx,
|
|
@@ -345,7 +345,7 @@ export class HttpBlobClient implements BlobClientInterface {
|
|
|
345
345
|
*/
|
|
346
346
|
private async tryFileStores(
|
|
347
347
|
getMissingBlobHashes: () => Buffer[],
|
|
348
|
-
fillResults: (blobs: BlobJson[]) => Blob[]
|
|
348
|
+
fillResults: (blobs: BlobJson[]) => Promise<Blob[]>,
|
|
349
349
|
ctx: { blockHash: string; blobHashes: string[] },
|
|
350
350
|
): Promise<void> {
|
|
351
351
|
// Shuffle clients for load distribution
|
|
@@ -366,7 +366,7 @@ export class HttpBlobClient implements BlobClientInterface {
|
|
|
366
366
|
});
|
|
367
367
|
const blobs = await client.getBlobsByHashes(blobHashStrings);
|
|
368
368
|
if (blobs.length > 0) {
|
|
369
|
-
const result = fillResults(blobs);
|
|
369
|
+
const result = await fillResults(blobs);
|
|
370
370
|
this.log.debug(
|
|
371
371
|
`Got ${blobs.length} blobs from filestore (total: ${result.length}/${ctx.blobHashes.length})`,
|
|
372
372
|
{
|
|
@@ -388,7 +388,7 @@ export class HttpBlobClient implements BlobClientInterface {
|
|
|
388
388
|
l1ConsensusHostIndex?: number,
|
|
389
389
|
): Promise<Blob[]> {
|
|
390
390
|
const blobs = await this.getBlobsFromHost(hostUrl, blockHashOrSlot, l1ConsensusHostIndex);
|
|
391
|
-
return processFetchedBlobs(blobs, blobHashes, this.log).filter((b): b is Blob => b !== undefined);
|
|
391
|
+
return (await processFetchedBlobs(blobs, blobHashes, this.log)).filter((b): b is Blob => b !== undefined);
|
|
392
392
|
}
|
|
393
393
|
|
|
394
394
|
public async getBlobsFromHost(
|
|
@@ -548,6 +548,11 @@ export class HttpBlobClient implements BlobClientInterface {
|
|
|
548
548
|
return this.archiveClient;
|
|
549
549
|
}
|
|
550
550
|
|
|
551
|
+
/** Returns true if this client can upload blobs to filestore. */
|
|
552
|
+
public canUpload(): boolean {
|
|
553
|
+
return this.fileStoreUploadClient !== undefined;
|
|
554
|
+
}
|
|
555
|
+
|
|
551
556
|
/**
|
|
552
557
|
* Start the blob client.
|
|
553
558
|
* Uploads the initial healthcheck file (awaited) and starts periodic uploads.
|
|
@@ -611,7 +616,11 @@ function parseBlobJson(data: any): BlobJson {
|
|
|
611
616
|
|
|
612
617
|
// Returns an array that maps each blob hash to the corresponding blob, or undefined if the blob is not found
|
|
613
618
|
// or the data does not match the commitment.
|
|
614
|
-
function processFetchedBlobs(
|
|
619
|
+
async function processFetchedBlobs(
|
|
620
|
+
blobs: BlobJson[],
|
|
621
|
+
blobHashes: Buffer[],
|
|
622
|
+
logger: Logger,
|
|
623
|
+
): Promise<(Blob | undefined)[]> {
|
|
615
624
|
const requestedBlobHashes = new Set<string>(blobHashes.map(bufferToHex));
|
|
616
625
|
const hashToBlob = new Map<string, Blob>();
|
|
617
626
|
for (const blobJson of blobs) {
|
|
@@ -621,7 +630,7 @@ function processFetchedBlobs(blobs: BlobJson[], blobHashes: Buffer[], logger: Lo
|
|
|
621
630
|
}
|
|
622
631
|
|
|
623
632
|
try {
|
|
624
|
-
const blob = Blob.fromJson(blobJson);
|
|
633
|
+
const blob = await Blob.fromJson(blobJson);
|
|
625
634
|
hashToBlob.set(hashHex, blob);
|
|
626
635
|
} catch (err) {
|
|
627
636
|
// If the above throws, it's likely that the blob commitment does not match the hash of the blob data.
|
package/src/client/interface.ts
CHANGED
package/src/client/local.ts
CHANGED
|
@@ -22,4 +22,9 @@ export class LocalBlobClient implements BlobClientInterface {
|
|
|
22
22
|
public getBlobSidecar(_blockId: string, blobHashes: Buffer[], _opts?: GetBlobSidecarOptions): Promise<Blob[]> {
|
|
23
23
|
return this.blobStore.getBlobsByHashes(blobHashes);
|
|
24
24
|
}
|
|
25
|
+
|
|
26
|
+
/** Returns true if this client can upload blobs. Always true for local client. */
|
|
27
|
+
public canUpload(): boolean {
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
25
30
|
}
|
package/src/client/tests.ts
CHANGED
|
@@ -28,7 +28,7 @@ export function runBlobClientTests(
|
|
|
28
28
|
});
|
|
29
29
|
|
|
30
30
|
it('should send and retrieve blobs by hash', async () => {
|
|
31
|
-
const blob = makeRandomBlob(5);
|
|
31
|
+
const blob = await makeRandomBlob(5);
|
|
32
32
|
const blobHash = blob.getEthVersionedBlobHash();
|
|
33
33
|
|
|
34
34
|
await client.sendBlobsToFilestore([blob]);
|
|
@@ -39,7 +39,7 @@ export function runBlobClientTests(
|
|
|
39
39
|
});
|
|
40
40
|
|
|
41
41
|
it('should handle multiple blobs', async () => {
|
|
42
|
-
const blobs = Array.from({ length: 3 }, () => makeRandomBlob(7));
|
|
42
|
+
const blobs = await Promise.all(Array.from({ length: 3 }, () => makeRandomBlob(7)));
|
|
43
43
|
const blobHashes = blobs.map(blob => blob.getEthVersionedBlobHash());
|
|
44
44
|
|
|
45
45
|
await client.sendBlobsToFilestore(blobs);
|