@aztec/archiver 3.0.0-canary.a9708bd → 3.0.0-devnet.2-patch.1

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 (127) hide show
  1. package/README.md +27 -6
  2. package/dest/archiver/archiver.d.ts +87 -64
  3. package/dest/archiver/archiver.d.ts.map +1 -1
  4. package/dest/archiver/archiver.js +463 -278
  5. package/dest/archiver/archiver_store.d.ts +46 -28
  6. package/dest/archiver/archiver_store.d.ts.map +1 -1
  7. package/dest/archiver/archiver_store_test_suite.d.ts +1 -1
  8. package/dest/archiver/archiver_store_test_suite.d.ts.map +1 -1
  9. package/dest/archiver/archiver_store_test_suite.js +316 -143
  10. package/dest/archiver/config.d.ts +6 -23
  11. package/dest/archiver/config.d.ts.map +1 -1
  12. package/dest/archiver/config.js +19 -12
  13. package/dest/archiver/errors.d.ts +1 -1
  14. package/dest/archiver/errors.d.ts.map +1 -1
  15. package/dest/archiver/index.d.ts +1 -1
  16. package/dest/archiver/instrumentation.d.ts +5 -3
  17. package/dest/archiver/instrumentation.d.ts.map +1 -1
  18. package/dest/archiver/instrumentation.js +14 -0
  19. package/dest/archiver/kv_archiver_store/block_store.d.ts +45 -9
  20. package/dest/archiver/kv_archiver_store/block_store.d.ts.map +1 -1
  21. package/dest/archiver/kv_archiver_store/block_store.js +99 -12
  22. package/dest/archiver/kv_archiver_store/contract_class_store.d.ts +2 -2
  23. package/dest/archiver/kv_archiver_store/contract_class_store.d.ts.map +1 -1
  24. package/dest/archiver/kv_archiver_store/contract_class_store.js +1 -1
  25. package/dest/archiver/kv_archiver_store/contract_instance_store.d.ts +2 -2
  26. package/dest/archiver/kv_archiver_store/contract_instance_store.d.ts.map +1 -1
  27. package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts +30 -30
  28. package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts.map +1 -1
  29. package/dest/archiver/kv_archiver_store/kv_archiver_store.js +26 -15
  30. package/dest/archiver/kv_archiver_store/log_store.d.ts +3 -10
  31. package/dest/archiver/kv_archiver_store/log_store.d.ts.map +1 -1
  32. package/dest/archiver/kv_archiver_store/log_store.js +4 -26
  33. package/dest/archiver/kv_archiver_store/message_store.d.ts +6 -5
  34. package/dest/archiver/kv_archiver_store/message_store.d.ts.map +1 -1
  35. package/dest/archiver/kv_archiver_store/message_store.js +15 -14
  36. package/dest/archiver/l1/bin/retrieve-calldata.d.ts +3 -0
  37. package/dest/archiver/l1/bin/retrieve-calldata.d.ts.map +1 -0
  38. package/dest/archiver/l1/bin/retrieve-calldata.js +147 -0
  39. package/dest/archiver/l1/calldata_retriever.d.ts +98 -0
  40. package/dest/archiver/l1/calldata_retriever.d.ts.map +1 -0
  41. package/dest/archiver/l1/calldata_retriever.js +403 -0
  42. package/dest/archiver/l1/data_retrieval.d.ts +87 -0
  43. package/dest/archiver/l1/data_retrieval.d.ts.map +1 -0
  44. package/dest/archiver/{data_retrieval.js → l1/data_retrieval.js} +118 -154
  45. package/dest/archiver/l1/debug_tx.d.ts +19 -0
  46. package/dest/archiver/l1/debug_tx.d.ts.map +1 -0
  47. package/dest/archiver/l1/debug_tx.js +73 -0
  48. package/dest/archiver/l1/spire_proposer.d.ts +70 -0
  49. package/dest/archiver/l1/spire_proposer.d.ts.map +1 -0
  50. package/dest/archiver/l1/spire_proposer.js +157 -0
  51. package/dest/archiver/l1/trace_tx.d.ts +97 -0
  52. package/dest/archiver/l1/trace_tx.d.ts.map +1 -0
  53. package/dest/archiver/l1/trace_tx.js +91 -0
  54. package/dest/archiver/l1/types.d.ts +12 -0
  55. package/dest/archiver/l1/types.d.ts.map +1 -0
  56. package/dest/archiver/l1/types.js +3 -0
  57. package/dest/archiver/l1/validate_trace.d.ts +29 -0
  58. package/dest/archiver/l1/validate_trace.d.ts.map +1 -0
  59. package/dest/archiver/l1/validate_trace.js +150 -0
  60. package/dest/archiver/structs/data_retrieval.d.ts +1 -1
  61. package/dest/archiver/structs/inbox_message.d.ts +4 -4
  62. package/dest/archiver/structs/inbox_message.d.ts.map +1 -1
  63. package/dest/archiver/structs/inbox_message.js +6 -5
  64. package/dest/archiver/structs/published.d.ts +3 -2
  65. package/dest/archiver/structs/published.d.ts.map +1 -1
  66. package/dest/archiver/validation.d.ts +10 -4
  67. package/dest/archiver/validation.d.ts.map +1 -1
  68. package/dest/archiver/validation.js +66 -44
  69. package/dest/factory.d.ts +3 -11
  70. package/dest/factory.d.ts.map +1 -1
  71. package/dest/factory.js +5 -17
  72. package/dest/index.d.ts +2 -2
  73. package/dest/index.d.ts.map +1 -1
  74. package/dest/index.js +1 -1
  75. package/dest/rpc/index.d.ts +2 -2
  76. package/dest/test/index.d.ts +1 -1
  77. package/dest/test/mock_archiver.d.ts +16 -8
  78. package/dest/test/mock_archiver.d.ts.map +1 -1
  79. package/dest/test/mock_archiver.js +19 -14
  80. package/dest/test/mock_l1_to_l2_message_source.d.ts +7 -6
  81. package/dest/test/mock_l1_to_l2_message_source.d.ts.map +1 -1
  82. package/dest/test/mock_l1_to_l2_message_source.js +10 -9
  83. package/dest/test/mock_l2_block_source.d.ts +24 -20
  84. package/dest/test/mock_l2_block_source.d.ts.map +1 -1
  85. package/dest/test/mock_l2_block_source.js +79 -13
  86. package/dest/test/mock_structs.d.ts +3 -2
  87. package/dest/test/mock_structs.d.ts.map +1 -1
  88. package/dest/test/mock_structs.js +9 -8
  89. package/package.json +18 -17
  90. package/src/archiver/archiver.ts +610 -363
  91. package/src/archiver/archiver_store.ts +55 -28
  92. package/src/archiver/archiver_store_test_suite.ts +369 -143
  93. package/src/archiver/config.ts +26 -51
  94. package/src/archiver/instrumentation.ts +19 -2
  95. package/src/archiver/kv_archiver_store/block_store.ts +139 -21
  96. package/src/archiver/kv_archiver_store/contract_class_store.ts +1 -1
  97. package/src/archiver/kv_archiver_store/contract_instance_store.ts +1 -1
  98. package/src/archiver/kv_archiver_store/kv_archiver_store.ts +48 -33
  99. package/src/archiver/kv_archiver_store/log_store.ts +4 -30
  100. package/src/archiver/kv_archiver_store/message_store.ts +21 -18
  101. package/src/archiver/l1/README.md +98 -0
  102. package/src/archiver/l1/bin/retrieve-calldata.ts +182 -0
  103. package/src/archiver/l1/calldata_retriever.ts +531 -0
  104. package/src/archiver/{data_retrieval.ts → l1/data_retrieval.ts} +198 -242
  105. package/src/archiver/l1/debug_tx.ts +99 -0
  106. package/src/archiver/l1/spire_proposer.ts +160 -0
  107. package/src/archiver/l1/trace_tx.ts +128 -0
  108. package/src/archiver/l1/types.ts +13 -0
  109. package/src/archiver/l1/validate_trace.ts +211 -0
  110. package/src/archiver/structs/inbox_message.ts +8 -8
  111. package/src/archiver/structs/published.ts +2 -1
  112. package/src/archiver/validation.ts +86 -32
  113. package/src/factory.ts +6 -26
  114. package/src/index.ts +1 -1
  115. package/src/test/fixtures/debug_traceTransaction-multicall3.json +88 -0
  116. package/src/test/fixtures/debug_traceTransaction-multiplePropose.json +153 -0
  117. package/src/test/fixtures/debug_traceTransaction-proxied.json +122 -0
  118. package/src/test/fixtures/trace_transaction-multicall3.json +65 -0
  119. package/src/test/fixtures/trace_transaction-multiplePropose.json +319 -0
  120. package/src/test/fixtures/trace_transaction-proxied.json +128 -0
  121. package/src/test/fixtures/trace_transaction-randomRevert.json +216 -0
  122. package/src/test/mock_archiver.ts +22 -16
  123. package/src/test/mock_l1_to_l2_message_source.ts +10 -9
  124. package/src/test/mock_l2_block_source.ts +110 -27
  125. package/src/test/mock_structs.ts +10 -9
  126. package/dest/archiver/data_retrieval.d.ts +0 -78
  127. package/dest/archiver/data_retrieval.d.ts.map +0 -1
@@ -2,17 +2,26 @@ import {
2
2
  INITIAL_L2_BLOCK_NUM,
3
3
  NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
4
4
  PRIVATE_LOG_SIZE_IN_FIELDS,
5
- PUBLIC_LOG_SIZE_IN_FIELDS,
6
5
  } from '@aztec/constants';
7
6
  import { makeTuple } from '@aztec/foundation/array';
7
+ import { BlockNumber, CheckpointNumber, EpochNumber } from '@aztec/foundation/branded-types';
8
8
  import { Buffer16, Buffer32 } from '@aztec/foundation/buffer';
9
9
  import { times, timesParallel } from '@aztec/foundation/collection';
10
- import { randomInt } from '@aztec/foundation/crypto';
11
- import { Fr } from '@aztec/foundation/fields';
10
+ import { randomInt } from '@aztec/foundation/crypto/random';
11
+ import { Fr } from '@aztec/foundation/curves/bn254';
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
+ wrapDataInBlock,
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);
@@ -81,7 +90,7 @@ export function describeArchiverDataStore(
81
90
 
82
91
  beforeEach(async () => {
83
92
  store = await getStore();
84
- blocks = await timesParallel(10, async i => makePublished(await L2Block.random(i + 1), i + 10));
93
+ blocks = await timesParallel(10, async i => makePublished(await L2Block.random(BlockNumber(i + 1)), i + 10));
85
94
  });
86
95
 
87
96
  describe('addBlocks', () => {
@@ -95,15 +104,18 @@ export function describeArchiverDataStore(
95
104
  });
96
105
 
97
106
  it('throws an error if the previous block does not exist in the store', async () => {
98
- const block = makePublished(await L2Block.random(2), 2);
107
+ const block = makePublished(await L2Block.random(BlockNumber(2)), 2);
99
108
  await expect(store.addBlocks([block])).rejects.toThrow(InitialBlockNumberNotSequentialError);
100
- await expect(store.getPublishedBlocks(1, 10)).resolves.toEqual([]);
109
+ await expect(store.getPublishedBlocks(BlockNumber(1), 10)).resolves.toEqual([]);
101
110
  });
102
111
 
103
112
  it('throws an error if there is a gap in the blocks being added', async () => {
104
- const blocks = [makePublished(await L2Block.random(1), 1), makePublished(await L2Block.random(3), 3)];
113
+ const blocks = [
114
+ makePublished(await L2Block.random(BlockNumber(1)), 1),
115
+ makePublished(await L2Block.random(BlockNumber(3)), 3),
116
+ ];
105
117
  await expect(store.addBlocks(blocks)).rejects.toThrow(BlockNumberNotSequentialError);
106
- await expect(store.getPublishedBlocks(1, 10)).resolves.toEqual([]);
118
+ await expect(store.getPublishedBlocks(BlockNumber(1), 10)).resolves.toEqual([]);
107
119
  });
108
120
  });
109
121
 
@@ -121,18 +133,44 @@ export function describeArchiverDataStore(
121
133
  });
122
134
 
123
135
  it('can unwind multiple empty blocks', async () => {
124
- const emptyBlocks = await timesParallel(10, async i => makePublished(await L2Block.random(i + 1, 0), i + 10));
136
+ const emptyBlocks = await timesParallel(10, async i =>
137
+ makePublished(await L2Block.random(BlockNumber(i + 1), 0), i + 10),
138
+ );
125
139
  await store.addBlocks(emptyBlocks);
126
140
  expect(await store.getSynchedL2BlockNumber()).toBe(10);
127
141
 
128
- await store.unwindBlocks(10, 3);
142
+ await store.unwindBlocks(BlockNumber(10), 3);
129
143
  expect(await store.getSynchedL2BlockNumber()).toBe(7);
130
- expect((await store.getPublishedBlocks(1, 10)).map(b => b.block.number)).toEqual([1, 2, 3, 4, 5, 6, 7]);
144
+ expect((await store.getPublishedBlocks(BlockNumber(1), 10)).map(b => b.block.number)).toEqual([
145
+ 1, 2, 3, 4, 5, 6, 7,
146
+ ]);
131
147
  });
132
148
 
133
149
  it('refuses to unwind blocks if the tip is not the last block', async () => {
134
150
  await store.addBlocks(blocks);
135
- await expect(store.unwindBlocks(5, 1)).rejects.toThrow(/can only unwind blocks from the tip/i);
151
+ await expect(store.unwindBlocks(BlockNumber(5), 1)).rejects.toThrow(/can only unwind blocks from the tip/i);
152
+ });
153
+
154
+ it('unwound blocks and headers cannot be retrieved by hash or archive', async () => {
155
+ await store.addBlocks(blocks);
156
+ const lastBlock = blocks[blocks.length - 1];
157
+ const blockHash = await lastBlock.block.hash();
158
+ const archive = lastBlock.block.archive.root;
159
+
160
+ // Verify block and header exist before unwinding
161
+ expect(await store.getPublishedBlockByHash(blockHash)).toBeDefined();
162
+ expect(await store.getPublishedBlockByArchive(archive)).toBeDefined();
163
+ expect(await store.getBlockHeaderByHash(blockHash)).toBeDefined();
164
+ expect(await store.getBlockHeaderByArchive(archive)).toBeDefined();
165
+
166
+ // Unwind the block
167
+ await store.unwindBlocks(lastBlock.block.number, 1);
168
+
169
+ // Verify neither block nor header can be retrieved after unwinding
170
+ expect(await store.getPublishedBlockByHash(blockHash)).toBeUndefined();
171
+ expect(await store.getPublishedBlockByArchive(archive)).toBeUndefined();
172
+ expect(await store.getBlockHeaderByHash(blockHash)).toBeUndefined();
173
+ expect(await store.getBlockHeaderByArchive(archive)).toBeUndefined();
136
174
  });
137
175
  });
138
176
 
@@ -142,32 +180,117 @@ export function describeArchiverDataStore(
142
180
  });
143
181
 
144
182
  it.each(blockTests)('retrieves previously stored blocks', async (start, limit, getExpectedBlocks) => {
145
- expectBlocksEqual(await store.getPublishedBlocks(start, limit), getExpectedBlocks());
183
+ expectBlocksEqual(await store.getPublishedBlocks(BlockNumber(start), limit), getExpectedBlocks());
146
184
  });
147
185
 
148
186
  it('returns an empty array if no blocks are found', async () => {
149
- await expect(store.getPublishedBlocks(12, 1)).resolves.toEqual([]);
187
+ await expect(store.getPublishedBlocks(BlockNumber(12), 1)).resolves.toEqual([]);
150
188
  });
151
189
 
152
190
  it('throws an error if limit is invalid', async () => {
153
- await expect(store.getPublishedBlocks(1, 0)).rejects.toThrow('Invalid limit: 0');
191
+ await expect(store.getPublishedBlocks(BlockNumber(1), 0)).rejects.toThrow('Invalid limit: 0');
154
192
  });
155
193
 
156
194
  it('throws an error if `from` it is out of range', async () => {
157
- await expect(store.getPublishedBlocks(INITIAL_L2_BLOCK_NUM - 100, 1)).rejects.toThrow('Invalid start: -99');
195
+ await expect(store.getPublishedBlocks((INITIAL_L2_BLOCK_NUM - 100) as BlockNumber, 1)).rejects.toThrow(
196
+ 'Invalid start: -99',
197
+ );
158
198
  });
159
199
 
160
200
  it('throws an error if unexpected initial block number is found', async () => {
161
- await store.addBlocks([makePublished(await L2Block.random(21), 31)], { force: true });
162
- await expect(store.getPublishedBlocks(20, 1)).rejects.toThrow(`mismatch`);
201
+ await store.addBlocks([makePublished(await L2Block.random(BlockNumber(21)), 31)], { force: true });
202
+ await expect(store.getPublishedBlocks(BlockNumber(20), 1)).rejects.toThrow(`mismatch`);
163
203
  });
164
204
 
165
205
  it('throws an error if a gap is found', async () => {
166
206
  await store.addBlocks(
167
- [makePublished(await L2Block.random(20), 30), makePublished(await L2Block.random(22), 32)],
207
+ [
208
+ makePublished(await L2Block.random(BlockNumber(20)), 30),
209
+ makePublished(await L2Block.random(BlockNumber(22)), 32),
210
+ ],
168
211
  { force: true },
169
212
  );
170
- await expect(store.getPublishedBlocks(20, 2)).rejects.toThrow(`mismatch`);
213
+ await expect(store.getPublishedBlocks(BlockNumber(20), 2)).rejects.toThrow(`mismatch`);
214
+ });
215
+ });
216
+
217
+ describe('getPublishedBlockByHash', () => {
218
+ beforeEach(async () => {
219
+ await store.addBlocks(blocks);
220
+ });
221
+
222
+ it('retrieves a block by its hash', async () => {
223
+ const expectedBlock = blocks[5];
224
+ const blockHash = await expectedBlock.block.hash();
225
+ const retrievedBlock = await store.getPublishedBlockByHash(blockHash);
226
+
227
+ expect(retrievedBlock).toBeDefined();
228
+ expectBlocksEqual([retrievedBlock!], [expectedBlock]);
229
+ });
230
+
231
+ it('returns undefined for non-existent block hash', async () => {
232
+ const nonExistentHash = Fr.random();
233
+ await expect(store.getPublishedBlockByHash(nonExistentHash)).resolves.toBeUndefined();
234
+ });
235
+ });
236
+
237
+ describe('getPublishedBlockByArchive', () => {
238
+ beforeEach(async () => {
239
+ await store.addBlocks(blocks);
240
+ });
241
+
242
+ it('retrieves a block by its archive root', async () => {
243
+ const expectedBlock = blocks[3];
244
+ const archive = expectedBlock.block.archive.root;
245
+ const retrievedBlock = await store.getPublishedBlockByArchive(archive);
246
+
247
+ expect(retrievedBlock).toBeDefined();
248
+ expectBlocksEqual([retrievedBlock!], [expectedBlock]);
249
+ });
250
+
251
+ it('returns undefined for non-existent archive root', async () => {
252
+ const nonExistentArchive = Fr.random();
253
+ await expect(store.getPublishedBlockByArchive(nonExistentArchive)).resolves.toBeUndefined();
254
+ });
255
+ });
256
+
257
+ describe('getBlockHeaderByHash', () => {
258
+ beforeEach(async () => {
259
+ await store.addBlocks(blocks);
260
+ });
261
+
262
+ it('retrieves a block header by its hash', async () => {
263
+ const expectedBlock = blocks[7];
264
+ const blockHash = await expectedBlock.block.hash();
265
+ const retrievedHeader = await store.getBlockHeaderByHash(blockHash);
266
+
267
+ expect(retrievedHeader).toBeDefined();
268
+ expect(retrievedHeader!.equals(expectedBlock.block.getBlockHeader())).toBe(true);
269
+ });
270
+
271
+ it('returns undefined for non-existent block hash', async () => {
272
+ const nonExistentHash = Fr.random();
273
+ await expect(store.getBlockHeaderByHash(nonExistentHash)).resolves.toBeUndefined();
274
+ });
275
+ });
276
+
277
+ describe('getBlockHeaderByArchive', () => {
278
+ beforeEach(async () => {
279
+ await store.addBlocks(blocks);
280
+ });
281
+
282
+ it('retrieves a block header by its archive root', async () => {
283
+ const expectedBlock = blocks[2];
284
+ const archive = expectedBlock.block.archive.root;
285
+ const retrievedHeader = await store.getBlockHeaderByArchive(archive);
286
+
287
+ expect(retrievedHeader).toBeDefined();
288
+ expect(retrievedHeader!.equals(expectedBlock.block.getBlockHeader())).toBe(true);
289
+ });
290
+
291
+ it('returns undefined for non-existent archive root', async () => {
292
+ const nonExistentArchive = Fr.random();
293
+ await expect(store.getBlockHeaderByArchive(nonExistentArchive)).resolves.toBeUndefined();
171
294
  });
172
295
  });
173
296
 
@@ -229,36 +352,19 @@ export function describeArchiverDataStore(
229
352
  });
230
353
  });
231
354
 
232
- describe('deleteLogs', () => {
233
- it('deletes private & public logs', async () => {
234
- const block = blocks[0].block;
235
- await store.addBlocks([blocks[0]]);
236
- await expect(store.addLogs([block])).resolves.toEqual(true);
355
+ it('deleteLogs', async () => {
356
+ const block = blocks[0].block;
357
+ await store.addBlocks([blocks[0]]);
358
+ await expect(store.addLogs([block])).resolves.toEqual(true);
237
359
 
238
- expect((await store.getPrivateLogs(1, 1)).length).toEqual(
239
- block.body.txEffects.map(txEffect => txEffect.privateLogs).flat().length,
240
- );
241
- expect((await store.getPublicLogs({ fromBlock: 1 })).logs.length).toEqual(
242
- block.body.txEffects.map(txEffect => txEffect.publicLogs).flat().length,
243
- );
360
+ expect((await store.getPublicLogs({ fromBlock: BlockNumber(1) })).logs.length).toEqual(
361
+ block.body.txEffects.map(txEffect => txEffect.publicLogs).flat().length,
362
+ );
244
363
 
245
- // This one is a pain for memory as we would never want to just delete memory in the middle.
246
- await store.deleteLogs([block]);
364
+ // This one is a pain for memory as we would never want to just delete memory in the middle.
365
+ await store.deleteLogs([block]);
247
366
 
248
- expect((await store.getPrivateLogs(1, 1)).length).toEqual(0);
249
- expect((await store.getPublicLogs({ fromBlock: 1 })).logs.length).toEqual(0);
250
- });
251
- });
252
-
253
- describe('getPrivateLogs', () => {
254
- it('gets added private logs', async () => {
255
- const block = blocks[0].block;
256
- await store.addBlocks([blocks[0]]);
257
- await store.addLogs([block]);
258
-
259
- const privateLogs = await store.getPrivateLogs(1, 1);
260
- expect(privateLogs).toEqual(block.body.txEffects.map(txEffect => txEffect.privateLogs).flat());
261
- });
367
+ expect((await store.getPublicLogs({ fromBlock: BlockNumber(1) })).logs.length).toEqual(0);
262
368
  });
263
369
 
264
370
  describe('getTxEffect', () => {
@@ -290,13 +396,13 @@ export function describeArchiverDataStore(
290
396
  });
291
397
 
292
398
  it.each([
293
- () => wrapInBlock(blocks[0].block.body.txEffects[0], blocks[0].block),
294
- () => wrapInBlock(blocks[9].block.body.txEffects[3], blocks[9].block),
295
- () => wrapInBlock(blocks[3].block.body.txEffects[1], blocks[3].block),
296
- () => wrapInBlock(blocks[5].block.body.txEffects[2], blocks[5].block),
297
- () => wrapInBlock(blocks[1].block.body.txEffects[0], blocks[1].block),
399
+ () => wrapDataInBlock(blocks[0].block.body.txEffects[0], blocks[0].block),
400
+ () => wrapDataInBlock(blocks[9].block.body.txEffects[3], blocks[9].block),
401
+ () => wrapDataInBlock(blocks[3].block.body.txEffects[1], blocks[3].block),
402
+ () => wrapDataInBlock(blocks[5].block.body.txEffects[2], blocks[5].block),
403
+ () => wrapDataInBlock(blocks[1].block.body.txEffects[0], blocks[1].block),
298
404
  ])('tries to retrieves a previously stored transaction after deleted', async getExpectedTx => {
299
- await store.unwindBlocks(blocks.length, blocks.length);
405
+ await store.unwindBlocks(BlockNumber(blocks.length), blocks.length);
300
406
 
301
407
  const expectedTx = await getExpectedTx();
302
408
  const actualTx = await store.getTxEffect(expectedTx.data.txHash);
@@ -308,7 +414,7 @@ export function describeArchiverDataStore(
308
414
  });
309
415
 
310
416
  it('does not fail if the block is unwound while requesting a tx', async () => {
311
- const expectedTx = await wrapInBlock(blocks[1].block.body.txEffects[0], blocks[1].block);
417
+ const expectedTx = await wrapDataInBlock(blocks[1].block.body.txEffects[0], blocks[1].block);
312
418
  let done = false;
313
419
  void (async () => {
314
420
  while (!done) {
@@ -316,14 +422,14 @@ export function describeArchiverDataStore(
316
422
  await sleep(1);
317
423
  }
318
424
  })();
319
- await store.unwindBlocks(blocks.length, blocks.length);
425
+ await store.unwindBlocks(BlockNumber(blocks.length), blocks.length);
320
426
  done = true;
321
427
  expect(await store.getTxEffect(expectedTx.data.txHash)).toEqual(undefined);
322
428
  });
323
429
  });
324
430
 
325
431
  describe('L1 to L2 Messages', () => {
326
- const initialL2BlockNumber = 13;
432
+ const initialCheckpointNumber = CheckpointNumber(13);
327
433
 
328
434
  const checkMessages = async (msgs: InboxMessage[]) => {
329
435
  expect(await store.getLastL1ToL2Message()).toEqual(msgs.at(-1));
@@ -331,43 +437,50 @@ export function describeArchiverDataStore(
331
437
  expect(await store.getTotalL1ToL2MessageCount()).toEqual(BigInt(msgs.length));
332
438
  };
333
439
 
334
- const makeInboxMessagesWithFullBlocks = (blockCount: number, opts: { initialL2BlockNumber?: number } = {}) =>
440
+ const makeInboxMessagesWithFullBlocks = (
441
+ blockCount: number,
442
+ opts: { initialCheckpointNumber?: CheckpointNumber } = {},
443
+ ) =>
335
444
  makeInboxMessages(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP * blockCount, {
336
445
  overrideFn: (msg, i) => {
337
- const l2BlockNumber =
338
- (opts.initialL2BlockNumber ?? initialL2BlockNumber) + Math.floor(i / NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP);
446
+ const checkpointNumber = CheckpointNumber(
447
+ (opts.initialCheckpointNumber ?? initialCheckpointNumber) +
448
+ Math.floor(i / NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP),
449
+ );
339
450
  const index =
340
- InboxLeaf.smallestIndexFromL2Block(l2BlockNumber) + BigInt(i % NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP);
341
- return { ...msg, l2BlockNumber, index };
451
+ InboxLeaf.smallestIndexForCheckpoint(checkpointNumber) + BigInt(i % NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP);
452
+ return { ...msg, checkpointNumber, index };
342
453
  },
343
454
  });
344
455
 
345
456
  it('stores first message ever', async () => {
346
- const msg = makeInboxMessage(Buffer16.ZERO, { index: 0n, l2BlockNumber: 1 });
457
+ const msg = makeInboxMessage(Buffer16.ZERO, { index: 0n, checkpointNumber: CheckpointNumber(1) });
347
458
  await store.addL1ToL2Messages([msg]);
348
459
 
349
460
  await checkMessages([msg]);
350
- expect(await store.getL1ToL2Messages(1)).toEqual([msg.leaf]);
461
+ expect(await store.getL1ToL2Messages(CheckpointNumber(1))).toEqual([msg.leaf]);
351
462
  });
352
463
 
353
464
  it('stores single message', async () => {
354
- const msg = makeInboxMessage(Buffer16.ZERO, { l2BlockNumber: 2 });
465
+ const msg = makeInboxMessage(Buffer16.ZERO, { checkpointNumber: CheckpointNumber(2) });
355
466
  await store.addL1ToL2Messages([msg]);
356
467
 
357
468
  await checkMessages([msg]);
358
- expect(await store.getL1ToL2Messages(2)).toEqual([msg.leaf]);
469
+ expect(await store.getL1ToL2Messages(CheckpointNumber(2))).toEqual([msg.leaf]);
359
470
  });
360
471
 
361
472
  it('stores and returns messages across different blocks', async () => {
362
- const msgs = makeInboxMessages(5, { initialL2BlockNumber });
473
+ const msgs = makeInboxMessages(5, { initialCheckpointNumber });
363
474
  await store.addL1ToL2Messages(msgs);
364
475
 
365
476
  await checkMessages(msgs);
366
- expect(await store.getL1ToL2Messages(initialL2BlockNumber + 2)).toEqual([msgs[2]].map(m => m.leaf));
477
+ expect(await store.getL1ToL2Messages(CheckpointNumber(initialCheckpointNumber + 2))).toEqual(
478
+ [msgs[2]].map(m => m.leaf),
479
+ );
367
480
  });
368
481
 
369
482
  it('stores the same messages again', async () => {
370
- const msgs = makeInboxMessages(5, { initialL2BlockNumber });
483
+ const msgs = makeInboxMessages(5, { initialCheckpointNumber });
371
484
  await store.addL1ToL2Messages(msgs);
372
485
  await store.addL1ToL2Messages(msgs.slice(2));
373
486
 
@@ -375,26 +488,29 @@ export function describeArchiverDataStore(
375
488
  });
376
489
 
377
490
  it('stores and returns messages across different blocks with gaps', async () => {
378
- const msgs1 = makeInboxMessages(3, { initialL2BlockNumber: 1 });
379
- const msgs2 = makeInboxMessages(3, { initialL2BlockNumber: 20, initialHash: msgs1.at(-1)!.rollingHash });
491
+ const msgs1 = makeInboxMessages(3, { initialCheckpointNumber: CheckpointNumber(1) });
492
+ const msgs2 = makeInboxMessages(3, {
493
+ initialCheckpointNumber: CheckpointNumber(20),
494
+ initialHash: msgs1.at(-1)!.rollingHash,
495
+ });
380
496
 
381
497
  await store.addL1ToL2Messages(msgs1);
382
498
  await store.addL1ToL2Messages(msgs2);
383
499
 
384
500
  await checkMessages([...msgs1, ...msgs2]);
385
501
 
386
- expect(await store.getL1ToL2Messages(1)).toEqual([msgs1[0].leaf]);
387
- expect(await store.getL1ToL2Messages(4)).toEqual([]);
388
- expect(await store.getL1ToL2Messages(20)).toEqual([msgs2[0].leaf]);
389
- expect(await store.getL1ToL2Messages(24)).toEqual([]);
502
+ expect(await store.getL1ToL2Messages(CheckpointNumber(1))).toEqual([msgs1[0].leaf]);
503
+ expect(await store.getL1ToL2Messages(CheckpointNumber(4))).toEqual([]);
504
+ expect(await store.getL1ToL2Messages(CheckpointNumber(20))).toEqual([msgs2[0].leaf]);
505
+ expect(await store.getL1ToL2Messages(CheckpointNumber(24))).toEqual([]);
390
506
  });
391
507
 
392
508
  it('stores and returns messages with block numbers larger than a byte', async () => {
393
- const msgs = makeInboxMessages(5, { initialL2BlockNumber: 1000 });
509
+ const msgs = makeInboxMessages(5, { initialCheckpointNumber: CheckpointNumber(1000) });
394
510
  await store.addL1ToL2Messages(msgs);
395
511
 
396
512
  await checkMessages(msgs);
397
- expect(await store.getL1ToL2Messages(1002)).toEqual([msgs[2]].map(m => m.leaf));
513
+ expect(await store.getL1ToL2Messages(CheckpointNumber(1002))).toEqual([msgs[2]].map(m => m.leaf));
398
514
  });
399
515
 
400
516
  it('stores and returns multiple messages per block', async () => {
@@ -402,7 +518,7 @@ export function describeArchiverDataStore(
402
518
  await store.addL1ToL2Messages(msgs);
403
519
 
404
520
  await checkMessages(msgs);
405
- const blockMessages = await store.getL1ToL2Messages(initialL2BlockNumber + 1);
521
+ const blockMessages = await store.getL1ToL2Messages(CheckpointNumber(initialCheckpointNumber + 1));
406
522
  expect(blockMessages).toHaveLength(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP);
407
523
  expect(blockMessages).toEqual(
408
524
  msgs.slice(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP * 2).map(m => m.leaf),
@@ -410,17 +526,21 @@ export function describeArchiverDataStore(
410
526
  });
411
527
 
412
528
  it('stores messages in multiple operations', async () => {
413
- const msgs = makeInboxMessages(20, { initialL2BlockNumber });
529
+ const msgs = makeInboxMessages(20, { initialCheckpointNumber });
414
530
  await store.addL1ToL2Messages(msgs.slice(0, 10));
415
531
  await store.addL1ToL2Messages(msgs.slice(10, 20));
416
532
 
417
- expect(await store.getL1ToL2Messages(initialL2BlockNumber + 2)).toEqual([msgs[2]].map(m => m.leaf));
418
- expect(await store.getL1ToL2Messages(initialL2BlockNumber + 12)).toEqual([msgs[12]].map(m => m.leaf));
533
+ expect(await store.getL1ToL2Messages(CheckpointNumber(initialCheckpointNumber + 2))).toEqual(
534
+ [msgs[2]].map(m => m.leaf),
535
+ );
536
+ expect(await store.getL1ToL2Messages(CheckpointNumber(initialCheckpointNumber + 12))).toEqual(
537
+ [msgs[12]].map(m => m.leaf),
538
+ );
419
539
  await checkMessages(msgs);
420
540
  });
421
541
 
422
542
  it('iterates over messages from start index', async () => {
423
- const msgs = makeInboxMessages(10, { initialL2BlockNumber });
543
+ const msgs = makeInboxMessages(10, { initialCheckpointNumber });
424
544
  await store.addL1ToL2Messages(msgs);
425
545
 
426
546
  const iterated = await toArray(store.iterateL1ToL2Messages({ start: msgs[3].index }));
@@ -428,8 +548,9 @@ export function describeArchiverDataStore(
428
548
  });
429
549
 
430
550
  it('iterates over messages in reverse', async () => {
431
- const msgs = makeInboxMessages(10, { initialL2BlockNumber });
551
+ const msgs = makeInboxMessages(10, { initialCheckpointNumber });
432
552
  await store.addL1ToL2Messages(msgs);
553
+ initialCheckpointNumber;
433
554
 
434
555
  const iterated = await toArray(store.iterateL1ToL2Messages({ reverse: true, end: msgs[3].index }));
435
556
  expect(iterated).toEqual(msgs.slice(0, 4).reverse());
@@ -441,8 +562,8 @@ export function describeArchiverDataStore(
441
562
  });
442
563
 
443
564
  it('throws if block number for the first message is out of order', async () => {
444
- const msgs = makeInboxMessages(4, { initialL2BlockNumber });
445
- msgs[2].l2BlockNumber = initialL2BlockNumber - 1;
565
+ const msgs = makeInboxMessages(4, { initialCheckpointNumber });
566
+ msgs[2].checkpointNumber = CheckpointNumber(initialCheckpointNumber - 1);
446
567
  await store.addL1ToL2Messages(msgs.slice(0, 2));
447
568
  await expect(store.addL1ToL2Messages(msgs.slice(2, 4))).rejects.toThrow(MessageStoreError);
448
569
  });
@@ -456,28 +577,28 @@ export function describeArchiverDataStore(
456
577
  it('throws if rolling hash for first message is not correct', async () => {
457
578
  const msgs = makeInboxMessages(4);
458
579
  msgs[2].rollingHash = Buffer16.random();
459
- await store.addL1ToL2Messages(msgs.slice(0, 2));
580
+ await store.addL1ToL2Messages(msgs.slice(0, CheckpointNumber(2)));
460
581
  await expect(store.addL1ToL2Messages(msgs.slice(2, 4))).rejects.toThrow(MessageStoreError);
461
582
  });
462
583
 
463
584
  it('throws if index is not in the correct range', async () => {
464
- const msgs = makeInboxMessages(5, { initialL2BlockNumber });
585
+ const msgs = makeInboxMessages(5, { initialCheckpointNumber });
465
586
  msgs.at(-1)!.index += 100n;
466
587
  await expect(store.addL1ToL2Messages(msgs)).rejects.toThrow(MessageStoreError);
467
588
  });
468
589
 
469
590
  it('throws if first index in block has gaps', async () => {
470
- const msgs = makeInboxMessages(4, { initialL2BlockNumber });
591
+ const msgs = makeInboxMessages(4, { initialCheckpointNumber });
471
592
  msgs[2].index++;
472
593
  await expect(store.addL1ToL2Messages(msgs)).rejects.toThrow(MessageStoreError);
473
594
  });
474
595
 
475
596
  it('throws if index does not follow previous one', async () => {
476
597
  const msgs = makeInboxMessages(2, {
477
- initialL2BlockNumber,
598
+ initialCheckpointNumber,
478
599
  overrideFn: (msg, i) => ({
479
600
  ...msg,
480
- l2BlockNumber: 2,
601
+ checkpointNumber: CheckpointNumber(2),
481
602
  index: BigInt(i + NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP * 2),
482
603
  }),
483
604
  });
@@ -486,28 +607,28 @@ export function describeArchiverDataStore(
486
607
  });
487
608
 
488
609
  it('removes messages up to the given block number', async () => {
489
- const msgs = makeInboxMessagesWithFullBlocks(4, { initialL2BlockNumber: 1 });
610
+ const msgs = makeInboxMessagesWithFullBlocks(4, { initialCheckpointNumber: CheckpointNumber(1) });
490
611
 
491
612
  await store.addL1ToL2Messages(msgs);
492
613
  await checkMessages(msgs);
493
614
 
494
- expect(await store.getL1ToL2Messages(1)).toHaveLength(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP);
495
- expect(await store.getL1ToL2Messages(2)).toHaveLength(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP);
496
- expect(await store.getL1ToL2Messages(3)).toHaveLength(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP);
497
- expect(await store.getL1ToL2Messages(4)).toHaveLength(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP);
615
+ expect(await store.getL1ToL2Messages(CheckpointNumber(1))).toHaveLength(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP);
616
+ expect(await store.getL1ToL2Messages(CheckpointNumber(2))).toHaveLength(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP);
617
+ expect(await store.getL1ToL2Messages(CheckpointNumber(3))).toHaveLength(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP);
618
+ expect(await store.getL1ToL2Messages(CheckpointNumber(4))).toHaveLength(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP);
498
619
 
499
- await store.rollbackL1ToL2MessagesToL2Block(2);
620
+ await store.rollbackL1ToL2MessagesToCheckpoint(CheckpointNumber(2));
500
621
 
501
- expect(await store.getL1ToL2Messages(1)).toHaveLength(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP);
502
- expect(await store.getL1ToL2Messages(2)).toHaveLength(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP);
503
- expect(await store.getL1ToL2Messages(3)).toHaveLength(0);
504
- expect(await store.getL1ToL2Messages(4)).toHaveLength(0);
622
+ expect(await store.getL1ToL2Messages(CheckpointNumber(1))).toHaveLength(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP);
623
+ expect(await store.getL1ToL2Messages(CheckpointNumber(2))).toHaveLength(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP);
624
+ expect(await store.getL1ToL2Messages(CheckpointNumber(3))).toHaveLength(0);
625
+ expect(await store.getL1ToL2Messages(CheckpointNumber(4))).toHaveLength(0);
505
626
 
506
627
  await checkMessages(msgs.slice(0, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP * 2));
507
628
  });
508
629
 
509
630
  it('removes messages starting with the given index', async () => {
510
- const msgs = makeInboxMessagesWithFullBlocks(4, { initialL2BlockNumber: 1 });
631
+ const msgs = makeInboxMessagesWithFullBlocks(4, { initialCheckpointNumber: CheckpointNumber(1) });
511
632
  await store.addL1ToL2Messages(msgs);
512
633
 
513
634
  await store.removeL1ToL2Messages(msgs[13].index);
@@ -527,7 +648,7 @@ export function describeArchiverDataStore(
527
648
  originalContractClassId: classId,
528
649
  });
529
650
  contractInstance = { ...randomInstance, address: await AztecAddress.random() };
530
- await store.addContractInstances([contractInstance], blockNum);
651
+ await store.addContractInstances([contractInstance], BlockNumber(blockNum));
531
652
  });
532
653
 
533
654
  it('returns previously stored contract instances', async () => {
@@ -541,7 +662,7 @@ export function describeArchiverDataStore(
541
662
  });
542
663
 
543
664
  it('returns undefined if previously stored contract instances was deleted', async () => {
544
- await store.deleteContractInstances([contractInstance], blockNum);
665
+ await store.deleteContractInstances([contractInstance], BlockNumber(blockNum));
545
666
  await expect(store.getContractInstance(contractInstance.address, timestamp)).resolves.toBeUndefined();
546
667
  });
547
668
  });
@@ -560,7 +681,7 @@ export function describeArchiverDataStore(
560
681
  originalContractClassId: classId,
561
682
  });
562
683
  contractInstance = { ...randomInstance, address: await AztecAddress.random() };
563
- await store.addContractInstances([contractInstance], 1);
684
+ await store.addContractInstances([contractInstance], BlockNumber(1));
564
685
  await store.addContractInstanceUpdates(
565
686
  [
566
687
  {
@@ -602,7 +723,7 @@ export function describeArchiverDataStore(
602
723
  ...randomInstance,
603
724
  address: await AztecAddress.random(),
604
725
  };
605
- await store.addContractInstances([otherContractInstance], 1);
726
+ await store.addContractInstances([otherContractInstance], BlockNumber(1));
606
727
 
607
728
  const fetchedInstance = await store.getContractInstance(otherContractInstance.address, timestampOfChange + 1n);
608
729
  expect(fetchedInstance?.originalContractClassId).toEqual(otherClassId);
@@ -620,7 +741,7 @@ export function describeArchiverDataStore(
620
741
  ...randomInstance,
621
742
  address: await AztecAddress.random(),
622
743
  };
623
- await store.addContractInstances([otherContractInstance], 1);
744
+ await store.addContractInstances([otherContractInstance], BlockNumber(1));
624
745
  await store.addContractInstanceUpdates(
625
746
  [
626
747
  {
@@ -648,7 +769,7 @@ export function describeArchiverDataStore(
648
769
  await store.addContractClasses(
649
770
  [contractClass],
650
771
  [await computePublicBytecodeCommitment(contractClass.packedBytecode)],
651
- blockNum,
772
+ BlockNumber(blockNum),
652
773
  );
653
774
  });
654
775
 
@@ -657,7 +778,7 @@ export function describeArchiverDataStore(
657
778
  });
658
779
 
659
780
  it('returns undefined if the initial deployed contract class was deleted', async () => {
660
- await store.deleteContractClasses([contractClass], blockNum);
781
+ await store.deleteContractClasses([contractClass], BlockNumber(blockNum));
661
782
  await expect(store.getContractClass(contractClass.id)).resolves.toBeUndefined();
662
783
  });
663
784
 
@@ -665,9 +786,9 @@ export function describeArchiverDataStore(
665
786
  await store.addContractClasses(
666
787
  [contractClass],
667
788
  [await computePublicBytecodeCommitment(contractClass.packedBytecode)],
668
- blockNum + 1,
789
+ BlockNumber(blockNum + 1),
669
790
  );
670
- await store.deleteContractClasses([contractClass], blockNum + 1);
791
+ await store.deleteContractClasses([contractClass], BlockNumber(blockNum + 1));
671
792
  await expect(store.getContractClass(contractClass.id)).resolves.toMatchObject(contractClass);
672
793
  });
673
794
 
@@ -728,8 +849,8 @@ export function describeArchiverDataStore(
728
849
  const makePublicLog = (tag: Fr) =>
729
850
  PublicLog.from({
730
851
  contractAddress: AztecAddress.fromNumber(1),
731
- fields: makeTuple(PUBLIC_LOG_SIZE_IN_FIELDS, i => (!i ? tag : new Fr(tag.toNumber() + i))),
732
- emittedLength: PUBLIC_LOG_SIZE_IN_FIELDS,
852
+ // Arbitrary length
853
+ fields: new Array(10).fill(null).map((_, i) => (!i ? tag : new Fr(tag.toNumber() + i))),
733
854
  });
734
855
 
735
856
  const mockPrivateLogs = (blockNumber: number, txIndex: number) => {
@@ -747,8 +868,8 @@ export function describeArchiverDataStore(
747
868
  };
748
869
 
749
870
  const mockBlockWithLogs = async (blockNumber: number): Promise<PublishedL2Block> => {
750
- const block = await L2Block.random(blockNumber);
751
- block.header.globalVariables.blockNumber = blockNumber;
871
+ const block = await L2Block.random(BlockNumber(blockNumber));
872
+ block.header.globalVariables.blockNumber = BlockNumber(blockNumber);
752
873
 
753
874
  block.body.txEffects = await timesParallel(numTxsPerBlock, async (txIndex: number) => {
754
875
  const txEffect = await TxEffect.random();
@@ -757,7 +878,7 @@ export function describeArchiverDataStore(
757
878
  return txEffect;
758
879
  });
759
880
 
760
- return {
881
+ return PublishedL2Block.fromFields({
761
882
  block: block,
762
883
  attestations: times(3, CommitteeAttestation.random),
763
884
  l1: {
@@ -765,7 +886,7 @@ export function describeArchiverDataStore(
765
886
  blockHash: makeBlockHash(blockNumber),
766
887
  timestamp: BigInt(blockNumber),
767
888
  },
768
- };
889
+ });
769
890
  };
770
891
 
771
892
  beforeEach(async () => {
@@ -878,11 +999,13 @@ export function describeArchiverDataStore(
878
999
  let blocks: PublishedL2Block[];
879
1000
 
880
1001
  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
- }));
1002
+ blocks = await timesParallel(numBlocks, async (index: number) =>
1003
+ PublishedL2Block.fromFields({
1004
+ block: await L2Block.random(BlockNumber(index + 1), txsPerBlock, numPublicFunctionCalls, numPublicLogs),
1005
+ l1: { blockNumber: BigInt(index), blockHash: makeBlockHash(index), timestamp: BigInt(index) },
1006
+ attestations: times(3, CommitteeAttestation.random),
1007
+ }),
1008
+ );
886
1009
 
887
1010
  await store.addBlocks(blocks);
888
1011
  await store.addLogs(blocks.map(b => b.block));
@@ -895,7 +1018,7 @@ export function describeArchiverDataStore(
895
1018
  const targetTxHash = blocks[targetBlockIndex].block.body.txEffects[targetTxIndex].txHash;
896
1019
 
897
1020
  await Promise.all([
898
- store.unwindBlocks(blocks.length, blocks.length),
1021
+ store.unwindBlocks(BlockNumber(blocks.length), blocks.length),
899
1022
  store.deleteLogs(blocks.map(b => b.block)),
900
1023
  ]);
901
1024
 
@@ -970,7 +1093,7 @@ export function describeArchiverDataStore(
970
1093
  const targetTxIndex = randomInt(txsPerBlock);
971
1094
  const targetLogIndex = randomInt(numPublicLogs);
972
1095
 
973
- const afterLog = new LogId(targetBlockIndex + INITIAL_L2_BLOCK_NUM, targetTxIndex, targetLogIndex);
1096
+ const afterLog = new LogId(BlockNumber(targetBlockIndex + INITIAL_L2_BLOCK_NUM), targetTxIndex, targetLogIndex);
974
1097
 
975
1098
  const response = await store.getPublicLogs({ afterLog });
976
1099
  const logs = response.logs;
@@ -992,42 +1115,54 @@ export function describeArchiverDataStore(
992
1115
  it('"txHash" filter param is ignored when "afterLog" is set', async () => {
993
1116
  // Get random txHash
994
1117
  const txHash = TxHash.random();
995
- const afterLog = new LogId(1, 0, 0);
1118
+ const afterLog = new LogId(BlockNumber(1), 0, 0);
996
1119
 
997
1120
  const response = await store.getPublicLogs({ txHash, afterLog });
998
1121
  expect(response.logs.length).toBeGreaterThan(1);
999
1122
  });
1000
1123
 
1001
1124
  it('intersecting works', async () => {
1002
- let logs = (await store.getPublicLogs({ fromBlock: -10, toBlock: -5 })).logs;
1125
+ let logs = (await store.getPublicLogs({ fromBlock: -10 as BlockNumber, toBlock: -5 as BlockNumber })).logs;
1003
1126
  expect(logs.length).toBe(0);
1004
1127
 
1005
1128
  // "fromBlock" gets correctly trimmed to range and "toBlock" is exclusive
1006
- logs = (await store.getPublicLogs({ fromBlock: -10, toBlock: 5 })).logs;
1129
+ logs = (await store.getPublicLogs({ fromBlock: -10 as BlockNumber, toBlock: BlockNumber(5) })).logs;
1007
1130
  let blockNumbers = new Set(logs.map(log => log.id.blockNumber));
1008
1131
  expect(blockNumbers).toEqual(new Set([1, 2, 3, 4]));
1009
1132
 
1010
1133
  // "toBlock" should be exclusive
1011
- logs = (await store.getPublicLogs({ fromBlock: 1, toBlock: 1 })).logs;
1134
+ logs = (await store.getPublicLogs({ fromBlock: BlockNumber(1), toBlock: BlockNumber(1) })).logs;
1012
1135
  expect(logs.length).toBe(0);
1013
1136
 
1014
- logs = (await store.getPublicLogs({ fromBlock: 10, toBlock: 5 })).logs;
1137
+ logs = (await store.getPublicLogs({ fromBlock: BlockNumber(10), toBlock: BlockNumber(5) })).logs;
1015
1138
  expect(logs.length).toBe(0);
1016
1139
 
1017
1140
  // both "fromBlock" and "toBlock" get correctly capped to range and logs from all blocks are returned
1018
- logs = (await store.getPublicLogs({ fromBlock: -100, toBlock: +100 })).logs;
1141
+ logs = (await store.getPublicLogs({ fromBlock: -100 as BlockNumber, toBlock: +100 })).logs;
1019
1142
  blockNumbers = new Set(logs.map(log => log.id.blockNumber));
1020
1143
  expect(blockNumbers.size).toBe(numBlocks);
1021
1144
 
1022
1145
  // intersecting with "afterLog" works
1023
- logs = (await store.getPublicLogs({ fromBlock: 2, toBlock: 5, afterLog: new LogId(4, 0, 0) })).logs;
1146
+ logs = (
1147
+ await store.getPublicLogs({
1148
+ fromBlock: BlockNumber(2),
1149
+ toBlock: BlockNumber(5),
1150
+ afterLog: new LogId(BlockNumber(4), 0, 0),
1151
+ })
1152
+ ).logs;
1024
1153
  blockNumbers = new Set(logs.map(log => log.id.blockNumber));
1025
1154
  expect(blockNumbers).toEqual(new Set([4]));
1026
1155
 
1027
- logs = (await store.getPublicLogs({ toBlock: 5, afterLog: new LogId(5, 1, 0) })).logs;
1156
+ logs = (await store.getPublicLogs({ toBlock: BlockNumber(5), afterLog: new LogId(BlockNumber(5), 1, 0) })).logs;
1028
1157
  expect(logs.length).toBe(0);
1029
1158
 
1030
- logs = (await store.getPublicLogs({ fromBlock: 2, toBlock: 5, afterLog: new LogId(100, 0, 0) })).logs;
1159
+ logs = (
1160
+ await store.getPublicLogs({
1161
+ fromBlock: BlockNumber(2),
1162
+ toBlock: BlockNumber(5),
1163
+ afterLog: new LogId(BlockNumber(100), 0, 0),
1164
+ })
1165
+ ).logs;
1031
1166
  expect(logs.length).toBe(0);
1032
1167
  });
1033
1168
 
@@ -1037,7 +1172,7 @@ export function describeArchiverDataStore(
1037
1172
  const targetTxIndex = randomInt(txsPerBlock);
1038
1173
  const targetLogIndex = randomInt(numPublicLogs);
1039
1174
 
1040
- const afterLog = new LogId(targetBlockIndex + INITIAL_L2_BLOCK_NUM, targetTxIndex, targetLogIndex);
1175
+ const afterLog = new LogId(BlockNumber(targetBlockIndex + INITIAL_L2_BLOCK_NUM), targetTxIndex, targetLogIndex);
1041
1176
 
1042
1177
  const response = await store.getPublicLogs({ afterLog, fromBlock: afterLog.blockNumber });
1043
1178
  const logs = response.logs;
@@ -1056,5 +1191,96 @@ export function describeArchiverDataStore(
1056
1191
  }
1057
1192
  });
1058
1193
  });
1194
+
1195
+ describe('pendingChainValidationStatus', () => {
1196
+ it('should return undefined when no status is set', async () => {
1197
+ const status = await store.getPendingChainValidationStatus();
1198
+ expect(status).toBeUndefined();
1199
+ });
1200
+
1201
+ it('should store and retrieve a valid validation status', async () => {
1202
+ const validStatus: ValidateBlockResult = { valid: true };
1203
+
1204
+ await store.setPendingChainValidationStatus(validStatus);
1205
+ const retrievedStatus = await store.getPendingChainValidationStatus();
1206
+
1207
+ expect(retrievedStatus).toEqual(validStatus);
1208
+ });
1209
+
1210
+ it('should store and retrieve an invalid validation status with insufficient attestations', async () => {
1211
+ const invalidStatus: ValidateBlockResult = {
1212
+ valid: false,
1213
+ block: randomBlockInfo(1),
1214
+ committee: [EthAddress.random(), EthAddress.random()],
1215
+ epoch: EpochNumber(123),
1216
+ seed: 456n,
1217
+ attestors: [EthAddress.random()],
1218
+ attestations: [CommitteeAttestation.random()],
1219
+ reason: 'insufficient-attestations',
1220
+ };
1221
+
1222
+ await store.setPendingChainValidationStatus(invalidStatus);
1223
+ const retrievedStatus = await store.getPendingChainValidationStatus();
1224
+
1225
+ expect(retrievedStatus).toEqual(invalidStatus);
1226
+ });
1227
+
1228
+ it('should store and retrieve an invalid validation status with invalid attestation', async () => {
1229
+ const invalidStatus: ValidateBlockResult = {
1230
+ valid: false,
1231
+ block: randomBlockInfo(2),
1232
+ committee: [EthAddress.random()],
1233
+ attestors: [EthAddress.random()],
1234
+ epoch: EpochNumber(789),
1235
+ seed: 101n,
1236
+ attestations: [CommitteeAttestation.random()],
1237
+ reason: 'invalid-attestation',
1238
+ invalidIndex: 5,
1239
+ };
1240
+
1241
+ await store.setPendingChainValidationStatus(invalidStatus);
1242
+ const retrievedStatus = await store.getPendingChainValidationStatus();
1243
+
1244
+ expect(retrievedStatus).toEqual(invalidStatus);
1245
+ });
1246
+
1247
+ it('should overwrite existing status when setting a new one', async () => {
1248
+ const firstStatus: ValidateBlockResult = { valid: true };
1249
+ const secondStatus: ValidateBlockResult = {
1250
+ valid: false,
1251
+ block: randomBlockInfo(3),
1252
+ committee: [EthAddress.random()],
1253
+ epoch: EpochNumber(999),
1254
+ seed: 888n,
1255
+ attestors: [EthAddress.random()],
1256
+ attestations: [CommitteeAttestation.random()],
1257
+ reason: 'insufficient-attestations',
1258
+ };
1259
+
1260
+ await store.setPendingChainValidationStatus(firstStatus);
1261
+ await store.setPendingChainValidationStatus(secondStatus);
1262
+ const retrievedStatus = await store.getPendingChainValidationStatus();
1263
+
1264
+ expect(retrievedStatus).toEqual(secondStatus);
1265
+ });
1266
+
1267
+ it('should handle empty committee and attestations arrays', async () => {
1268
+ const statusWithEmptyArrays: ValidateBlockResult = {
1269
+ valid: false,
1270
+ block: randomBlockInfo(4),
1271
+ committee: [],
1272
+ epoch: EpochNumber(0),
1273
+ seed: 0n,
1274
+ attestors: [],
1275
+ attestations: [],
1276
+ reason: 'insufficient-attestations',
1277
+ };
1278
+
1279
+ await store.setPendingChainValidationStatus(statusWithEmptyArrays);
1280
+ const retrievedStatus = await store.getPendingChainValidationStatus();
1281
+
1282
+ expect(retrievedStatus).toEqual(statusWithEmptyArrays);
1283
+ });
1284
+ });
1059
1285
  });
1060
1286
  }