@aztec/archiver 3.0.0-nightly.20250910 → 3.0.0-nightly.20250912

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 (35) hide show
  1. package/README.md +25 -4
  2. package/dest/archiver/archiver.d.ts +8 -4
  3. package/dest/archiver/archiver.d.ts.map +1 -1
  4. package/dest/archiver/archiver.js +50 -25
  5. package/dest/archiver/archiver_store.d.ts +5 -1
  6. package/dest/archiver/archiver_store.d.ts.map +1 -1
  7. package/dest/archiver/archiver_store_test_suite.d.ts.map +1 -1
  8. package/dest/archiver/archiver_store_test_suite.js +103 -5
  9. package/dest/archiver/config.d.ts +4 -18
  10. package/dest/archiver/config.d.ts.map +1 -1
  11. package/dest/archiver/config.js +5 -1
  12. package/dest/archiver/data_retrieval.d.ts +2 -2
  13. package/dest/archiver/data_retrieval.d.ts.map +1 -1
  14. package/dest/archiver/data_retrieval.js +3 -3
  15. package/dest/archiver/kv_archiver_store/block_store.d.ts +11 -1
  16. package/dest/archiver/kv_archiver_store/block_store.d.ts.map +1 -1
  17. package/dest/archiver/kv_archiver_store/block_store.js +27 -3
  18. package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts +3 -1
  19. package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts.map +1 -1
  20. package/dest/archiver/kv_archiver_store/kv_archiver_store.js +6 -0
  21. package/dest/archiver/validation.d.ts.map +1 -1
  22. package/dest/archiver/validation.js +7 -4
  23. package/dest/test/mock_l2_block_source.d.ts +2 -10
  24. package/dest/test/mock_l2_block_source.d.ts.map +1 -1
  25. package/dest/test/mock_l2_block_source.js +2 -2
  26. package/package.json +13 -13
  27. package/src/archiver/archiver.ts +54 -27
  28. package/src/archiver/archiver_store.ts +7 -1
  29. package/src/archiver/archiver_store_test_suite.ts +120 -18
  30. package/src/archiver/config.ts +13 -28
  31. package/src/archiver/data_retrieval.ts +3 -7
  32. package/src/archiver/kv_archiver_store/block_store.ts +44 -4
  33. package/src/archiver/kv_archiver_store/kv_archiver_store.ts +9 -1
  34. package/src/archiver/validation.ts +22 -2
  35. package/src/test/mock_l2_block_source.ts +19 -10
@@ -12,7 +12,16 @@ import { Fr } from '@aztec/foundation/fields';
12
12
  import { toArray } from '@aztec/foundation/iterable';
13
13
  import { sleep } from '@aztec/foundation/sleep';
14
14
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
15
- import { CommitteeAttestation, L2Block, L2BlockHash, wrapInBlock } from '@aztec/stdlib/block';
15
+ import {
16
+ CommitteeAttestation,
17
+ EthAddress,
18
+ L2Block,
19
+ L2BlockHash,
20
+ PublishedL2Block,
21
+ type ValidateBlockResult,
22
+ randomBlockInfo,
23
+ wrapInBlock,
24
+ } from '@aztec/stdlib/block';
16
25
  import {
17
26
  type ContractClassPublic,
18
27
  type ContractInstanceWithAddress,
@@ -34,7 +43,6 @@ import type { ArchiverDataStore, ArchiverL1SynchPoint } from './archiver_store.j
34
43
  import { BlockNumberNotSequentialError, InitialBlockNumberNotSequentialError } from './errors.js';
35
44
  import { MessageStoreError } from './kv_archiver_store/message_store.js';
36
45
  import type { InboxMessage } from './structs/inbox_message.js';
37
- import type { PublishedL2Block } from './structs/published.js';
38
46
 
39
47
  /**
40
48
  * @param testName - The name of the test suite.
@@ -58,15 +66,16 @@ export function describeArchiverDataStore(
58
66
 
59
67
  const makeBlockHash = (blockNumber: number) => `0x${blockNumber.toString(16).padStart(64, '0')}`;
60
68
 
61
- const makePublished = (block: L2Block, l1BlockNumber: number): PublishedL2Block => ({
62
- block: block,
63
- l1: {
64
- blockNumber: BigInt(l1BlockNumber),
65
- blockHash: makeBlockHash(l1BlockNumber),
66
- timestamp: BigInt(l1BlockNumber * 1000),
67
- },
68
- attestations: times(3, CommitteeAttestation.random),
69
- });
69
+ const makePublished = (block: L2Block, l1BlockNumber: number): PublishedL2Block =>
70
+ PublishedL2Block.fromFields({
71
+ block: block,
72
+ l1: {
73
+ blockNumber: BigInt(l1BlockNumber),
74
+ blockHash: makeBlockHash(l1BlockNumber),
75
+ timestamp: BigInt(l1BlockNumber * 1000),
76
+ },
77
+ attestations: times(3, CommitteeAttestation.random),
78
+ });
70
79
 
71
80
  const expectBlocksEqual = (actual: PublishedL2Block[], expected: PublishedL2Block[]) => {
72
81
  expect(actual.length).toEqual(expected.length);
@@ -757,7 +766,7 @@ export function describeArchiverDataStore(
757
766
  return txEffect;
758
767
  });
759
768
 
760
- return {
769
+ return PublishedL2Block.fromFields({
761
770
  block: block,
762
771
  attestations: times(3, CommitteeAttestation.random),
763
772
  l1: {
@@ -765,7 +774,7 @@ export function describeArchiverDataStore(
765
774
  blockHash: makeBlockHash(blockNumber),
766
775
  timestamp: BigInt(blockNumber),
767
776
  },
768
- };
777
+ });
769
778
  };
770
779
 
771
780
  beforeEach(async () => {
@@ -878,11 +887,13 @@ export function describeArchiverDataStore(
878
887
  let blocks: PublishedL2Block[];
879
888
 
880
889
  beforeEach(async () => {
881
- blocks = await timesParallel(numBlocks, async (index: number) => ({
882
- block: await L2Block.random(index + 1, txsPerBlock, numPublicFunctionCalls, numPublicLogs),
883
- l1: { blockNumber: BigInt(index), blockHash: makeBlockHash(index), timestamp: BigInt(index) },
884
- attestations: times(3, CommitteeAttestation.random),
885
- }));
890
+ blocks = await timesParallel(numBlocks, async (index: number) =>
891
+ PublishedL2Block.fromFields({
892
+ block: await L2Block.random(index + 1, txsPerBlock, numPublicFunctionCalls, numPublicLogs),
893
+ l1: { blockNumber: BigInt(index), blockHash: makeBlockHash(index), timestamp: BigInt(index) },
894
+ attestations: times(3, CommitteeAttestation.random),
895
+ }),
896
+ );
886
897
 
887
898
  await store.addBlocks(blocks);
888
899
  await store.addLogs(blocks.map(b => b.block));
@@ -1056,5 +1067,96 @@ export function describeArchiverDataStore(
1056
1067
  }
1057
1068
  });
1058
1069
  });
1070
+
1071
+ describe('pendingChainValidationStatus', () => {
1072
+ it('should return undefined when no status is set', async () => {
1073
+ const status = await store.getPendingChainValidationStatus();
1074
+ expect(status).toBeUndefined();
1075
+ });
1076
+
1077
+ it('should store and retrieve a valid validation status', async () => {
1078
+ const validStatus: ValidateBlockResult = { valid: true };
1079
+
1080
+ await store.setPendingChainValidationStatus(validStatus);
1081
+ const retrievedStatus = await store.getPendingChainValidationStatus();
1082
+
1083
+ expect(retrievedStatus).toEqual(validStatus);
1084
+ });
1085
+
1086
+ it('should store and retrieve an invalid validation status with insufficient attestations', async () => {
1087
+ const invalidStatus: ValidateBlockResult = {
1088
+ valid: false,
1089
+ block: randomBlockInfo(1),
1090
+ committee: [EthAddress.random(), EthAddress.random()],
1091
+ epoch: 123n,
1092
+ seed: 456n,
1093
+ attestors: [EthAddress.random()],
1094
+ attestations: [CommitteeAttestation.random()],
1095
+ reason: 'insufficient-attestations',
1096
+ };
1097
+
1098
+ await store.setPendingChainValidationStatus(invalidStatus);
1099
+ const retrievedStatus = await store.getPendingChainValidationStatus();
1100
+
1101
+ expect(retrievedStatus).toEqual(invalidStatus);
1102
+ });
1103
+
1104
+ it('should store and retrieve an invalid validation status with invalid attestation', async () => {
1105
+ const invalidStatus: ValidateBlockResult = {
1106
+ valid: false,
1107
+ block: randomBlockInfo(2),
1108
+ committee: [EthAddress.random()],
1109
+ attestors: [EthAddress.random()],
1110
+ epoch: 789n,
1111
+ seed: 101n,
1112
+ attestations: [CommitteeAttestation.random()],
1113
+ reason: 'invalid-attestation',
1114
+ invalidIndex: 5,
1115
+ };
1116
+
1117
+ await store.setPendingChainValidationStatus(invalidStatus);
1118
+ const retrievedStatus = await store.getPendingChainValidationStatus();
1119
+
1120
+ expect(retrievedStatus).toEqual(invalidStatus);
1121
+ });
1122
+
1123
+ it('should overwrite existing status when setting a new one', async () => {
1124
+ const firstStatus: ValidateBlockResult = { valid: true };
1125
+ const secondStatus: ValidateBlockResult = {
1126
+ valid: false,
1127
+ block: randomBlockInfo(3),
1128
+ committee: [EthAddress.random()],
1129
+ epoch: 999n,
1130
+ seed: 888n,
1131
+ attestors: [EthAddress.random()],
1132
+ attestations: [CommitteeAttestation.random()],
1133
+ reason: 'insufficient-attestations',
1134
+ };
1135
+
1136
+ await store.setPendingChainValidationStatus(firstStatus);
1137
+ await store.setPendingChainValidationStatus(secondStatus);
1138
+ const retrievedStatus = await store.getPendingChainValidationStatus();
1139
+
1140
+ expect(retrievedStatus).toEqual(secondStatus);
1141
+ });
1142
+
1143
+ it('should handle empty committee and attestations arrays', async () => {
1144
+ const statusWithEmptyArrays: ValidateBlockResult = {
1145
+ valid: false,
1146
+ block: randomBlockInfo(4),
1147
+ committee: [],
1148
+ epoch: 0n,
1149
+ seed: 0n,
1150
+ attestors: [],
1151
+ attestations: [],
1152
+ reason: 'insufficient-attestations',
1153
+ };
1154
+
1155
+ await store.setPendingChainValidationStatus(statusWithEmptyArrays);
1156
+ const retrievedStatus = await store.getPendingChainValidationStatus();
1157
+
1158
+ expect(retrievedStatus).toEqual(statusWithEmptyArrays);
1159
+ });
1160
+ });
1059
1161
  });
1060
1162
  }
@@ -1,47 +1,28 @@
1
1
  import { type BlobSinkConfig, blobSinkConfigMapping } from '@aztec/blob-sink/client';
2
2
  import {
3
- type L1ContractAddresses,
4
3
  type L1ContractsConfig,
5
4
  type L1ReaderConfig,
6
5
  l1ContractAddressesMapping,
7
6
  l1ContractsConfigMappings,
8
7
  l1ReaderConfigMappings,
9
8
  } from '@aztec/ethereum';
10
- import { type ConfigMappingsType, getConfigFromMappings, numberConfigHelper } from '@aztec/foundation/config';
9
+ import {
10
+ type ConfigMappingsType,
11
+ booleanConfigHelper,
12
+ getConfigFromMappings,
13
+ numberConfigHelper,
14
+ } from '@aztec/foundation/config';
11
15
  import { type ChainConfig, chainConfigMappings } from '@aztec/stdlib/config';
16
+ import type { ArchiverSpecificConfig } from '@aztec/stdlib/interfaces/server';
12
17
 
13
18
  /**
19
+ * The archiver configuration.
14
20
  * There are 2 polling intervals used in this configuration. The first is the archiver polling interval, archiverPollingIntervalMS.
15
21
  * This is the interval between successive calls to eth_blockNumber via viem.
16
22
  * Results of calls to eth_blockNumber are cached by viem with this cache being updated periodically at the interval specified by viemPollingIntervalMS.
17
23
  * As a result the maximum observed polling time for new blocks will be viemPollingIntervalMS + archiverPollingIntervalMS.
18
24
  */
19
-
20
- /**
21
- * The archiver configuration.
22
- */
23
- export type ArchiverConfig = {
24
- /** The polling interval in ms for retrieving new L2 blocks and encrypted logs. */
25
- archiverPollingIntervalMS?: number;
26
-
27
- /** The number of L2 blocks the archiver will attempt to download at a time. */
28
- archiverBatchSize?: number;
29
-
30
- /** The polling interval viem uses in ms */
31
- viemPollingIntervalMS?: number;
32
-
33
- /** The deployed L1 contract addresses */
34
- l1Contracts: L1ContractAddresses;
35
-
36
- /** The max number of logs that can be obtained in 1 "getPublicLogs" call. */
37
- maxLogs?: number;
38
-
39
- /** The maximum possible size of the archiver DB in KB. Overwrites the general dataStoreMapSizeKB. */
40
- archiverStoreMapSizeKb?: number;
41
- } & L1ReaderConfig &
42
- L1ContractsConfig &
43
- BlobSinkConfig &
44
- ChainConfig;
25
+ export type ArchiverConfig = ArchiverSpecificConfig & L1ReaderConfig & L1ContractsConfig & BlobSinkConfig & ChainConfig;
45
26
 
46
27
  export const archiverConfigMappings: ConfigMappingsType<ArchiverConfig> = {
47
28
  ...blobSinkConfigMapping,
@@ -65,6 +46,10 @@ export const archiverConfigMappings: ConfigMappingsType<ArchiverConfig> = {
65
46
  parseEnv: (val: string | undefined) => (val ? +val : undefined),
66
47
  description: 'The maximum possible size of the archiver DB in KB. Overwrites the general dataStoreMapSizeKB.',
67
48
  },
49
+ skipValidateBlockAttestations: {
50
+ description: 'Whether to skip validating block attestations (use only for testing).',
51
+ ...booleanConfigHelper(false),
52
+ },
68
53
  ...chainConfigMappings,
69
54
  ...l1ReaderConfigMappings,
70
55
  viemPollingIntervalMS: {
@@ -15,7 +15,7 @@ import type { ViemSignature } from '@aztec/foundation/eth-signature';
15
15
  import { Fr } from '@aztec/foundation/fields';
16
16
  import { type Logger, createLogger } from '@aztec/foundation/log';
17
17
  import { type InboxAbi, RollupAbi } from '@aztec/l1-artifacts';
18
- import { Body, CommitteeAttestation, L2Block } from '@aztec/stdlib/block';
18
+ import { Body, CommitteeAttestation, L2Block, PublishedL2Block } from '@aztec/stdlib/block';
19
19
  import { Proof } from '@aztec/stdlib/proofs';
20
20
  import { AppendOnlyTreeSnapshot } from '@aztec/stdlib/trees';
21
21
  import { BlockHeader, GlobalVariables, ProposedBlockHeader, StateReference } from '@aztec/stdlib/tx';
@@ -33,7 +33,7 @@ import {
33
33
  import { NoBlobBodiesFoundError } from './errors.js';
34
34
  import type { DataRetrieval } from './structs/data_retrieval.js';
35
35
  import type { InboxMessage } from './structs/inbox_message.js';
36
- import type { L1PublishedData, PublishedL2Block } from './structs/published.js';
36
+ import type { L1PublishedData } from './structs/published.js';
37
37
 
38
38
  export type RetrievedL2Block = {
39
39
  l2BlockNumber: number;
@@ -87,11 +87,7 @@ export function retrievedBlockToPublishedL2Block(retrievedBlock: RetrievedL2Bloc
87
87
 
88
88
  const block = new L2Block(archive, header, body);
89
89
 
90
- return {
91
- block,
92
- l1,
93
- attestations,
94
- };
90
+ return PublishedL2Block.fromFields({ block, l1, attestations });
95
91
  }
96
92
 
97
93
  /**
@@ -6,7 +6,15 @@ import { BufferReader } from '@aztec/foundation/serialize';
6
6
  import { bufferToHex } from '@aztec/foundation/string';
7
7
  import type { AztecAsyncKVStore, AztecAsyncMap, AztecAsyncSingleton, Range } from '@aztec/kv-store';
8
8
  import type { AztecAddress } from '@aztec/stdlib/aztec-address';
9
- import { Body, CommitteeAttestation, L2Block, L2BlockHash } from '@aztec/stdlib/block';
9
+ import {
10
+ Body,
11
+ CommitteeAttestation,
12
+ L2Block,
13
+ L2BlockHash,
14
+ PublishedL2Block,
15
+ type ValidateBlockResult,
16
+ } from '@aztec/stdlib/block';
17
+ import { deserializeValidateBlockResult, serializeValidateBlockResult } from '@aztec/stdlib/block';
10
18
  import { AppendOnlyTreeSnapshot } from '@aztec/stdlib/trees';
11
19
  import {
12
20
  BlockHeader,
@@ -19,7 +27,7 @@ import {
19
27
  } from '@aztec/stdlib/tx';
20
28
 
21
29
  import { BlockNumberNotSequentialError, InitialBlockNumberNotSequentialError } from '../errors.js';
22
- import type { L1PublishedData, PublishedL2Block } from '../structs/published.js';
30
+ import type { L1PublishedData } from '../structs/published.js';
23
31
 
24
32
  export { TxReceipt, type TxEffect, type TxHash } from '@aztec/stdlib/tx';
25
33
 
@@ -52,6 +60,9 @@ export class BlockStore {
52
60
  /** Stores l2 block number of the last proven block */
53
61
  #lastProvenL2Block: AztecAsyncSingleton<number>;
54
62
 
63
+ /** Stores the pending chain validation status */
64
+ #pendingChainValidationStatus: AztecAsyncSingleton<Buffer>;
65
+
55
66
  /** Index mapping a contract's address (as a string) to its location in a block */
56
67
  #contractIndex: AztecAsyncMap<string, BlockIndexValue>;
57
68
 
@@ -64,6 +75,7 @@ export class BlockStore {
64
75
  this.#contractIndex = db.openMap('archiver_contract_index');
65
76
  this.#lastSynchedL1Block = db.openSingleton('archiver_last_synched_l1_block');
66
77
  this.#lastProvenL2Block = db.openSingleton('archiver_last_proven_l2_block');
78
+ this.#pendingChainValidationStatus = db.openSingleton('archiver_pending_chain_validation_status');
67
79
  }
68
80
 
69
81
  /**
@@ -224,7 +236,10 @@ export class BlockStore {
224
236
  }
225
237
  }
226
238
 
227
- private async getBlockFromBlockStorage(blockNumber: number, blockStorage: BlockStorage) {
239
+ private async getBlockFromBlockStorage(
240
+ blockNumber: number,
241
+ blockStorage: BlockStorage,
242
+ ): Promise<PublishedL2Block | undefined> {
228
243
  const header = BlockHeader.fromBuffer(blockStorage.header);
229
244
  const archive = AppendOnlyTreeSnapshot.fromBuffer(blockStorage.archive);
230
245
  const blockHash = blockStorage.blockHash;
@@ -257,7 +272,7 @@ export class BlockStore {
257
272
  );
258
273
  }
259
274
  const attestations = blockStorage.attestations.map(CommitteeAttestation.fromBuffer);
260
- return { block, l1: blockStorage.l1, attestations };
275
+ return PublishedL2Block.fromFields({ block, l1: blockStorage.l1, attestations });
261
276
  }
262
277
 
263
278
  /**
@@ -361,4 +376,29 @@ export class BlockStore {
361
376
 
362
377
  return { start, limit };
363
378
  }
379
+
380
+ /**
381
+ * Gets the pending chain validation status.
382
+ * @returns The validation status or undefined if not set.
383
+ */
384
+ async getPendingChainValidationStatus(): Promise<ValidateBlockResult | undefined> {
385
+ const buffer = await this.#pendingChainValidationStatus.getAsync();
386
+ if (!buffer) {
387
+ return undefined;
388
+ }
389
+ return deserializeValidateBlockResult(buffer);
390
+ }
391
+
392
+ /**
393
+ * Sets the pending chain validation status.
394
+ * @param status - The validation status to store.
395
+ */
396
+ async setPendingChainValidationStatus(status: ValidateBlockResult | undefined): Promise<void> {
397
+ if (status) {
398
+ const buffer = serializeValidateBlockResult(status);
399
+ await this.#pendingChainValidationStatus.set(buffer);
400
+ } else {
401
+ await this.#pendingChainValidationStatus.delete();
402
+ }
403
+ }
364
404
  }
@@ -5,7 +5,7 @@ import { createLogger } from '@aztec/foundation/log';
5
5
  import type { AztecAsyncKVStore, CustomRange, StoreSize } from '@aztec/kv-store';
6
6
  import { FunctionSelector } from '@aztec/stdlib/abi';
7
7
  import type { AztecAddress } from '@aztec/stdlib/aztec-address';
8
- import type { L2Block } from '@aztec/stdlib/block';
8
+ import type { L2Block, ValidateBlockResult } from '@aztec/stdlib/block';
9
9
  import type {
10
10
  ContractClassPublic,
11
11
  ContractDataSource,
@@ -395,4 +395,12 @@ export class KVArchiverDataStore implements ArchiverDataStore, ContractDataSourc
395
395
  public removeL1ToL2Messages(startIndex: bigint): Promise<void> {
396
396
  return this.#messageStore.removeL1ToL2Messages(startIndex);
397
397
  }
398
+
399
+ public getPendingChainValidationStatus(): Promise<ValidateBlockResult | undefined> {
400
+ return this.#blockStore.getPendingChainValidationStatus();
401
+ }
402
+
403
+ public setPendingChainValidationStatus(status: ValidateBlockResult | undefined): Promise<void> {
404
+ return this.#blockStore.setPendingChainValidationStatus(status);
405
+ }
398
406
  }
@@ -20,6 +20,7 @@ export async function validateBlockAttestations(
20
20
  logger?: Logger,
21
21
  ): Promise<ValidateBlockResult> {
22
22
  const attestations = getAttestationsFromPublishedL2Block(publishedBlock);
23
+ const attestors = attestations.map(a => a.getSender());
23
24
  const { block } = publishedBlock;
24
25
  const blockHash = await block.hash().then(hash => hash.toString());
25
26
  const archiveRoot = block.archive.root.toString();
@@ -51,7 +52,17 @@ export async function validateBlockAttestations(
51
52
  if (!committeeSet.has(signer)) {
52
53
  logger?.warn(`Attestation from non-committee member ${signer} at slot ${slot}`, { committee });
53
54
  const reason = 'invalid-attestation';
54
- return { valid: false, reason, invalidIndex: i, block: publishedBlock, committee, seed, epoch, attestations };
55
+ return {
56
+ valid: false,
57
+ reason,
58
+ invalidIndex: i,
59
+ block: publishedBlock.block.toBlockInfo(),
60
+ committee,
61
+ seed,
62
+ epoch,
63
+ attestors,
64
+ attestations: publishedBlock.attestations,
65
+ };
55
66
  }
56
67
  }
57
68
 
@@ -62,7 +73,16 @@ export async function validateBlockAttestations(
62
73
  ...logData,
63
74
  });
64
75
  const reason = 'insufficient-attestations';
65
- return { valid: false, reason, block: publishedBlock, committee, seed, epoch, attestations };
76
+ return {
77
+ valid: false,
78
+ reason,
79
+ block: publishedBlock.block.toBlockInfo(),
80
+ committee,
81
+ seed,
82
+ epoch,
83
+ attestors,
84
+ attestations: publishedBlock.attestations,
85
+ };
66
86
  }
67
87
 
68
88
  logger?.debug(`Block attestations validated successfully for block ${block.number} at slot ${slot}`, logData);
@@ -5,7 +5,14 @@ import type { Fr } from '@aztec/foundation/fields';
5
5
  import { createLogger } from '@aztec/foundation/log';
6
6
  import type { FunctionSelector } from '@aztec/stdlib/abi';
7
7
  import type { AztecAddress } from '@aztec/stdlib/aztec-address';
8
- import { L2Block, L2BlockHash, type L2BlockSource, type L2Tips, type ValidateBlockResult } from '@aztec/stdlib/block';
8
+ import {
9
+ L2Block,
10
+ L2BlockHash,
11
+ type L2BlockSource,
12
+ type L2Tips,
13
+ PublishedL2Block,
14
+ type ValidateBlockResult,
15
+ } from '@aztec/stdlib/block';
9
16
  import type { ContractClassPublic, ContractDataSource, ContractInstanceWithAddress } from '@aztec/stdlib/contract';
10
17
  import { EmptyL1RollupConstants, type L1RollupConstants, getSlotRangeForEpoch } from '@aztec/stdlib/epoch-helpers';
11
18
  import { type BlockHeader, TxHash, TxReceipt, TxStatus } from '@aztec/stdlib/tx';
@@ -106,15 +113,17 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
106
113
 
107
114
  public async getPublishedBlocks(from: number, limit: number, proven?: boolean) {
108
115
  const blocks = await this.getBlocks(from, limit, proven);
109
- return blocks.map(block => ({
110
- block,
111
- l1: {
112
- blockNumber: BigInt(block.number),
113
- blockHash: Buffer32.random().toString(),
114
- timestamp: BigInt(block.number),
115
- },
116
- attestations: [],
117
- }));
116
+ return blocks.map(block =>
117
+ PublishedL2Block.fromFields({
118
+ block,
119
+ l1: {
120
+ blockNumber: BigInt(block.number),
121
+ blockHash: Buffer32.random().toString(),
122
+ timestamp: BigInt(block.number),
123
+ },
124
+ attestations: [],
125
+ }),
126
+ );
118
127
  }
119
128
 
120
129
  getBlockHeader(number: number | 'latest'): Promise<BlockHeader | undefined> {