@aztec/archiver 0.0.1-commit.3469e52 → 0.0.1-commit.381b1a9

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 (97) hide show
  1. package/README.md +9 -0
  2. package/dest/archiver.d.ts +12 -8
  3. package/dest/archiver.d.ts.map +1 -1
  4. package/dest/archiver.js +81 -120
  5. package/dest/errors.d.ts +6 -1
  6. package/dest/errors.d.ts.map +1 -1
  7. package/dest/errors.js +8 -0
  8. package/dest/factory.d.ts +3 -1
  9. package/dest/factory.d.ts.map +1 -1
  10. package/dest/factory.js +14 -11
  11. package/dest/index.d.ts +2 -1
  12. package/dest/index.d.ts.map +1 -1
  13. package/dest/index.js +1 -0
  14. package/dest/l1/bin/retrieve-calldata.js +35 -32
  15. package/dest/l1/calldata_retriever.d.ts +73 -50
  16. package/dest/l1/calldata_retriever.d.ts.map +1 -1
  17. package/dest/l1/calldata_retriever.js +190 -259
  18. package/dest/l1/data_retrieval.d.ts +4 -7
  19. package/dest/l1/data_retrieval.d.ts.map +1 -1
  20. package/dest/l1/data_retrieval.js +12 -16
  21. package/dest/l1/spire_proposer.d.ts +5 -5
  22. package/dest/l1/spire_proposer.d.ts.map +1 -1
  23. package/dest/l1/spire_proposer.js +9 -17
  24. package/dest/l1/validate_trace.d.ts +6 -3
  25. package/dest/l1/validate_trace.d.ts.map +1 -1
  26. package/dest/l1/validate_trace.js +13 -9
  27. package/dest/modules/data_source_base.d.ts +25 -21
  28. package/dest/modules/data_source_base.d.ts.map +1 -1
  29. package/dest/modules/data_source_base.js +45 -120
  30. package/dest/modules/data_store_updater.d.ts +40 -21
  31. package/dest/modules/data_store_updater.d.ts.map +1 -1
  32. package/dest/modules/data_store_updater.js +114 -64
  33. package/dest/modules/instrumentation.d.ts +6 -4
  34. package/dest/modules/instrumentation.d.ts.map +1 -1
  35. package/dest/modules/instrumentation.js +26 -12
  36. package/dest/modules/l1_synchronizer.d.ts +5 -8
  37. package/dest/modules/l1_synchronizer.d.ts.map +1 -1
  38. package/dest/modules/l1_synchronizer.js +46 -20
  39. package/dest/store/block_store.d.ts +49 -32
  40. package/dest/store/block_store.d.ts.map +1 -1
  41. package/dest/store/block_store.js +165 -54
  42. package/dest/store/contract_class_store.d.ts +1 -1
  43. package/dest/store/contract_class_store.d.ts.map +1 -1
  44. package/dest/store/contract_class_store.js +11 -7
  45. package/dest/store/kv_archiver_store.d.ts +53 -25
  46. package/dest/store/kv_archiver_store.d.ts.map +1 -1
  47. package/dest/store/kv_archiver_store.js +50 -17
  48. package/dest/store/l2_tips_cache.d.ts +19 -0
  49. package/dest/store/l2_tips_cache.d.ts.map +1 -0
  50. package/dest/store/l2_tips_cache.js +89 -0
  51. package/dest/store/log_store.d.ts +4 -4
  52. package/dest/store/log_store.d.ts.map +1 -1
  53. package/dest/store/log_store.js +105 -47
  54. package/dest/store/message_store.js +1 -1
  55. package/dest/test/fake_l1_state.d.ts +16 -4
  56. package/dest/test/fake_l1_state.d.ts.map +1 -1
  57. package/dest/test/fake_l1_state.js +84 -20
  58. package/dest/test/index.js +3 -1
  59. package/dest/test/mock_archiver.d.ts +1 -1
  60. package/dest/test/mock_archiver.d.ts.map +1 -1
  61. package/dest/test/mock_archiver.js +3 -2
  62. package/dest/test/mock_l2_block_source.d.ts +39 -23
  63. package/dest/test/mock_l2_block_source.d.ts.map +1 -1
  64. package/dest/test/mock_l2_block_source.js +157 -112
  65. package/dest/test/mock_structs.d.ts +6 -2
  66. package/dest/test/mock_structs.d.ts.map +1 -1
  67. package/dest/test/mock_structs.js +24 -10
  68. package/dest/test/noop_l1_archiver.d.ts +26 -0
  69. package/dest/test/noop_l1_archiver.d.ts.map +1 -0
  70. package/dest/test/noop_l1_archiver.js +72 -0
  71. package/package.json +14 -13
  72. package/src/archiver.ts +106 -149
  73. package/src/errors.ts +12 -0
  74. package/src/factory.ts +29 -12
  75. package/src/index.ts +1 -0
  76. package/src/l1/README.md +25 -68
  77. package/src/l1/bin/retrieve-calldata.ts +45 -33
  78. package/src/l1/calldata_retriever.ts +249 -379
  79. package/src/l1/data_retrieval.ts +10 -20
  80. package/src/l1/spire_proposer.ts +7 -15
  81. package/src/l1/validate_trace.ts +24 -6
  82. package/src/modules/data_source_base.ts +76 -166
  83. package/src/modules/data_store_updater.ts +130 -66
  84. package/src/modules/instrumentation.ts +26 -14
  85. package/src/modules/l1_synchronizer.ts +55 -26
  86. package/src/store/block_store.ts +216 -92
  87. package/src/store/contract_class_store.ts +11 -7
  88. package/src/store/kv_archiver_store.ts +88 -30
  89. package/src/store/l2_tips_cache.ts +89 -0
  90. package/src/store/log_store.ts +171 -55
  91. package/src/store/message_store.ts +1 -1
  92. package/src/test/fake_l1_state.ts +112 -23
  93. package/src/test/index.ts +3 -0
  94. package/src/test/mock_archiver.ts +3 -2
  95. package/src/test/mock_l2_block_source.ts +211 -129
  96. package/src/test/mock_structs.ts +45 -15
  97. package/src/test/noop_l1_archiver.ts +115 -0
@@ -1,12 +1,12 @@
1
1
  import { INITIAL_L2_BLOCK_NUM } from '@aztec/constants';
2
2
  import { BlockNumber } from '@aztec/foundation/branded-types';
3
- import { filterAsync } from '@aztec/foundation/collection';
3
+ import { compactArray, filterAsync } from '@aztec/foundation/collection';
4
4
  import { Fr } from '@aztec/foundation/curves/bn254';
5
5
  import { createLogger } from '@aztec/foundation/log';
6
6
  import { BufferReader, numToUInt32BE } from '@aztec/foundation/serialize';
7
7
  import type { AztecAsyncKVStore, AztecAsyncMap } from '@aztec/kv-store';
8
8
  import type { AztecAddress } from '@aztec/stdlib/aztec-address';
9
- import { L2BlockHash, L2BlockNew } from '@aztec/stdlib/block';
9
+ import { BlockHash, L2Block } from '@aztec/stdlib/block';
10
10
  import { MAX_LOGS_PER_TAG } from '@aztec/stdlib/interfaces/api-limit';
11
11
  import type { GetContractClassLogsResponse, GetPublicLogsResponse } from '@aztec/stdlib/interfaces/client';
12
12
  import {
@@ -20,6 +20,7 @@ import {
20
20
  Tag,
21
21
  TxScopedL2Log,
22
22
  } from '@aztec/stdlib/logs';
23
+ import { TxHash } from '@aztec/stdlib/tx';
23
24
 
24
25
  import type { BlockStore } from './block_store.js';
25
26
 
@@ -59,7 +60,7 @@ export class LogStore {
59
60
  * @param block - The L2 block to extract logs from.
60
61
  * @returns An object containing the private and public tagged logs for the block.
61
62
  */
62
- #extractTaggedLogsFromBlock(block: L2BlockNew) {
63
+ #extractTaggedLogsFromBlock(block: L2Block) {
63
64
  // SiloedTag (as string) -> array of log buffers.
64
65
  const privateTaggedLogs = new Map<string, Buffer[]>();
65
66
  // "{contractAddress}_{tag}" (as string) -> array of log buffers.
@@ -120,7 +121,7 @@ export class LogStore {
120
121
  * @returns A map from tag (as string) to an array of serialized private logs belonging to that tag, and a map from
121
122
  * "{contractAddress}_{tag}" (as string) to an array of serialized public logs belonging to that key.
122
123
  */
123
- #extractTaggedLogs(blocks: L2BlockNew[]): {
124
+ #extractTaggedLogs(blocks: L2Block[]): {
124
125
  privateTaggedLogs: Map<string, Buffer[]>;
125
126
  publicTaggedLogs: Map<string, Buffer[]>;
126
127
  } {
@@ -146,7 +147,7 @@ export class LogStore {
146
147
  return { privateTaggedLogs, publicTaggedLogs };
147
148
  }
148
149
 
149
- async #addPrivateLogs(blocks: L2BlockNew[]): Promise<void> {
150
+ async #addPrivateLogs(blocks: L2Block[]): Promise<void> {
150
151
  const newBlocks = await filterAsync(
151
152
  blocks,
152
153
  async block => !(await this.#privateLogKeysByBlock.hasAsync(block.number)),
@@ -181,7 +182,7 @@ export class LogStore {
181
182
  }
182
183
  }
183
184
 
184
- async #addPublicLogs(blocks: L2BlockNew[]): Promise<void> {
185
+ async #addPublicLogs(blocks: L2Block[]): Promise<void> {
185
186
  const newBlocks = await filterAsync(
186
187
  blocks,
187
188
  async block => !(await this.#publicLogKeysByBlock.hasAsync(block.number)),
@@ -219,6 +220,7 @@ export class LogStore {
219
220
  .map((txEffect, txIndex) =>
220
221
  [
221
222
  numToUInt32BE(txIndex),
223
+ txEffect.txHash.toBuffer(),
222
224
  numToUInt32BE(txEffect.publicLogs.length),
223
225
  txEffect.publicLogs.map(log => log.toBuffer()),
224
226
  ].flat(),
@@ -229,7 +231,7 @@ export class LogStore {
229
231
  }
230
232
  }
231
233
 
232
- async #addContractClassLogs(blocks: L2BlockNew[]): Promise<void> {
234
+ async #addContractClassLogs(blocks: L2Block[]): Promise<void> {
233
235
  const newBlocks = await filterAsync(
234
236
  blocks,
235
237
  async block => !(await this.#contractClassLogsByBlock.hasAsync(block.number)),
@@ -242,6 +244,7 @@ export class LogStore {
242
244
  .map((txEffect, txIndex) =>
243
245
  [
244
246
  numToUInt32BE(txIndex),
247
+ txEffect.txHash.toBuffer(),
245
248
  numToUInt32BE(txEffect.contractClassLogs.length),
246
249
  txEffect.contractClassLogs.map(log => log.toBuffer()),
247
250
  ].flat(),
@@ -260,7 +263,7 @@ export class LogStore {
260
263
  * @param blocks - The blocks for which to add the logs.
261
264
  * @returns True if the operation is successful.
262
265
  */
263
- addLogs(blocks: L2BlockNew[]): Promise<boolean> {
266
+ addLogs(blocks: L2Block[]): Promise<boolean> {
264
267
  return this.db.transactionAsync(async () => {
265
268
  await Promise.all([
266
269
  this.#addPrivateLogs(blocks),
@@ -271,34 +274,65 @@ export class LogStore {
271
274
  });
272
275
  }
273
276
 
274
- #packWithBlockHash(blockHash: Fr, data: Buffer<ArrayBufferLike>[]): Buffer<ArrayBufferLike> {
277
+ #packWithBlockHash(blockHash: BlockHash, data: Buffer<ArrayBufferLike>[]): Buffer<ArrayBufferLike> {
275
278
  return Buffer.concat([blockHash.toBuffer(), ...data]);
276
279
  }
277
280
 
278
- #unpackBlockHash(reader: BufferReader): L2BlockHash {
281
+ #unpackBlockHash(reader: BufferReader): BlockHash {
279
282
  const blockHash = reader.remainingBytes() > 0 ? reader.readObject(Fr) : undefined;
280
283
 
281
284
  if (!blockHash) {
282
285
  throw new Error('Failed to read block hash from log entry buffer');
283
286
  }
284
287
 
285
- return L2BlockHash.fromField(blockHash);
288
+ return new BlockHash(blockHash);
286
289
  }
287
290
 
288
- deleteLogs(blocks: L2BlockNew[]): Promise<boolean> {
291
+ deleteLogs(blocks: L2Block[]): Promise<boolean> {
289
292
  return this.db.transactionAsync(async () => {
290
- await Promise.all(
291
- blocks.map(async block => {
292
- // Delete private logs
293
- const privateKeys = (await this.#privateLogKeysByBlock.getAsync(block.number)) ?? [];
294
- await Promise.all(privateKeys.map(tag => this.#privateLogsByTag.delete(tag)));
295
-
296
- // Delete public logs
297
- const publicKeys = (await this.#publicLogKeysByBlock.getAsync(block.number)) ?? [];
298
- await Promise.all(publicKeys.map(key => this.#publicLogsByContractAndTag.delete(key)));
299
- }),
293
+ const blockNumbers = new Set(blocks.map(block => block.number));
294
+ const firstBlockToDelete = Math.min(...blockNumbers);
295
+
296
+ // Collect all unique private tags across all blocks being deleted
297
+ const allPrivateTags = new Set(
298
+ compactArray(await Promise.all(blocks.map(block => this.#privateLogKeysByBlock.getAsync(block.number)))).flat(),
299
+ );
300
+
301
+ // Trim private logs: for each tag, delete all instances including and after the first block being deleted.
302
+ // This hinges on the invariant that logs for a given tag are always inserted in order of block number, which is enforced in #addPrivateLogs.
303
+ for (const tag of allPrivateTags) {
304
+ const existing = await this.#privateLogsByTag.getAsync(tag);
305
+ if (existing === undefined || existing.length === 0) {
306
+ continue;
307
+ }
308
+ const lastIndexToKeep = existing.findLastIndex(
309
+ buf => TxScopedL2Log.getBlockNumberFromBuffer(buf) < firstBlockToDelete,
310
+ );
311
+ const remaining = existing.slice(0, lastIndexToKeep + 1);
312
+ await (remaining.length > 0 ? this.#privateLogsByTag.set(tag, remaining) : this.#privateLogsByTag.delete(tag));
313
+ }
314
+
315
+ // Collect all unique public keys across all blocks being deleted
316
+ const allPublicKeys = new Set(
317
+ compactArray(await Promise.all(blocks.map(block => this.#publicLogKeysByBlock.getAsync(block.number)))).flat(),
300
318
  );
301
319
 
320
+ // And do the same as we did with private logs
321
+ for (const key of allPublicKeys) {
322
+ const existing = await this.#publicLogsByContractAndTag.getAsync(key);
323
+ if (existing === undefined || existing.length === 0) {
324
+ continue;
325
+ }
326
+ const lastIndexToKeep = existing.findLastIndex(
327
+ buf => TxScopedL2Log.getBlockNumberFromBuffer(buf) < firstBlockToDelete,
328
+ );
329
+ const remaining = existing.slice(0, lastIndexToKeep + 1);
330
+ await (remaining.length > 0
331
+ ? this.#publicLogsByContractAndTag.set(key, remaining)
332
+ : this.#publicLogsByContractAndTag.delete(key));
333
+ }
334
+
335
+ // After trimming the tagged logs, we can delete the block-level keys that track which tags are in which blocks.
302
336
  await Promise.all(
303
337
  blocks.map(block =>
304
338
  Promise.all([
@@ -386,24 +420,33 @@ export class LogStore {
386
420
  }
387
421
 
388
422
  const buffer = (await this.#publicLogsByBlock.getAsync(blockNumber)) ?? Buffer.alloc(0);
389
- const publicLogsInBlock: [PublicLog[]] = [[]];
423
+ const publicLogsInBlock: { txHash: TxHash; logs: PublicLog[] }[] = [];
390
424
  const reader = new BufferReader(buffer);
391
425
 
392
426
  const blockHash = this.#unpackBlockHash(reader);
393
427
 
394
428
  while (reader.remainingBytes() > 0) {
395
429
  const indexOfTx = reader.readNumber();
430
+ const txHash = reader.readObject(TxHash);
396
431
  const numLogsInTx = reader.readNumber();
397
- publicLogsInBlock[indexOfTx] = [];
432
+ publicLogsInBlock[indexOfTx] = { txHash, logs: [] };
398
433
  for (let i = 0; i < numLogsInTx; i++) {
399
- publicLogsInBlock[indexOfTx].push(reader.readObject(PublicLog));
434
+ publicLogsInBlock[indexOfTx].logs.push(reader.readObject(PublicLog));
400
435
  }
401
436
  }
402
437
 
403
- const txLogs = publicLogsInBlock[txIndex];
438
+ const txData = publicLogsInBlock[txIndex];
404
439
 
405
440
  const logs: ExtendedPublicLog[] = [];
406
- const maxLogsHit = this.#accumulateLogs(logs, blockNumber, blockHash, txIndex, txLogs, filter);
441
+ const maxLogsHit = this.#accumulatePublicLogs(
442
+ logs,
443
+ blockNumber,
444
+ blockHash,
445
+ txIndex,
446
+ txData.txHash,
447
+ txData.logs,
448
+ filter,
449
+ );
407
450
 
408
451
  return { logs, maxLogsHit };
409
452
  }
@@ -424,22 +467,31 @@ export class LogStore {
424
467
 
425
468
  let maxLogsHit = false;
426
469
  loopOverBlocks: for await (const [blockNumber, logBuffer] of this.#publicLogsByBlock.entriesAsync({ start, end })) {
427
- const publicLogsInBlock: [PublicLog[]] = [[]];
470
+ const publicLogsInBlock: { txHash: TxHash; logs: PublicLog[] }[] = [];
428
471
  const reader = new BufferReader(logBuffer);
429
472
 
430
473
  const blockHash = this.#unpackBlockHash(reader);
431
474
 
432
475
  while (reader.remainingBytes() > 0) {
433
476
  const indexOfTx = reader.readNumber();
477
+ const txHash = reader.readObject(TxHash);
434
478
  const numLogsInTx = reader.readNumber();
435
- publicLogsInBlock[indexOfTx] = [];
479
+ publicLogsInBlock[indexOfTx] = { txHash, logs: [] };
436
480
  for (let i = 0; i < numLogsInTx; i++) {
437
- publicLogsInBlock[indexOfTx].push(reader.readObject(PublicLog));
481
+ publicLogsInBlock[indexOfTx].logs.push(reader.readObject(PublicLog));
438
482
  }
439
483
  }
440
484
  for (let txIndex = filter.afterLog?.txIndex ?? 0; txIndex < publicLogsInBlock.length; txIndex++) {
441
- const txLogs = publicLogsInBlock[txIndex];
442
- maxLogsHit = this.#accumulateLogs(logs, blockNumber, blockHash, txIndex, txLogs, filter);
485
+ const txData = publicLogsInBlock[txIndex];
486
+ maxLogsHit = this.#accumulatePublicLogs(
487
+ logs,
488
+ blockNumber,
489
+ blockHash,
490
+ txIndex,
491
+ txData.txHash,
492
+ txData.logs,
493
+ filter,
494
+ );
443
495
  if (maxLogsHit) {
444
496
  this.#log.debug(`Max logs hit at block ${blockNumber}`);
445
497
  break loopOverBlocks;
@@ -475,24 +527,33 @@ export class LogStore {
475
527
  return { logs: [], maxLogsHit: false };
476
528
  }
477
529
  const contractClassLogsBuffer = (await this.#contractClassLogsByBlock.getAsync(blockNumber)) ?? Buffer.alloc(0);
478
- const contractClassLogsInBlock: [ContractClassLog[]] = [[]];
530
+ const contractClassLogsInBlock: { txHash: TxHash; logs: ContractClassLog[] }[] = [];
479
531
 
480
532
  const reader = new BufferReader(contractClassLogsBuffer);
481
533
  const blockHash = this.#unpackBlockHash(reader);
482
534
 
483
535
  while (reader.remainingBytes() > 0) {
484
536
  const indexOfTx = reader.readNumber();
537
+ const txHash = reader.readObject(TxHash);
485
538
  const numLogsInTx = reader.readNumber();
486
- contractClassLogsInBlock[indexOfTx] = [];
539
+ contractClassLogsInBlock[indexOfTx] = { txHash, logs: [] };
487
540
  for (let i = 0; i < numLogsInTx; i++) {
488
- contractClassLogsInBlock[indexOfTx].push(reader.readObject(ContractClassLog));
541
+ contractClassLogsInBlock[indexOfTx].logs.push(reader.readObject(ContractClassLog));
489
542
  }
490
543
  }
491
544
 
492
- const txLogs = contractClassLogsInBlock[txIndex];
545
+ const txData = contractClassLogsInBlock[txIndex];
493
546
 
494
547
  const logs: ExtendedContractClassLog[] = [];
495
- const maxLogsHit = this.#accumulateLogs(logs, blockNumber, blockHash, txIndex, txLogs, filter);
548
+ const maxLogsHit = this.#accumulateContractClassLogs(
549
+ logs,
550
+ blockNumber,
551
+ blockHash,
552
+ txIndex,
553
+ txData.txHash,
554
+ txData.logs,
555
+ filter,
556
+ );
496
557
 
497
558
  return { logs, maxLogsHit };
498
559
  }
@@ -516,20 +577,29 @@ export class LogStore {
516
577
  start,
517
578
  end,
518
579
  })) {
519
- const contractClassLogsInBlock: [ContractClassLog[]] = [[]];
580
+ const contractClassLogsInBlock: { txHash: TxHash; logs: ContractClassLog[] }[] = [];
520
581
  const reader = new BufferReader(logBuffer);
521
582
  const blockHash = this.#unpackBlockHash(reader);
522
583
  while (reader.remainingBytes() > 0) {
523
584
  const indexOfTx = reader.readNumber();
585
+ const txHash = reader.readObject(TxHash);
524
586
  const numLogsInTx = reader.readNumber();
525
- contractClassLogsInBlock[indexOfTx] = [];
587
+ contractClassLogsInBlock[indexOfTx] = { txHash, logs: [] };
526
588
  for (let i = 0; i < numLogsInTx; i++) {
527
- contractClassLogsInBlock[indexOfTx].push(reader.readObject(ContractClassLog));
589
+ contractClassLogsInBlock[indexOfTx].logs.push(reader.readObject(ContractClassLog));
528
590
  }
529
591
  }
530
592
  for (let txIndex = filter.afterLog?.txIndex ?? 0; txIndex < contractClassLogsInBlock.length; txIndex++) {
531
- const txLogs = contractClassLogsInBlock[txIndex];
532
- maxLogsHit = this.#accumulateLogs(logs, blockNumber, blockHash, txIndex, txLogs, filter);
593
+ const txData = contractClassLogsInBlock[txIndex];
594
+ maxLogsHit = this.#accumulateContractClassLogs(
595
+ logs,
596
+ blockNumber,
597
+ blockHash,
598
+ txIndex,
599
+ txData.txHash,
600
+ txData.logs,
601
+ filter,
602
+ );
533
603
  if (maxLogsHit) {
534
604
  this.#log.debug(`Max logs hit at block ${blockNumber}`);
535
605
  break loopOverBlocks;
@@ -540,28 +610,74 @@ export class LogStore {
540
610
  return { logs, maxLogsHit };
541
611
  }
542
612
 
543
- #accumulateLogs(
544
- results: (ExtendedContractClassLog | ExtendedPublicLog)[],
613
+ #accumulatePublicLogs(
614
+ results: ExtendedPublicLog[],
545
615
  blockNumber: number,
546
- blockHash: L2BlockHash,
616
+ blockHash: BlockHash,
547
617
  txIndex: number,
548
- txLogs: (ContractClassLog | PublicLog)[],
618
+ txHash: TxHash,
619
+ txLogs: PublicLog[],
549
620
  filter: LogFilter = {},
550
621
  ): boolean {
622
+ if (filter.fromBlock && blockNumber < filter.fromBlock) {
623
+ return false;
624
+ }
625
+ if (filter.toBlock && blockNumber >= filter.toBlock) {
626
+ return false;
627
+ }
628
+ if (filter.txHash && !txHash.equals(filter.txHash)) {
629
+ return false;
630
+ }
631
+
551
632
  let maxLogsHit = false;
552
633
  let logIndex = typeof filter.afterLog?.logIndex === 'number' ? filter.afterLog.logIndex + 1 : 0;
553
634
  for (; logIndex < txLogs.length; logIndex++) {
554
635
  const log = txLogs[logIndex];
555
- if (!filter.contractAddress || log.contractAddress.equals(filter.contractAddress)) {
556
- if (log instanceof ContractClassLog) {
557
- results.push(
558
- new ExtendedContractClassLog(new LogId(BlockNumber(blockNumber), blockHash, txIndex, logIndex), log),
559
- );
560
- } else if (log instanceof PublicLog) {
561
- results.push(new ExtendedPublicLog(new LogId(BlockNumber(blockNumber), blockHash, txIndex, logIndex), log));
562
- } else {
563
- throw new Error('Unknown log type');
636
+ if (
637
+ (!filter.contractAddress || log.contractAddress.equals(filter.contractAddress)) &&
638
+ (!filter.tag || log.fields[0]?.equals(filter.tag))
639
+ ) {
640
+ results.push(
641
+ new ExtendedPublicLog(new LogId(BlockNumber(blockNumber), blockHash, txHash, txIndex, logIndex), log),
642
+ );
643
+
644
+ if (results.length >= this.#logsMaxPageSize) {
645
+ maxLogsHit = true;
646
+ break;
564
647
  }
648
+ }
649
+ }
650
+
651
+ return maxLogsHit;
652
+ }
653
+
654
+ #accumulateContractClassLogs(
655
+ results: ExtendedContractClassLog[],
656
+ blockNumber: number,
657
+ blockHash: BlockHash,
658
+ txIndex: number,
659
+ txHash: TxHash,
660
+ txLogs: ContractClassLog[],
661
+ filter: LogFilter = {},
662
+ ): boolean {
663
+ if (filter.fromBlock && blockNumber < filter.fromBlock) {
664
+ return false;
665
+ }
666
+ if (filter.toBlock && blockNumber >= filter.toBlock) {
667
+ return false;
668
+ }
669
+ if (filter.txHash && !txHash.equals(filter.txHash)) {
670
+ return false;
671
+ }
672
+
673
+ let maxLogsHit = false;
674
+ let logIndex = typeof filter.afterLog?.logIndex === 'number' ? filter.afterLog.logIndex + 1 : 0;
675
+ for (; logIndex < txLogs.length; logIndex++) {
676
+ const log = txLogs[logIndex];
677
+ if (!filter.contractAddress || log.contractAddress.equals(filter.contractAddress)) {
678
+ results.push(
679
+ new ExtendedContractClassLog(new LogId(BlockNumber(blockNumber), blockHash, txHash, txIndex, logIndex), log),
680
+ );
565
681
 
566
682
  if (results.length >= this.#logsMaxPageSize) {
567
683
  maxLogsHit = true;
@@ -137,7 +137,7 @@ export class MessageStore {
137
137
  );
138
138
  }
139
139
 
140
- // Check the first message in a block has the correct index.
140
+ // Check the first message in a checkpoint has the correct index.
141
141
  if (
142
142
  (!lastMessage || message.checkpointNumber > lastMessage.checkpointNumber) &&
143
143
  message.index !== expectedStart