@aztec/blob-client 0.0.1-commit.88e6f9396 → 0.0.1-commit.8c0b8ff

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.
@@ -14,10 +14,6 @@ export declare class HttpBlobClient implements BlobClientInterface {
14
14
  protected readonly fileStoreUploadClient: FileStoreBlobClient | undefined;
15
15
  private disabled;
16
16
  private healthcheckUploadIntervalId?;
17
- /** Cached beacon genesis time (seconds since Unix epoch). Fetched once at startup. */
18
- private beaconGenesisTime?;
19
- /** Cached beacon slot duration in seconds. Fetched once at startup. */
20
- private beaconSecondsPerSlot?;
21
17
  constructor(config?: BlobClientConfig, opts?: {
22
18
  logger?: Logger;
23
19
  archiveClient?: BlobArchiveClient;
@@ -58,7 +54,7 @@ export declare class HttpBlobClient implements BlobClientInterface {
58
54
  getBlobSidecar(blockHash: `0x${string}`, blobHashes: Buffer[], opts?: GetBlobSidecarOptions): Promise<Blob[]>;
59
55
  private tryFileStores;
60
56
  getBlobSidecarFrom(hostUrl: string, blockHashOrSlot: string | number, blobHashes?: Buffer[], l1ConsensusHostIndex?: number): Promise<Blob[]>;
61
- getBlobsFromHost(hostUrl: string, blockHashOrSlot: string | number, l1ConsensusHostIndex?: number, blobHashes?: Buffer[]): Promise<BlobJson[]>;
57
+ getBlobsFromHost(hostUrl: string, blockHashOrSlot: string | number, l1ConsensusHostIndex?: number): Promise<BlobJson[]>;
62
58
  private fetchBlobSidecars;
63
59
  private getLatestSlotNumber;
64
60
  private getSlotNumber;
@@ -68,18 +64,16 @@ export declare class HttpBlobClient implements BlobClientInterface {
68
64
  canUpload(): boolean;
69
65
  /**
70
66
  * Start the blob client.
71
- * Fetches and caches beacon genesis config for timestamp-based slot resolution,
72
- * then uploads the initial healthcheck file (awaited) and starts periodic uploads.
67
+ * Uploads the initial healthcheck file (awaited) and starts periodic uploads.
73
68
  */
74
69
  start(): Promise<void>;
75
70
  /**
76
71
  * Start periodic healthcheck upload to the file store to ensure it remains available even if accidentally deleted.
77
72
  */
78
73
  private startPeriodicHealthcheckUpload;
79
- private fetchBeaconConfig;
80
74
  /**
81
75
  * Stop the blob client, clearing any periodic tasks.
82
76
  */
83
77
  stop(): void;
84
78
  }
85
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaHR0cC5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NsaWVudC9odHRwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxJQUFJLEVBQUUsS0FBSyxRQUFRLEVBQStCLE1BQU0saUJBQWlCLENBQUM7QUFHbkYsT0FBTyxFQUFFLEtBQUssTUFBTSxFQUFnQixNQUFNLHVCQUF1QixDQUFDO0FBT2xFLE9BQU8sS0FBSyxFQUFFLGlCQUFpQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDakUsT0FBTyxLQUFLLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSx1Q0FBdUMsQ0FBQztBQUVqRixPQUFPLEVBQUUsS0FBSyxnQkFBZ0IsRUFBOEIsTUFBTSxhQUFhLENBQUM7QUFDaEYsT0FBTyxLQUFLLEVBQUUsbUJBQW1CLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUVqRixxQkFBYSxjQUFlLFlBQVcsbUJBQW1CO0lBa0J0RCxPQUFPLENBQUMsUUFBUSxDQUFDLElBQUk7SUFqQnZCLFNBQVMsQ0FBQyxRQUFRLENBQUMsR0FBRyxFQUFFLE1BQU0sQ0FBQztJQUMvQixTQUFTLENBQUMsUUFBUSxDQUFDLE1BQU0sRUFBRSxnQkFBZ0IsQ0FBQztJQUM1QyxTQUFTLENBQUMsUUFBUSxDQUFDLGFBQWEsRUFBRSxpQkFBaUIsR0FBRyxTQUFTLENBQUM7SUFDaEUsU0FBUyxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQUUsT0FBTyxLQUFLLENBQUM7SUFDdkMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxnQkFBZ0IsRUFBRSxtQkFBbUIsRUFBRSxDQUFDO0lBQzNELFNBQVMsQ0FBQyxRQUFRLENBQUMscUJBQXFCLEVBQUUsbUJBQW1CLEdBQUcsU0FBUyxDQUFDO0lBRTFFLE9BQU8sQ0FBQyxRQUFRLENBQVM7SUFDekIsT0FBTyxDQUFDLDJCQUEyQixDQUFDLENBQWlCO0lBRXJELHNGQUFzRjtJQUN0RixPQUFPLENBQUMsaUJBQWlCLENBQUMsQ0FBUztJQUNuQyx1RUFBdUU7SUFDdkUsT0FBTyxDQUFDLG9CQUFvQixDQUFDLENBQVM7SUFFdEMsWUFDRSxNQUFNLENBQUMsRUFBRSxnQkFBZ0IsRUFDUixJQUFJLEdBQUU7UUFDckIsTUFBTSxDQUFDLEVBQUUsTUFBTSxDQUFDO1FBQ2hCLGFBQWEsQ0FBQyxFQUFFLGlCQUFpQixDQUFDO1FBQ2xDLGdCQUFnQixDQUFDLEVBQUUsbUJBQW1CLEVBQUUsQ0FBQztRQUN6QyxxQkFBcUIsQ0FBQyxFQUFFLG1CQUFtQixDQUFDO1FBQzVDLHlFQUF5RTtRQUN6RSxjQUFjLENBQUMsRUFBRSxDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsS0FBSyxJQUFJLENBQUM7S0FDckMsRUF3QlA7SUFFRDs7O09BR0c7SUFDSCxPQUFPLENBQUMsc0JBQXNCO0lBVTlCOzs7OztPQUtHO0lBQ0ksV0FBVyxDQUFDLEtBQUssRUFBRSxPQUFPLEdBQUcsSUFBSSxDQUd2QztJQUVZLFdBQVcsa0JBb0V2QjtJQUVZLG9CQUFvQixDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLENBbUJqRTtJQUVEOzs7Ozs7Ozs7Ozs7OztPQWNHO0lBQ1UsY0FBYyxDQUN6QixTQUFTLEVBQUUsS0FBSyxNQUFNLEVBQUUsRUFDeEIsVUFBVSxFQUFFLE1BQU0sRUFBRSxFQUNwQixJQUFJLENBQUMsRUFBRSxxQkFBcUIsR0FDM0IsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDLENBa0pqQjtZQVFhLGFBQWE7SUFzQ2Qsa0JBQWtCLENBQzdCLE9BQU8sRUFBRSxNQUFNLEVBQ2YsZUFBZSxFQUFFLE1BQU0sR0FBRyxNQUFNLEVBQ2hDLFVBQVUsR0FBRSxNQUFNLEVBQU8sRUFDekIsb0JBQW9CLENBQUMsRUFBRSxNQUFNLEdBQzVCLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUdqQjtJQUVZLGdCQUFnQixDQUMzQixPQUFPLEVBQUUsTUFBTSxFQUNmLGVBQWUsRUFBRSxNQUFNLEdBQUcsTUFBTSxFQUNoQyxvQkFBb0IsQ0FBQyxFQUFFLE1BQU0sRUFDN0IsVUFBVSxDQUFDLEVBQUUsTUFBTSxFQUFFLEdBQ3BCLE9BQU8sQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQXNDckI7SUFFRCxPQUFPLENBQUMsaUJBQWlCO1lBcUJYLG1CQUFtQjtZQW1DbkIsYUFBYTtJQTZFM0Isc0NBQXNDO0lBQy9CLGdCQUFnQixJQUFJLGlCQUFpQixHQUFHLFNBQVMsQ0FFdkQ7SUFFRCxpRUFBaUU7SUFDMUQsU0FBUyxJQUFJLE9BQU8sQ0FFMUI7SUFFRDs7OztPQUlHO0lBQ1UsS0FBSyxJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FXbEM7SUFFRDs7T0FFRztJQUNILE9BQU8sQ0FBQyw4QkFBOEI7WUFnQnhCLGlCQUFpQjtJQTBDL0I7O09BRUc7SUFDSSxJQUFJLElBQUksSUFBSSxDQUtsQjtDQUNGIn0=
79
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaHR0cC5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NsaWVudC9odHRwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxJQUFJLEVBQUUsS0FBSyxRQUFRLEVBQStCLE1BQU0saUJBQWlCLENBQUM7QUFHbkYsT0FBTyxFQUFFLEtBQUssTUFBTSxFQUFnQixNQUFNLHVCQUF1QixDQUFDO0FBT2xFLE9BQU8sS0FBSyxFQUFFLGlCQUFpQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDakUsT0FBTyxLQUFLLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSx1Q0FBdUMsQ0FBQztBQUVqRixPQUFPLEVBQUUsS0FBSyxnQkFBZ0IsRUFBOEIsTUFBTSxhQUFhLENBQUM7QUFDaEYsT0FBTyxLQUFLLEVBQUUsbUJBQW1CLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUVqRixxQkFBYSxjQUFlLFlBQVcsbUJBQW1CO0lBYXRELE9BQU8sQ0FBQyxRQUFRLENBQUMsSUFBSTtJQVp2QixTQUFTLENBQUMsUUFBUSxDQUFDLEdBQUcsRUFBRSxNQUFNLENBQUM7SUFDL0IsU0FBUyxDQUFDLFFBQVEsQ0FBQyxNQUFNLEVBQUUsZ0JBQWdCLENBQUM7SUFDNUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxhQUFhLEVBQUUsaUJBQWlCLEdBQUcsU0FBUyxDQUFDO0lBQ2hFLFNBQVMsQ0FBQyxRQUFRLENBQUMsS0FBSyxFQUFFLE9BQU8sS0FBSyxDQUFDO0lBQ3ZDLFNBQVMsQ0FBQyxRQUFRLENBQUMsZ0JBQWdCLEVBQUUsbUJBQW1CLEVBQUUsQ0FBQztJQUMzRCxTQUFTLENBQUMsUUFBUSxDQUFDLHFCQUFxQixFQUFFLG1CQUFtQixHQUFHLFNBQVMsQ0FBQztJQUUxRSxPQUFPLENBQUMsUUFBUSxDQUFTO0lBQ3pCLE9BQU8sQ0FBQywyQkFBMkIsQ0FBQyxDQUFpQjtJQUVyRCxZQUNFLE1BQU0sQ0FBQyxFQUFFLGdCQUFnQixFQUNSLElBQUksR0FBRTtRQUNyQixNQUFNLENBQUMsRUFBRSxNQUFNLENBQUM7UUFDaEIsYUFBYSxDQUFDLEVBQUUsaUJBQWlCLENBQUM7UUFDbEMsZ0JBQWdCLENBQUMsRUFBRSxtQkFBbUIsRUFBRSxDQUFDO1FBQ3pDLHFCQUFxQixDQUFDLEVBQUUsbUJBQW1CLENBQUM7UUFDNUMseUVBQXlFO1FBQ3pFLGNBQWMsQ0FBQyxFQUFFLENBQUMsS0FBSyxFQUFFLElBQUksRUFBRSxLQUFLLElBQUksQ0FBQztLQUNyQyxFQXdCUDtJQUVEOzs7T0FHRztJQUNILE9BQU8sQ0FBQyxzQkFBc0I7SUFVOUI7Ozs7O09BS0c7SUFDSSxXQUFXLENBQUMsS0FBSyxFQUFFLE9BQU8sR0FBRyxJQUFJLENBR3ZDO0lBRVksV0FBVyxrQkF3R3ZCO0lBRVksb0JBQW9CLENBQUMsS0FBSyxFQUFFLElBQUksRUFBRSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FtQmpFO0lBRUQ7Ozs7Ozs7Ozs7Ozs7O09BY0c7SUFDVSxjQUFjLENBQ3pCLFNBQVMsRUFBRSxLQUFLLE1BQU0sRUFBRSxFQUN4QixVQUFVLEVBQUUsTUFBTSxFQUFFLEVBQ3BCLElBQUksQ0FBQyxFQUFFLHFCQUFxQixHQUMzQixPQUFPLENBQUMsSUFBSSxFQUFFLENBQUMsQ0E2SWpCO1lBUWEsYUFBYTtJQXNDZCxrQkFBa0IsQ0FDN0IsT0FBTyxFQUFFLE1BQU0sRUFDZixlQUFlLEVBQUUsTUFBTSxHQUFHLE1BQU0sRUFDaEMsVUFBVSxHQUFFLE1BQU0sRUFBTyxFQUN6QixvQkFBb0IsQ0FBQyxFQUFFLE1BQU0sR0FDNUIsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDLENBR2pCO0lBRVksZ0JBQWdCLENBQzNCLE9BQU8sRUFBRSxNQUFNLEVBQ2YsZUFBZSxFQUFFLE1BQU0sR0FBRyxNQUFNLEVBQ2hDLG9CQUFvQixDQUFDLEVBQUUsTUFBTSxHQUM1QixPQUFPLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FzQ3JCO0lBRUQsT0FBTyxDQUFDLGlCQUFpQjtZQVlYLG1CQUFtQjtZQW1DbkIsYUFBYTtJQTZEM0Isc0NBQXNDO0lBQy9CLGdCQUFnQixJQUFJLGlCQUFpQixHQUFHLFNBQVMsQ0FFdkQ7SUFFRCxpRUFBaUU7SUFDMUQsU0FBUyxJQUFJLE9BQU8sQ0FFMUI7SUFFRDs7O09BR0c7SUFDVSxLQUFLLElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxDQVNsQztJQUVEOztPQUVHO0lBQ0gsT0FBTyxDQUFDLDhCQUE4QjtJQVd0Qzs7T0FFRztJQUNJLElBQUksSUFBSSxJQUFJLENBS2xCO0NBQ0YifQ==
@@ -1 +1 @@
1
- {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/client/http.ts"],"names":[],"mappings":"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"}
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"}
@@ -18,8 +18,6 @@ export class HttpBlobClient {
18
18
  fileStoreUploadClient;
19
19
  disabled;
20
20
  healthcheckUploadIntervalId;
21
- /** Cached beacon genesis time (seconds since Unix epoch). Fetched once at startup. */ beaconGenesisTime;
22
- /** Cached beacon slot duration in seconds. Fetched once at startup. */ beaconSecondsPerSlot;
23
21
  constructor(config, opts = {}){
24
22
  this.opts = opts;
25
23
  this.disabled = false;
@@ -69,22 +67,50 @@ export class HttpBlobClient {
69
67
  l1ConsensusHostUrls,
70
68
  archiveUrl
71
69
  });
72
- let successfulSourceCount = 0;
70
+ let consensusSuperNodes = 0;
71
+ let consensusNonSuperNodes = 0;
72
+ let archiveSources = 0;
73
+ let blobSinks = 0;
73
74
  if (l1ConsensusHostUrls && l1ConsensusHostUrls.length > 0) {
74
75
  for(let l1ConsensusHostIndex = 0; l1ConsensusHostIndex < l1ConsensusHostUrls.length; l1ConsensusHostIndex++){
75
76
  const l1ConsensusHostUrl = l1ConsensusHostUrls[l1ConsensusHostIndex];
76
77
  try {
77
- 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);
78
79
  const res = await this.fetch(url, options);
79
- if (res.ok) {
80
- this.log.info(`L1 consensus host is reachable`, {
80
+ if (!res.ok) {
81
+ this.log.error(`Failure reaching L1 consensus host: ${res.statusText} (${res.status})`, {
81
82
  l1ConsensusHostUrl
82
83
  });
83
- successfulSourceCount++;
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
+ }
84
109
  } else {
85
- this.log.error(`Failure reaching L1 consensus host: ${res.statusText} (${res.status})`, {
110
+ this.log.info(`L1 consensus host is reachable but could not determine head slot`, {
86
111
  l1ConsensusHostUrl
87
112
  });
113
+ consensusNonSuperNodes++;
88
114
  }
89
115
  } catch (err) {
90
116
  this.log.error(`Error reaching L1 consensus host`, err, {
@@ -92,8 +118,6 @@ export class HttpBlobClient {
92
118
  });
93
119
  }
94
120
  }
95
- } else {
96
- this.log.warn('No L1 consensus host urls configured');
97
121
  }
98
122
  if (this.archiveClient) {
99
123
  try {
@@ -102,14 +126,12 @@ export class HttpBlobClient {
102
126
  latest,
103
127
  archiveUrl
104
128
  });
105
- successfulSourceCount++;
129
+ archiveSources++;
106
130
  } catch (err) {
107
131
  this.log.error(`Error reaching archive client`, err, {
108
132
  archiveUrl
109
133
  });
110
134
  }
111
- } else {
112
- this.log.warn('No archive client configured');
113
135
  }
114
136
  if (this.fileStoreClients.length > 0) {
115
137
  for (const fileStoreClient of this.fileStoreClients){
@@ -119,7 +141,7 @@ export class HttpBlobClient {
119
141
  this.log.info(`FileStore is reachable`, {
120
142
  url: fileStoreClient.getBaseUrl()
121
143
  });
122
- successfulSourceCount++;
144
+ blobSinks++;
123
145
  } else {
124
146
  this.log.warn(`FileStore is not accessible`, {
125
147
  url: fileStoreClient.getBaseUrl()
@@ -132,12 +154,22 @@ export class HttpBlobClient {
132
154
  }
133
155
  }
134
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
+ }
135
163
  if (successfulSourceCount === 0) {
136
164
  if (this.config.blobAllowEmptySources) {
137
- this.log.warn('No blob sources are reachable');
165
+ this.log.warn(summary);
138
166
  } else {
139
- throw new Error('No blob sources are reachable');
167
+ throw new Error(summary);
140
168
  }
169
+ } else if (consensusSuperNodes === 0) {
170
+ this.log.warn(summary);
171
+ } else {
172
+ this.log.info(summary);
141
173
  }
142
174
  }
143
175
  async sendBlobsToFilestore(blobs) {
@@ -223,7 +255,7 @@ export class HttpBlobClient {
223
255
  ...ctx
224
256
  };
225
257
  this.log.trace(`Attempting to get slot number for block hash`, consensusCtx);
226
- const slotNumber = await this.getSlotNumber(blockHash, opts?.parentBeaconBlockRoot, opts?.l1BlockTimestamp);
258
+ const slotNumber = await this.getSlotNumber(blockHash);
227
259
  this.log.debug(`Got slot number ${slotNumber} from consensus host for querying blobs`, consensusCtx);
228
260
  if (slotNumber) {
229
261
  let l1ConsensusHostUrl;
@@ -238,7 +270,7 @@ export class HttpBlobClient {
238
270
  l1ConsensusHostUrl,
239
271
  ...ctx
240
272
  });
241
- const blobs = await this.getBlobsFromHost(l1ConsensusHostUrl, slotNumber, l1ConsensusHostIndex, getMissingBlobHashes());
273
+ const blobs = await this.getBlobsFromHost(l1ConsensusHostUrl, slotNumber, l1ConsensusHostIndex);
242
274
  const result = await fillResults(blobs);
243
275
  this.log.debug(`Got ${blobs.length} blobs from consensus host (total: ${result.length}/${blobHashes.length})`, {
244
276
  slotNumber,
@@ -337,14 +369,14 @@ export class HttpBlobClient {
337
369
  }
338
370
  }
339
371
  async getBlobSidecarFrom(hostUrl, blockHashOrSlot, blobHashes = [], l1ConsensusHostIndex) {
340
- const blobs = await this.getBlobsFromHost(hostUrl, blockHashOrSlot, l1ConsensusHostIndex, blobHashes);
372
+ const blobs = await this.getBlobsFromHost(hostUrl, blockHashOrSlot, l1ConsensusHostIndex);
341
373
  return (await processFetchedBlobs(blobs, blobHashes, this.log)).filter((b)=>b !== undefined);
342
374
  }
343
- async getBlobsFromHost(hostUrl, blockHashOrSlot, l1ConsensusHostIndex, blobHashes) {
375
+ async getBlobsFromHost(hostUrl, blockHashOrSlot, l1ConsensusHostIndex) {
344
376
  try {
345
- let res = await this.fetchBlobSidecars(hostUrl, blockHashOrSlot, l1ConsensusHostIndex, blobHashes);
377
+ let res = await this.fetchBlobSidecars(hostUrl, blockHashOrSlot, l1ConsensusHostIndex);
346
378
  if (res.ok) {
347
- return await parseBlobJsonsFromResponse(await res.json(), this.log);
379
+ return parseBlobJsonsFromResponse(await res.json(), this.log);
348
380
  }
349
381
  if (res.status === 404 && typeof blockHashOrSlot === 'number') {
350
382
  const latestSlot = await this.getLatestSlotNumber(hostUrl, l1ConsensusHostIndex);
@@ -357,9 +389,9 @@ export class HttpBlobClient {
357
389
  let currentSlot = blockHashOrSlot + 1;
358
390
  while(res.status === 404 && maxRetries > 0 && latestSlot !== undefined && currentSlot <= latestSlot){
359
391
  this.log.debug(`Trying slot ${currentSlot}`);
360
- res = await this.fetchBlobSidecars(hostUrl, currentSlot, l1ConsensusHostIndex, blobHashes);
392
+ res = await this.fetchBlobSidecars(hostUrl, currentSlot, l1ConsensusHostIndex);
361
393
  if (res.ok) {
362
- return await parseBlobJsonsFromResponse(await res.json(), this.log);
394
+ return parseBlobJsonsFromResponse(await res.json(), this.log);
363
395
  }
364
396
  currentSlot++;
365
397
  maxRetries--;
@@ -376,15 +408,8 @@ export class HttpBlobClient {
376
408
  return [];
377
409
  }
378
410
  }
379
- fetchBlobSidecars(hostUrl, blockHashOrSlot, l1ConsensusHostIndex, blobHashes) {
380
- let baseUrl = `${hostUrl}/eth/v1/beacon/blobs/${blockHashOrSlot}`;
381
- if (blobHashes && blobHashes.length > 0) {
382
- const params = new URLSearchParams();
383
- for (const hash of blobHashes){
384
- params.append('versioned_hashes', `0x${hash.toString('hex')}`);
385
- }
386
- baseUrl += `?${params.toString()}`;
387
- }
411
+ fetchBlobSidecars(hostUrl, blockHashOrSlot, l1ConsensusHostIndex) {
412
+ const baseUrl = `${hostUrl}/eth/v1/beacon/blob_sidecars/${blockHashOrSlot}`;
388
413
  const { url, ...options } = getBeaconNodeFetchOptions(baseUrl, this.config, l1ConsensusHostIndex);
389
414
  this.log.debug(`Fetching blob sidecar for ${blockHashOrSlot}`, {
390
415
  url,
@@ -430,45 +455,36 @@ export class HttpBlobClient {
430
455
  *
431
456
  * @param blockHash - The block hash
432
457
  * @returns The slot number
433
- */ async getSlotNumber(blockHash, parentBeaconBlockRoot, l1BlockTimestamp) {
458
+ */ async getSlotNumber(blockHash) {
434
459
  const { l1ConsensusHostUrls, l1RpcUrls } = this.config;
435
460
  if (!l1ConsensusHostUrls || l1ConsensusHostUrls.length === 0) {
436
461
  this.log.debug('No consensus host url configured');
437
462
  return undefined;
438
463
  }
439
- // Primary path: compute slot from timestamp if genesis config is cached (no network call needed)
440
- if (l1BlockTimestamp !== undefined && this.beaconGenesisTime !== undefined && this.beaconSecondsPerSlot !== undefined) {
441
- const slot = Number((l1BlockTimestamp - this.beaconGenesisTime) / BigInt(this.beaconSecondsPerSlot));
442
- this.log.debug(`Computed slot ${slot} from L1 block timestamp`, {
443
- l1BlockTimestamp
444
- });
445
- return slot;
464
+ if (!l1RpcUrls || l1RpcUrls.length === 0) {
465
+ this.log.debug('No execution host url configured');
466
+ return undefined;
446
467
  }
447
- if (!parentBeaconBlockRoot) {
448
- // parentBeaconBlockRoot not provided by caller — fetch it from the execution RPC
449
- if (!l1RpcUrls || l1RpcUrls.length === 0) {
450
- this.log.debug('No execution host url configured');
451
- return undefined;
452
- }
453
- const client = createPublicClient({
454
- transport: makeL1HttpTransport(l1RpcUrls, {
455
- timeout: this.config.l1HttpTimeoutMS
456
- })
468
+ // Ping execution node to get the parentBeaconBlockRoot for this block
469
+ let parentBeaconBlockRoot;
470
+ const client = createPublicClient({
471
+ transport: makeL1HttpTransport(l1RpcUrls, {
472
+ timeout: this.config.l1HttpTimeoutMS
473
+ })
474
+ });
475
+ try {
476
+ const res = await client.request({
477
+ method: 'eth_getBlockByHash',
478
+ params: [
479
+ blockHash,
480
+ /*tx flag*/ false
481
+ ]
457
482
  });
458
- try {
459
- const res = await client.request({
460
- method: 'eth_getBlockByHash',
461
- params: [
462
- blockHash,
463
- /*tx flag*/ false
464
- ]
465
- });
466
- if (res.parentBeaconBlockRoot) {
467
- parentBeaconBlockRoot = res.parentBeaconBlockRoot;
468
- }
469
- } catch (err) {
470
- this.log.error(`Error getting parent beacon block root`, err);
483
+ if (res.parentBeaconBlockRoot) {
484
+ parentBeaconBlockRoot = res.parentBeaconBlockRoot;
471
485
  }
486
+ } catch (err) {
487
+ this.log.error(`Error getting parent beacon block root`, err);
472
488
  }
473
489
  if (!parentBeaconBlockRoot) {
474
490
  this.log.error(`No parent beacon block root found for block ${blockHash}`);
@@ -500,10 +516,8 @@ export class HttpBlobClient {
500
516
  }
501
517
  /**
502
518
  * Start the blob client.
503
- * Fetches and caches beacon genesis config for timestamp-based slot resolution,
504
- * then uploads the initial healthcheck file (awaited) and starts periodic uploads.
519
+ * Uploads the initial healthcheck file (awaited) and starts periodic uploads.
505
520
  */ async start() {
506
- await this.fetchBeaconConfig();
507
521
  if (!this.fileStoreUploadClient) {
508
522
  return;
509
523
  }
@@ -522,40 +536,6 @@ export class HttpBlobClient {
522
536
  }, intervalMs);
523
537
  }
524
538
  /**
525
- * Fetches and caches beacon genesis time and slot duration from the first available consensus host.
526
- * These static values enable timestamp-based slot resolution, eliminating the per-fetch headers call.
527
- * Logs a warning and leaves fields undefined if all hosts fail, callers fall back gracefully.
528
- */ async fetchBeaconConfig() {
529
- const { l1ConsensusHostUrls } = this.config;
530
- if (!l1ConsensusHostUrls || l1ConsensusHostUrls.length === 0) {
531
- return;
532
- }
533
- for(let i = 0; i < l1ConsensusHostUrls.length; i++){
534
- try {
535
- const { url: genesisUrl, ...genesisOptions } = getBeaconNodeFetchOptions(`${l1ConsensusHostUrls[i]}/eth/v1/config/genesis`, this.config, i);
536
- const { url: specUrl, ...specOptions } = getBeaconNodeFetchOptions(`${l1ConsensusHostUrls[i]}/eth/v1/config/spec`, this.config, i);
537
- const [genesisRes, specRes] = await Promise.all([
538
- this.fetch(genesisUrl, genesisOptions),
539
- this.fetch(specUrl, specOptions)
540
- ]);
541
- if (genesisRes.ok && specRes.ok) {
542
- const genesis = await genesisRes.json();
543
- const spec = await specRes.json();
544
- this.beaconGenesisTime = BigInt(genesis.data.genesisTime);
545
- this.beaconSecondsPerSlot = parseInt(spec.data.secondsPerSlot);
546
- this.log.debug(`Fetched beacon genesis config`, {
547
- genesisTime: this.beaconGenesisTime,
548
- secondsPerSlot: this.beaconSecondsPerSlot
549
- });
550
- return;
551
- }
552
- } catch (err) {
553
- this.log.warn(`Failed to fetch beacon config from host ${l1ConsensusHostUrls[i]}`, err);
554
- }
555
- }
556
- this.log.warn('Could not fetch beacon genesis config from any consensus host — will use headers call fallback');
557
- }
558
- /**
559
539
  * Stop the blob client, clearing any periodic tasks.
560
540
  */ stop() {
561
541
  if (this.healthcheckUploadIntervalId) {
@@ -564,9 +544,10 @@ export class HttpBlobClient {
564
544
  }
565
545
  }
566
546
  }
567
- async function parseBlobJsonsFromResponse(response, logger) {
547
+ function parseBlobJsonsFromResponse(response, logger) {
568
548
  try {
569
- return await Promise.all(response.data.map(parseBlobJson));
549
+ const blobs = response.data.map(parseBlobJson);
550
+ return blobs;
570
551
  } catch (err) {
571
552
  logger.error(`Error parsing blob json from response`, err);
572
553
  return [];
@@ -576,9 +557,10 @@ async function parseBlobJsonsFromResponse(response, logger) {
576
557
  // https://ethereum.github.io/beacon-APIs/?urls.primaryName=dev#/Beacon/getBlobSidecars
577
558
  // Here we attempt to parse the response data to Buffer, and check the lengths (via Blob's constructor), to avoid
578
559
  // throwing an error down the line when calling Blob.fromJson().
579
- async function parseBlobJson(rawHex) {
580
- const blobBuffer = Buffer.from(rawHex.slice(2), 'hex');
581
- const blob = await Blob.fromBlobBuffer(blobBuffer);
560
+ function parseBlobJson(data) {
561
+ const blobBuffer = Buffer.from(data.blob.slice(2), 'hex');
562
+ const commitmentBuffer = Buffer.from(data.kzg_commitment.slice(2), 'hex');
563
+ const blob = new Blob(blobBuffer, commitmentBuffer);
582
564
  return blob.toJSON();
583
565
  }
584
566
  // Returns an array that maps each blob hash to the corresponding blob, or undefined if the blob is not found
@@ -10,17 +10,6 @@ export interface GetBlobSidecarOptions {
10
10
  * - Near tip: FileStore first with no retries (data should exist), L1 consensus second (freshest data), then FileStore with retries, then archive (eg. blobscan)
11
11
  */
12
12
  isHistoricalSync?: boolean;
13
- /**
14
- * The parent beacon block root for the L1 block containing the blobs.
15
- * If provided, skips the eth_getBlockByHash execution RPC call inside getSlotNumber.
16
- */
17
- parentBeaconBlockRoot?: string;
18
- /**
19
- * The timestamp of the L1 execution block containing the blobs.
20
- * When provided alongside a cached beacon genesis config (fetched at startup), allows computing
21
- * the beacon slot directly via timestamp math, skipping the beacon headers network call entirely.
22
- */
23
- l1BlockTimestamp?: bigint;
24
13
  }
25
14
  export interface BlobClientInterface {
26
15
  /** Sends the given blobs to the filestore, to be indexed by blob hash. */
@@ -36,4 +25,4 @@ export interface BlobClientInterface {
36
25
  /** Returns true if this client can upload blobs to filestore. */
37
26
  canUpload(): boolean;
38
27
  }
39
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZXJmYWNlLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY2xpZW50L2ludGVyZmFjZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxJQUFJLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUU1Qzs7R0FFRztBQUNILE1BQU0sV0FBVyxxQkFBcUI7SUFDcEM7Ozs7O09BS0c7SUFDSCxnQkFBZ0IsQ0FBQyxFQUFFLE9BQU8sQ0FBQztJQUMzQjs7O09BR0c7SUFDSCxxQkFBcUIsQ0FBQyxFQUFFLE1BQU0sQ0FBQztJQUMvQjs7OztPQUlHO0lBQ0gsZ0JBQWdCLENBQUMsRUFBRSxNQUFNLENBQUM7Q0FDM0I7QUFFRCxNQUFNLFdBQVcsbUJBQW1CO0lBQ2xDLDBFQUEwRTtJQUMxRSxvQkFBb0IsQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3RELHFFQUFxRTtJQUNyRSxjQUFjLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxVQUFVLENBQUMsRUFBRSxNQUFNLEVBQUUsRUFBRSxJQUFJLENBQUMsRUFBRSxxQkFBcUIsR0FBRyxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUN0Ryw2RUFBNkU7SUFDN0UsS0FBSyxDQUFDLElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3hCLG9GQUFvRjtJQUNwRixXQUFXLElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzdCLDBEQUEwRDtJQUMxRCxJQUFJLENBQUMsSUFBSSxJQUFJLENBQUM7SUFDZCxpRUFBaUU7SUFDakUsU0FBUyxJQUFJLE9BQU8sQ0FBQztDQUN0QiJ9
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;IAC3B;;;OAGG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;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"}
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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/blob-client",
3
- "version": "0.0.1-commit.88e6f9396",
3
+ "version": "0.0.1-commit.8c0b8ff",
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.88e6f9396",
60
- "@aztec/ethereum": "0.0.1-commit.88e6f9396",
61
- "@aztec/foundation": "0.0.1-commit.88e6f9396",
62
- "@aztec/kv-store": "0.0.1-commit.88e6f9396",
63
- "@aztec/stdlib": "0.0.1-commit.88e6f9396",
64
- "@aztec/telemetry-client": "0.0.1-commit.88e6f9396",
59
+ "@aztec/blob-lib": "0.0.1-commit.8c0b8ff",
60
+ "@aztec/ethereum": "0.0.1-commit.8c0b8ff",
61
+ "@aztec/foundation": "0.0.1-commit.8c0b8ff",
62
+ "@aztec/kv-store": "0.0.1-commit.8c0b8ff",
63
+ "@aztec/stdlib": "0.0.1-commit.8c0b8ff",
64
+ "@aztec/telemetry-client": "0.0.1-commit.8c0b8ff",
65
65
  "express": "^4.21.2",
66
66
  "snappy": "^7.2.2",
67
67
  "source-map-support": "^0.5.21",
@@ -25,11 +25,6 @@ export class HttpBlobClient implements BlobClientInterface {
25
25
  private disabled = false;
26
26
  private healthcheckUploadIntervalId?: NodeJS.Timeout;
27
27
 
28
- /** Cached beacon genesis time (seconds since Unix epoch). Fetched once at startup. */
29
- private beaconGenesisTime?: bigint;
30
- /** Cached beacon slot duration in seconds. Fetched once at startup. */
31
- private beaconSecondsPerSlot?: number;
32
-
33
28
  constructor(
34
29
  config?: BlobClientConfig,
35
30
  private readonly opts: {
@@ -95,44 +90,68 @@ export class HttpBlobClient implements BlobClientInterface {
95
90
  const archiveUrl = this.archiveClient?.getBaseUrl();
96
91
  this.log.info(`Testing configured blob sources`, { l1ConsensusHostUrls, archiveUrl });
97
92
 
98
- let successfulSourceCount = 0;
93
+ let consensusSuperNodes = 0;
94
+ let consensusNonSuperNodes = 0;
95
+ let archiveSources = 0;
96
+ let blobSinks = 0;
99
97
 
100
98
  if (l1ConsensusHostUrls && l1ConsensusHostUrls.length > 0) {
101
99
  for (let l1ConsensusHostIndex = 0; l1ConsensusHostIndex < l1ConsensusHostUrls.length; l1ConsensusHostIndex++) {
102
100
  const l1ConsensusHostUrl = l1ConsensusHostUrls[l1ConsensusHostIndex];
103
101
  try {
104
102
  const { url, ...options } = getBeaconNodeFetchOptions(
105
- `${l1ConsensusHostUrl}/eth/v1/beacon/headers`,
103
+ `${l1ConsensusHostUrl}/eth/v1/beacon/headers/head`,
106
104
  this.config,
107
105
  l1ConsensusHostIndex,
108
106
  );
109
107
  const res = await this.fetch(url, options);
110
- if (res.ok) {
111
- this.log.info(`L1 consensus host is reachable`, { l1ConsensusHostUrl });
112
- successfulSourceCount++;
113
- } else {
108
+ if (!res.ok) {
114
109
  this.log.error(`Failure reaching L1 consensus host: ${res.statusText} (${res.status})`, {
115
110
  l1ConsensusHostUrl,
116
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++;
117
140
  }
118
141
  } catch (err) {
119
142
  this.log.error(`Error reaching L1 consensus host`, err, { l1ConsensusHostUrl });
120
143
  }
121
144
  }
122
- } else {
123
- this.log.warn('No L1 consensus host urls configured');
124
145
  }
125
146
 
126
147
  if (this.archiveClient) {
127
148
  try {
128
149
  const latest = await this.archiveClient.getLatestBlock();
129
150
  this.log.info(`Archive client is reachable and synced to L1 block ${latest.number}`, { latest, archiveUrl });
130
- successfulSourceCount++;
151
+ archiveSources++;
131
152
  } catch (err) {
132
153
  this.log.error(`Error reaching archive client`, err, { archiveUrl });
133
154
  }
134
- } else {
135
- this.log.warn('No archive client configured');
136
155
  }
137
156
 
138
157
  if (this.fileStoreClients.length > 0) {
@@ -141,7 +160,7 @@ export class HttpBlobClient implements BlobClientInterface {
141
160
  const accessible = await fileStoreClient.testConnection();
142
161
  if (accessible) {
143
162
  this.log.info(`FileStore is reachable`, { url: fileStoreClient.getBaseUrl() });
144
- successfulSourceCount++;
163
+ blobSinks++;
145
164
  } else {
146
165
  this.log.warn(`FileStore is not accessible`, { url: fileStoreClient.getBaseUrl() });
147
166
  }
@@ -151,12 +170,24 @@ export class HttpBlobClient implements BlobClientInterface {
151
170
  }
152
171
  }
153
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
+
154
181
  if (successfulSourceCount === 0) {
155
182
  if (this.config.blobAllowEmptySources) {
156
- this.log.warn('No blob sources are reachable');
183
+ this.log.warn(summary);
157
184
  } else {
158
- throw new Error('No blob sources are reachable');
185
+ throw new Error(summary);
159
186
  }
187
+ } else if (consensusSuperNodes === 0) {
188
+ this.log.warn(summary);
189
+ } else {
190
+ this.log.info(summary);
160
191
  }
161
192
  }
162
193
 
@@ -257,7 +288,7 @@ export class HttpBlobClient implements BlobClientInterface {
257
288
  // The beacon api can query by slot number, so we get that first
258
289
  const consensusCtx = { l1ConsensusHostUrls, ...ctx };
259
290
  this.log.trace(`Attempting to get slot number for block hash`, consensusCtx);
260
- const slotNumber = await this.getSlotNumber(blockHash, opts?.parentBeaconBlockRoot, opts?.l1BlockTimestamp);
291
+ const slotNumber = await this.getSlotNumber(blockHash);
261
292
  this.log.debug(`Got slot number ${slotNumber} from consensus host for querying blobs`, consensusCtx);
262
293
 
263
294
  if (slotNumber) {
@@ -274,12 +305,7 @@ export class HttpBlobClient implements BlobClientInterface {
274
305
  l1ConsensusHostUrl,
275
306
  ...ctx,
276
307
  });
277
- const blobs = await this.getBlobsFromHost(
278
- l1ConsensusHostUrl,
279
- slotNumber,
280
- l1ConsensusHostIndex,
281
- getMissingBlobHashes(),
282
- );
308
+ const blobs = await this.getBlobsFromHost(l1ConsensusHostUrl, slotNumber, l1ConsensusHostIndex);
283
309
  const result = await fillResults(blobs);
284
310
  this.log.debug(
285
311
  `Got ${blobs.length} blobs from consensus host (total: ${result.length}/${blobHashes.length})`,
@@ -398,7 +424,7 @@ export class HttpBlobClient implements BlobClientInterface {
398
424
  blobHashes: Buffer[] = [],
399
425
  l1ConsensusHostIndex?: number,
400
426
  ): Promise<Blob[]> {
401
- const blobs = await this.getBlobsFromHost(hostUrl, blockHashOrSlot, l1ConsensusHostIndex, blobHashes);
427
+ const blobs = await this.getBlobsFromHost(hostUrl, blockHashOrSlot, l1ConsensusHostIndex);
402
428
  return (await processFetchedBlobs(blobs, blobHashes, this.log)).filter((b): b is Blob => b !== undefined);
403
429
  }
404
430
 
@@ -406,12 +432,11 @@ export class HttpBlobClient implements BlobClientInterface {
406
432
  hostUrl: string,
407
433
  blockHashOrSlot: string | number,
408
434
  l1ConsensusHostIndex?: number,
409
- blobHashes?: Buffer[],
410
435
  ): Promise<BlobJson[]> {
411
436
  try {
412
- let res = await this.fetchBlobSidecars(hostUrl, blockHashOrSlot, l1ConsensusHostIndex, blobHashes);
437
+ let res = await this.fetchBlobSidecars(hostUrl, blockHashOrSlot, l1ConsensusHostIndex);
413
438
  if (res.ok) {
414
- return await parseBlobJsonsFromResponse(await res.json(), this.log);
439
+ return parseBlobJsonsFromResponse(await res.json(), this.log);
415
440
  }
416
441
 
417
442
  if (res.status === 404 && typeof blockHashOrSlot === 'number') {
@@ -426,9 +451,9 @@ export class HttpBlobClient implements BlobClientInterface {
426
451
  let currentSlot = blockHashOrSlot + 1;
427
452
  while (res.status === 404 && maxRetries > 0 && latestSlot !== undefined && currentSlot <= latestSlot) {
428
453
  this.log.debug(`Trying slot ${currentSlot}`);
429
- res = await this.fetchBlobSidecars(hostUrl, currentSlot, l1ConsensusHostIndex, blobHashes);
454
+ res = await this.fetchBlobSidecars(hostUrl, currentSlot, l1ConsensusHostIndex);
430
455
  if (res.ok) {
431
- return await parseBlobJsonsFromResponse(await res.json(), this.log);
456
+ return parseBlobJsonsFromResponse(await res.json(), this.log);
432
457
  }
433
458
  currentSlot++;
434
459
  maxRetries--;
@@ -451,17 +476,8 @@ export class HttpBlobClient implements BlobClientInterface {
451
476
  hostUrl: string,
452
477
  blockHashOrSlot: string | number,
453
478
  l1ConsensusHostIndex?: number,
454
- blobHashes?: Buffer[],
455
479
  ): Promise<Response> {
456
- let baseUrl = `${hostUrl}/eth/v1/beacon/blobs/${blockHashOrSlot}`;
457
-
458
- if (blobHashes && blobHashes.length > 0) {
459
- const params = new URLSearchParams();
460
- for (const hash of blobHashes) {
461
- params.append('versioned_hashes', `0x${hash.toString('hex')}`);
462
- }
463
- baseUrl += `?${params.toString()}`;
464
- }
480
+ const baseUrl = `${hostUrl}/eth/v1/beacon/blob_sidecars/${blockHashOrSlot}`;
465
481
 
466
482
  const { url, ...options } = getBeaconNodeFetchOptions(baseUrl, this.config, l1ConsensusHostIndex);
467
483
  this.log.debug(`Fetching blob sidecar for ${blockHashOrSlot}`, { url, ...options });
@@ -503,50 +519,34 @@ export class HttpBlobClient implements BlobClientInterface {
503
519
  * @param blockHash - The block hash
504
520
  * @returns The slot number
505
521
  */
506
- private async getSlotNumber(
507
- blockHash: `0x${string}`,
508
- parentBeaconBlockRoot?: string,
509
- l1BlockTimestamp?: bigint,
510
- ): Promise<number | undefined> {
522
+ private async getSlotNumber(blockHash: `0x${string}`): Promise<number | undefined> {
511
523
  const { l1ConsensusHostUrls, l1RpcUrls } = this.config;
512
524
  if (!l1ConsensusHostUrls || l1ConsensusHostUrls.length === 0) {
513
525
  this.log.debug('No consensus host url configured');
514
526
  return undefined;
515
527
  }
516
528
 
517
- // Primary path: compute slot from timestamp if genesis config is cached (no network call needed)
518
- if (
519
- l1BlockTimestamp !== undefined &&
520
- this.beaconGenesisTime !== undefined &&
521
- this.beaconSecondsPerSlot !== undefined
522
- ) {
523
- const slot = Number((l1BlockTimestamp - this.beaconGenesisTime) / BigInt(this.beaconSecondsPerSlot));
524
- this.log.debug(`Computed slot ${slot} from L1 block timestamp`, { l1BlockTimestamp });
525
- return slot;
529
+ if (!l1RpcUrls || l1RpcUrls.length === 0) {
530
+ this.log.debug('No execution host url configured');
531
+ return undefined;
526
532
  }
527
533
 
528
- if (!parentBeaconBlockRoot) {
529
- // parentBeaconBlockRoot not provided by caller — fetch it from the execution RPC
530
- if (!l1RpcUrls || l1RpcUrls.length === 0) {
531
- this.log.debug('No execution host url configured');
532
- return undefined;
533
- }
534
-
535
- const client = createPublicClient({
536
- transport: makeL1HttpTransport(l1RpcUrls, { timeout: this.config.l1HttpTimeoutMS }),
534
+ // Ping execution node to get the parentBeaconBlockRoot for this block
535
+ let parentBeaconBlockRoot: string | undefined;
536
+ const client = createPublicClient({
537
+ transport: makeL1HttpTransport(l1RpcUrls, { timeout: this.config.l1HttpTimeoutMS }),
538
+ });
539
+ try {
540
+ const res: RpcBlock = await client.request({
541
+ method: 'eth_getBlockByHash',
542
+ params: [blockHash, /*tx flag*/ false],
537
543
  });
538
- try {
539
- const res: RpcBlock = await client.request({
540
- method: 'eth_getBlockByHash',
541
- params: [blockHash, /*tx flag*/ false],
542
- });
543
544
 
544
- if (res.parentBeaconBlockRoot) {
545
- parentBeaconBlockRoot = res.parentBeaconBlockRoot;
546
- }
547
- } catch (err) {
548
- this.log.error(`Error getting parent beacon block root`, err);
545
+ if (res.parentBeaconBlockRoot) {
546
+ parentBeaconBlockRoot = res.parentBeaconBlockRoot;
549
547
  }
548
+ } catch (err) {
549
+ this.log.error(`Error getting parent beacon block root`, err);
550
550
  }
551
551
 
552
552
  if (!parentBeaconBlockRoot) {
@@ -592,12 +592,9 @@ export class HttpBlobClient implements BlobClientInterface {
592
592
 
593
593
  /**
594
594
  * Start the blob client.
595
- * Fetches and caches beacon genesis config for timestamp-based slot resolution,
596
- * then uploads the initial healthcheck file (awaited) and starts periodic uploads.
595
+ * Uploads the initial healthcheck file (awaited) and starts periodic uploads.
597
596
  */
598
597
  public async start(): Promise<void> {
599
- await this.fetchBeaconConfig();
600
-
601
598
  if (!this.fileStoreUploadClient) {
602
599
  return;
603
600
  }
@@ -622,53 +619,6 @@ export class HttpBlobClient implements BlobClientInterface {
622
619
  }, intervalMs);
623
620
  }
624
621
 
625
- /**
626
- * Fetches and caches beacon genesis time and slot duration from the first available consensus host.
627
- * These static values enable timestamp-based slot resolution, eliminating the per-fetch headers call.
628
- * Logs a warning and leaves fields undefined if all hosts fail, callers fall back gracefully.
629
- */
630
- private async fetchBeaconConfig(): Promise<void> {
631
- const { l1ConsensusHostUrls } = this.config;
632
- if (!l1ConsensusHostUrls || l1ConsensusHostUrls.length === 0) {
633
- return;
634
- }
635
-
636
- for (let i = 0; i < l1ConsensusHostUrls.length; i++) {
637
- try {
638
- const { url: genesisUrl, ...genesisOptions } = getBeaconNodeFetchOptions(
639
- `${l1ConsensusHostUrls[i]}/eth/v1/config/genesis`,
640
- this.config,
641
- i,
642
- );
643
- const { url: specUrl, ...specOptions } = getBeaconNodeFetchOptions(
644
- `${l1ConsensusHostUrls[i]}/eth/v1/config/spec`,
645
- this.config,
646
- i,
647
- );
648
-
649
- const [genesisRes, specRes] = await Promise.all([
650
- this.fetch(genesisUrl, genesisOptions),
651
- this.fetch(specUrl, specOptions),
652
- ]);
653
-
654
- if (genesisRes.ok && specRes.ok) {
655
- const genesis = await genesisRes.json();
656
- const spec = await specRes.json();
657
- this.beaconGenesisTime = BigInt(genesis.data.genesisTime);
658
- this.beaconSecondsPerSlot = parseInt(spec.data.secondsPerSlot);
659
- this.log.debug(`Fetched beacon genesis config`, {
660
- genesisTime: this.beaconGenesisTime,
661
- secondsPerSlot: this.beaconSecondsPerSlot,
662
- });
663
- return;
664
- }
665
- } catch (err) {
666
- this.log.warn(`Failed to fetch beacon config from host ${l1ConsensusHostUrls[i]}`, err);
667
- }
668
- }
669
- this.log.warn('Could not fetch beacon genesis config from any consensus host — will use headers call fallback');
670
- }
671
-
672
622
  /**
673
623
  * Stop the blob client, clearing any periodic tasks.
674
624
  */
@@ -680,9 +630,10 @@ export class HttpBlobClient implements BlobClientInterface {
680
630
  }
681
631
  }
682
632
 
683
- async function parseBlobJsonsFromResponse(response: any, logger: Logger): Promise<BlobJson[]> {
633
+ function parseBlobJsonsFromResponse(response: any, logger: Logger): BlobJson[] {
684
634
  try {
685
- return await Promise.all((response.data as string[]).map(parseBlobJson));
635
+ const blobs = response.data.map(parseBlobJson);
636
+ return blobs;
686
637
  } catch (err) {
687
638
  logger.error(`Error parsing blob json from response`, err);
688
639
  return [];
@@ -693,9 +644,10 @@ async function parseBlobJsonsFromResponse(response: any, logger: Logger): Promis
693
644
  // https://ethereum.github.io/beacon-APIs/?urls.primaryName=dev#/Beacon/getBlobSidecars
694
645
  // Here we attempt to parse the response data to Buffer, and check the lengths (via Blob's constructor), to avoid
695
646
  // throwing an error down the line when calling Blob.fromJson().
696
- async function parseBlobJson(rawHex: string): Promise<BlobJson> {
697
- const blobBuffer = Buffer.from(rawHex.slice(2), 'hex');
698
- const blob = await Blob.fromBlobBuffer(blobBuffer);
647
+ function parseBlobJson(data: any): BlobJson {
648
+ const blobBuffer = Buffer.from(data.blob.slice(2), 'hex');
649
+ const commitmentBuffer = Buffer.from(data.kzg_commitment.slice(2), 'hex');
650
+ const blob = new Blob(blobBuffer, commitmentBuffer);
699
651
  return blob.toJSON();
700
652
  }
701
653
 
@@ -11,17 +11,6 @@ export interface GetBlobSidecarOptions {
11
11
  * - Near tip: FileStore first with no retries (data should exist), L1 consensus second (freshest data), then FileStore with retries, then archive (eg. blobscan)
12
12
  */
13
13
  isHistoricalSync?: boolean;
14
- /**
15
- * The parent beacon block root for the L1 block containing the blobs.
16
- * If provided, skips the eth_getBlockByHash execution RPC call inside getSlotNumber.
17
- */
18
- parentBeaconBlockRoot?: string;
19
- /**
20
- * The timestamp of the L1 execution block containing the blobs.
21
- * When provided alongside a cached beacon genesis config (fetched at startup), allows computing
22
- * the beacon slot directly via timestamp math, skipping the beacon headers network call entirely.
23
- */
24
- l1BlockTimestamp?: bigint;
25
14
  }
26
15
 
27
16
  export interface BlobClientInterface {