@aztec/archiver 0.80.0 → 0.82.0
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/dest/archiver/archiver.d.ts +8 -20
- package/dest/archiver/archiver.d.ts.map +1 -1
- package/dest/archiver/archiver.js +72 -102
- package/dest/archiver/archiver_store.d.ts +5 -19
- package/dest/archiver/archiver_store.d.ts.map +1 -1
- package/dest/archiver/archiver_store_test_suite.d.ts.map +1 -1
- package/dest/archiver/archiver_store_test_suite.js +105 -142
- package/dest/archiver/config.d.ts +2 -0
- package/dest/archiver/config.d.ts.map +1 -1
- package/dest/archiver/config.js +5 -0
- package/dest/archiver/data_retrieval.d.ts +3 -4
- package/dest/archiver/data_retrieval.d.ts.map +1 -1
- package/dest/archiver/data_retrieval.js +8 -3
- package/dest/archiver/index.d.ts +1 -2
- package/dest/archiver/index.d.ts.map +1 -1
- package/dest/archiver/index.js +0 -1
- package/dest/archiver/kv_archiver_store/block_store.d.ts +6 -6
- package/dest/archiver/kv_archiver_store/block_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/block_store.js +24 -21
- package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts +6 -14
- package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/kv_archiver_store.js +2 -19
- package/dest/archiver/kv_archiver_store/log_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/log_store.js +11 -42
- package/dest/archiver/structs/published.d.ts +1 -10
- package/dest/archiver/structs/published.d.ts.map +1 -1
- package/dest/archiver/structs/published.js +1 -1
- package/dest/factory.d.ts +1 -1
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +6 -24
- package/dest/test/mock_l2_block_source.d.ts +10 -0
- package/dest/test/mock_l2_block_source.d.ts.map +1 -1
- package/dest/test/mock_l2_block_source.js +16 -0
- package/package.json +12 -13
- package/src/archiver/archiver.ts +86 -124
- package/src/archiver/archiver_store.ts +5 -21
- package/src/archiver/archiver_store_test_suite.ts +116 -147
- package/src/archiver/config.ts +8 -0
- package/src/archiver/data_retrieval.ts +12 -11
- package/src/archiver/index.ts +1 -2
- package/src/archiver/kv_archiver_store/block_store.ts +28 -27
- package/src/archiver/kv_archiver_store/kv_archiver_store.ts +6 -27
- package/src/archiver/kv_archiver_store/log_store.ts +12 -59
- package/src/archiver/structs/published.ts +1 -11
- package/src/factory.ts +3 -28
- package/src/test/mock_l2_block_source.ts +18 -0
- package/dest/archiver/kv_archiver_store/nullifier_store.d.ts +0 -12
- package/dest/archiver/kv_archiver_store/nullifier_store.d.ts.map +0 -1
- package/dest/archiver/kv_archiver_store/nullifier_store.js +0 -73
- package/dest/archiver/memory_archiver_store/memory_archiver_store.d.ts +0 -175
- package/dest/archiver/memory_archiver_store/memory_archiver_store.d.ts.map +0 -1
- package/dest/archiver/memory_archiver_store/memory_archiver_store.js +0 -636
- package/src/archiver/kv_archiver_store/nullifier_store.ts +0 -97
- package/src/archiver/memory_archiver_store/memory_archiver_store.ts +0 -801
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
INITIAL_L2_BLOCK_NUM,
|
|
3
3
|
L1_TO_L2_MSG_SUBTREE_HEIGHT,
|
|
4
|
-
MAX_NULLIFIERS_PER_TX,
|
|
5
4
|
PRIVATE_LOG_SIZE_IN_FIELDS,
|
|
6
5
|
PUBLIC_LOG_DATA_SIZE_IN_FIELDS,
|
|
7
6
|
} from '@aztec/constants';
|
|
8
7
|
import { times, timesParallel } from '@aztec/foundation/collection';
|
|
9
8
|
import { randomInt } from '@aztec/foundation/crypto';
|
|
9
|
+
import { Signature } from '@aztec/foundation/eth-signature';
|
|
10
10
|
import { Fr } from '@aztec/foundation/fields';
|
|
11
11
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
12
12
|
import { L2Block, wrapInBlock } from '@aztec/stdlib/block';
|
|
@@ -27,7 +27,7 @@ import '@aztec/stdlib/testing/jest';
|
|
|
27
27
|
import { TxEffect, TxHash } from '@aztec/stdlib/tx';
|
|
28
28
|
|
|
29
29
|
import type { ArchiverDataStore, ArchiverL1SynchPoint } from './archiver_store.js';
|
|
30
|
-
import type {
|
|
30
|
+
import type { PublishedL2Block } from './structs/published.js';
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
33
|
* @param testName - The name of the test suite.
|
|
@@ -39,8 +39,9 @@ export function describeArchiverDataStore(
|
|
|
39
39
|
) {
|
|
40
40
|
describe(testName, () => {
|
|
41
41
|
let store: ArchiverDataStore;
|
|
42
|
-
let blocks:
|
|
43
|
-
|
|
42
|
+
let blocks: PublishedL2Block[];
|
|
43
|
+
|
|
44
|
+
const blockTests: [number, number, () => PublishedL2Block[]][] = [
|
|
44
45
|
[1, 1, () => blocks.slice(0, 1)],
|
|
45
46
|
[10, 1, () => blocks.slice(9, 10)],
|
|
46
47
|
[1, 10, () => blocks.slice(0, 10)],
|
|
@@ -48,18 +49,30 @@ export function describeArchiverDataStore(
|
|
|
48
49
|
[5, 2, () => blocks.slice(4, 6)],
|
|
49
50
|
];
|
|
50
51
|
|
|
51
|
-
const
|
|
52
|
-
|
|
52
|
+
const makePublished = (block: L2Block, l1BlockNumber: number): PublishedL2Block => ({
|
|
53
|
+
block: block,
|
|
53
54
|
l1: {
|
|
54
55
|
blockNumber: BigInt(l1BlockNumber),
|
|
55
56
|
blockHash: `0x${l1BlockNumber}`,
|
|
56
57
|
timestamp: BigInt(l1BlockNumber * 1000),
|
|
57
58
|
},
|
|
59
|
+
signatures: times(3, Signature.random),
|
|
58
60
|
});
|
|
59
61
|
|
|
62
|
+
const expectBlocksEqual = (actual: PublishedL2Block[], expected: PublishedL2Block[]) => {
|
|
63
|
+
expect(actual.length).toEqual(expected.length);
|
|
64
|
+
for (let i = 0; i < expected.length; i++) {
|
|
65
|
+
const expectedBlock = expected[i];
|
|
66
|
+
const actualBlock = actual[i];
|
|
67
|
+
expect(actualBlock.l1).toEqual(expectedBlock.l1);
|
|
68
|
+
expect(actualBlock.block.equals(expectedBlock.block)).toBe(true);
|
|
69
|
+
expect(actualBlock.signatures.every((s, i) => s.equals(expectedBlock.signatures[i]))).toBe(true);
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
|
|
60
73
|
beforeEach(async () => {
|
|
61
74
|
store = await getStore();
|
|
62
|
-
blocks = await timesParallel(10, async i =>
|
|
75
|
+
blocks = await timesParallel(10, async i => makePublished(await L2Block.random(i + 1), i + 10));
|
|
63
76
|
});
|
|
64
77
|
|
|
65
78
|
describe('addBlocks', () => {
|
|
@@ -78,7 +91,7 @@ export function describeArchiverDataStore(
|
|
|
78
91
|
await store.addBlocks(blocks);
|
|
79
92
|
const blockNumber = await store.getSynchedL2BlockNumber();
|
|
80
93
|
|
|
81
|
-
|
|
94
|
+
expectBlocksEqual(await store.getBlocks(blockNumber, 1), [blocks[blocks.length - 1]]);
|
|
82
95
|
|
|
83
96
|
await store.unwindBlocks(blockNumber, 1);
|
|
84
97
|
|
|
@@ -87,13 +100,13 @@ export function describeArchiverDataStore(
|
|
|
87
100
|
});
|
|
88
101
|
|
|
89
102
|
it('can unwind multiple empty blocks', async () => {
|
|
90
|
-
const emptyBlocks = await timesParallel(10, async i =>
|
|
103
|
+
const emptyBlocks = await timesParallel(10, async i => makePublished(await L2Block.random(i + 1, 0), i + 10));
|
|
91
104
|
await store.addBlocks(emptyBlocks);
|
|
92
105
|
expect(await store.getSynchedL2BlockNumber()).toBe(10);
|
|
93
106
|
|
|
94
107
|
await store.unwindBlocks(10, 3);
|
|
95
108
|
expect(await store.getSynchedL2BlockNumber()).toBe(7);
|
|
96
|
-
expect((await store.getBlocks(1, 10)).map(b => b.
|
|
109
|
+
expect((await store.getBlocks(1, 10)).map(b => b.block.number)).toEqual([1, 2, 3, 4, 5, 6, 7]);
|
|
97
110
|
});
|
|
98
111
|
|
|
99
112
|
it('refuses to unwind blocks if the tip is not the last block', async () => {
|
|
@@ -108,7 +121,7 @@ export function describeArchiverDataStore(
|
|
|
108
121
|
});
|
|
109
122
|
|
|
110
123
|
it.each(blockTests)('retrieves previously stored blocks', async (start, limit, getExpectedBlocks) => {
|
|
111
|
-
await
|
|
124
|
+
expectBlocksEqual(await store.getBlocks(start, limit), getExpectedBlocks());
|
|
112
125
|
});
|
|
113
126
|
|
|
114
127
|
it('returns an empty array if no blocks are found', async () => {
|
|
@@ -131,7 +144,7 @@ export function describeArchiverDataStore(
|
|
|
131
144
|
|
|
132
145
|
it("returns the most recently added block's number", async () => {
|
|
133
146
|
await store.addBlocks(blocks);
|
|
134
|
-
await expect(store.getSynchedL2BlockNumber()).resolves.toEqual(blocks.at(-1)!.
|
|
147
|
+
await expect(store.getSynchedL2BlockNumber()).resolves.toEqual(blocks.at(-1)!.block.number);
|
|
135
148
|
});
|
|
136
149
|
});
|
|
137
150
|
|
|
@@ -165,14 +178,14 @@ export function describeArchiverDataStore(
|
|
|
165
178
|
|
|
166
179
|
describe('addLogs', () => {
|
|
167
180
|
it('adds private & public logs', async () => {
|
|
168
|
-
const block = blocks[0].
|
|
181
|
+
const block = blocks[0].block;
|
|
169
182
|
await expect(store.addLogs([block])).resolves.toEqual(true);
|
|
170
183
|
});
|
|
171
184
|
});
|
|
172
185
|
|
|
173
186
|
describe('deleteLogs', () => {
|
|
174
187
|
it('deletes private & public logs', async () => {
|
|
175
|
-
const block = blocks[0].
|
|
188
|
+
const block = blocks[0].block;
|
|
176
189
|
await store.addBlocks([blocks[0]]);
|
|
177
190
|
await expect(store.addLogs([block])).resolves.toEqual(true);
|
|
178
191
|
|
|
@@ -193,7 +206,7 @@ export function describeArchiverDataStore(
|
|
|
193
206
|
|
|
194
207
|
describe('getPrivateLogs', () => {
|
|
195
208
|
it('gets added private logs', async () => {
|
|
196
|
-
const block = blocks[0].
|
|
209
|
+
const block = blocks[0].block;
|
|
197
210
|
await store.addBlocks([blocks[0]]);
|
|
198
211
|
await store.addLogs([block]);
|
|
199
212
|
|
|
@@ -204,16 +217,16 @@ export function describeArchiverDataStore(
|
|
|
204
217
|
|
|
205
218
|
describe('getTxEffect', () => {
|
|
206
219
|
beforeEach(async () => {
|
|
207
|
-
await store.addLogs(blocks.map(b => b.
|
|
220
|
+
await store.addLogs(blocks.map(b => b.block));
|
|
208
221
|
await store.addBlocks(blocks);
|
|
209
222
|
});
|
|
210
223
|
|
|
211
224
|
it.each([
|
|
212
|
-
() => wrapInBlock(blocks[0].
|
|
213
|
-
() => wrapInBlock(blocks[9].
|
|
214
|
-
() => wrapInBlock(blocks[3].
|
|
215
|
-
() => wrapInBlock(blocks[5].
|
|
216
|
-
() => wrapInBlock(blocks[1].
|
|
225
|
+
() => wrapInBlock(blocks[0].block.body.txEffects[0], blocks[0].block),
|
|
226
|
+
() => wrapInBlock(blocks[9].block.body.txEffects[3], blocks[9].block),
|
|
227
|
+
() => wrapInBlock(blocks[3].block.body.txEffects[1], blocks[3].block),
|
|
228
|
+
() => wrapInBlock(blocks[5].block.body.txEffects[2], blocks[5].block),
|
|
229
|
+
() => wrapInBlock(blocks[1].block.body.txEffects[0], blocks[1].block),
|
|
217
230
|
])('retrieves a previously stored transaction', async getExpectedTx => {
|
|
218
231
|
const expectedTx = await getExpectedTx();
|
|
219
232
|
const actualTx = await store.getTxEffect(expectedTx.data.txHash);
|
|
@@ -225,11 +238,11 @@ export function describeArchiverDataStore(
|
|
|
225
238
|
});
|
|
226
239
|
|
|
227
240
|
it.each([
|
|
228
|
-
() => wrapInBlock(blocks[0].
|
|
229
|
-
() => wrapInBlock(blocks[9].
|
|
230
|
-
() => wrapInBlock(blocks[3].
|
|
231
|
-
() => wrapInBlock(blocks[5].
|
|
232
|
-
() => wrapInBlock(blocks[1].
|
|
241
|
+
() => wrapInBlock(blocks[0].block.body.txEffects[0], blocks[0].block),
|
|
242
|
+
() => wrapInBlock(blocks[9].block.body.txEffects[3], blocks[9].block),
|
|
243
|
+
() => wrapInBlock(blocks[3].block.body.txEffects[1], blocks[3].block),
|
|
244
|
+
() => wrapInBlock(blocks[5].block.body.txEffects[2], blocks[5].block),
|
|
245
|
+
() => wrapInBlock(blocks[1].block.body.txEffects[0], blocks[1].block),
|
|
233
246
|
])('tries to retrieves a previously stored transaction after deleted', async getExpectedTx => {
|
|
234
247
|
await store.unwindBlocks(blocks.length, blocks.length);
|
|
235
248
|
|
|
@@ -292,16 +305,65 @@ export function describeArchiverDataStore(
|
|
|
292
305
|
});
|
|
293
306
|
|
|
294
307
|
it('returns previously stored contract instances', async () => {
|
|
295
|
-
await expect(store.getContractInstance(contractInstance.address)).resolves.toMatchObject(
|
|
308
|
+
await expect(store.getContractInstance(contractInstance.address, blockNum)).resolves.toMatchObject(
|
|
309
|
+
contractInstance,
|
|
310
|
+
);
|
|
296
311
|
});
|
|
297
312
|
|
|
298
313
|
it('returns undefined if contract instance is not found', async () => {
|
|
299
|
-
await expect(store.getContractInstance(await AztecAddress.random())).resolves.toBeUndefined();
|
|
314
|
+
await expect(store.getContractInstance(await AztecAddress.random(), blockNum)).resolves.toBeUndefined();
|
|
300
315
|
});
|
|
301
316
|
|
|
302
317
|
it('returns undefined if previously stored contract instances was deleted', async () => {
|
|
303
318
|
await store.deleteContractInstances([contractInstance], blockNum);
|
|
304
|
-
await expect(store.getContractInstance(contractInstance.address)).resolves.toBeUndefined();
|
|
319
|
+
await expect(store.getContractInstance(contractInstance.address, blockNum)).resolves.toBeUndefined();
|
|
320
|
+
});
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
describe('contractInstanceUpdates', () => {
|
|
324
|
+
let contractInstance: ContractInstanceWithAddress;
|
|
325
|
+
let classId: Fr;
|
|
326
|
+
let nextClassId: Fr;
|
|
327
|
+
const blockOfChange = 10;
|
|
328
|
+
|
|
329
|
+
beforeEach(async () => {
|
|
330
|
+
classId = Fr.random();
|
|
331
|
+
nextClassId = Fr.random();
|
|
332
|
+
const randomInstance = await SerializableContractInstance.random({
|
|
333
|
+
currentContractClassId: classId,
|
|
334
|
+
originalContractClassId: classId,
|
|
335
|
+
});
|
|
336
|
+
contractInstance = { ...randomInstance, address: await AztecAddress.random() };
|
|
337
|
+
await store.addContractInstances([contractInstance], 1);
|
|
338
|
+
await store.addContractInstanceUpdates(
|
|
339
|
+
[
|
|
340
|
+
{
|
|
341
|
+
prevContractClassId: classId,
|
|
342
|
+
newContractClassId: nextClassId,
|
|
343
|
+
blockOfChange,
|
|
344
|
+
address: contractInstance.address,
|
|
345
|
+
},
|
|
346
|
+
],
|
|
347
|
+
blockOfChange - 1,
|
|
348
|
+
);
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
it('gets the correct current class id for a contract not updated yet', async () => {
|
|
352
|
+
const fetchedInstance = await store.getContractInstance(contractInstance.address, blockOfChange - 1);
|
|
353
|
+
expect(fetchedInstance?.originalContractClassId).toEqual(classId);
|
|
354
|
+
expect(fetchedInstance?.currentContractClassId).toEqual(classId);
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
it('gets the correct current class id for a contract that has just been updated', async () => {
|
|
358
|
+
const fetchedInstance = await store.getContractInstance(contractInstance.address, blockOfChange);
|
|
359
|
+
expect(fetchedInstance?.originalContractClassId).toEqual(classId);
|
|
360
|
+
expect(fetchedInstance?.currentContractClassId).toEqual(nextClassId);
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
it('gets the correct current class id for a contract that was updated in the past', async () => {
|
|
364
|
+
const fetchedInstance = await store.getContractInstance(contractInstance.address, blockOfChange + 1);
|
|
365
|
+
expect(fetchedInstance?.originalContractClassId).toEqual(classId);
|
|
366
|
+
expect(fetchedInstance?.currentContractClassId).toEqual(nextClassId);
|
|
305
367
|
});
|
|
306
368
|
});
|
|
307
369
|
|
|
@@ -378,31 +440,19 @@ export function describeArchiverDataStore(
|
|
|
378
440
|
const numPrivateLogsPerTx = 3;
|
|
379
441
|
const numPublicLogsPerTx = 2;
|
|
380
442
|
|
|
381
|
-
let blocks:
|
|
443
|
+
let blocks: PublishedL2Block[];
|
|
382
444
|
|
|
383
445
|
const makeTag = (blockNumber: number, txIndex: number, logIndex: number, isPublic = false) =>
|
|
384
446
|
new Fr((blockNumber * 100 + txIndex * 10 + logIndex) * (isPublic ? 123 : 1));
|
|
385
447
|
|
|
386
|
-
// See parseLogFromPublic
|
|
387
|
-
// Search the codebase for "disgusting encoding" to see other hardcoded instances of this encoding, that you might need to change if you ever find yourself here.
|
|
388
|
-
const makeLengthsField = (publicValuesLen: number, privateValuesLen: number) => {
|
|
389
|
-
const buf = Buffer.alloc(32);
|
|
390
|
-
buf.writeUint16BE(publicValuesLen, 27);
|
|
391
|
-
buf.writeUint16BE(privateValuesLen, 30);
|
|
392
|
-
return Fr.fromBuffer(buf);
|
|
393
|
-
};
|
|
394
|
-
|
|
395
448
|
const makePrivateLog = (tag: Fr) =>
|
|
396
449
|
PrivateLog.fromFields([tag, ...times(PRIVATE_LOG_SIZE_IN_FIELDS - 1, i => new Fr(tag.toNumber() + i))]);
|
|
397
450
|
|
|
398
|
-
// The tag lives in field 1, not 0, of a public log
|
|
399
|
-
// See extractTaggedLogsFromPublic and noir-projects/aztec-nr/aztec/src/macros/notes/mod.nr -> emit_log
|
|
400
451
|
const makePublicLog = (tag: Fr) =>
|
|
401
452
|
PublicLog.fromFields([
|
|
402
453
|
AztecAddress.fromNumber(1).toField(), // log address
|
|
403
|
-
|
|
404
|
-
tag, //
|
|
405
|
-
...times(PUBLIC_LOG_DATA_SIZE_IN_FIELDS - 1, i => new Fr(tag.toNumber() + i)), // fields 2 to end
|
|
454
|
+
tag, // field 0
|
|
455
|
+
...times(PUBLIC_LOG_DATA_SIZE_IN_FIELDS - 1, i => new Fr(tag.toNumber() + i)), // fields 1 to end
|
|
406
456
|
]);
|
|
407
457
|
|
|
408
458
|
const mockPrivateLogs = (blockNumber: number, txIndex: number) => {
|
|
@@ -419,7 +469,7 @@ export function describeArchiverDataStore(
|
|
|
419
469
|
});
|
|
420
470
|
};
|
|
421
471
|
|
|
422
|
-
const mockBlockWithLogs = async (blockNumber: number): Promise<
|
|
472
|
+
const mockBlockWithLogs = async (blockNumber: number): Promise<PublishedL2Block> => {
|
|
423
473
|
const block = await L2Block.random(blockNumber);
|
|
424
474
|
block.header.globalVariables.blockNumber = new Fr(blockNumber);
|
|
425
475
|
|
|
@@ -431,7 +481,8 @@ export function describeArchiverDataStore(
|
|
|
431
481
|
});
|
|
432
482
|
|
|
433
483
|
return {
|
|
434
|
-
|
|
484
|
+
block: block,
|
|
485
|
+
signatures: times(3, Signature.random),
|
|
435
486
|
l1: { blockNumber: BigInt(blockNumber), blockHash: `0x${blockNumber}`, timestamp: BigInt(blockNumber) },
|
|
436
487
|
};
|
|
437
488
|
};
|
|
@@ -440,7 +491,7 @@ export function describeArchiverDataStore(
|
|
|
440
491
|
blocks = await timesParallel(numBlocks, (index: number) => mockBlockWithLogs(index));
|
|
441
492
|
|
|
442
493
|
await store.addBlocks(blocks);
|
|
443
|
-
await store.addLogs(blocks.map(b => b.
|
|
494
|
+
await store.addLogs(blocks.map(b => b.block));
|
|
444
495
|
});
|
|
445
496
|
|
|
446
497
|
it('is possible to batch request private logs via tags', async () => {
|
|
@@ -452,14 +503,14 @@ export function describeArchiverDataStore(
|
|
|
452
503
|
[
|
|
453
504
|
expect.objectContaining({
|
|
454
505
|
blockNumber: 1,
|
|
455
|
-
|
|
506
|
+
log: makePrivateLog(tags[0]),
|
|
456
507
|
isFromPublic: false,
|
|
457
508
|
}),
|
|
458
509
|
],
|
|
459
510
|
[
|
|
460
511
|
expect.objectContaining({
|
|
461
512
|
blockNumber: 0,
|
|
462
|
-
|
|
513
|
+
log: makePrivateLog(tags[1]),
|
|
463
514
|
isFromPublic: false,
|
|
464
515
|
}),
|
|
465
516
|
],
|
|
@@ -476,12 +527,12 @@ export function describeArchiverDataStore(
|
|
|
476
527
|
[
|
|
477
528
|
expect.objectContaining({
|
|
478
529
|
blockNumber: 0,
|
|
479
|
-
|
|
530
|
+
log: makePrivateLog(tags[0]),
|
|
480
531
|
isFromPublic: false,
|
|
481
532
|
}),
|
|
482
533
|
expect.objectContaining({
|
|
483
534
|
blockNumber: 0,
|
|
484
|
-
|
|
535
|
+
log: makePublicLog(tags[0]),
|
|
485
536
|
isFromPublic: true,
|
|
486
537
|
}),
|
|
487
538
|
],
|
|
@@ -494,11 +545,11 @@ export function describeArchiverDataStore(
|
|
|
494
545
|
// Create a block containing logs that have the same tag as the blocks before.
|
|
495
546
|
const newBlockNumber = numBlocks;
|
|
496
547
|
const newBlock = await mockBlockWithLogs(newBlockNumber);
|
|
497
|
-
const newLog = newBlock.
|
|
548
|
+
const newLog = newBlock.block.body.txEffects[1].privateLogs[1];
|
|
498
549
|
newLog.fields[0] = tags[0];
|
|
499
|
-
newBlock.
|
|
550
|
+
newBlock.block.body.txEffects[1].privateLogs[1] = newLog;
|
|
500
551
|
await store.addBlocks([newBlock]);
|
|
501
|
-
await store.addLogs([newBlock.
|
|
552
|
+
await store.addLogs([newBlock.block]);
|
|
502
553
|
|
|
503
554
|
const logsByTags = await store.getLogsByTags(tags);
|
|
504
555
|
|
|
@@ -506,12 +557,12 @@ export function describeArchiverDataStore(
|
|
|
506
557
|
[
|
|
507
558
|
expect.objectContaining({
|
|
508
559
|
blockNumber: 1,
|
|
509
|
-
|
|
560
|
+
log: makePrivateLog(tags[0]),
|
|
510
561
|
isFromPublic: false,
|
|
511
562
|
}),
|
|
512
563
|
expect.objectContaining({
|
|
513
564
|
blockNumber: newBlockNumber,
|
|
514
|
-
|
|
565
|
+
log: newLog,
|
|
515
566
|
isFromPublic: false,
|
|
516
567
|
}),
|
|
517
568
|
],
|
|
@@ -530,42 +581,12 @@ export function describeArchiverDataStore(
|
|
|
530
581
|
[
|
|
531
582
|
expect.objectContaining({
|
|
532
583
|
blockNumber: 1,
|
|
533
|
-
|
|
584
|
+
log: makePrivateLog(tags[1]),
|
|
534
585
|
isFromPublic: false,
|
|
535
586
|
}),
|
|
536
587
|
],
|
|
537
588
|
]);
|
|
538
589
|
});
|
|
539
|
-
|
|
540
|
-
it('is not possible to add public logs by tag if they are invalid', async () => {
|
|
541
|
-
const tag = makeTag(99, 88, 77);
|
|
542
|
-
const invalidLogs = [
|
|
543
|
-
PublicLog.fromFields([
|
|
544
|
-
AztecAddress.fromNumber(1).toField(),
|
|
545
|
-
makeLengthsField(2, 3), // This field claims we have 5 items, but we actually have more
|
|
546
|
-
tag,
|
|
547
|
-
...times(PUBLIC_LOG_DATA_SIZE_IN_FIELDS - 1, i => new Fr(tag.toNumber() + i)),
|
|
548
|
-
]),
|
|
549
|
-
PublicLog.fromFields([
|
|
550
|
-
AztecAddress.fromNumber(1).toField(),
|
|
551
|
-
makeLengthsField(2, PUBLIC_LOG_DATA_SIZE_IN_FIELDS), // This field claims we have more than the max items
|
|
552
|
-
tag,
|
|
553
|
-
...times(PUBLIC_LOG_DATA_SIZE_IN_FIELDS - 1, i => new Fr(tag.toNumber() + i)),
|
|
554
|
-
]),
|
|
555
|
-
];
|
|
556
|
-
|
|
557
|
-
// Create a block containing these invalid logs
|
|
558
|
-
const newBlockNumber = numBlocks;
|
|
559
|
-
const newBlock = await mockBlockWithLogs(newBlockNumber);
|
|
560
|
-
newBlock.data.body.txEffects[0].publicLogs = invalidLogs;
|
|
561
|
-
await store.addBlocks([newBlock]);
|
|
562
|
-
await store.addLogs([newBlock.data]);
|
|
563
|
-
|
|
564
|
-
const logsByTags = await store.getLogsByTags([tag]);
|
|
565
|
-
|
|
566
|
-
// Neither of the logs should have been added:
|
|
567
|
-
expect(logsByTags).toEqual([[]]);
|
|
568
|
-
});
|
|
569
590
|
});
|
|
570
591
|
|
|
571
592
|
describe('getPublicLogs', () => {
|
|
@@ -573,27 +594,28 @@ export function describeArchiverDataStore(
|
|
|
573
594
|
const numPublicFunctionCalls = 3;
|
|
574
595
|
const numPublicLogs = 2;
|
|
575
596
|
const numBlocks = 10;
|
|
576
|
-
let blocks:
|
|
597
|
+
let blocks: PublishedL2Block[];
|
|
577
598
|
|
|
578
599
|
beforeEach(async () => {
|
|
579
600
|
blocks = await timesParallel(numBlocks, async (index: number) => ({
|
|
580
|
-
|
|
601
|
+
block: await L2Block.random(index + 1, txsPerBlock, numPublicFunctionCalls, numPublicLogs),
|
|
581
602
|
l1: { blockNumber: BigInt(index), blockHash: `0x${index}`, timestamp: BigInt(index) },
|
|
603
|
+
signatures: times(3, Signature.random),
|
|
582
604
|
}));
|
|
583
605
|
|
|
584
606
|
await store.addBlocks(blocks);
|
|
585
|
-
await store.addLogs(blocks.map(b => b.
|
|
607
|
+
await store.addLogs(blocks.map(b => b.block));
|
|
586
608
|
});
|
|
587
609
|
|
|
588
610
|
it('no logs returned if deleted ("txHash" filter param is respected variant)', async () => {
|
|
589
611
|
// get random tx
|
|
590
612
|
const targetBlockIndex = randomInt(numBlocks);
|
|
591
613
|
const targetTxIndex = randomInt(txsPerBlock);
|
|
592
|
-
const targetTxHash = blocks[targetBlockIndex].
|
|
614
|
+
const targetTxHash = blocks[targetBlockIndex].block.body.txEffects[targetTxIndex].txHash;
|
|
593
615
|
|
|
594
616
|
await Promise.all([
|
|
595
617
|
store.unwindBlocks(blocks.length, blocks.length),
|
|
596
|
-
store.deleteLogs(blocks.map(b => b.
|
|
618
|
+
store.deleteLogs(blocks.map(b => b.block)),
|
|
597
619
|
]);
|
|
598
620
|
|
|
599
621
|
const response = await store.getPublicLogs({ txHash: targetTxHash });
|
|
@@ -607,7 +629,7 @@ export function describeArchiverDataStore(
|
|
|
607
629
|
// get random tx
|
|
608
630
|
const targetBlockIndex = randomInt(numBlocks);
|
|
609
631
|
const targetTxIndex = randomInt(txsPerBlock);
|
|
610
|
-
const targetTxHash = blocks[targetBlockIndex].
|
|
632
|
+
const targetTxHash = blocks[targetBlockIndex].block.body.txEffects[targetTxIndex].txHash;
|
|
611
633
|
|
|
612
634
|
const response = await store.getPublicLogs({ txHash: targetTxHash });
|
|
613
635
|
const logs = response.logs;
|
|
@@ -650,7 +672,7 @@ export function describeArchiverDataStore(
|
|
|
650
672
|
const targetTxIndex = randomInt(txsPerBlock);
|
|
651
673
|
const targetLogIndex = randomInt(numPublicLogs * numPublicFunctionCalls);
|
|
652
674
|
const targetContractAddress =
|
|
653
|
-
blocks[targetBlockIndex].
|
|
675
|
+
blocks[targetBlockIndex].block.body.txEffects[targetTxIndex].publicLogs[targetLogIndex].contractAddress;
|
|
654
676
|
|
|
655
677
|
const response = await store.getPublicLogs({ contractAddress: targetContractAddress });
|
|
656
678
|
|
|
@@ -753,58 +775,5 @@ export function describeArchiverDataStore(
|
|
|
753
775
|
}
|
|
754
776
|
});
|
|
755
777
|
});
|
|
756
|
-
|
|
757
|
-
describe('findNullifiersIndexesWithBlock', () => {
|
|
758
|
-
let blocks: L2Block[];
|
|
759
|
-
const numBlocks = 10;
|
|
760
|
-
const nullifiersPerBlock = new Map<number, Fr[]>();
|
|
761
|
-
|
|
762
|
-
beforeEach(async () => {
|
|
763
|
-
blocks = await timesParallel(numBlocks, (index: number) => L2Block.random(index + 1, 1));
|
|
764
|
-
|
|
765
|
-
blocks.forEach((block, blockIndex) => {
|
|
766
|
-
nullifiersPerBlock.set(
|
|
767
|
-
blockIndex,
|
|
768
|
-
block.body.txEffects.flatMap(txEffect => txEffect.nullifiers),
|
|
769
|
-
);
|
|
770
|
-
});
|
|
771
|
-
});
|
|
772
|
-
|
|
773
|
-
it('returns wrapped nullifiers with blocks if they exist', async () => {
|
|
774
|
-
await store.addNullifiers(blocks);
|
|
775
|
-
const nullifiersToRetrieve = [...nullifiersPerBlock.get(0)!, ...nullifiersPerBlock.get(5)!, Fr.random()];
|
|
776
|
-
const blockScopedNullifiers = await store.findNullifiersIndexesWithBlock(10, nullifiersToRetrieve);
|
|
777
|
-
|
|
778
|
-
expect(blockScopedNullifiers).toHaveLength(nullifiersToRetrieve.length);
|
|
779
|
-
const [undefinedNullifier] = blockScopedNullifiers.slice(-1);
|
|
780
|
-
const realNullifiers = blockScopedNullifiers.slice(0, -1);
|
|
781
|
-
realNullifiers.forEach((blockScopedNullifier, index) => {
|
|
782
|
-
expect(blockScopedNullifier).not.toBeUndefined();
|
|
783
|
-
const { data, l2BlockNumber } = blockScopedNullifier!;
|
|
784
|
-
expect(data).toEqual(expect.any(BigInt));
|
|
785
|
-
expect(l2BlockNumber).toEqual(index < MAX_NULLIFIERS_PER_TX ? 1 : 6);
|
|
786
|
-
});
|
|
787
|
-
expect(undefinedNullifier).toBeUndefined();
|
|
788
|
-
});
|
|
789
|
-
|
|
790
|
-
it('returns wrapped nullifiers filtering by blockNumber', async () => {
|
|
791
|
-
await store.addNullifiers(blocks);
|
|
792
|
-
const nullifiersToRetrieve = [...nullifiersPerBlock.get(0)!, ...nullifiersPerBlock.get(5)!];
|
|
793
|
-
const blockScopedNullifiers = await store.findNullifiersIndexesWithBlock(5, nullifiersToRetrieve);
|
|
794
|
-
|
|
795
|
-
expect(blockScopedNullifiers).toHaveLength(nullifiersToRetrieve.length);
|
|
796
|
-
const undefinedNullifiers = blockScopedNullifiers.slice(-MAX_NULLIFIERS_PER_TX);
|
|
797
|
-
const realNullifiers = blockScopedNullifiers.slice(0, -MAX_NULLIFIERS_PER_TX);
|
|
798
|
-
realNullifiers.forEach(blockScopedNullifier => {
|
|
799
|
-
expect(blockScopedNullifier).not.toBeUndefined();
|
|
800
|
-
const { data, l2BlockNumber } = blockScopedNullifier!;
|
|
801
|
-
expect(data).toEqual(expect.any(BigInt));
|
|
802
|
-
expect(l2BlockNumber).toEqual(1);
|
|
803
|
-
});
|
|
804
|
-
undefinedNullifiers.forEach(undefinedNullifier => {
|
|
805
|
-
expect(undefinedNullifier).toBeUndefined();
|
|
806
|
-
});
|
|
807
|
-
});
|
|
808
|
-
});
|
|
809
778
|
});
|
|
810
779
|
}
|
package/src/archiver/config.ts
CHANGED
|
@@ -40,6 +40,9 @@ export type ArchiverConfig = {
|
|
|
40
40
|
|
|
41
41
|
/** The max number of logs that can be obtained in 1 "getPublicLogs" call. */
|
|
42
42
|
maxLogs?: number;
|
|
43
|
+
|
|
44
|
+
/** The maximum possible size of the archiver DB in KB. Overwrites the general dataStoreMapSizeKB. */
|
|
45
|
+
archiverStoreMapSizeKb?: number;
|
|
43
46
|
} & L1ReaderConfig &
|
|
44
47
|
L1ContractsConfig &
|
|
45
48
|
BlobSinkConfig &
|
|
@@ -72,6 +75,11 @@ export const archiverConfigMappings: ConfigMappingsType<ArchiverConfig> = {
|
|
|
72
75
|
description: 'The max number of logs that can be obtained in 1 "getPublicLogs" call.',
|
|
73
76
|
...numberConfigHelper(1_000),
|
|
74
77
|
},
|
|
78
|
+
archiverStoreMapSizeKb: {
|
|
79
|
+
env: 'ARCHIVER_STORE_MAP_SIZE_KB',
|
|
80
|
+
parseEnv: (val: string | undefined) => (val ? +val : undefined),
|
|
81
|
+
description: 'The maximum possible size of the archiver DB in KB. Overwrites the general dataStoreMapSizeKB.',
|
|
82
|
+
},
|
|
75
83
|
...chainConfigMappings,
|
|
76
84
|
...l1ReaderConfigMappings,
|
|
77
85
|
viemPollingIntervalMS: {
|
|
@@ -3,7 +3,7 @@ import type { BlobSinkClientInterface } from '@aztec/blob-sink/client';
|
|
|
3
3
|
import type { EpochProofPublicInputArgs, ViemPublicClient } from '@aztec/ethereum';
|
|
4
4
|
import { asyncPool } from '@aztec/foundation/async-pool';
|
|
5
5
|
import type { EthAddress } from '@aztec/foundation/eth-address';
|
|
6
|
-
import type
|
|
6
|
+
import { Signature, type ViemSignature } from '@aztec/foundation/eth-signature';
|
|
7
7
|
import { Fr } from '@aztec/foundation/fields';
|
|
8
8
|
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
9
9
|
import { numToUInt32BE } from '@aztec/foundation/serialize';
|
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
|
|
26
26
|
import { NoBlobBodiesFoundError } from './errors.js';
|
|
27
27
|
import type { DataRetrieval } from './structs/data_retrieval.js';
|
|
28
|
-
import type {
|
|
28
|
+
import type { L1PublishedData, PublishedL2Block } from './structs/published.js';
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
31
|
* Fetches new L2 blocks.
|
|
@@ -43,8 +43,8 @@ export async function retrieveBlocksFromRollup(
|
|
|
43
43
|
searchStartBlock: bigint,
|
|
44
44
|
searchEndBlock: bigint,
|
|
45
45
|
logger: Logger = createLogger('archiver'),
|
|
46
|
-
): Promise<
|
|
47
|
-
const retrievedBlocks:
|
|
46
|
+
): Promise<PublishedL2Block[]> {
|
|
47
|
+
const retrievedBlocks: PublishedL2Block[] = [];
|
|
48
48
|
do {
|
|
49
49
|
if (searchStartBlock > searchEndBlock) {
|
|
50
50
|
break;
|
|
@@ -96,8 +96,8 @@ export async function processL2BlockProposedLogs(
|
|
|
96
96
|
blobSinkClient: BlobSinkClientInterface,
|
|
97
97
|
logs: GetContractEventsReturnType<typeof RollupAbi, 'L2BlockProposed'>,
|
|
98
98
|
logger: Logger,
|
|
99
|
-
): Promise<
|
|
100
|
-
const retrievedBlocks:
|
|
99
|
+
): Promise<PublishedL2Block[]> {
|
|
100
|
+
const retrievedBlocks: PublishedL2Block[] = [];
|
|
101
101
|
await asyncPool(10, logs, async log => {
|
|
102
102
|
const l2BlockNumber = log.args.blockNumber!;
|
|
103
103
|
const archive = log.args.archive!;
|
|
@@ -122,7 +122,7 @@ export async function processL2BlockProposedLogs(
|
|
|
122
122
|
timestamp: await getL1BlockTime(publicClient, log.blockNumber),
|
|
123
123
|
};
|
|
124
124
|
|
|
125
|
-
retrievedBlocks.push({
|
|
125
|
+
retrievedBlocks.push({ ...block, l1 });
|
|
126
126
|
} else {
|
|
127
127
|
logger.warn(`Ignoring L2 block ${l2BlockNumber} due to archive root mismatch`, {
|
|
128
128
|
actual: archive,
|
|
@@ -203,11 +203,11 @@ async function getBlockFromRollupTx(
|
|
|
203
203
|
publicClient: ViemPublicClient,
|
|
204
204
|
blobSinkClient: BlobSinkClientInterface,
|
|
205
205
|
txHash: `0x${string}`,
|
|
206
|
-
blobHashes: Buffer[], //
|
|
206
|
+
blobHashes: Buffer[], // TODO(md): buffer32?
|
|
207
207
|
l2BlockNum: bigint,
|
|
208
208
|
rollupAddress: Hex,
|
|
209
209
|
logger: Logger,
|
|
210
|
-
): Promise<
|
|
210
|
+
): Promise<Omit<PublishedL2Block, 'l1'>> {
|
|
211
211
|
const { input: forwarderData, blockHash } = await publicClient.getTransaction({ hash: txHash });
|
|
212
212
|
|
|
213
213
|
const rollupData = extractRollupProposeCalldata(forwarderData, rollupAddress);
|
|
@@ -220,7 +220,7 @@ async function getBlockFromRollupTx(
|
|
|
220
220
|
throw new Error(`Unexpected rollup method called ${rollupFunctionName}`);
|
|
221
221
|
}
|
|
222
222
|
|
|
223
|
-
const [decodedArgs,
|
|
223
|
+
const [decodedArgs, signatures] = rollupArgs! as readonly [
|
|
224
224
|
{
|
|
225
225
|
header: Hex;
|
|
226
226
|
archive: Hex;
|
|
@@ -268,7 +268,8 @@ async function getBlockFromRollupTx(
|
|
|
268
268
|
]),
|
|
269
269
|
);
|
|
270
270
|
|
|
271
|
-
|
|
271
|
+
const block = new L2Block(archive, header, blockBody);
|
|
272
|
+
return { block, signatures: signatures.map(Signature.fromViemSignature) };
|
|
272
273
|
}
|
|
273
274
|
|
|
274
275
|
/**
|
package/src/archiver/index.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export * from './archiver.js';
|
|
2
2
|
export * from './config.js';
|
|
3
|
-
export { type
|
|
4
|
-
export { MemoryArchiverStore } from './memory_archiver_store/memory_archiver_store.js';
|
|
3
|
+
export { type PublishedL2Block, type L1PublishedData } from './structs/published.js';
|
|
5
4
|
export type { ArchiverDataStore } from './archiver_store.js';
|
|
6
5
|
export { KVArchiverDataStore } from './kv_archiver_store/kv_archiver_store.js';
|
|
7
6
|
export { ContractInstanceStore } from './kv_archiver_store/contract_instance_store.js';
|