@aztec/blob-client 4.2.0-nightly.20260324 → 4.2.0-nightly.20260327
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/dest/client/http.d.ts +1 -1
- package/dest/client/http.d.ts.map +1 -1
- package/dest/client/http.js +48 -14
- package/package.json +7 -7
- package/src/client/http.ts +50 -14
package/dest/client/http.d.ts
CHANGED
|
@@ -76,4 +76,4 @@ export declare class HttpBlobClient implements BlobClientInterface {
|
|
|
76
76
|
*/
|
|
77
77
|
stop(): void;
|
|
78
78
|
}
|
|
79
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
79
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaHR0cC5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NsaWVudC9odHRwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxJQUFJLEVBQUUsS0FBSyxRQUFRLEVBQStCLE1BQU0saUJBQWlCLENBQUM7QUFHbkYsT0FBTyxFQUFFLEtBQUssTUFBTSxFQUFnQixNQUFNLHVCQUF1QixDQUFDO0FBT2xFLE9BQU8sS0FBSyxFQUFFLGlCQUFpQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDakUsT0FBTyxLQUFLLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSx1Q0FBdUMsQ0FBQztBQUVqRixPQUFPLEVBQUUsS0FBSyxnQkFBZ0IsRUFBOEIsTUFBTSxhQUFhLENBQUM7QUFDaEYsT0FBTyxLQUFLLEVBQUUsbUJBQW1CLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUVqRixxQkFBYSxjQUFlLFlBQVcsbUJBQW1CO0lBYXRELE9BQU8sQ0FBQyxRQUFRLENBQUMsSUFBSTtJQVp2QixTQUFTLENBQUMsUUFBUSxDQUFDLEdBQUcsRUFBRSxNQUFNLENBQUM7SUFDL0IsU0FBUyxDQUFDLFFBQVEsQ0FBQyxNQUFNLEVBQUUsZ0JBQWdCLENBQUM7SUFDNUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxhQUFhLEVBQUUsaUJBQWlCLEdBQUcsU0FBUyxDQUFDO0lBQ2hFLFNBQVMsQ0FBQyxRQUFRLENBQUMsS0FBSyxFQUFFLE9BQU8sS0FBSyxDQUFDO0lBQ3ZDLFNBQVMsQ0FBQyxRQUFRLENBQUMsZ0JBQWdCLEVBQUUsbUJBQW1CLEVBQUUsQ0FBQztJQUMzRCxTQUFTLENBQUMsUUFBUSxDQUFDLHFCQUFxQixFQUFFLG1CQUFtQixHQUFHLFNBQVMsQ0FBQztJQUUxRSxPQUFPLENBQUMsUUFBUSxDQUFTO0lBQ3pCLE9BQU8sQ0FBQywyQkFBMkIsQ0FBQyxDQUFpQjtJQUVyRCxZQUNFLE1BQU0sQ0FBQyxFQUFFLGdCQUFnQixFQUNSLElBQUksR0FBRTtRQUNyQixNQUFNLENBQUMsRUFBRSxNQUFNLENBQUM7UUFDaEIsYUFBYSxDQUFDLEVBQUUsaUJBQWlCLENBQUM7UUFDbEMsZ0JBQWdCLENBQUMsRUFBRSxtQkFBbUIsRUFBRSxDQUFDO1FBQ3pDLHFCQUFxQixDQUFDLEVBQUUsbUJBQW1CLENBQUM7UUFDNUMseUVBQXlFO1FBQ3pFLGNBQWMsQ0FBQyxFQUFFLENBQUMsS0FBSyxFQUFFLElBQUksRUFBRSxLQUFLLElBQUksQ0FBQztLQUNyQyxFQXdCUDtJQUVEOzs7T0FHRztJQUNILE9BQU8sQ0FBQyxzQkFBc0I7SUFVOUI7Ozs7O09BS0c7SUFDSSxXQUFXLENBQUMsS0FBSyxFQUFFLE9BQU8sR0FBRyxJQUFJLENBR3ZDO0lBRVksV0FBVyxrQkF3R3ZCO0lBRVksb0JBQW9CLENBQUMsS0FBSyxFQUFFLElBQUksRUFBRSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FtQmpFO0lBRUQ7Ozs7Ozs7Ozs7Ozs7O09BY0c7SUFDVSxjQUFjLENBQ3pCLFNBQVMsRUFBRSxLQUFLLE1BQU0sRUFBRSxFQUN4QixVQUFVLEVBQUUsTUFBTSxFQUFFLEVBQ3BCLElBQUksQ0FBQyxFQUFFLHFCQUFxQixHQUMzQixPQUFPLENBQUMsSUFBSSxFQUFFLENBQUMsQ0E2SWpCO1lBUWEsYUFBYTtJQXNDZCxrQkFBa0IsQ0FDN0IsT0FBTyxFQUFFLE1BQU0sRUFDZixlQUFlLEVBQUUsTUFBTSxHQUFHLE1BQU0sRUFDaEMsVUFBVSxHQUFFLE1BQU0sRUFBTyxFQUN6QixvQkFBb0IsQ0FBQyxFQUFFLE1BQU0sR0FDNUIsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDLENBR2pCO0lBRVksZ0JBQWdCLENBQzNCLE9BQU8sRUFBRSxNQUFNLEVBQ2YsZUFBZSxFQUFFLE1BQU0sR0FBRyxNQUFNLEVBQ2hDLG9CQUFvQixDQUFDLEVBQUUsTUFBTSxHQUM1QixPQUFPLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FzQ3JCO0lBRUQsT0FBTyxDQUFDLGlCQUFpQjtZQVlYLG1CQUFtQjtZQW1DbkIsYUFBYTtJQTZEM0Isc0NBQXNDO0lBQy9CLGdCQUFnQixJQUFJLGlCQUFpQixHQUFHLFNBQVMsQ0FFdkQ7SUFFRCxpRUFBaUU7SUFDMUQsU0FBUyxJQUFJLE9BQU8sQ0FFMUI7SUFFRDs7O09BR0c7SUFDVSxLQUFLLElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxDQVNsQztJQUVEOztPQUVHO0lBQ0gsT0FBTyxDQUFDLDhCQUE4QjtJQVd0Qzs7T0FFRztJQUNJLElBQUksSUFBSSxJQUFJLENBS2xCO0NBQ0YifQ==
|
|
@@ -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;AAGnF,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,
|
|
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;AAGnF,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,kBAwGvB;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
|
@@ -67,22 +67,50 @@ export class HttpBlobClient {
|
|
|
67
67
|
l1ConsensusHostUrls,
|
|
68
68
|
archiveUrl
|
|
69
69
|
});
|
|
70
|
-
let
|
|
70
|
+
let consensusSuperNodes = 0;
|
|
71
|
+
let consensusNonSuperNodes = 0;
|
|
72
|
+
let archiveSources = 0;
|
|
73
|
+
let blobSinks = 0;
|
|
71
74
|
if (l1ConsensusHostUrls && l1ConsensusHostUrls.length > 0) {
|
|
72
75
|
for(let l1ConsensusHostIndex = 0; l1ConsensusHostIndex < l1ConsensusHostUrls.length; l1ConsensusHostIndex++){
|
|
73
76
|
const l1ConsensusHostUrl = l1ConsensusHostUrls[l1ConsensusHostIndex];
|
|
74
77
|
try {
|
|
75
|
-
const { url, ...options } = getBeaconNodeFetchOptions(`${l1ConsensusHostUrl}/eth/v1/beacon/headers`, this.config, l1ConsensusHostIndex);
|
|
78
|
+
const { url, ...options } = getBeaconNodeFetchOptions(`${l1ConsensusHostUrl}/eth/v1/beacon/headers/head`, this.config, l1ConsensusHostIndex);
|
|
76
79
|
const res = await this.fetch(url, options);
|
|
77
|
-
if (res.ok) {
|
|
78
|
-
this.log.
|
|
80
|
+
if (!res.ok) {
|
|
81
|
+
this.log.error(`Failure reaching L1 consensus host: ${res.statusText} (${res.status})`, {
|
|
79
82
|
l1ConsensusHostUrl
|
|
80
83
|
});
|
|
81
|
-
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
this.log.info(`L1 consensus host is reachable`, {
|
|
87
|
+
l1ConsensusHostUrl
|
|
88
|
+
});
|
|
89
|
+
// Check if the host serves blob sidecars (supernode/semi-supernode).
|
|
90
|
+
// Post-Fusaka (PeerDAS), non-supernode beacon nodes no longer serve the
|
|
91
|
+
// blob sidecar endpoint. A 200 response (even with an empty data array
|
|
92
|
+
// for a slot with no blobs) means the node supports serving blob sidecars.
|
|
93
|
+
const body = await res.json();
|
|
94
|
+
const headSlot = body?.data?.header?.message?.slot;
|
|
95
|
+
if (headSlot) {
|
|
96
|
+
const { url: blobUrl, ...blobOptions } = getBeaconNodeFetchOptions(`${l1ConsensusHostUrl}/eth/v1/beacon/blobs/${headSlot}`, this.config, l1ConsensusHostIndex);
|
|
97
|
+
const blobRes = await this.fetch(blobUrl, blobOptions);
|
|
98
|
+
if (blobRes.ok) {
|
|
99
|
+
this.log.info(`L1 consensus host serves blob sidecars (supernode)`, {
|
|
100
|
+
l1ConsensusHostUrl
|
|
101
|
+
});
|
|
102
|
+
consensusSuperNodes++;
|
|
103
|
+
} else {
|
|
104
|
+
this.log.info(`L1 consensus host does not serve blob sidecars`, {
|
|
105
|
+
l1ConsensusHostUrl
|
|
106
|
+
});
|
|
107
|
+
consensusNonSuperNodes++;
|
|
108
|
+
}
|
|
82
109
|
} else {
|
|
83
|
-
this.log.
|
|
110
|
+
this.log.info(`L1 consensus host is reachable but could not determine head slot`, {
|
|
84
111
|
l1ConsensusHostUrl
|
|
85
112
|
});
|
|
113
|
+
consensusNonSuperNodes++;
|
|
86
114
|
}
|
|
87
115
|
} catch (err) {
|
|
88
116
|
this.log.error(`Error reaching L1 consensus host`, err, {
|
|
@@ -90,8 +118,6 @@ export class HttpBlobClient {
|
|
|
90
118
|
});
|
|
91
119
|
}
|
|
92
120
|
}
|
|
93
|
-
} else {
|
|
94
|
-
this.log.warn('No L1 consensus host urls configured');
|
|
95
121
|
}
|
|
96
122
|
if (this.archiveClient) {
|
|
97
123
|
try {
|
|
@@ -100,14 +126,12 @@ export class HttpBlobClient {
|
|
|
100
126
|
latest,
|
|
101
127
|
archiveUrl
|
|
102
128
|
});
|
|
103
|
-
|
|
129
|
+
archiveSources++;
|
|
104
130
|
} catch (err) {
|
|
105
131
|
this.log.error(`Error reaching archive client`, err, {
|
|
106
132
|
archiveUrl
|
|
107
133
|
});
|
|
108
134
|
}
|
|
109
|
-
} else {
|
|
110
|
-
this.log.warn('No archive client configured');
|
|
111
135
|
}
|
|
112
136
|
if (this.fileStoreClients.length > 0) {
|
|
113
137
|
for (const fileStoreClient of this.fileStoreClients){
|
|
@@ -117,7 +141,7 @@ export class HttpBlobClient {
|
|
|
117
141
|
this.log.info(`FileStore is reachable`, {
|
|
118
142
|
url: fileStoreClient.getBaseUrl()
|
|
119
143
|
});
|
|
120
|
-
|
|
144
|
+
blobSinks++;
|
|
121
145
|
} else {
|
|
122
146
|
this.log.warn(`FileStore is not accessible`, {
|
|
123
147
|
url: fileStoreClient.getBaseUrl()
|
|
@@ -130,12 +154,22 @@ export class HttpBlobClient {
|
|
|
130
154
|
}
|
|
131
155
|
}
|
|
132
156
|
}
|
|
157
|
+
// Emit a single summary after validating all sources
|
|
158
|
+
const successfulSourceCount = consensusSuperNodes + archiveSources + blobSinks;
|
|
159
|
+
let summary = `Blob client running with consensusSuperNodes=${consensusSuperNodes} archiveSources=${archiveSources} blobSinks=${blobSinks}`;
|
|
160
|
+
if (consensusNonSuperNodes > 0) {
|
|
161
|
+
summary += `. ${consensusNonSuperNodes} consensus client(s) ignored because they are not running in supernode or semi-supernode mode`;
|
|
162
|
+
}
|
|
133
163
|
if (successfulSourceCount === 0) {
|
|
134
164
|
if (this.config.blobAllowEmptySources) {
|
|
135
|
-
this.log.warn(
|
|
165
|
+
this.log.warn(summary);
|
|
136
166
|
} else {
|
|
137
|
-
throw new Error(
|
|
167
|
+
throw new Error(summary);
|
|
138
168
|
}
|
|
169
|
+
} else if (consensusSuperNodes === 0) {
|
|
170
|
+
this.log.warn(summary);
|
|
171
|
+
} else {
|
|
172
|
+
this.log.info(summary);
|
|
139
173
|
}
|
|
140
174
|
}
|
|
141
175
|
async sendBlobsToFilestore(blobs) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/blob-client",
|
|
3
|
-
"version": "4.2.0-nightly.
|
|
3
|
+
"version": "4.2.0-nightly.20260327",
|
|
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": "4.2.0-nightly.
|
|
60
|
-
"@aztec/ethereum": "4.2.0-nightly.
|
|
61
|
-
"@aztec/foundation": "4.2.0-nightly.
|
|
62
|
-
"@aztec/kv-store": "4.2.0-nightly.
|
|
63
|
-
"@aztec/stdlib": "4.2.0-nightly.
|
|
64
|
-
"@aztec/telemetry-client": "4.2.0-nightly.
|
|
59
|
+
"@aztec/blob-lib": "4.2.0-nightly.20260327",
|
|
60
|
+
"@aztec/ethereum": "4.2.0-nightly.20260327",
|
|
61
|
+
"@aztec/foundation": "4.2.0-nightly.20260327",
|
|
62
|
+
"@aztec/kv-store": "4.2.0-nightly.20260327",
|
|
63
|
+
"@aztec/stdlib": "4.2.0-nightly.20260327",
|
|
64
|
+
"@aztec/telemetry-client": "4.2.0-nightly.20260327",
|
|
65
65
|
"express": "^4.21.2",
|
|
66
66
|
"snappy": "^7.2.2",
|
|
67
67
|
"source-map-support": "^0.5.21",
|
package/src/client/http.ts
CHANGED
|
@@ -90,44 +90,68 @@ export class HttpBlobClient implements BlobClientInterface {
|
|
|
90
90
|
const archiveUrl = this.archiveClient?.getBaseUrl();
|
|
91
91
|
this.log.info(`Testing configured blob sources`, { l1ConsensusHostUrls, archiveUrl });
|
|
92
92
|
|
|
93
|
-
let
|
|
93
|
+
let consensusSuperNodes = 0;
|
|
94
|
+
let consensusNonSuperNodes = 0;
|
|
95
|
+
let archiveSources = 0;
|
|
96
|
+
let blobSinks = 0;
|
|
94
97
|
|
|
95
98
|
if (l1ConsensusHostUrls && l1ConsensusHostUrls.length > 0) {
|
|
96
99
|
for (let l1ConsensusHostIndex = 0; l1ConsensusHostIndex < l1ConsensusHostUrls.length; l1ConsensusHostIndex++) {
|
|
97
100
|
const l1ConsensusHostUrl = l1ConsensusHostUrls[l1ConsensusHostIndex];
|
|
98
101
|
try {
|
|
99
102
|
const { url, ...options } = getBeaconNodeFetchOptions(
|
|
100
|
-
`${l1ConsensusHostUrl}/eth/v1/beacon/headers`,
|
|
103
|
+
`${l1ConsensusHostUrl}/eth/v1/beacon/headers/head`,
|
|
101
104
|
this.config,
|
|
102
105
|
l1ConsensusHostIndex,
|
|
103
106
|
);
|
|
104
107
|
const res = await this.fetch(url, options);
|
|
105
|
-
if (res.ok) {
|
|
106
|
-
this.log.info(`L1 consensus host is reachable`, { l1ConsensusHostUrl });
|
|
107
|
-
successfulSourceCount++;
|
|
108
|
-
} else {
|
|
108
|
+
if (!res.ok) {
|
|
109
109
|
this.log.error(`Failure reaching L1 consensus host: ${res.statusText} (${res.status})`, {
|
|
110
110
|
l1ConsensusHostUrl,
|
|
111
111
|
});
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
this.log.info(`L1 consensus host is reachable`, { l1ConsensusHostUrl });
|
|
116
|
+
|
|
117
|
+
// Check if the host serves blob sidecars (supernode/semi-supernode).
|
|
118
|
+
// Post-Fusaka (PeerDAS), non-supernode beacon nodes no longer serve the
|
|
119
|
+
// blob sidecar endpoint. A 200 response (even with an empty data array
|
|
120
|
+
// for a slot with no blobs) means the node supports serving blob sidecars.
|
|
121
|
+
const body = await res.json();
|
|
122
|
+
const headSlot = body?.data?.header?.message?.slot;
|
|
123
|
+
if (headSlot) {
|
|
124
|
+
const { url: blobUrl, ...blobOptions } = getBeaconNodeFetchOptions(
|
|
125
|
+
`${l1ConsensusHostUrl}/eth/v1/beacon/blobs/${headSlot}`,
|
|
126
|
+
this.config,
|
|
127
|
+
l1ConsensusHostIndex,
|
|
128
|
+
);
|
|
129
|
+
const blobRes = await this.fetch(blobUrl, blobOptions);
|
|
130
|
+
if (blobRes.ok) {
|
|
131
|
+
this.log.info(`L1 consensus host serves blob sidecars (supernode)`, { l1ConsensusHostUrl });
|
|
132
|
+
consensusSuperNodes++;
|
|
133
|
+
} else {
|
|
134
|
+
this.log.info(`L1 consensus host does not serve blob sidecars`, { l1ConsensusHostUrl });
|
|
135
|
+
consensusNonSuperNodes++;
|
|
136
|
+
}
|
|
137
|
+
} else {
|
|
138
|
+
this.log.info(`L1 consensus host is reachable but could not determine head slot`, { l1ConsensusHostUrl });
|
|
139
|
+
consensusNonSuperNodes++;
|
|
112
140
|
}
|
|
113
141
|
} catch (err) {
|
|
114
142
|
this.log.error(`Error reaching L1 consensus host`, err, { l1ConsensusHostUrl });
|
|
115
143
|
}
|
|
116
144
|
}
|
|
117
|
-
} else {
|
|
118
|
-
this.log.warn('No L1 consensus host urls configured');
|
|
119
145
|
}
|
|
120
146
|
|
|
121
147
|
if (this.archiveClient) {
|
|
122
148
|
try {
|
|
123
149
|
const latest = await this.archiveClient.getLatestBlock();
|
|
124
150
|
this.log.info(`Archive client is reachable and synced to L1 block ${latest.number}`, { latest, archiveUrl });
|
|
125
|
-
|
|
151
|
+
archiveSources++;
|
|
126
152
|
} catch (err) {
|
|
127
153
|
this.log.error(`Error reaching archive client`, err, { archiveUrl });
|
|
128
154
|
}
|
|
129
|
-
} else {
|
|
130
|
-
this.log.warn('No archive client configured');
|
|
131
155
|
}
|
|
132
156
|
|
|
133
157
|
if (this.fileStoreClients.length > 0) {
|
|
@@ -136,7 +160,7 @@ export class HttpBlobClient implements BlobClientInterface {
|
|
|
136
160
|
const accessible = await fileStoreClient.testConnection();
|
|
137
161
|
if (accessible) {
|
|
138
162
|
this.log.info(`FileStore is reachable`, { url: fileStoreClient.getBaseUrl() });
|
|
139
|
-
|
|
163
|
+
blobSinks++;
|
|
140
164
|
} else {
|
|
141
165
|
this.log.warn(`FileStore is not accessible`, { url: fileStoreClient.getBaseUrl() });
|
|
142
166
|
}
|
|
@@ -146,12 +170,24 @@ export class HttpBlobClient implements BlobClientInterface {
|
|
|
146
170
|
}
|
|
147
171
|
}
|
|
148
172
|
|
|
173
|
+
// Emit a single summary after validating all sources
|
|
174
|
+
const successfulSourceCount = consensusSuperNodes + archiveSources + blobSinks;
|
|
175
|
+
|
|
176
|
+
let summary = `Blob client running with consensusSuperNodes=${consensusSuperNodes} archiveSources=${archiveSources} blobSinks=${blobSinks}`;
|
|
177
|
+
if (consensusNonSuperNodes > 0) {
|
|
178
|
+
summary += `. ${consensusNonSuperNodes} consensus client(s) ignored because they are not running in supernode or semi-supernode mode`;
|
|
179
|
+
}
|
|
180
|
+
|
|
149
181
|
if (successfulSourceCount === 0) {
|
|
150
182
|
if (this.config.blobAllowEmptySources) {
|
|
151
|
-
this.log.warn(
|
|
183
|
+
this.log.warn(summary);
|
|
152
184
|
} else {
|
|
153
|
-
throw new Error(
|
|
185
|
+
throw new Error(summary);
|
|
154
186
|
}
|
|
187
|
+
} else if (consensusSuperNodes === 0) {
|
|
188
|
+
this.log.warn(summary);
|
|
189
|
+
} else {
|
|
190
|
+
this.log.info(summary);
|
|
155
191
|
}
|
|
156
192
|
}
|
|
157
193
|
|