@aztec/archiver 0.80.0 → 0.81.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 +5 -9
- package/dest/archiver/archiver.d.ts.map +1 -1
- package/dest/archiver/archiver.js +36 -49
- package/dest/archiver/archiver_store.d.ts +5 -4
- 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 +104 -91
- 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 -1
- package/dest/archiver/index.d.ts.map +1 -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 +4 -4
- 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 -3
- package/dest/archiver/kv_archiver_store/log_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/log_store.js +9 -41
- package/dest/archiver/memory_archiver_store/memory_archiver_store.d.ts +4 -4
- package/dest/archiver/memory_archiver_store/memory_archiver_store.d.ts.map +1 -1
- package/dest/archiver/memory_archiver_store/memory_archiver_store.js +25 -54
- 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/test/mock_l2_block_source.d.ts +9 -0
- package/dest/test/mock_l2_block_source.d.ts.map +1 -1
- package/dest/test/mock_l2_block_source.js +13 -0
- package/package.json +13 -13
- package/src/archiver/archiver.ts +44 -60
- package/src/archiver/archiver_store.ts +5 -4
- package/src/archiver/archiver_store_test_suite.ts +116 -93
- package/src/archiver/data_retrieval.ts +11 -10
- package/src/archiver/index.ts +1 -1
- package/src/archiver/kv_archiver_store/block_store.ts +28 -27
- package/src/archiver/kv_archiver_store/kv_archiver_store.ts +5 -6
- package/src/archiver/kv_archiver_store/log_store.ts +11 -59
- package/src/archiver/memory_archiver_store/memory_archiver_store.ts +35 -66
- package/src/archiver/structs/published.ts +1 -11
- package/src/test/mock_l2_block_source.ts +14 -0
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
} from '@aztec/constants';
|
|
8
8
|
import { times, timesParallel } from '@aztec/foundation/collection';
|
|
9
9
|
import { randomInt } from '@aztec/foundation/crypto';
|
|
10
|
+
import { Signature } from '@aztec/foundation/eth-signature';
|
|
10
11
|
import { Fr } from '@aztec/foundation/fields';
|
|
11
12
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
12
13
|
import { L2Block, wrapInBlock } from '@aztec/stdlib/block';
|
|
@@ -27,7 +28,7 @@ import '@aztec/stdlib/testing/jest';
|
|
|
27
28
|
import { TxEffect, TxHash } from '@aztec/stdlib/tx';
|
|
28
29
|
|
|
29
30
|
import type { ArchiverDataStore, ArchiverL1SynchPoint } from './archiver_store.js';
|
|
30
|
-
import type {
|
|
31
|
+
import type { PublishedL2Block } from './structs/published.js';
|
|
31
32
|
|
|
32
33
|
/**
|
|
33
34
|
* @param testName - The name of the test suite.
|
|
@@ -39,8 +40,9 @@ export function describeArchiverDataStore(
|
|
|
39
40
|
) {
|
|
40
41
|
describe(testName, () => {
|
|
41
42
|
let store: ArchiverDataStore;
|
|
42
|
-
let blocks:
|
|
43
|
-
|
|
43
|
+
let blocks: PublishedL2Block[];
|
|
44
|
+
|
|
45
|
+
const blockTests: [number, number, () => PublishedL2Block[]][] = [
|
|
44
46
|
[1, 1, () => blocks.slice(0, 1)],
|
|
45
47
|
[10, 1, () => blocks.slice(9, 10)],
|
|
46
48
|
[1, 10, () => blocks.slice(0, 10)],
|
|
@@ -48,18 +50,30 @@ export function describeArchiverDataStore(
|
|
|
48
50
|
[5, 2, () => blocks.slice(4, 6)],
|
|
49
51
|
];
|
|
50
52
|
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
+
const makePublished = (block: L2Block, l1BlockNumber: number): PublishedL2Block => ({
|
|
54
|
+
block: block,
|
|
53
55
|
l1: {
|
|
54
56
|
blockNumber: BigInt(l1BlockNumber),
|
|
55
57
|
blockHash: `0x${l1BlockNumber}`,
|
|
56
58
|
timestamp: BigInt(l1BlockNumber * 1000),
|
|
57
59
|
},
|
|
60
|
+
signatures: times(3, Signature.random),
|
|
58
61
|
});
|
|
59
62
|
|
|
63
|
+
const expectBlocksEqual = (actual: PublishedL2Block[], expected: PublishedL2Block[]) => {
|
|
64
|
+
expect(actual.length).toEqual(expected.length);
|
|
65
|
+
for (let i = 0; i < expected.length; i++) {
|
|
66
|
+
const expectedBlock = expected[i];
|
|
67
|
+
const actualBlock = actual[i];
|
|
68
|
+
expect(actualBlock.l1).toEqual(expectedBlock.l1);
|
|
69
|
+
expect(actualBlock.block.equals(expectedBlock.block)).toBe(true);
|
|
70
|
+
expect(actualBlock.signatures.every((s, i) => s.equals(expectedBlock.signatures[i]))).toBe(true);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
|
|
60
74
|
beforeEach(async () => {
|
|
61
75
|
store = await getStore();
|
|
62
|
-
blocks = await timesParallel(10, async i =>
|
|
76
|
+
blocks = await timesParallel(10, async i => makePublished(await L2Block.random(i + 1), i + 10));
|
|
63
77
|
});
|
|
64
78
|
|
|
65
79
|
describe('addBlocks', () => {
|
|
@@ -78,7 +92,7 @@ export function describeArchiverDataStore(
|
|
|
78
92
|
await store.addBlocks(blocks);
|
|
79
93
|
const blockNumber = await store.getSynchedL2BlockNumber();
|
|
80
94
|
|
|
81
|
-
|
|
95
|
+
expectBlocksEqual(await store.getBlocks(blockNumber, 1), [blocks[blocks.length - 1]]);
|
|
82
96
|
|
|
83
97
|
await store.unwindBlocks(blockNumber, 1);
|
|
84
98
|
|
|
@@ -87,13 +101,13 @@ export function describeArchiverDataStore(
|
|
|
87
101
|
});
|
|
88
102
|
|
|
89
103
|
it('can unwind multiple empty blocks', async () => {
|
|
90
|
-
const emptyBlocks = await timesParallel(10, async i =>
|
|
104
|
+
const emptyBlocks = await timesParallel(10, async i => makePublished(await L2Block.random(i + 1, 0), i + 10));
|
|
91
105
|
await store.addBlocks(emptyBlocks);
|
|
92
106
|
expect(await store.getSynchedL2BlockNumber()).toBe(10);
|
|
93
107
|
|
|
94
108
|
await store.unwindBlocks(10, 3);
|
|
95
109
|
expect(await store.getSynchedL2BlockNumber()).toBe(7);
|
|
96
|
-
expect((await store.getBlocks(1, 10)).map(b => b.
|
|
110
|
+
expect((await store.getBlocks(1, 10)).map(b => b.block.number)).toEqual([1, 2, 3, 4, 5, 6, 7]);
|
|
97
111
|
});
|
|
98
112
|
|
|
99
113
|
it('refuses to unwind blocks if the tip is not the last block', async () => {
|
|
@@ -108,7 +122,7 @@ export function describeArchiverDataStore(
|
|
|
108
122
|
});
|
|
109
123
|
|
|
110
124
|
it.each(blockTests)('retrieves previously stored blocks', async (start, limit, getExpectedBlocks) => {
|
|
111
|
-
await
|
|
125
|
+
expectBlocksEqual(await store.getBlocks(start, limit), getExpectedBlocks());
|
|
112
126
|
});
|
|
113
127
|
|
|
114
128
|
it('returns an empty array if no blocks are found', async () => {
|
|
@@ -131,7 +145,7 @@ export function describeArchiverDataStore(
|
|
|
131
145
|
|
|
132
146
|
it("returns the most recently added block's number", async () => {
|
|
133
147
|
await store.addBlocks(blocks);
|
|
134
|
-
await expect(store.getSynchedL2BlockNumber()).resolves.toEqual(blocks.at(-1)!.
|
|
148
|
+
await expect(store.getSynchedL2BlockNumber()).resolves.toEqual(blocks.at(-1)!.block.number);
|
|
135
149
|
});
|
|
136
150
|
});
|
|
137
151
|
|
|
@@ -165,14 +179,14 @@ export function describeArchiverDataStore(
|
|
|
165
179
|
|
|
166
180
|
describe('addLogs', () => {
|
|
167
181
|
it('adds private & public logs', async () => {
|
|
168
|
-
const block = blocks[0].
|
|
182
|
+
const block = blocks[0].block;
|
|
169
183
|
await expect(store.addLogs([block])).resolves.toEqual(true);
|
|
170
184
|
});
|
|
171
185
|
});
|
|
172
186
|
|
|
173
187
|
describe('deleteLogs', () => {
|
|
174
188
|
it('deletes private & public logs', async () => {
|
|
175
|
-
const block = blocks[0].
|
|
189
|
+
const block = blocks[0].block;
|
|
176
190
|
await store.addBlocks([blocks[0]]);
|
|
177
191
|
await expect(store.addLogs([block])).resolves.toEqual(true);
|
|
178
192
|
|
|
@@ -193,7 +207,7 @@ export function describeArchiverDataStore(
|
|
|
193
207
|
|
|
194
208
|
describe('getPrivateLogs', () => {
|
|
195
209
|
it('gets added private logs', async () => {
|
|
196
|
-
const block = blocks[0].
|
|
210
|
+
const block = blocks[0].block;
|
|
197
211
|
await store.addBlocks([blocks[0]]);
|
|
198
212
|
await store.addLogs([block]);
|
|
199
213
|
|
|
@@ -204,16 +218,16 @@ export function describeArchiverDataStore(
|
|
|
204
218
|
|
|
205
219
|
describe('getTxEffect', () => {
|
|
206
220
|
beforeEach(async () => {
|
|
207
|
-
await store.addLogs(blocks.map(b => b.
|
|
221
|
+
await store.addLogs(blocks.map(b => b.block));
|
|
208
222
|
await store.addBlocks(blocks);
|
|
209
223
|
});
|
|
210
224
|
|
|
211
225
|
it.each([
|
|
212
|
-
() => wrapInBlock(blocks[0].
|
|
213
|
-
() => wrapInBlock(blocks[9].
|
|
214
|
-
() => wrapInBlock(blocks[3].
|
|
215
|
-
() => wrapInBlock(blocks[5].
|
|
216
|
-
() => wrapInBlock(blocks[1].
|
|
226
|
+
() => wrapInBlock(blocks[0].block.body.txEffects[0], blocks[0].block),
|
|
227
|
+
() => wrapInBlock(blocks[9].block.body.txEffects[3], blocks[9].block),
|
|
228
|
+
() => wrapInBlock(blocks[3].block.body.txEffects[1], blocks[3].block),
|
|
229
|
+
() => wrapInBlock(blocks[5].block.body.txEffects[2], blocks[5].block),
|
|
230
|
+
() => wrapInBlock(blocks[1].block.body.txEffects[0], blocks[1].block),
|
|
217
231
|
])('retrieves a previously stored transaction', async getExpectedTx => {
|
|
218
232
|
const expectedTx = await getExpectedTx();
|
|
219
233
|
const actualTx = await store.getTxEffect(expectedTx.data.txHash);
|
|
@@ -225,11 +239,11 @@ export function describeArchiverDataStore(
|
|
|
225
239
|
});
|
|
226
240
|
|
|
227
241
|
it.each([
|
|
228
|
-
() => wrapInBlock(blocks[0].
|
|
229
|
-
() => wrapInBlock(blocks[9].
|
|
230
|
-
() => wrapInBlock(blocks[3].
|
|
231
|
-
() => wrapInBlock(blocks[5].
|
|
232
|
-
() => wrapInBlock(blocks[1].
|
|
242
|
+
() => wrapInBlock(blocks[0].block.body.txEffects[0], blocks[0].block),
|
|
243
|
+
() => wrapInBlock(blocks[9].block.body.txEffects[3], blocks[9].block),
|
|
244
|
+
() => wrapInBlock(blocks[3].block.body.txEffects[1], blocks[3].block),
|
|
245
|
+
() => wrapInBlock(blocks[5].block.body.txEffects[2], blocks[5].block),
|
|
246
|
+
() => wrapInBlock(blocks[1].block.body.txEffects[0], blocks[1].block),
|
|
233
247
|
])('tries to retrieves a previously stored transaction after deleted', async getExpectedTx => {
|
|
234
248
|
await store.unwindBlocks(blocks.length, blocks.length);
|
|
235
249
|
|
|
@@ -292,16 +306,65 @@ export function describeArchiverDataStore(
|
|
|
292
306
|
});
|
|
293
307
|
|
|
294
308
|
it('returns previously stored contract instances', async () => {
|
|
295
|
-
await expect(store.getContractInstance(contractInstance.address)).resolves.toMatchObject(
|
|
309
|
+
await expect(store.getContractInstance(contractInstance.address, blockNum)).resolves.toMatchObject(
|
|
310
|
+
contractInstance,
|
|
311
|
+
);
|
|
296
312
|
});
|
|
297
313
|
|
|
298
314
|
it('returns undefined if contract instance is not found', async () => {
|
|
299
|
-
await expect(store.getContractInstance(await AztecAddress.random())).resolves.toBeUndefined();
|
|
315
|
+
await expect(store.getContractInstance(await AztecAddress.random(), blockNum)).resolves.toBeUndefined();
|
|
300
316
|
});
|
|
301
317
|
|
|
302
318
|
it('returns undefined if previously stored contract instances was deleted', async () => {
|
|
303
319
|
await store.deleteContractInstances([contractInstance], blockNum);
|
|
304
|
-
await expect(store.getContractInstance(contractInstance.address)).resolves.toBeUndefined();
|
|
320
|
+
await expect(store.getContractInstance(contractInstance.address, blockNum)).resolves.toBeUndefined();
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
describe('contractInstanceUpdates', () => {
|
|
325
|
+
let contractInstance: ContractInstanceWithAddress;
|
|
326
|
+
let classId: Fr;
|
|
327
|
+
let nextClassId: Fr;
|
|
328
|
+
const blockOfChange = 10;
|
|
329
|
+
|
|
330
|
+
beforeEach(async () => {
|
|
331
|
+
classId = Fr.random();
|
|
332
|
+
nextClassId = Fr.random();
|
|
333
|
+
const randomInstance = await SerializableContractInstance.random({
|
|
334
|
+
currentContractClassId: classId,
|
|
335
|
+
originalContractClassId: classId,
|
|
336
|
+
});
|
|
337
|
+
contractInstance = { ...randomInstance, address: await AztecAddress.random() };
|
|
338
|
+
await store.addContractInstances([contractInstance], 1);
|
|
339
|
+
await store.addContractInstanceUpdates(
|
|
340
|
+
[
|
|
341
|
+
{
|
|
342
|
+
prevContractClassId: classId,
|
|
343
|
+
newContractClassId: nextClassId,
|
|
344
|
+
blockOfChange,
|
|
345
|
+
address: contractInstance.address,
|
|
346
|
+
},
|
|
347
|
+
],
|
|
348
|
+
blockOfChange - 1,
|
|
349
|
+
);
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
it('gets the correct current class id for a contract not updated yet', async () => {
|
|
353
|
+
const fetchedInstance = await store.getContractInstance(contractInstance.address, blockOfChange - 1);
|
|
354
|
+
expect(fetchedInstance?.originalContractClassId).toEqual(classId);
|
|
355
|
+
expect(fetchedInstance?.currentContractClassId).toEqual(classId);
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
it('gets the correct current class id for a contract that has just been updated', async () => {
|
|
359
|
+
const fetchedInstance = await store.getContractInstance(contractInstance.address, blockOfChange);
|
|
360
|
+
expect(fetchedInstance?.originalContractClassId).toEqual(classId);
|
|
361
|
+
expect(fetchedInstance?.currentContractClassId).toEqual(nextClassId);
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
it('gets the correct current class id for a contract that was updated in the past', async () => {
|
|
365
|
+
const fetchedInstance = await store.getContractInstance(contractInstance.address, blockOfChange + 1);
|
|
366
|
+
expect(fetchedInstance?.originalContractClassId).toEqual(classId);
|
|
367
|
+
expect(fetchedInstance?.currentContractClassId).toEqual(nextClassId);
|
|
305
368
|
});
|
|
306
369
|
});
|
|
307
370
|
|
|
@@ -378,31 +441,19 @@ export function describeArchiverDataStore(
|
|
|
378
441
|
const numPrivateLogsPerTx = 3;
|
|
379
442
|
const numPublicLogsPerTx = 2;
|
|
380
443
|
|
|
381
|
-
let blocks:
|
|
444
|
+
let blocks: PublishedL2Block[];
|
|
382
445
|
|
|
383
446
|
const makeTag = (blockNumber: number, txIndex: number, logIndex: number, isPublic = false) =>
|
|
384
447
|
new Fr((blockNumber * 100 + txIndex * 10 + logIndex) * (isPublic ? 123 : 1));
|
|
385
448
|
|
|
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
449
|
const makePrivateLog = (tag: Fr) =>
|
|
396
450
|
PrivateLog.fromFields([tag, ...times(PRIVATE_LOG_SIZE_IN_FIELDS - 1, i => new Fr(tag.toNumber() + i))]);
|
|
397
451
|
|
|
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
452
|
const makePublicLog = (tag: Fr) =>
|
|
401
453
|
PublicLog.fromFields([
|
|
402
454
|
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
|
|
455
|
+
tag, // field 0
|
|
456
|
+
...times(PUBLIC_LOG_DATA_SIZE_IN_FIELDS - 1, i => new Fr(tag.toNumber() + i)), // fields 1 to end
|
|
406
457
|
]);
|
|
407
458
|
|
|
408
459
|
const mockPrivateLogs = (blockNumber: number, txIndex: number) => {
|
|
@@ -419,7 +470,7 @@ export function describeArchiverDataStore(
|
|
|
419
470
|
});
|
|
420
471
|
};
|
|
421
472
|
|
|
422
|
-
const mockBlockWithLogs = async (blockNumber: number): Promise<
|
|
473
|
+
const mockBlockWithLogs = async (blockNumber: number): Promise<PublishedL2Block> => {
|
|
423
474
|
const block = await L2Block.random(blockNumber);
|
|
424
475
|
block.header.globalVariables.blockNumber = new Fr(blockNumber);
|
|
425
476
|
|
|
@@ -431,7 +482,8 @@ export function describeArchiverDataStore(
|
|
|
431
482
|
});
|
|
432
483
|
|
|
433
484
|
return {
|
|
434
|
-
|
|
485
|
+
block: block,
|
|
486
|
+
signatures: times(3, Signature.random),
|
|
435
487
|
l1: { blockNumber: BigInt(blockNumber), blockHash: `0x${blockNumber}`, timestamp: BigInt(blockNumber) },
|
|
436
488
|
};
|
|
437
489
|
};
|
|
@@ -440,7 +492,7 @@ export function describeArchiverDataStore(
|
|
|
440
492
|
blocks = await timesParallel(numBlocks, (index: number) => mockBlockWithLogs(index));
|
|
441
493
|
|
|
442
494
|
await store.addBlocks(blocks);
|
|
443
|
-
await store.addLogs(blocks.map(b => b.
|
|
495
|
+
await store.addLogs(blocks.map(b => b.block));
|
|
444
496
|
});
|
|
445
497
|
|
|
446
498
|
it('is possible to batch request private logs via tags', async () => {
|
|
@@ -452,14 +504,14 @@ export function describeArchiverDataStore(
|
|
|
452
504
|
[
|
|
453
505
|
expect.objectContaining({
|
|
454
506
|
blockNumber: 1,
|
|
455
|
-
|
|
507
|
+
log: makePrivateLog(tags[0]),
|
|
456
508
|
isFromPublic: false,
|
|
457
509
|
}),
|
|
458
510
|
],
|
|
459
511
|
[
|
|
460
512
|
expect.objectContaining({
|
|
461
513
|
blockNumber: 0,
|
|
462
|
-
|
|
514
|
+
log: makePrivateLog(tags[1]),
|
|
463
515
|
isFromPublic: false,
|
|
464
516
|
}),
|
|
465
517
|
],
|
|
@@ -476,12 +528,12 @@ export function describeArchiverDataStore(
|
|
|
476
528
|
[
|
|
477
529
|
expect.objectContaining({
|
|
478
530
|
blockNumber: 0,
|
|
479
|
-
|
|
531
|
+
log: makePrivateLog(tags[0]),
|
|
480
532
|
isFromPublic: false,
|
|
481
533
|
}),
|
|
482
534
|
expect.objectContaining({
|
|
483
535
|
blockNumber: 0,
|
|
484
|
-
|
|
536
|
+
log: makePublicLog(tags[0]),
|
|
485
537
|
isFromPublic: true,
|
|
486
538
|
}),
|
|
487
539
|
],
|
|
@@ -494,11 +546,11 @@ export function describeArchiverDataStore(
|
|
|
494
546
|
// Create a block containing logs that have the same tag as the blocks before.
|
|
495
547
|
const newBlockNumber = numBlocks;
|
|
496
548
|
const newBlock = await mockBlockWithLogs(newBlockNumber);
|
|
497
|
-
const newLog = newBlock.
|
|
549
|
+
const newLog = newBlock.block.body.txEffects[1].privateLogs[1];
|
|
498
550
|
newLog.fields[0] = tags[0];
|
|
499
|
-
newBlock.
|
|
551
|
+
newBlock.block.body.txEffects[1].privateLogs[1] = newLog;
|
|
500
552
|
await store.addBlocks([newBlock]);
|
|
501
|
-
await store.addLogs([newBlock.
|
|
553
|
+
await store.addLogs([newBlock.block]);
|
|
502
554
|
|
|
503
555
|
const logsByTags = await store.getLogsByTags(tags);
|
|
504
556
|
|
|
@@ -506,12 +558,12 @@ export function describeArchiverDataStore(
|
|
|
506
558
|
[
|
|
507
559
|
expect.objectContaining({
|
|
508
560
|
blockNumber: 1,
|
|
509
|
-
|
|
561
|
+
log: makePrivateLog(tags[0]),
|
|
510
562
|
isFromPublic: false,
|
|
511
563
|
}),
|
|
512
564
|
expect.objectContaining({
|
|
513
565
|
blockNumber: newBlockNumber,
|
|
514
|
-
|
|
566
|
+
log: newLog,
|
|
515
567
|
isFromPublic: false,
|
|
516
568
|
}),
|
|
517
569
|
],
|
|
@@ -530,42 +582,12 @@ export function describeArchiverDataStore(
|
|
|
530
582
|
[
|
|
531
583
|
expect.objectContaining({
|
|
532
584
|
blockNumber: 1,
|
|
533
|
-
|
|
585
|
+
log: makePrivateLog(tags[1]),
|
|
534
586
|
isFromPublic: false,
|
|
535
587
|
}),
|
|
536
588
|
],
|
|
537
589
|
]);
|
|
538
590
|
});
|
|
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
591
|
});
|
|
570
592
|
|
|
571
593
|
describe('getPublicLogs', () => {
|
|
@@ -573,27 +595,28 @@ export function describeArchiverDataStore(
|
|
|
573
595
|
const numPublicFunctionCalls = 3;
|
|
574
596
|
const numPublicLogs = 2;
|
|
575
597
|
const numBlocks = 10;
|
|
576
|
-
let blocks:
|
|
598
|
+
let blocks: PublishedL2Block[];
|
|
577
599
|
|
|
578
600
|
beforeEach(async () => {
|
|
579
601
|
blocks = await timesParallel(numBlocks, async (index: number) => ({
|
|
580
|
-
|
|
602
|
+
block: await L2Block.random(index + 1, txsPerBlock, numPublicFunctionCalls, numPublicLogs),
|
|
581
603
|
l1: { blockNumber: BigInt(index), blockHash: `0x${index}`, timestamp: BigInt(index) },
|
|
604
|
+
signatures: times(3, Signature.random),
|
|
582
605
|
}));
|
|
583
606
|
|
|
584
607
|
await store.addBlocks(blocks);
|
|
585
|
-
await store.addLogs(blocks.map(b => b.
|
|
608
|
+
await store.addLogs(blocks.map(b => b.block));
|
|
586
609
|
});
|
|
587
610
|
|
|
588
611
|
it('no logs returned if deleted ("txHash" filter param is respected variant)', async () => {
|
|
589
612
|
// get random tx
|
|
590
613
|
const targetBlockIndex = randomInt(numBlocks);
|
|
591
614
|
const targetTxIndex = randomInt(txsPerBlock);
|
|
592
|
-
const targetTxHash = blocks[targetBlockIndex].
|
|
615
|
+
const targetTxHash = blocks[targetBlockIndex].block.body.txEffects[targetTxIndex].txHash;
|
|
593
616
|
|
|
594
617
|
await Promise.all([
|
|
595
618
|
store.unwindBlocks(blocks.length, blocks.length),
|
|
596
|
-
store.deleteLogs(blocks.map(b => b.
|
|
619
|
+
store.deleteLogs(blocks.map(b => b.block)),
|
|
597
620
|
]);
|
|
598
621
|
|
|
599
622
|
const response = await store.getPublicLogs({ txHash: targetTxHash });
|
|
@@ -607,7 +630,7 @@ export function describeArchiverDataStore(
|
|
|
607
630
|
// get random tx
|
|
608
631
|
const targetBlockIndex = randomInt(numBlocks);
|
|
609
632
|
const targetTxIndex = randomInt(txsPerBlock);
|
|
610
|
-
const targetTxHash = blocks[targetBlockIndex].
|
|
633
|
+
const targetTxHash = blocks[targetBlockIndex].block.body.txEffects[targetTxIndex].txHash;
|
|
611
634
|
|
|
612
635
|
const response = await store.getPublicLogs({ txHash: targetTxHash });
|
|
613
636
|
const logs = response.logs;
|
|
@@ -650,7 +673,7 @@ export function describeArchiverDataStore(
|
|
|
650
673
|
const targetTxIndex = randomInt(txsPerBlock);
|
|
651
674
|
const targetLogIndex = randomInt(numPublicLogs * numPublicFunctionCalls);
|
|
652
675
|
const targetContractAddress =
|
|
653
|
-
blocks[targetBlockIndex].
|
|
676
|
+
blocks[targetBlockIndex].block.body.txEffects[targetTxIndex].publicLogs[targetLogIndex].contractAddress;
|
|
654
677
|
|
|
655
678
|
const response = await store.getPublicLogs({ contractAddress: targetContractAddress });
|
|
656
679
|
|
|
@@ -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,
|
|
@@ -207,7 +207,7 @@ async function getBlockFromRollupTx(
|
|
|
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,6 +1,6 @@
|
|
|
1
1
|
export * from './archiver.js';
|
|
2
2
|
export * from './config.js';
|
|
3
|
-
export { type
|
|
3
|
+
export { type PublishedL2Block, type L1PublishedData } from './structs/published.js';
|
|
4
4
|
export { MemoryArchiverStore } from './memory_archiver_store/memory_archiver_store.js';
|
|
5
5
|
export type { ArchiverDataStore } from './archiver_store.js';
|
|
6
6
|
export { KVArchiverDataStore } from './kv_archiver_store/kv_archiver_store.js';
|