@aztec/archiver 3.0.0-nightly.20251222 → 3.0.0-nightly.20251224

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dest/archiver/archiver.d.ts +10 -14
  2. package/dest/archiver/archiver.d.ts.map +1 -1
  3. package/dest/archiver/archiver.js +23 -18
  4. package/dest/archiver/archiver_store.d.ts +11 -8
  5. package/dest/archiver/archiver_store.d.ts.map +1 -1
  6. package/dest/archiver/archiver_store_test_suite.d.ts +1 -1
  7. package/dest/archiver/archiver_store_test_suite.d.ts.map +1 -1
  8. package/dest/archiver/archiver_store_test_suite.js +134 -39
  9. package/dest/archiver/config.d.ts +3 -3
  10. package/dest/archiver/config.d.ts.map +1 -1
  11. package/dest/archiver/config.js +2 -2
  12. package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts +4 -10
  13. package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts.map +1 -1
  14. package/dest/archiver/kv_archiver_store/kv_archiver_store.js +9 -8
  15. package/dest/archiver/kv_archiver_store/log_store.d.ts +11 -8
  16. package/dest/archiver/kv_archiver_store/log_store.d.ts.map +1 -1
  17. package/dest/archiver/kv_archiver_store/log_store.js +114 -48
  18. package/dest/archiver/l1/bin/retrieve-calldata.js +3 -1
  19. package/dest/archiver/l1/data_retrieval.d.ts +5 -5
  20. package/dest/archiver/l1/data_retrieval.d.ts.map +1 -1
  21. package/dest/archiver/l1/data_retrieval.js +9 -9
  22. package/dest/factory.d.ts +1 -1
  23. package/dest/factory.js +1 -1
  24. package/package.json +13 -13
  25. package/src/archiver/archiver.ts +29 -20
  26. package/src/archiver/archiver_store.ts +11 -7
  27. package/src/archiver/archiver_store_test_suite.ts +157 -43
  28. package/src/archiver/config.ts +7 -3
  29. package/src/archiver/kv_archiver_store/kv_archiver_store.ts +11 -10
  30. package/src/archiver/kv_archiver_store/log_store.ts +158 -53
  31. package/src/archiver/l1/bin/retrieve-calldata.ts +1 -1
  32. package/src/archiver/l1/data_retrieval.ts +10 -10
  33. package/src/factory.ts +1 -1
@@ -30,7 +30,7 @@ import {
30
30
  SerializableContractInstance,
31
31
  computePublicBytecodeCommitment,
32
32
  } from '@aztec/stdlib/contract';
33
- import { ContractClassLog, LogId, PrivateLog, PublicLog } from '@aztec/stdlib/logs';
33
+ import { ContractClassLog, LogId, PrivateLog, PublicLog, SiloedTag, Tag } from '@aztec/stdlib/logs';
34
34
  import { InboxLeaf } from '@aztec/stdlib/messaging';
35
35
  import { CheckpointHeader } from '@aztec/stdlib/rollup';
36
36
  import {
@@ -2198,46 +2198,35 @@ export function describeArchiverDataStore(
2198
2198
  });
2199
2199
  });
2200
2200
 
2201
- describe('getLogsByTags', () => {
2201
+ describe('getPrivateLogsByTags', () => {
2202
2202
  const numBlocksForLogs = 3;
2203
2203
  const numTxsPerBlock = 4;
2204
2204
  const numPrivateLogsPerTx = 3;
2205
- const numPublicLogsPerTx = 2;
2206
2205
 
2207
2206
  let logsCheckpoints: PublishedCheckpoint[];
2208
2207
 
2209
- const makeTag = (blockNumber: number, txIndex: number, logIndex: number, isPublic = false) =>
2210
- blockNumber === 1 && txIndex === 0 && logIndex === 0
2211
- ? Fr.ZERO // Shared tag
2212
- : new Fr((blockNumber * 100 + txIndex * 10 + logIndex) * (isPublic ? 123 : 1));
2208
+ const makePrivateLogTag = (blockNumber: number, txIndex: number, logIndex: number): SiloedTag =>
2209
+ new SiloedTag(
2210
+ blockNumber === 1 && txIndex === 0 && logIndex === 0
2211
+ ? Fr.ZERO // Shared tag
2212
+ : new Fr(blockNumber * 100 + txIndex * 10 + logIndex),
2213
+ );
2213
2214
 
2214
- const makePrivateLog = (tag: Fr) =>
2215
+ const makePrivateLog = (tag: SiloedTag) =>
2215
2216
  PrivateLog.from({
2216
- fields: makeTuple(PRIVATE_LOG_SIZE_IN_FIELDS, i => (!i ? tag : new Fr(tag.toNumber() + i))),
2217
+ fields: makeTuple(PRIVATE_LOG_SIZE_IN_FIELDS, i =>
2218
+ !i ? tag.value : new Fr(tag.value.toBigInt() + BigInt(i)),
2219
+ ),
2217
2220
  emittedLength: PRIVATE_LOG_SIZE_IN_FIELDS,
2218
2221
  });
2219
2222
 
2220
- const makePublicLog = (tag: Fr) =>
2221
- PublicLog.from({
2222
- contractAddress: AztecAddress.fromNumber(1),
2223
- // Arbitrary length
2224
- fields: new Array(10).fill(null).map((_, i) => (!i ? tag : new Fr(tag.toNumber() + i))),
2225
- });
2226
-
2227
2223
  const mockPrivateLogs = (blockNumber: number, txIndex: number) => {
2228
2224
  return times(numPrivateLogsPerTx, (logIndex: number) => {
2229
- const tag = makeTag(blockNumber, txIndex, logIndex);
2225
+ const tag = makePrivateLogTag(blockNumber, txIndex, logIndex);
2230
2226
  return makePrivateLog(tag);
2231
2227
  });
2232
2228
  };
2233
2229
 
2234
- const mockPublicLogs = (blockNumber: number, txIndex: number) => {
2235
- return times(numPublicLogsPerTx, (logIndex: number) => {
2236
- const tag = makeTag(blockNumber, txIndex, logIndex, /* isPublic */ true);
2237
- return makePublicLog(tag);
2238
- });
2239
- };
2240
-
2241
2230
  const mockCheckpointWithLogs = async (
2242
2231
  blockNumber: number,
2243
2232
  previousArchive?: AppendOnlyTreeSnapshot,
@@ -2253,7 +2242,7 @@ export function describeArchiverDataStore(
2253
2242
  block.body.txEffects = await timesParallel(numTxsPerBlock, async (txIndex: number) => {
2254
2243
  const txEffect = await TxEffect.random();
2255
2244
  txEffect.privateLogs = mockPrivateLogs(blockNumber, txIndex);
2256
- txEffect.publicLogs = mockPublicLogs(blockNumber, txIndex);
2245
+ txEffect.publicLogs = []; // No public logs needed for private log tests
2257
2246
  return txEffect;
2258
2247
  });
2259
2248
 
@@ -2279,9 +2268,9 @@ export function describeArchiverDataStore(
2279
2268
  });
2280
2269
 
2281
2270
  it('is possible to batch request private logs via tags', async () => {
2282
- const tags = [makeTag(2, 1, 2), makeTag(1, 2, 0)];
2271
+ const tags = [makePrivateLogTag(2, 1, 2), makePrivateLogTag(1, 2, 0)];
2283
2272
 
2284
- const logsByTags = await store.getLogsByTags(tags);
2273
+ const logsByTags = await store.getPrivateLogsByTags(tags);
2285
2274
 
2286
2275
  expect(logsByTags).toEqual([
2287
2276
  [
@@ -2303,11 +2292,21 @@ export function describeArchiverDataStore(
2303
2292
  ]);
2304
2293
  });
2305
2294
 
2306
- it('is possible to batch request all logs (private and public) via tags', async () => {
2307
- // Tag(1, 0, 0) is shared with the first private log and the first public log.
2308
- const tags = [makeTag(1, 0, 0)];
2295
+ it('is possible to batch request logs that have the same tag but different content', async () => {
2296
+ const tags = [makePrivateLogTag(1, 2, 1)];
2309
2297
 
2310
- const logsByTags = await store.getLogsByTags(tags);
2298
+ // Create a checkpoint containing logs that have the same tag as the checkpoints before.
2299
+ // Chain from the last checkpoint's archive
2300
+ const newBlockNumber = numBlocksForLogs + 1;
2301
+ const previousArchive = logsCheckpoints[logsCheckpoints.length - 1].checkpoint.blocks[0].archive;
2302
+ const newCheckpoint = await mockCheckpointWithLogs(newBlockNumber, previousArchive);
2303
+ const newLog = newCheckpoint.checkpoint.blocks[0].body.txEffects[1].privateLogs[1];
2304
+ newLog.fields[0] = tags[0].value;
2305
+ newCheckpoint.checkpoint.blocks[0].body.txEffects[1].privateLogs[1] = newLog;
2306
+ await store.addCheckpoints([newCheckpoint]);
2307
+ await store.addLogs([newCheckpoint.checkpoint.blocks[0]]);
2308
+
2309
+ const logsByTags = await store.getPrivateLogsByTags(tags);
2311
2310
 
2312
2311
  expect(logsByTags).toEqual([
2313
2312
  [
@@ -2317,54 +2316,169 @@ export function describeArchiverDataStore(
2317
2316
  log: makePrivateLog(tags[0]),
2318
2317
  isFromPublic: false,
2319
2318
  }),
2319
+ expect.objectContaining({
2320
+ blockNumber: newBlockNumber,
2321
+ blockHash: L2BlockHash.fromField(await newCheckpoint.checkpoint.blocks[0].header.hash()),
2322
+ log: newLog,
2323
+ isFromPublic: false,
2324
+ }),
2325
+ ],
2326
+ ]);
2327
+ });
2328
+
2329
+ it('is possible to request logs for non-existing tags and determine their position', async () => {
2330
+ const tags = [makePrivateLogTag(99, 88, 77), makePrivateLogTag(1, 1, 1)];
2331
+
2332
+ const logsByTags = await store.getPrivateLogsByTags(tags);
2333
+
2334
+ expect(logsByTags).toEqual([
2335
+ [
2336
+ // No logs for the first tag.
2337
+ ],
2338
+ [
2320
2339
  expect.objectContaining({
2321
2340
  blockNumber: 1,
2322
2341
  blockHash: L2BlockHash.fromField(await logsCheckpoints[1 - 1].checkpoint.blocks[0].header.hash()),
2342
+ log: makePrivateLog(tags[1]),
2343
+ isFromPublic: false,
2344
+ }),
2345
+ ],
2346
+ ]);
2347
+ });
2348
+ });
2349
+
2350
+ describe('getPublicLogsByTagsFromContract', () => {
2351
+ const numBlocksForLogs = 3;
2352
+ const numTxsPerBlock = 4;
2353
+ const numPublicLogsPerTx = 2;
2354
+ const contractAddress = AztecAddress.fromNumber(543254);
2355
+
2356
+ let logsCheckpoints: PublishedCheckpoint[];
2357
+
2358
+ const makePublicLogTag = (blockNumber: number, txIndex: number, logIndex: number): Tag =>
2359
+ new Tag(
2360
+ blockNumber === 1 && txIndex === 0 && logIndex === 0
2361
+ ? Fr.ZERO // Shared tag
2362
+ : new Fr((blockNumber * 100 + txIndex * 10 + logIndex) * 123),
2363
+ );
2364
+
2365
+ const makePublicLog = (tag: Tag) =>
2366
+ PublicLog.from({
2367
+ contractAddress: contractAddress,
2368
+ // Arbitrary length
2369
+ fields: new Array(10).fill(null).map((_, i) => (!i ? tag.value : new Fr(tag.value.toBigInt() + BigInt(i)))),
2370
+ });
2371
+
2372
+ const mockPublicLogs = (blockNumber: number, txIndex: number) => {
2373
+ return times(numPublicLogsPerTx, (logIndex: number) => {
2374
+ const tag = makePublicLogTag(blockNumber, txIndex, logIndex);
2375
+ return makePublicLog(tag);
2376
+ });
2377
+ };
2378
+
2379
+ const mockCheckpointWithLogs = async (
2380
+ blockNumber: number,
2381
+ previousArchive?: AppendOnlyTreeSnapshot,
2382
+ ): Promise<PublishedCheckpoint> => {
2383
+ const block = await L2BlockNew.random(BlockNumber(blockNumber), {
2384
+ checkpointNumber: CheckpointNumber(blockNumber),
2385
+ indexWithinCheckpoint: 0,
2386
+ state: makeStateForBlock(blockNumber, numTxsPerBlock),
2387
+ ...(previousArchive ? { lastArchive: previousArchive } : {}),
2388
+ });
2389
+ block.header.globalVariables.blockNumber = BlockNumber(blockNumber);
2390
+
2391
+ block.body.txEffects = await timesParallel(numTxsPerBlock, async (txIndex: number) => {
2392
+ const txEffect = await TxEffect.random();
2393
+ txEffect.privateLogs = []; // No private logs needed for public log tests
2394
+ txEffect.publicLogs = mockPublicLogs(blockNumber, txIndex);
2395
+ return txEffect;
2396
+ });
2397
+
2398
+ const checkpoint = new Checkpoint(
2399
+ AppendOnlyTreeSnapshot.random(),
2400
+ CheckpointHeader.random(),
2401
+ [block],
2402
+ CheckpointNumber(blockNumber),
2403
+ );
2404
+ return makePublishedCheckpoint(checkpoint, blockNumber);
2405
+ };
2406
+
2407
+ beforeEach(async () => {
2408
+ // Create checkpoints sequentially to chain archive roots
2409
+ logsCheckpoints = [];
2410
+ for (let i = 0; i < numBlocksForLogs; i++) {
2411
+ const previousArchive = i > 0 ? logsCheckpoints[i - 1].checkpoint.blocks[0].archive : undefined;
2412
+ logsCheckpoints.push(await mockCheckpointWithLogs(i + 1, previousArchive));
2413
+ }
2414
+
2415
+ await store.addCheckpoints(logsCheckpoints);
2416
+ await store.addLogs(logsCheckpoints.flatMap(p => p.checkpoint.blocks));
2417
+ });
2418
+
2419
+ it('is possible to batch request public logs via tags', async () => {
2420
+ const tags = [makePublicLogTag(2, 1, 1), makePublicLogTag(1, 2, 0)];
2421
+
2422
+ const logsByTags = await store.getPublicLogsByTagsFromContract(contractAddress, tags);
2423
+
2424
+ expect(logsByTags).toEqual([
2425
+ [
2426
+ expect.objectContaining({
2427
+ blockNumber: 2,
2428
+ blockHash: L2BlockHash.fromField(await logsCheckpoints[2 - 1].checkpoint.blocks[0].header.hash()),
2323
2429
  log: makePublicLog(tags[0]),
2324
2430
  isFromPublic: true,
2325
2431
  }),
2326
2432
  ],
2433
+ [
2434
+ expect.objectContaining({
2435
+ blockNumber: 1,
2436
+ blockHash: L2BlockHash.fromField(await logsCheckpoints[1 - 1].checkpoint.blocks[0].header.hash()),
2437
+ log: makePublicLog(tags[1]),
2438
+ isFromPublic: true,
2439
+ }),
2440
+ ],
2327
2441
  ]);
2328
2442
  });
2329
2443
 
2330
2444
  it('is possible to batch request logs that have the same tag but different content', async () => {
2331
- const tags = [makeTag(1, 2, 1)];
2445
+ const tags = [makePublicLogTag(1, 2, 1)];
2332
2446
 
2333
2447
  // Create a checkpoint containing logs that have the same tag as the checkpoints before.
2334
2448
  // Chain from the last checkpoint's archive
2335
2449
  const newBlockNumber = numBlocksForLogs + 1;
2336
2450
  const previousArchive = logsCheckpoints[logsCheckpoints.length - 1].checkpoint.blocks[0].archive;
2337
2451
  const newCheckpoint = await mockCheckpointWithLogs(newBlockNumber, previousArchive);
2338
- const newLog = newCheckpoint.checkpoint.blocks[0].body.txEffects[1].privateLogs[1];
2339
- newLog.fields[0] = tags[0];
2340
- newCheckpoint.checkpoint.blocks[0].body.txEffects[1].privateLogs[1] = newLog;
2452
+ const newLog = newCheckpoint.checkpoint.blocks[0].body.txEffects[1].publicLogs[1];
2453
+ newLog.fields[0] = tags[0].value;
2454
+ newCheckpoint.checkpoint.blocks[0].body.txEffects[1].publicLogs[1] = newLog;
2341
2455
  await store.addCheckpoints([newCheckpoint]);
2342
2456
  await store.addLogs([newCheckpoint.checkpoint.blocks[0]]);
2343
2457
 
2344
- const logsByTags = await store.getLogsByTags(tags);
2458
+ const logsByTags = await store.getPublicLogsByTagsFromContract(contractAddress, tags);
2345
2459
 
2346
2460
  expect(logsByTags).toEqual([
2347
2461
  [
2348
2462
  expect.objectContaining({
2349
2463
  blockNumber: 1,
2350
2464
  blockHash: L2BlockHash.fromField(await logsCheckpoints[1 - 1].checkpoint.blocks[0].header.hash()),
2351
- log: makePrivateLog(tags[0]),
2352
- isFromPublic: false,
2465
+ log: makePublicLog(tags[0]),
2466
+ isFromPublic: true,
2353
2467
  }),
2354
2468
  expect.objectContaining({
2355
2469
  blockNumber: newBlockNumber,
2356
2470
  blockHash: L2BlockHash.fromField(await newCheckpoint.checkpoint.blocks[0].header.hash()),
2357
2471
  log: newLog,
2358
- isFromPublic: false,
2472
+ isFromPublic: true,
2359
2473
  }),
2360
2474
  ],
2361
2475
  ]);
2362
2476
  });
2363
2477
 
2364
2478
  it('is possible to request logs for non-existing tags and determine their position', async () => {
2365
- const tags = [makeTag(99, 88, 77), makeTag(1, 1, 1)];
2479
+ const tags = [makePublicLogTag(99, 88, 77), makePublicLogTag(1, 1, 0)];
2366
2480
 
2367
- const logsByTags = await store.getLogsByTags(tags);
2481
+ const logsByTags = await store.getPublicLogsByTagsFromContract(contractAddress, tags);
2368
2482
 
2369
2483
  expect(logsByTags).toEqual([
2370
2484
  [
@@ -2374,8 +2488,8 @@ export function describeArchiverDataStore(
2374
2488
  expect.objectContaining({
2375
2489
  blockNumber: 1,
2376
2490
  blockHash: L2BlockHash.fromField(await logsCheckpoints[1 - 1].checkpoint.blocks[0].header.hash()),
2377
- log: makePrivateLog(tags[1]),
2378
- isFromPublic: false,
2491
+ log: makePublicLog(tags[1]),
2492
+ isFromPublic: true,
2379
2493
  }),
2380
2494
  ],
2381
2495
  ]);
@@ -1,4 +1,4 @@
1
- import { type BlobSinkConfig, blobSinkConfigMapping } from '@aztec/blob-sink/client/config';
1
+ import { type BlobClientConfig, blobClientConfigMapping } from '@aztec/blob-client/client/config';
2
2
  import { type L1ContractsConfig, l1ContractsConfigMappings } from '@aztec/ethereum/config';
3
3
  import { l1ContractAddressesMapping } from '@aztec/ethereum/l1-contract-addresses';
4
4
  import { type L1ReaderConfig, l1ReaderConfigMappings } from '@aztec/ethereum/l1-reader';
@@ -18,10 +18,14 @@ import type { ArchiverSpecificConfig } from '@aztec/stdlib/interfaces/server';
18
18
  * Results of calls to eth_blockNumber are cached by viem with this cache being updated periodically at the interval specified by viemPollingIntervalMS.
19
19
  * As a result the maximum observed polling time for new blocks will be viemPollingIntervalMS + archiverPollingIntervalMS.
20
20
  */
21
- export type ArchiverConfig = ArchiverSpecificConfig & L1ReaderConfig & L1ContractsConfig & BlobSinkConfig & ChainConfig;
21
+ export type ArchiverConfig = ArchiverSpecificConfig &
22
+ L1ReaderConfig &
23
+ L1ContractsConfig &
24
+ BlobClientConfig &
25
+ ChainConfig;
22
26
 
23
27
  export const archiverConfigMappings: ConfigMappingsType<ArchiverConfig> = {
24
- ...blobSinkConfigMapping,
28
+ ...blobClientConfigMapping,
25
29
  archiverPollingIntervalMS: {
26
30
  env: 'ARCHIVER_POLLING_INTERVAL_MS',
27
31
  description: 'The polling interval in ms for retrieving new L2 blocks and encrypted logs.',
@@ -17,7 +17,7 @@ import type {
17
17
  UtilityFunctionWithMembershipProof,
18
18
  } from '@aztec/stdlib/contract';
19
19
  import type { GetContractClassLogsResponse, GetPublicLogsResponse } from '@aztec/stdlib/interfaces/client';
20
- import type { LogFilter, TxScopedL2Log } from '@aztec/stdlib/logs';
20
+ import type { LogFilter, SiloedTag, Tag, TxScopedL2Log } from '@aztec/stdlib/logs';
21
21
  import type { BlockHeader, TxHash, TxReceipt } from '@aztec/stdlib/tx';
22
22
  import type { UInt64 } from '@aztec/stdlib/types';
23
23
 
@@ -318,16 +318,17 @@ export class KVArchiverDataStore implements ArchiverDataStore, ContractDataSourc
318
318
  return this.#messageStore.getL1ToL2Messages(checkpointNumber);
319
319
  }
320
320
 
321
- /**
322
- * Gets all logs that match any of the received tags (i.e. logs with their first field equal to a tag).
323
- * @param tags - The tags to filter the logs by.
324
- * @param logsPerTag - How many logs to return per tag. Default returns everything
325
- * @returns For each received tag, an array of matching logs is returned. An empty array implies no logs match
326
- * that tag.
327
- */
328
- getLogsByTags(tags: Fr[], logsPerTag?: number): Promise<TxScopedL2Log[][]> {
321
+ getPrivateLogsByTags(tags: SiloedTag[]): Promise<TxScopedL2Log[][]> {
322
+ try {
323
+ return this.#logStore.getPrivateLogsByTags(tags);
324
+ } catch (err) {
325
+ return Promise.reject(err);
326
+ }
327
+ }
328
+
329
+ getPublicLogsByTagsFromContract(contractAddress: AztecAddress, tags: Tag[]): Promise<TxScopedL2Log[][]> {
329
330
  try {
330
- return this.#logStore.getLogsByTags(tags, logsPerTag);
331
+ return this.#logStore.getPublicLogsByTagsFromContract(contractAddress, tags);
331
332
  } catch (err) {
332
333
  return Promise.reject(err);
333
334
  }