@aztec/archiver 0.0.1-commit.d431d1c → 0.0.1-commit.d6f2b3f94
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -0
- package/dest/archiver.d.ts +6 -5
- package/dest/archiver.d.ts.map +1 -1
- package/dest/archiver.js +34 -22
- package/dest/errors.d.ts +6 -1
- package/dest/errors.d.ts.map +1 -1
- package/dest/errors.js +8 -0
- package/dest/factory.d.ts +5 -2
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +11 -8
- package/dest/l1/bin/retrieve-calldata.js +17 -18
- package/dest/l1/data_retrieval.d.ts +1 -1
- package/dest/l1/data_retrieval.d.ts.map +1 -1
- package/dest/l1/data_retrieval.js +3 -3
- package/dest/l1/validate_trace.d.ts +6 -3
- package/dest/l1/validate_trace.d.ts.map +1 -1
- package/dest/l1/validate_trace.js +13 -9
- package/dest/modules/data_source_base.d.ts +17 -18
- package/dest/modules/data_source_base.d.ts.map +1 -1
- package/dest/modules/data_source_base.js +21 -52
- package/dest/modules/data_store_updater.d.ts +23 -19
- package/dest/modules/data_store_updater.d.ts.map +1 -1
- package/dest/modules/data_store_updater.js +47 -49
- package/dest/modules/instrumentation.d.ts +3 -3
- package/dest/modules/instrumentation.d.ts.map +1 -1
- package/dest/modules/instrumentation.js +17 -10
- package/dest/modules/l1_synchronizer.d.ts +1 -1
- package/dest/modules/l1_synchronizer.d.ts.map +1 -1
- package/dest/modules/l1_synchronizer.js +9 -10
- package/dest/store/block_store.d.ts +35 -21
- package/dest/store/block_store.d.ts.map +1 -1
- package/dest/store/block_store.js +81 -40
- package/dest/store/contract_class_store.d.ts +1 -1
- package/dest/store/contract_class_store.d.ts.map +1 -1
- package/dest/store/contract_class_store.js +11 -7
- package/dest/store/kv_archiver_store.d.ts +28 -24
- package/dest/store/kv_archiver_store.d.ts.map +1 -1
- package/dest/store/kv_archiver_store.js +20 -17
- package/dest/store/log_store.d.ts +4 -4
- package/dest/store/log_store.d.ts.map +1 -1
- package/dest/store/log_store.js +57 -37
- package/dest/test/fake_l1_state.d.ts +4 -4
- package/dest/test/fake_l1_state.d.ts.map +1 -1
- package/dest/test/index.js +3 -1
- package/dest/test/mock_archiver.js +1 -1
- package/dest/test/mock_l2_block_source.d.ts +20 -20
- package/dest/test/mock_l2_block_source.d.ts.map +1 -1
- package/dest/test/mock_l2_block_source.js +40 -41
- package/dest/test/mock_structs.d.ts +3 -2
- package/dest/test/mock_structs.d.ts.map +1 -1
- package/dest/test/mock_structs.js +11 -9
- package/dest/test/noop_l1_archiver.d.ts +23 -0
- package/dest/test/noop_l1_archiver.d.ts.map +1 -0
- package/dest/test/noop_l1_archiver.js +68 -0
- package/package.json +14 -13
- package/src/archiver.ts +46 -28
- package/src/errors.ts +12 -0
- package/src/factory.ts +23 -13
- package/src/l1/bin/retrieve-calldata.ts +16 -17
- package/src/l1/data_retrieval.ts +4 -4
- package/src/l1/validate_trace.ts +24 -6
- package/src/modules/data_source_base.ts +26 -77
- package/src/modules/data_store_updater.ts +59 -55
- package/src/modules/instrumentation.ts +17 -12
- package/src/modules/l1_synchronizer.ts +11 -12
- package/src/store/block_store.ts +107 -60
- package/src/store/contract_class_store.ts +11 -7
- package/src/store/kv_archiver_store.ts +36 -28
- package/src/store/log_store.ts +105 -43
- package/src/test/fake_l1_state.ts +2 -2
- package/src/test/index.ts +3 -0
- package/src/test/mock_archiver.ts +1 -1
- package/src/test/mock_l2_block_source.ts +54 -64
- package/src/test/mock_structs.ts +26 -10
- package/src/test/noop_l1_archiver.ts +109 -0
package/src/store/log_store.ts
CHANGED
|
@@ -6,7 +6,7 @@ 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 {
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
266
|
+
addLogs(blocks: L2Block[]): Promise<boolean> {
|
|
264
267
|
return this.db.transactionAsync(async () => {
|
|
265
268
|
await Promise.all([
|
|
266
269
|
this.#addPrivateLogs(blocks),
|
|
@@ -271,21 +274,21 @@ export class LogStore {
|
|
|
271
274
|
});
|
|
272
275
|
}
|
|
273
276
|
|
|
274
|
-
#packWithBlockHash(blockHash:
|
|
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):
|
|
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
|
|
288
|
+
return new BlockHash(blockHash);
|
|
286
289
|
}
|
|
287
290
|
|
|
288
|
-
deleteLogs(blocks:
|
|
291
|
+
deleteLogs(blocks: L2Block[]): Promise<boolean> {
|
|
289
292
|
return this.db.transactionAsync(async () => {
|
|
290
293
|
await Promise.all(
|
|
291
294
|
blocks.map(async block => {
|
|
@@ -386,24 +389,33 @@ export class LogStore {
|
|
|
386
389
|
}
|
|
387
390
|
|
|
388
391
|
const buffer = (await this.#publicLogsByBlock.getAsync(blockNumber)) ?? Buffer.alloc(0);
|
|
389
|
-
const publicLogsInBlock:
|
|
392
|
+
const publicLogsInBlock: { txHash: TxHash; logs: PublicLog[] }[] = [];
|
|
390
393
|
const reader = new BufferReader(buffer);
|
|
391
394
|
|
|
392
395
|
const blockHash = this.#unpackBlockHash(reader);
|
|
393
396
|
|
|
394
397
|
while (reader.remainingBytes() > 0) {
|
|
395
398
|
const indexOfTx = reader.readNumber();
|
|
399
|
+
const txHash = reader.readObject(TxHash);
|
|
396
400
|
const numLogsInTx = reader.readNumber();
|
|
397
|
-
publicLogsInBlock[indexOfTx] = [];
|
|
401
|
+
publicLogsInBlock[indexOfTx] = { txHash, logs: [] };
|
|
398
402
|
for (let i = 0; i < numLogsInTx; i++) {
|
|
399
|
-
publicLogsInBlock[indexOfTx].push(reader.readObject(PublicLog));
|
|
403
|
+
publicLogsInBlock[indexOfTx].logs.push(reader.readObject(PublicLog));
|
|
400
404
|
}
|
|
401
405
|
}
|
|
402
406
|
|
|
403
|
-
const
|
|
407
|
+
const txData = publicLogsInBlock[txIndex];
|
|
404
408
|
|
|
405
409
|
const logs: ExtendedPublicLog[] = [];
|
|
406
|
-
const maxLogsHit = this.#
|
|
410
|
+
const maxLogsHit = this.#accumulatePublicLogs(
|
|
411
|
+
logs,
|
|
412
|
+
blockNumber,
|
|
413
|
+
blockHash,
|
|
414
|
+
txIndex,
|
|
415
|
+
txData.txHash,
|
|
416
|
+
txData.logs,
|
|
417
|
+
filter,
|
|
418
|
+
);
|
|
407
419
|
|
|
408
420
|
return { logs, maxLogsHit };
|
|
409
421
|
}
|
|
@@ -424,22 +436,31 @@ export class LogStore {
|
|
|
424
436
|
|
|
425
437
|
let maxLogsHit = false;
|
|
426
438
|
loopOverBlocks: for await (const [blockNumber, logBuffer] of this.#publicLogsByBlock.entriesAsync({ start, end })) {
|
|
427
|
-
const publicLogsInBlock:
|
|
439
|
+
const publicLogsInBlock: { txHash: TxHash; logs: PublicLog[] }[] = [];
|
|
428
440
|
const reader = new BufferReader(logBuffer);
|
|
429
441
|
|
|
430
442
|
const blockHash = this.#unpackBlockHash(reader);
|
|
431
443
|
|
|
432
444
|
while (reader.remainingBytes() > 0) {
|
|
433
445
|
const indexOfTx = reader.readNumber();
|
|
446
|
+
const txHash = reader.readObject(TxHash);
|
|
434
447
|
const numLogsInTx = reader.readNumber();
|
|
435
|
-
publicLogsInBlock[indexOfTx] = [];
|
|
448
|
+
publicLogsInBlock[indexOfTx] = { txHash, logs: [] };
|
|
436
449
|
for (let i = 0; i < numLogsInTx; i++) {
|
|
437
|
-
publicLogsInBlock[indexOfTx].push(reader.readObject(PublicLog));
|
|
450
|
+
publicLogsInBlock[indexOfTx].logs.push(reader.readObject(PublicLog));
|
|
438
451
|
}
|
|
439
452
|
}
|
|
440
453
|
for (let txIndex = filter.afterLog?.txIndex ?? 0; txIndex < publicLogsInBlock.length; txIndex++) {
|
|
441
|
-
const
|
|
442
|
-
maxLogsHit = this.#
|
|
454
|
+
const txData = publicLogsInBlock[txIndex];
|
|
455
|
+
maxLogsHit = this.#accumulatePublicLogs(
|
|
456
|
+
logs,
|
|
457
|
+
blockNumber,
|
|
458
|
+
blockHash,
|
|
459
|
+
txIndex,
|
|
460
|
+
txData.txHash,
|
|
461
|
+
txData.logs,
|
|
462
|
+
filter,
|
|
463
|
+
);
|
|
443
464
|
if (maxLogsHit) {
|
|
444
465
|
this.#log.debug(`Max logs hit at block ${blockNumber}`);
|
|
445
466
|
break loopOverBlocks;
|
|
@@ -475,24 +496,33 @@ export class LogStore {
|
|
|
475
496
|
return { logs: [], maxLogsHit: false };
|
|
476
497
|
}
|
|
477
498
|
const contractClassLogsBuffer = (await this.#contractClassLogsByBlock.getAsync(blockNumber)) ?? Buffer.alloc(0);
|
|
478
|
-
const contractClassLogsInBlock:
|
|
499
|
+
const contractClassLogsInBlock: { txHash: TxHash; logs: ContractClassLog[] }[] = [];
|
|
479
500
|
|
|
480
501
|
const reader = new BufferReader(contractClassLogsBuffer);
|
|
481
502
|
const blockHash = this.#unpackBlockHash(reader);
|
|
482
503
|
|
|
483
504
|
while (reader.remainingBytes() > 0) {
|
|
484
505
|
const indexOfTx = reader.readNumber();
|
|
506
|
+
const txHash = reader.readObject(TxHash);
|
|
485
507
|
const numLogsInTx = reader.readNumber();
|
|
486
|
-
contractClassLogsInBlock[indexOfTx] = [];
|
|
508
|
+
contractClassLogsInBlock[indexOfTx] = { txHash, logs: [] };
|
|
487
509
|
for (let i = 0; i < numLogsInTx; i++) {
|
|
488
|
-
contractClassLogsInBlock[indexOfTx].push(reader.readObject(ContractClassLog));
|
|
510
|
+
contractClassLogsInBlock[indexOfTx].logs.push(reader.readObject(ContractClassLog));
|
|
489
511
|
}
|
|
490
512
|
}
|
|
491
513
|
|
|
492
|
-
const
|
|
514
|
+
const txData = contractClassLogsInBlock[txIndex];
|
|
493
515
|
|
|
494
516
|
const logs: ExtendedContractClassLog[] = [];
|
|
495
|
-
const maxLogsHit = this.#
|
|
517
|
+
const maxLogsHit = this.#accumulateContractClassLogs(
|
|
518
|
+
logs,
|
|
519
|
+
blockNumber,
|
|
520
|
+
blockHash,
|
|
521
|
+
txIndex,
|
|
522
|
+
txData.txHash,
|
|
523
|
+
txData.logs,
|
|
524
|
+
filter,
|
|
525
|
+
);
|
|
496
526
|
|
|
497
527
|
return { logs, maxLogsHit };
|
|
498
528
|
}
|
|
@@ -516,20 +546,29 @@ export class LogStore {
|
|
|
516
546
|
start,
|
|
517
547
|
end,
|
|
518
548
|
})) {
|
|
519
|
-
const contractClassLogsInBlock:
|
|
549
|
+
const contractClassLogsInBlock: { txHash: TxHash; logs: ContractClassLog[] }[] = [];
|
|
520
550
|
const reader = new BufferReader(logBuffer);
|
|
521
551
|
const blockHash = this.#unpackBlockHash(reader);
|
|
522
552
|
while (reader.remainingBytes() > 0) {
|
|
523
553
|
const indexOfTx = reader.readNumber();
|
|
554
|
+
const txHash = reader.readObject(TxHash);
|
|
524
555
|
const numLogsInTx = reader.readNumber();
|
|
525
|
-
contractClassLogsInBlock[indexOfTx] = [];
|
|
556
|
+
contractClassLogsInBlock[indexOfTx] = { txHash, logs: [] };
|
|
526
557
|
for (let i = 0; i < numLogsInTx; i++) {
|
|
527
|
-
contractClassLogsInBlock[indexOfTx].push(reader.readObject(ContractClassLog));
|
|
558
|
+
contractClassLogsInBlock[indexOfTx].logs.push(reader.readObject(ContractClassLog));
|
|
528
559
|
}
|
|
529
560
|
}
|
|
530
561
|
for (let txIndex = filter.afterLog?.txIndex ?? 0; txIndex < contractClassLogsInBlock.length; txIndex++) {
|
|
531
|
-
const
|
|
532
|
-
maxLogsHit = this.#
|
|
562
|
+
const txData = contractClassLogsInBlock[txIndex];
|
|
563
|
+
maxLogsHit = this.#accumulateContractClassLogs(
|
|
564
|
+
logs,
|
|
565
|
+
blockNumber,
|
|
566
|
+
blockHash,
|
|
567
|
+
txIndex,
|
|
568
|
+
txData.txHash,
|
|
569
|
+
txData.logs,
|
|
570
|
+
filter,
|
|
571
|
+
);
|
|
533
572
|
if (maxLogsHit) {
|
|
534
573
|
this.#log.debug(`Max logs hit at block ${blockNumber}`);
|
|
535
574
|
break loopOverBlocks;
|
|
@@ -540,12 +579,13 @@ export class LogStore {
|
|
|
540
579
|
return { logs, maxLogsHit };
|
|
541
580
|
}
|
|
542
581
|
|
|
543
|
-
#
|
|
544
|
-
results:
|
|
582
|
+
#accumulatePublicLogs(
|
|
583
|
+
results: ExtendedPublicLog[],
|
|
545
584
|
blockNumber: number,
|
|
546
|
-
blockHash:
|
|
585
|
+
blockHash: BlockHash,
|
|
547
586
|
txIndex: number,
|
|
548
|
-
|
|
587
|
+
txHash: TxHash,
|
|
588
|
+
txLogs: PublicLog[],
|
|
549
589
|
filter: LogFilter = {},
|
|
550
590
|
): boolean {
|
|
551
591
|
let maxLogsHit = false;
|
|
@@ -553,15 +593,37 @@ export class LogStore {
|
|
|
553
593
|
for (; logIndex < txLogs.length; logIndex++) {
|
|
554
594
|
const log = txLogs[logIndex];
|
|
555
595
|
if (!filter.contractAddress || log.contractAddress.equals(filter.contractAddress)) {
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
throw new Error('Unknown log type');
|
|
596
|
+
results.push(
|
|
597
|
+
new ExtendedPublicLog(new LogId(BlockNumber(blockNumber), blockHash, txHash, txIndex, logIndex), log),
|
|
598
|
+
);
|
|
599
|
+
|
|
600
|
+
if (results.length >= this.#logsMaxPageSize) {
|
|
601
|
+
maxLogsHit = true;
|
|
602
|
+
break;
|
|
564
603
|
}
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
return maxLogsHit;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
#accumulateContractClassLogs(
|
|
611
|
+
results: ExtendedContractClassLog[],
|
|
612
|
+
blockNumber: number,
|
|
613
|
+
blockHash: BlockHash,
|
|
614
|
+
txIndex: number,
|
|
615
|
+
txHash: TxHash,
|
|
616
|
+
txLogs: ContractClassLog[],
|
|
617
|
+
filter: LogFilter = {},
|
|
618
|
+
): boolean {
|
|
619
|
+
let maxLogsHit = false;
|
|
620
|
+
let logIndex = typeof filter.afterLog?.logIndex === 'number' ? filter.afterLog.logIndex + 1 : 0;
|
|
621
|
+
for (; logIndex < txLogs.length; logIndex++) {
|
|
622
|
+
const log = txLogs[logIndex];
|
|
623
|
+
if (!filter.contractAddress || log.contractAddress.equals(filter.contractAddress)) {
|
|
624
|
+
results.push(
|
|
625
|
+
new ExtendedContractClassLog(new LogId(BlockNumber(blockNumber), blockHash, txHash, txIndex, logIndex), log),
|
|
626
|
+
);
|
|
565
627
|
|
|
566
628
|
if (results.length >= this.#logsMaxPageSize) {
|
|
567
629
|
maxLogsHit = true;
|
|
@@ -10,7 +10,7 @@ import { Fr } from '@aztec/foundation/curves/bn254';
|
|
|
10
10
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
11
11
|
import { createLogger } from '@aztec/foundation/log';
|
|
12
12
|
import { RollupAbi } from '@aztec/l1-artifacts';
|
|
13
|
-
import { CommitteeAttestation, CommitteeAttestationsAndSigners,
|
|
13
|
+
import { CommitteeAttestation, CommitteeAttestationsAndSigners, L2Block } from '@aztec/stdlib/block';
|
|
14
14
|
import { Checkpoint } from '@aztec/stdlib/checkpoint';
|
|
15
15
|
import { getSlotAtTimestamp } from '@aztec/stdlib/epoch-helpers';
|
|
16
16
|
import { InboxLeaf } from '@aztec/stdlib/messaging';
|
|
@@ -51,7 +51,7 @@ type AddCheckpointOptions = {
|
|
|
51
51
|
/** Number of L2 blocks in the checkpoint. Default: 1 */
|
|
52
52
|
numBlocks?: number;
|
|
53
53
|
/** Or the actual blocks for the checkpoint */
|
|
54
|
-
blocks?:
|
|
54
|
+
blocks?: L2Block[];
|
|
55
55
|
/** Number of transactions per block. Default: 4 */
|
|
56
56
|
txsPerBlock?: number;
|
|
57
57
|
/** Max number of effects per tx (for generating large blobs). Default: undefined */
|
package/src/test/index.ts
CHANGED
|
@@ -2,3 +2,6 @@ export * from './mock_structs.js';
|
|
|
2
2
|
export * from './mock_l2_block_source.js';
|
|
3
3
|
export * from './mock_l1_to_l2_message_source.js';
|
|
4
4
|
export * from './mock_archiver.js';
|
|
5
|
+
// NOTE: noop_l1_archiver.js is intentionally NOT exported here because it imports
|
|
6
|
+
// jest-mock-extended, which depends on @jest/globals and can only run inside Jest.
|
|
7
|
+
// Import it directly: import { NoopL1Archiver } from '@aztec/archiver/test/noop-l1';
|
|
@@ -57,7 +57,7 @@ export class MockPrefilledArchiver extends MockArchiver {
|
|
|
57
57
|
|
|
58
58
|
const fromBlock = this.l2Blocks.length;
|
|
59
59
|
// TODO: Add L2 blocks and checkpoints separately once archiver has the apis for that.
|
|
60
|
-
this.
|
|
60
|
+
this.addProposedBlocks(this.prefilled.slice(fromBlock, fromBlock + numBlocks).flatMap(c => c.blocks));
|
|
61
61
|
return Promise.resolve();
|
|
62
62
|
}
|
|
63
63
|
}
|
|
@@ -8,9 +8,9 @@ import { createLogger } from '@aztec/foundation/log';
|
|
|
8
8
|
import type { FunctionSelector } from '@aztec/stdlib/abi';
|
|
9
9
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
10
10
|
import {
|
|
11
|
+
BlockHash,
|
|
11
12
|
CheckpointedL2Block,
|
|
12
|
-
|
|
13
|
-
L2BlockNew,
|
|
13
|
+
L2Block,
|
|
14
14
|
type L2BlockSource,
|
|
15
15
|
type L2Tips,
|
|
16
16
|
type ValidateCheckpointResult,
|
|
@@ -18,14 +18,14 @@ import {
|
|
|
18
18
|
import { Checkpoint, L1PublishedData, PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
|
|
19
19
|
import type { ContractClassPublic, ContractDataSource, ContractInstanceWithAddress } from '@aztec/stdlib/contract';
|
|
20
20
|
import { EmptyL1RollupConstants, type L1RollupConstants, getSlotRangeForEpoch } from '@aztec/stdlib/epoch-helpers';
|
|
21
|
-
import { type BlockHeader, TxHash, TxReceipt, TxStatus } from '@aztec/stdlib/tx';
|
|
21
|
+
import { type BlockHeader, TxExecutionResult, TxHash, TxReceipt, TxStatus } from '@aztec/stdlib/tx';
|
|
22
22
|
import type { UInt64 } from '@aztec/stdlib/types';
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* A mocked implementation of L2BlockSource to be used in tests.
|
|
26
26
|
*/
|
|
27
27
|
export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
28
|
-
protected l2Blocks:
|
|
28
|
+
protected l2Blocks: L2Block[] = [];
|
|
29
29
|
|
|
30
30
|
private provenBlockNumber: number = 0;
|
|
31
31
|
private finalizedBlockNumber: number = 0;
|
|
@@ -36,16 +36,16 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
36
36
|
public async createBlocks(numBlocks: number) {
|
|
37
37
|
for (let i = 0; i < numBlocks; i++) {
|
|
38
38
|
const blockNum = this.l2Blocks.length + 1;
|
|
39
|
-
const block = await
|
|
39
|
+
const block = await L2Block.random(BlockNumber(blockNum), { slotNumber: SlotNumber(blockNum) });
|
|
40
40
|
this.l2Blocks.push(block);
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
this.log.verbose(`Created ${numBlocks} blocks in the mock L2 block source`);
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
public
|
|
46
|
+
public addProposedBlocks(blocks: L2Block[]) {
|
|
47
47
|
this.l2Blocks.push(...blocks);
|
|
48
|
-
this.log.verbose(`Added ${blocks.length} blocks to the mock L2 block source`);
|
|
48
|
+
this.log.verbose(`Added ${blocks.length} proposed blocks to the mock L2 block source`);
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
public removeBlocks(numBlocks: number) {
|
|
@@ -96,6 +96,14 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
96
96
|
return Promise.resolve(BlockNumber(this.provenBlockNumber));
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
+
public getCheckpointedL2BlockNumber() {
|
|
100
|
+
return Promise.resolve(BlockNumber(this.checkpointedBlockNumber));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
public getFinalizedL2BlockNumber() {
|
|
104
|
+
return Promise.resolve(BlockNumber(this.finalizedBlockNumber));
|
|
105
|
+
}
|
|
106
|
+
|
|
99
107
|
public getCheckpointedBlock(number: BlockNumber): Promise<CheckpointedL2Block | undefined> {
|
|
100
108
|
if (number > this.checkpointedBlockNumber) {
|
|
101
109
|
return Promise.resolve(undefined);
|
|
@@ -105,7 +113,7 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
105
113
|
return Promise.resolve(undefined);
|
|
106
114
|
}
|
|
107
115
|
const checkpointedBlock = new CheckpointedL2Block(
|
|
108
|
-
CheckpointNumber(number),
|
|
116
|
+
CheckpointNumber.fromBlockNumber(number),
|
|
109
117
|
block,
|
|
110
118
|
new L1PublishedData(BigInt(number), BigInt(number), `0x${number.toString(16).padStart(64, '0')}`),
|
|
111
119
|
[],
|
|
@@ -113,11 +121,7 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
113
121
|
return Promise.resolve(checkpointedBlock);
|
|
114
122
|
}
|
|
115
123
|
|
|
116
|
-
public async getCheckpointedBlocks(
|
|
117
|
-
from: BlockNumber,
|
|
118
|
-
limit: number,
|
|
119
|
-
_proven?: boolean,
|
|
120
|
-
): Promise<CheckpointedL2Block[]> {
|
|
124
|
+
public async getCheckpointedBlocks(from: BlockNumber, limit: number): Promise<CheckpointedL2Block[]> {
|
|
121
125
|
const result: CheckpointedL2Block[] = [];
|
|
122
126
|
for (let i = 0; i < limit; i++) {
|
|
123
127
|
const blockNum = from + i;
|
|
@@ -137,7 +141,7 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
137
141
|
* @param number - The block number to return (inclusive).
|
|
138
142
|
* @returns The requested L2 block.
|
|
139
143
|
*/
|
|
140
|
-
public getBlock(number: number): Promise<
|
|
144
|
+
public getBlock(number: number): Promise<L2Block | undefined> {
|
|
141
145
|
const block = this.l2Blocks[number - 1];
|
|
142
146
|
return Promise.resolve(block);
|
|
143
147
|
}
|
|
@@ -147,7 +151,7 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
147
151
|
* @param number - The block number to return.
|
|
148
152
|
* @returns The requested L2 block.
|
|
149
153
|
*/
|
|
150
|
-
public
|
|
154
|
+
public getL2Block(number: BlockNumber): Promise<L2Block | undefined> {
|
|
151
155
|
const block = this.l2Blocks[number - 1];
|
|
152
156
|
return Promise.resolve(block);
|
|
153
157
|
}
|
|
@@ -158,20 +162,16 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
158
162
|
* @param limit - The maximum number of blocks to return.
|
|
159
163
|
* @returns The requested mocked L2 blocks.
|
|
160
164
|
*/
|
|
161
|
-
public getBlocks(from: number, limit: number
|
|
162
|
-
return Promise.resolve(
|
|
163
|
-
this.l2Blocks
|
|
164
|
-
.slice(from - 1, from - 1 + limit)
|
|
165
|
-
.filter(b => !proven || this.provenBlockNumber === undefined || b.number <= this.provenBlockNumber),
|
|
166
|
-
);
|
|
165
|
+
public getBlocks(from: number, limit: number): Promise<L2Block[]> {
|
|
166
|
+
return Promise.resolve(this.l2Blocks.slice(from - 1, from - 1 + limit));
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
-
public
|
|
169
|
+
public getCheckpoints(from: CheckpointNumber, limit: number) {
|
|
170
170
|
// TODO(mbps): Implement this properly. This only works when we have one block per checkpoint.
|
|
171
171
|
const blocks = this.l2Blocks.slice(from - 1, from - 1 + limit);
|
|
172
172
|
return Promise.all(
|
|
173
173
|
blocks.map(async block => {
|
|
174
|
-
// Create a checkpoint from the block - manually construct since
|
|
174
|
+
// Create a checkpoint from the block - manually construct since L2Block doesn't have toCheckpoint()
|
|
175
175
|
const checkpoint = await Checkpoint.random(block.checkpointNumber, { numBlocks: 1 });
|
|
176
176
|
checkpoint.blocks = [block];
|
|
177
177
|
return new PublishedCheckpoint(
|
|
@@ -189,39 +189,18 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
189
189
|
if (!block) {
|
|
190
190
|
return undefined;
|
|
191
191
|
}
|
|
192
|
-
// Create a checkpoint from the block - manually construct since
|
|
192
|
+
// Create a checkpoint from the block - manually construct since L2Block doesn't have toCheckpoint()
|
|
193
193
|
const checkpoint = await Checkpoint.random(block.checkpointNumber, { numBlocks: 1 });
|
|
194
194
|
checkpoint.blocks = [block];
|
|
195
195
|
return checkpoint;
|
|
196
196
|
}
|
|
197
197
|
|
|
198
|
-
public
|
|
199
|
-
const blocks = this.l2Blocks
|
|
200
|
-
.slice(from - 1, from - 1 + limit)
|
|
201
|
-
.filter(b => !proven || this.provenBlockNumber === undefined || b.number <= this.provenBlockNumber);
|
|
202
|
-
return Promise.resolve(
|
|
203
|
-
blocks.map(block =>
|
|
204
|
-
CheckpointedL2Block.fromFields({
|
|
205
|
-
checkpointNumber: CheckpointNumber(block.number),
|
|
206
|
-
block,
|
|
207
|
-
l1: new L1PublishedData(BigInt(block.number), BigInt(block.number), Buffer32.random().toString()),
|
|
208
|
-
attestations: [],
|
|
209
|
-
}),
|
|
210
|
-
),
|
|
211
|
-
);
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
getL2BlocksNew(from: BlockNumber, limit: number, proven?: boolean): Promise<L2BlockNew[]> {
|
|
215
|
-
// getBlocks already returns L2BlockNew[], so just return directly
|
|
216
|
-
return this.getBlocks(from, limit, proven);
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
public async getPublishedBlockByHash(blockHash: Fr): Promise<CheckpointedL2Block | undefined> {
|
|
198
|
+
public async getCheckpointedBlockByHash(blockHash: BlockHash): Promise<CheckpointedL2Block | undefined> {
|
|
220
199
|
for (const block of this.l2Blocks) {
|
|
221
200
|
const hash = await block.hash();
|
|
222
201
|
if (hash.equals(blockHash)) {
|
|
223
202
|
return CheckpointedL2Block.fromFields({
|
|
224
|
-
checkpointNumber: CheckpointNumber(block.number),
|
|
203
|
+
checkpointNumber: CheckpointNumber.fromBlockNumber(block.number),
|
|
225
204
|
block,
|
|
226
205
|
l1: new L1PublishedData(BigInt(block.number), BigInt(block.number), Buffer32.random().toString()),
|
|
227
206
|
attestations: [],
|
|
@@ -231,14 +210,14 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
231
210
|
return undefined;
|
|
232
211
|
}
|
|
233
212
|
|
|
234
|
-
public
|
|
213
|
+
public getCheckpointedBlockByArchive(archive: Fr): Promise<CheckpointedL2Block | undefined> {
|
|
235
214
|
const block = this.l2Blocks.find(b => b.archive.root.equals(archive));
|
|
236
215
|
if (!block) {
|
|
237
216
|
return Promise.resolve(undefined);
|
|
238
217
|
}
|
|
239
218
|
return Promise.resolve(
|
|
240
219
|
CheckpointedL2Block.fromFields({
|
|
241
|
-
checkpointNumber: CheckpointNumber(block.number),
|
|
220
|
+
checkpointNumber: CheckpointNumber.fromBlockNumber(block.number),
|
|
242
221
|
block,
|
|
243
222
|
l1: new L1PublishedData(BigInt(block.number), BigInt(block.number), Buffer32.random().toString()),
|
|
244
223
|
attestations: [],
|
|
@@ -246,7 +225,7 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
246
225
|
);
|
|
247
226
|
}
|
|
248
227
|
|
|
249
|
-
public async
|
|
228
|
+
public async getL2BlockByHash(blockHash: BlockHash): Promise<L2Block | undefined> {
|
|
250
229
|
for (const block of this.l2Blocks) {
|
|
251
230
|
const hash = await block.hash();
|
|
252
231
|
if (hash.equals(blockHash)) {
|
|
@@ -256,12 +235,12 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
256
235
|
return undefined;
|
|
257
236
|
}
|
|
258
237
|
|
|
259
|
-
public
|
|
238
|
+
public getL2BlockByArchive(archive: Fr): Promise<L2Block | undefined> {
|
|
260
239
|
const block = this.l2Blocks.find(b => b.archive.root.equals(archive));
|
|
261
240
|
return Promise.resolve(block);
|
|
262
241
|
}
|
|
263
242
|
|
|
264
|
-
public async getBlockHeaderByHash(blockHash:
|
|
243
|
+
public async getBlockHeaderByHash(blockHash: BlockHash): Promise<BlockHeader | undefined> {
|
|
265
244
|
for (const block of this.l2Blocks) {
|
|
266
245
|
const hash = await block.hash();
|
|
267
246
|
if (hash.equals(blockHash)) {
|
|
@@ -288,7 +267,7 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
288
267
|
const slot = b.header.globalVariables.slotNumber;
|
|
289
268
|
return slot >= start && slot <= end;
|
|
290
269
|
});
|
|
291
|
-
// Create checkpoints from blocks - manually construct since
|
|
270
|
+
// Create checkpoints from blocks - manually construct since L2Block doesn't have toCheckpoint()
|
|
292
271
|
return Promise.all(
|
|
293
272
|
blocks.map(async block => {
|
|
294
273
|
const checkpoint = await Checkpoint.random(block.checkpointNumber, { numBlocks: 1 });
|
|
@@ -298,24 +277,33 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
298
277
|
);
|
|
299
278
|
}
|
|
300
279
|
|
|
301
|
-
|
|
280
|
+
getCheckpointedBlocksForEpoch(epochNumber: EpochNumber): Promise<CheckpointedL2Block[]> {
|
|
302
281
|
const epochDuration = DefaultL1ContractsConfig.aztecEpochDuration;
|
|
303
282
|
const [start, end] = getSlotRangeForEpoch(epochNumber, { epochDuration });
|
|
304
283
|
const blocks = this.l2Blocks.filter(b => {
|
|
305
284
|
const slot = b.header.globalVariables.slotNumber;
|
|
306
285
|
return slot >= start && slot <= end;
|
|
307
286
|
});
|
|
308
|
-
return Promise.resolve(
|
|
287
|
+
return Promise.resolve(
|
|
288
|
+
blocks.map(block =>
|
|
289
|
+
CheckpointedL2Block.fromFields({
|
|
290
|
+
checkpointNumber: CheckpointNumber.fromBlockNumber(block.number),
|
|
291
|
+
block,
|
|
292
|
+
l1: new L1PublishedData(BigInt(block.number), BigInt(block.number), Buffer32.random().toString()),
|
|
293
|
+
attestations: [],
|
|
294
|
+
}),
|
|
295
|
+
),
|
|
296
|
+
);
|
|
309
297
|
}
|
|
310
298
|
|
|
311
|
-
getBlocksForSlot(slotNumber: SlotNumber): Promise<
|
|
299
|
+
getBlocksForSlot(slotNumber: SlotNumber): Promise<L2Block[]> {
|
|
312
300
|
const blocks = this.l2Blocks.filter(b => b.header.globalVariables.slotNumber === slotNumber);
|
|
313
301
|
return Promise.resolve(blocks);
|
|
314
302
|
}
|
|
315
303
|
|
|
316
|
-
async
|
|
317
|
-
const
|
|
318
|
-
return
|
|
304
|
+
async getCheckpointedBlockHeadersForEpoch(epochNumber: EpochNumber): Promise<BlockHeader[]> {
|
|
305
|
+
const checkpointedBlocks = await this.getCheckpointedBlocksForEpoch(epochNumber);
|
|
306
|
+
return checkpointedBlocks.map(b => b.block.header);
|
|
319
307
|
}
|
|
320
308
|
|
|
321
309
|
/**
|
|
@@ -334,7 +322,7 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
334
322
|
return {
|
|
335
323
|
data: txEffect,
|
|
336
324
|
l2BlockNumber: block.number,
|
|
337
|
-
l2BlockHash:
|
|
325
|
+
l2BlockHash: await block.hash(),
|
|
338
326
|
txIndexInBlock: block.body.txEffects.indexOf(txEffect),
|
|
339
327
|
};
|
|
340
328
|
}
|
|
@@ -348,12 +336,14 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
348
336
|
for (const block of this.l2Blocks) {
|
|
349
337
|
for (const txEffect of block.body.txEffects) {
|
|
350
338
|
if (txEffect.txHash.equals(txHash)) {
|
|
339
|
+
// In mock, assume all txs are checkpointed with successful execution
|
|
351
340
|
return new TxReceipt(
|
|
352
341
|
txHash,
|
|
353
|
-
TxStatus.
|
|
354
|
-
|
|
342
|
+
TxStatus.CHECKPOINTED,
|
|
343
|
+
TxExecutionResult.SUCCESS,
|
|
344
|
+
undefined,
|
|
355
345
|
txEffect.transactionFee.toBigInt(),
|
|
356
|
-
|
|
346
|
+
await block.hash(),
|
|
357
347
|
block.number,
|
|
358
348
|
);
|
|
359
349
|
}
|
|
@@ -394,7 +384,7 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
394
384
|
|
|
395
385
|
const makeTipId = (blockId: typeof latestBlockId) => ({
|
|
396
386
|
block: blockId,
|
|
397
|
-
checkpoint: { number: CheckpointNumber(blockId.number), hash: blockId.hash },
|
|
387
|
+
checkpoint: { number: CheckpointNumber.fromBlockNumber(blockId.number), hash: blockId.hash },
|
|
398
388
|
});
|
|
399
389
|
|
|
400
390
|
return {
|