@aztec/archiver 0.72.1 → 0.74.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 +2 -2
- package/dest/archiver/archiver.d.ts.map +1 -1
- package/dest/archiver/archiver.js +31 -16
- package/dest/archiver/archiver_store.d.ts +2 -2
- package/dest/archiver/archiver_store.d.ts.map +1 -1
- package/dest/archiver/archiver_store_test_suite.d.ts +1 -1
- package/dest/archiver/archiver_store_test_suite.d.ts.map +1 -1
- package/dest/archiver/archiver_store_test_suite.js +14 -14
- package/dest/archiver/config.d.ts +1 -1
- package/dest/archiver/config.d.ts.map +1 -1
- package/dest/archiver/config.js +4 -4
- package/dest/archiver/data_retrieval.d.ts +3 -2
- package/dest/archiver/data_retrieval.d.ts.map +1 -1
- package/dest/archiver/data_retrieval.js +83 -16
- package/dest/archiver/errors.d.ts +4 -0
- package/dest/archiver/errors.d.ts.map +1 -0
- package/dest/archiver/errors.js +6 -0
- package/dest/archiver/kv_archiver_store/block_store.d.ts +16 -16
- package/dest/archiver/kv_archiver_store/block_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/block_store.js +53 -53
- package/dest/archiver/kv_archiver_store/contract_class_store.d.ts +5 -5
- package/dest/archiver/kv_archiver_store/contract_class_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/contract_class_store.js +13 -12
- package/dest/archiver/kv_archiver_store/contract_instance_store.d.ts +3 -3
- package/dest/archiver/kv_archiver_store/contract_instance_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/contract_instance_store.js +3 -3
- package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts +3 -7
- package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/kv_archiver_store.js +39 -61
- package/dest/archiver/kv_archiver_store/log_store.d.ts +5 -5
- package/dest/archiver/kv_archiver_store/log_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/log_store.js +54 -53
- package/dest/archiver/kv_archiver_store/message_store.d.ts +6 -6
- package/dest/archiver/kv_archiver_store/message_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/message_store.js +16 -16
- package/dest/archiver/kv_archiver_store/nullifier_store.d.ts +2 -2
- package/dest/archiver/kv_archiver_store/nullifier_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/nullifier_store.js +31 -22
- package/dest/archiver/memory_archiver_store/memory_archiver_store.d.ts +2 -2
- package/dest/archiver/memory_archiver_store/memory_archiver_store.d.ts.map +1 -1
- package/dest/archiver/memory_archiver_store/memory_archiver_store.js +24 -22
- package/dest/factory.js +7 -7
- package/dest/test/mock_l2_block_source.d.ts +2 -2
- package/dest/test/mock_l2_block_source.d.ts.map +1 -1
- package/dest/test/mock_l2_block_source.js +12 -9
- package/package.json +12 -12
- package/src/archiver/archiver.ts +38 -18
- package/src/archiver/archiver_store.ts +1 -1
- package/src/archiver/archiver_store_test_suite.ts +17 -14
- package/src/archiver/config.ts +4 -4
- package/src/archiver/data_retrieval.ts +108 -12
- package/src/archiver/errors.ts +5 -0
- package/src/archiver/kv_archiver_store/block_store.ts +66 -67
- package/src/archiver/kv_archiver_store/contract_class_store.ts +17 -15
- package/src/archiver/kv_archiver_store/contract_instance_store.ts +5 -5
- package/src/archiver/kv_archiver_store/kv_archiver_store.ts +43 -62
- package/src/archiver/kv_archiver_store/log_store.ts +79 -71
- package/src/archiver/kv_archiver_store/message_store.ts +22 -22
- package/src/archiver/kv_archiver_store/nullifier_store.ts +48 -30
- package/src/archiver/memory_archiver_store/memory_archiver_store.ts +44 -43
- package/src/factory.ts +10 -8
- package/src/test/mock_l2_block_source.ts +18 -16
|
@@ -7,17 +7,18 @@ import {
|
|
|
7
7
|
type UnconstrainedFunctionWithMembershipProof,
|
|
8
8
|
Vector,
|
|
9
9
|
} from '@aztec/circuits.js';
|
|
10
|
+
import { toArray } from '@aztec/foundation/iterable';
|
|
10
11
|
import { BufferReader, numToUInt8, serializeToBuffer } from '@aztec/foundation/serialize';
|
|
11
|
-
import {
|
|
12
|
+
import type { AztecAsyncKVStore, AztecAsyncMap } from '@aztec/kv-store';
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* LMDB implementation of the ArchiverDataStore interface.
|
|
15
16
|
*/
|
|
16
17
|
export class ContractClassStore {
|
|
17
|
-
#contractClasses:
|
|
18
|
-
#bytecodeCommitments:
|
|
18
|
+
#contractClasses: AztecAsyncMap<string, Buffer>;
|
|
19
|
+
#bytecodeCommitments: AztecAsyncMap<string, Buffer>;
|
|
19
20
|
|
|
20
|
-
constructor(private db:
|
|
21
|
+
constructor(private db: AztecAsyncKVStore) {
|
|
21
22
|
this.#contractClasses = db.openMap('archiver_contract_classes');
|
|
22
23
|
this.#bytecodeCommitments = db.openMap('archiver_bytecode_commitments');
|
|
23
24
|
}
|
|
@@ -35,25 +36,25 @@ export class ContractClassStore {
|
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
async deleteContractClasses(contractClass: ContractClassPublic, blockNumber: number): Promise<void> {
|
|
38
|
-
const restoredContractClass = this.#contractClasses.
|
|
39
|
+
const restoredContractClass = await this.#contractClasses.getAsync(contractClass.id.toString());
|
|
39
40
|
if (restoredContractClass && deserializeContractClassPublic(restoredContractClass).l2BlockNumber >= blockNumber) {
|
|
40
41
|
await this.#contractClasses.delete(contractClass.id.toString());
|
|
41
42
|
await this.#bytecodeCommitments.delete(contractClass.id.toString());
|
|
42
43
|
}
|
|
43
44
|
}
|
|
44
45
|
|
|
45
|
-
getContractClass(id: Fr): ContractClassPublic | undefined {
|
|
46
|
-
const contractClass = this.#contractClasses.
|
|
46
|
+
async getContractClass(id: Fr): Promise<ContractClassPublic | undefined> {
|
|
47
|
+
const contractClass = await this.#contractClasses.getAsync(id.toString());
|
|
47
48
|
return contractClass && { ...deserializeContractClassPublic(contractClass), id };
|
|
48
49
|
}
|
|
49
50
|
|
|
50
|
-
getBytecodeCommitment(id: Fr): Fr | undefined {
|
|
51
|
-
const value = this.#bytecodeCommitments.
|
|
51
|
+
async getBytecodeCommitment(id: Fr): Promise<Fr | undefined> {
|
|
52
|
+
const value = await this.#bytecodeCommitments.getAsync(id.toString());
|
|
52
53
|
return value === undefined ? undefined : Fr.fromBuffer(value);
|
|
53
54
|
}
|
|
54
55
|
|
|
55
|
-
getContractClassIds(): Fr[] {
|
|
56
|
-
return
|
|
56
|
+
async getContractClassIds(): Promise<Fr[]> {
|
|
57
|
+
return (await toArray(this.#contractClasses.keysAsync())).map(key => Fr.fromHexString(key));
|
|
57
58
|
}
|
|
58
59
|
|
|
59
60
|
async addFunctions(
|
|
@@ -61,8 +62,8 @@ export class ContractClassStore {
|
|
|
61
62
|
newPrivateFunctions: ExecutablePrivateFunctionWithMembershipProof[],
|
|
62
63
|
newUnconstrainedFunctions: UnconstrainedFunctionWithMembershipProof[],
|
|
63
64
|
): Promise<boolean> {
|
|
64
|
-
await this.db.
|
|
65
|
-
const existingClassBuffer = this.#contractClasses.
|
|
65
|
+
await this.db.transactionAsync(async () => {
|
|
66
|
+
const existingClassBuffer = await this.#contractClasses.getAsync(contractClassId.toString());
|
|
66
67
|
if (!existingClassBuffer) {
|
|
67
68
|
throw new Error(`Unknown contract class ${contractClassId} when adding private functions to store`);
|
|
68
69
|
}
|
|
@@ -83,9 +84,10 @@ export class ContractClassStore {
|
|
|
83
84
|
),
|
|
84
85
|
],
|
|
85
86
|
};
|
|
86
|
-
|
|
87
|
+
await this.#contractClasses.set(contractClassId.toString(), serializeContractClassPublic(updatedClass));
|
|
87
88
|
});
|
|
88
|
-
|
|
89
|
+
|
|
90
|
+
return true;
|
|
89
91
|
}
|
|
90
92
|
}
|
|
91
93
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { type AztecAddress, type ContractInstanceWithAddress, SerializableContractInstance } from '@aztec/circuits.js';
|
|
2
|
-
import {
|
|
2
|
+
import type { AztecAsyncKVStore, AztecAsyncMap } from '@aztec/kv-store';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* LMDB implementation of the ArchiverDataStore interface.
|
|
6
6
|
*/
|
|
7
7
|
export class ContractInstanceStore {
|
|
8
|
-
#contractInstances:
|
|
8
|
+
#contractInstances: AztecAsyncMap<string, Buffer>;
|
|
9
9
|
|
|
10
|
-
constructor(db:
|
|
10
|
+
constructor(db: AztecAsyncKVStore) {
|
|
11
11
|
this.#contractInstances = db.openMap('archiver_contract_instances');
|
|
12
12
|
}
|
|
13
13
|
|
|
@@ -22,8 +22,8 @@ export class ContractInstanceStore {
|
|
|
22
22
|
return this.#contractInstances.delete(contractInstance.address.toString());
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
getContractInstance(address: AztecAddress): ContractInstanceWithAddress | undefined {
|
|
26
|
-
const contractInstance = this.#contractInstances.
|
|
25
|
+
async getContractInstance(address: AztecAddress): Promise<ContractInstanceWithAddress | undefined> {
|
|
26
|
+
const contractInstance = await this.#contractInstances.getAsync(address.toString());
|
|
27
27
|
return contractInstance && SerializableContractInstance.fromBuffer(contractInstance).withAddress(address);
|
|
28
28
|
}
|
|
29
29
|
}
|
|
@@ -20,8 +20,9 @@ import {
|
|
|
20
20
|
} from '@aztec/circuits.js';
|
|
21
21
|
import { FunctionSelector } from '@aztec/foundation/abi';
|
|
22
22
|
import { type AztecAddress } from '@aztec/foundation/aztec-address';
|
|
23
|
+
import { toArray } from '@aztec/foundation/iterable';
|
|
23
24
|
import { createLogger } from '@aztec/foundation/log';
|
|
24
|
-
import { type
|
|
25
|
+
import { type AztecAsyncKVStore, type StoreSize } from '@aztec/kv-store';
|
|
25
26
|
|
|
26
27
|
import { type ArchiverDataStore, type ArchiverL1SynchPoint } from '../archiver_store.js';
|
|
27
28
|
import { type DataRetrieval } from '../structs/data_retrieval.js';
|
|
@@ -47,7 +48,7 @@ export class KVArchiverDataStore implements ArchiverDataStore {
|
|
|
47
48
|
|
|
48
49
|
#log = createLogger('archiver:data-store');
|
|
49
50
|
|
|
50
|
-
constructor(private db:
|
|
51
|
+
constructor(private db: AztecAsyncKVStore, logsMaxPageSize: number = 1000) {
|
|
51
52
|
this.#blockStore = new BlockStore(db);
|
|
52
53
|
this.#logStore = new LogStore(db, this.#blockStore, logsMaxPageSize);
|
|
53
54
|
this.#messageStore = new MessageStore(db);
|
|
@@ -63,30 +64,28 @@ export class KVArchiverDataStore implements ArchiverDataStore {
|
|
|
63
64
|
return Promise.resolve(this.functionNames.get(selector.toString()));
|
|
64
65
|
}
|
|
65
66
|
|
|
66
|
-
registerContractFunctionSignatures(_address: AztecAddress, signatures: string[]): Promise<void> {
|
|
67
|
+
async registerContractFunctionSignatures(_address: AztecAddress, signatures: string[]): Promise<void> {
|
|
67
68
|
for (const sig of signatures) {
|
|
68
69
|
try {
|
|
69
|
-
const selector = FunctionSelector.fromSignature(sig);
|
|
70
|
+
const selector = await FunctionSelector.fromSignature(sig);
|
|
70
71
|
this.functionNames.set(selector.toString(), sig.slice(0, sig.indexOf('(')));
|
|
71
72
|
} catch {
|
|
72
73
|
this.#log.warn(`Failed to parse signature: ${sig}. Ignoring`);
|
|
73
74
|
}
|
|
74
75
|
}
|
|
75
|
-
|
|
76
|
-
return Promise.resolve();
|
|
77
76
|
}
|
|
78
77
|
|
|
79
78
|
getContractClass(id: Fr): Promise<ContractClassPublic | undefined> {
|
|
80
|
-
return
|
|
79
|
+
return this.#contractClassStore.getContractClass(id);
|
|
81
80
|
}
|
|
82
81
|
|
|
83
82
|
getContractClassIds(): Promise<Fr[]> {
|
|
84
|
-
return
|
|
83
|
+
return this.#contractClassStore.getContractClassIds();
|
|
85
84
|
}
|
|
86
85
|
|
|
87
86
|
getContractInstance(address: AztecAddress): Promise<ContractInstanceWithAddress | undefined> {
|
|
88
87
|
const contract = this.#contractInstanceStore.getContractInstance(address);
|
|
89
|
-
return
|
|
88
|
+
return contract;
|
|
90
89
|
}
|
|
91
90
|
|
|
92
91
|
async addContractClasses(
|
|
@@ -108,7 +107,7 @@ export class KVArchiverDataStore implements ArchiverDataStore {
|
|
|
108
107
|
}
|
|
109
108
|
|
|
110
109
|
getBytecodeCommitment(contractClassId: Fr): Promise<Fr | undefined> {
|
|
111
|
-
return
|
|
110
|
+
return this.#contractClassStore.getBytecodeCommitment(contractClassId);
|
|
112
111
|
}
|
|
113
112
|
|
|
114
113
|
addFunctions(
|
|
@@ -155,12 +154,7 @@ export class KVArchiverDataStore implements ArchiverDataStore {
|
|
|
155
154
|
* @returns The requested L2 blocks
|
|
156
155
|
*/
|
|
157
156
|
getBlocks(start: number, limit: number): Promise<L1Published<L2Block>[]> {
|
|
158
|
-
|
|
159
|
-
return Promise.resolve(Array.from(this.#blockStore.getBlocks(start, limit)));
|
|
160
|
-
} catch (err) {
|
|
161
|
-
// this function is sync so if any errors are thrown we need to make sure they're passed on as rejected Promises
|
|
162
|
-
return Promise.reject(err);
|
|
163
|
-
}
|
|
157
|
+
return toArray(this.#blockStore.getBlocks(start, limit));
|
|
164
158
|
}
|
|
165
159
|
|
|
166
160
|
/**
|
|
@@ -171,12 +165,7 @@ export class KVArchiverDataStore implements ArchiverDataStore {
|
|
|
171
165
|
* @returns The requested L2 blocks
|
|
172
166
|
*/
|
|
173
167
|
getBlockHeaders(start: number, limit: number): Promise<BlockHeader[]> {
|
|
174
|
-
|
|
175
|
-
return Promise.resolve(Array.from(this.#blockStore.getBlockHeaders(start, limit)));
|
|
176
|
-
} catch (err) {
|
|
177
|
-
// this function is sync so if any errors are thrown we need to make sure they're passed on as rejected Promises
|
|
178
|
-
return Promise.reject(err);
|
|
179
|
-
}
|
|
168
|
+
return toArray(this.#blockStore.getBlockHeaders(start, limit));
|
|
180
169
|
}
|
|
181
170
|
|
|
182
171
|
/**
|
|
@@ -185,7 +174,7 @@ export class KVArchiverDataStore implements ArchiverDataStore {
|
|
|
185
174
|
* @returns The requested tx effect (or undefined if not found).
|
|
186
175
|
*/
|
|
187
176
|
getTxEffect(txHash: TxHash) {
|
|
188
|
-
return
|
|
177
|
+
return this.#blockStore.getTxEffect(txHash);
|
|
189
178
|
}
|
|
190
179
|
|
|
191
180
|
/**
|
|
@@ -194,7 +183,7 @@ export class KVArchiverDataStore implements ArchiverDataStore {
|
|
|
194
183
|
* @returns The requested tx receipt (or undefined if not found).
|
|
195
184
|
*/
|
|
196
185
|
getSettledTxReceipt(txHash: TxHash): Promise<TxReceipt | undefined> {
|
|
197
|
-
return
|
|
186
|
+
return this.#blockStore.getSettledTxReceipt(txHash);
|
|
198
187
|
}
|
|
199
188
|
|
|
200
189
|
/**
|
|
@@ -228,7 +217,7 @@ export class KVArchiverDataStore implements ArchiverDataStore {
|
|
|
228
217
|
}
|
|
229
218
|
|
|
230
219
|
getTotalL1ToL2MessageCount(): Promise<bigint> {
|
|
231
|
-
return
|
|
220
|
+
return this.#messageStore.getTotalL1ToL2MessageCount();
|
|
232
221
|
}
|
|
233
222
|
|
|
234
223
|
/**
|
|
@@ -237,7 +226,7 @@ export class KVArchiverDataStore implements ArchiverDataStore {
|
|
|
237
226
|
* @returns True if the operation is successful.
|
|
238
227
|
*/
|
|
239
228
|
addL1ToL2Messages(messages: DataRetrieval<InboxLeaf>): Promise<boolean> {
|
|
240
|
-
return
|
|
229
|
+
return this.#messageStore.addL1ToL2Messages(messages);
|
|
241
230
|
}
|
|
242
231
|
|
|
243
232
|
/**
|
|
@@ -246,7 +235,7 @@ export class KVArchiverDataStore implements ArchiverDataStore {
|
|
|
246
235
|
* @returns The index of the L1 to L2 message in the L1 to L2 message tree (undefined if not found).
|
|
247
236
|
*/
|
|
248
237
|
getL1ToL2MessageIndex(l1ToL2Message: Fr): Promise<bigint | undefined> {
|
|
249
|
-
return
|
|
238
|
+
return this.#messageStore.getL1ToL2MessageIndex(l1ToL2Message);
|
|
250
239
|
}
|
|
251
240
|
|
|
252
241
|
/**
|
|
@@ -255,11 +244,7 @@ export class KVArchiverDataStore implements ArchiverDataStore {
|
|
|
255
244
|
* @returns The L1 to L2 messages/leaves of the messages subtree (throws if not found).
|
|
256
245
|
*/
|
|
257
246
|
getL1ToL2Messages(blockNumber: bigint): Promise<Fr[]> {
|
|
258
|
-
|
|
259
|
-
return Promise.resolve(this.#messageStore.getL1ToL2Messages(blockNumber));
|
|
260
|
-
} catch (err) {
|
|
261
|
-
return Promise.reject(err);
|
|
262
|
-
}
|
|
247
|
+
return this.#messageStore.getL1ToL2Messages(blockNumber);
|
|
263
248
|
}
|
|
264
249
|
|
|
265
250
|
/**
|
|
@@ -269,11 +254,7 @@ export class KVArchiverDataStore implements ArchiverDataStore {
|
|
|
269
254
|
* @returns An array of private logs from the specified range of blocks.
|
|
270
255
|
*/
|
|
271
256
|
getPrivateLogs(from: number, limit: number): Promise<PrivateLog[]> {
|
|
272
|
-
|
|
273
|
-
return Promise.resolve(Array.from(this.#logStore.getPrivateLogs(from, limit)));
|
|
274
|
-
} catch (err) {
|
|
275
|
-
return Promise.reject(err);
|
|
276
|
-
}
|
|
257
|
+
return this.#logStore.getPrivateLogs(from, limit);
|
|
277
258
|
}
|
|
278
259
|
|
|
279
260
|
/**
|
|
@@ -297,7 +278,7 @@ export class KVArchiverDataStore implements ArchiverDataStore {
|
|
|
297
278
|
*/
|
|
298
279
|
getPublicLogs(filter: LogFilter): Promise<GetPublicLogsResponse> {
|
|
299
280
|
try {
|
|
300
|
-
return
|
|
281
|
+
return this.#logStore.getPublicLogs(filter);
|
|
301
282
|
} catch (err) {
|
|
302
283
|
return Promise.reject(err);
|
|
303
284
|
}
|
|
@@ -310,7 +291,7 @@ export class KVArchiverDataStore implements ArchiverDataStore {
|
|
|
310
291
|
*/
|
|
311
292
|
getContractClassLogs(filter: LogFilter): Promise<GetContractClassLogsResponse> {
|
|
312
293
|
try {
|
|
313
|
-
return
|
|
294
|
+
return this.#logStore.getContractClassLogs(filter);
|
|
314
295
|
} catch (err) {
|
|
315
296
|
return Promise.reject(err);
|
|
316
297
|
}
|
|
@@ -321,48 +302,48 @@ export class KVArchiverDataStore implements ArchiverDataStore {
|
|
|
321
302
|
* @returns The number of the latest L2 block processed.
|
|
322
303
|
*/
|
|
323
304
|
getSynchedL2BlockNumber(): Promise<number> {
|
|
324
|
-
return
|
|
305
|
+
return this.#blockStore.getSynchedL2BlockNumber();
|
|
325
306
|
}
|
|
326
307
|
|
|
327
308
|
getProvenL2BlockNumber(): Promise<number> {
|
|
328
|
-
return
|
|
309
|
+
return this.#blockStore.getProvenL2BlockNumber();
|
|
329
310
|
}
|
|
330
311
|
|
|
331
312
|
getProvenL2EpochNumber(): Promise<number | undefined> {
|
|
332
|
-
return
|
|
313
|
+
return this.#blockStore.getProvenL2EpochNumber();
|
|
333
314
|
}
|
|
334
315
|
|
|
335
|
-
setProvenL2BlockNumber(blockNumber: number) {
|
|
336
|
-
this.#blockStore.setProvenL2BlockNumber(blockNumber);
|
|
337
|
-
return Promise.resolve();
|
|
316
|
+
async setProvenL2BlockNumber(blockNumber: number) {
|
|
317
|
+
await this.#blockStore.setProvenL2BlockNumber(blockNumber);
|
|
338
318
|
}
|
|
339
319
|
|
|
340
|
-
setProvenL2EpochNumber(epochNumber: number) {
|
|
341
|
-
this.#blockStore.setProvenL2EpochNumber(epochNumber);
|
|
342
|
-
return Promise.resolve();
|
|
320
|
+
async setProvenL2EpochNumber(epochNumber: number) {
|
|
321
|
+
await this.#blockStore.setProvenL2EpochNumber(epochNumber);
|
|
343
322
|
}
|
|
344
323
|
|
|
345
|
-
setBlockSynchedL1BlockNumber(l1BlockNumber: bigint) {
|
|
346
|
-
this.#blockStore.setSynchedL1BlockNumber(l1BlockNumber);
|
|
347
|
-
return Promise.resolve();
|
|
324
|
+
async setBlockSynchedL1BlockNumber(l1BlockNumber: bigint) {
|
|
325
|
+
await this.#blockStore.setSynchedL1BlockNumber(l1BlockNumber);
|
|
348
326
|
}
|
|
349
327
|
|
|
350
|
-
setMessageSynchedL1BlockNumber(l1BlockNumber: bigint) {
|
|
351
|
-
this.#messageStore.setSynchedL1BlockNumber(l1BlockNumber);
|
|
352
|
-
return Promise.resolve();
|
|
328
|
+
async setMessageSynchedL1BlockNumber(l1BlockNumber: bigint) {
|
|
329
|
+
await this.#messageStore.setSynchedL1BlockNumber(l1BlockNumber);
|
|
353
330
|
}
|
|
354
331
|
|
|
355
332
|
/**
|
|
356
333
|
* Gets the last L1 block number processed by the archiver
|
|
357
334
|
*/
|
|
358
|
-
getSynchPoint(): Promise<ArchiverL1SynchPoint> {
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
335
|
+
async getSynchPoint(): Promise<ArchiverL1SynchPoint> {
|
|
336
|
+
const [blocksSynchedTo, messagesSynchedTo] = await Promise.all([
|
|
337
|
+
this.#blockStore.getSynchedL1BlockNumber(),
|
|
338
|
+
this.#messageStore.getSynchedL1BlockNumber(),
|
|
339
|
+
]);
|
|
340
|
+
return {
|
|
341
|
+
blocksSynchedTo,
|
|
342
|
+
messagesSynchedTo,
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
public estimateSize(): Promise<StoreSize> {
|
|
366
347
|
return this.db.estimateSize();
|
|
367
348
|
}
|
|
368
349
|
}
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
} from '@aztec/circuits.js/constants';
|
|
19
19
|
import { createLogger } from '@aztec/foundation/log';
|
|
20
20
|
import { BufferReader, numToUInt32BE } from '@aztec/foundation/serialize';
|
|
21
|
-
import {
|
|
21
|
+
import type { AztecAsyncKVStore, AztecAsyncMap } from '@aztec/kv-store';
|
|
22
22
|
|
|
23
23
|
import { type BlockStore } from './block_store.js';
|
|
24
24
|
|
|
@@ -26,15 +26,15 @@ import { type BlockStore } from './block_store.js';
|
|
|
26
26
|
* A store for logs
|
|
27
27
|
*/
|
|
28
28
|
export class LogStore {
|
|
29
|
-
#logsByTag:
|
|
30
|
-
#logTagsByBlock:
|
|
31
|
-
#privateLogsByBlock:
|
|
32
|
-
#publicLogsByBlock:
|
|
33
|
-
#contractClassLogsByBlock:
|
|
29
|
+
#logsByTag: AztecAsyncMap<string, Buffer[]>;
|
|
30
|
+
#logTagsByBlock: AztecAsyncMap<number, string[]>;
|
|
31
|
+
#privateLogsByBlock: AztecAsyncMap<number, Buffer>;
|
|
32
|
+
#publicLogsByBlock: AztecAsyncMap<number, Buffer>;
|
|
33
|
+
#contractClassLogsByBlock: AztecAsyncMap<number, Buffer>;
|
|
34
34
|
#logsMaxPageSize: number;
|
|
35
35
|
#log = createLogger('archiver:log_store');
|
|
36
36
|
|
|
37
|
-
constructor(private db:
|
|
37
|
+
constructor(private db: AztecAsyncKVStore, private blockStore: BlockStore, logsMaxPageSize: number = 1000) {
|
|
38
38
|
this.#logsByTag = db.openMap('archiver_tagged_logs_by_tag');
|
|
39
39
|
this.#logTagsByBlock = db.openMap('archiver_log_tags_by_block');
|
|
40
40
|
this.#privateLogsByBlock = db.openMap('archiver_private_logs_by_block');
|
|
@@ -79,21 +79,19 @@ export class LogStore {
|
|
|
79
79
|
const txHash = txEffect.txHash;
|
|
80
80
|
const dataStartIndexForTx = dataStartIndexForBlock + txIndex * MAX_NOTE_HASHES_PER_TX;
|
|
81
81
|
txEffect.publicLogs.forEach(log => {
|
|
82
|
-
// Check that each log stores
|
|
82
|
+
// Check that each log stores 2 lengths in its first field. If not, it's not a tagged log:
|
|
83
83
|
const firstFieldBuf = log.log[0].toBuffer();
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
// See parseLogFromPublic - the first field of a tagged log is 8 bytes structured:
|
|
90
|
-
// [ publicLen[0], publicLen[1], 0, privateLen[0], privateLen[1], 0, ciphertextLen[0], ciphertextLen[1]]
|
|
84
|
+
// See macros/note/mod/ and see how finalization_log[0] is constructed, to understand this monstrosity. (It wasn't me).
|
|
85
|
+
// 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.
|
|
86
|
+
if (!firstFieldBuf.subarray(0, 27).equals(Buffer.alloc(27)) || firstFieldBuf[29] !== 0) {
|
|
87
|
+
// See parseLogFromPublic - the first field of a tagged log is 5 bytes structured:
|
|
88
|
+
// [ publicLen[0], publicLen[1], 0, privateLen[0], privateLen[1]]
|
|
91
89
|
this.#log.warn(`Skipping public log with invalid first field: ${log.log[0]}`);
|
|
92
90
|
return;
|
|
93
91
|
}
|
|
94
92
|
// Check that the length values line up with the log contents
|
|
95
|
-
const publicValuesLength = firstFieldBuf.subarray(-
|
|
96
|
-
const privateValuesLength = firstFieldBuf.subarray(-
|
|
93
|
+
const publicValuesLength = firstFieldBuf.subarray(-5).readUint16BE();
|
|
94
|
+
const privateValuesLength = firstFieldBuf.subarray(-5).readUint16BE(3);
|
|
97
95
|
// Add 1 for the first field holding lengths
|
|
98
96
|
const totalLogLength = 1 + publicValuesLength + privateValuesLength;
|
|
99
97
|
// Note that zeroes can be valid log values, so we can only assert that we do not go over the given length
|
|
@@ -127,7 +125,7 @@ export class LogStore {
|
|
|
127
125
|
* @param blocks - The blocks for which to add the logs.
|
|
128
126
|
* @returns True if the operation is successful.
|
|
129
127
|
*/
|
|
130
|
-
|
|
128
|
+
addLogs(blocks: L2Block[]): Promise<boolean> {
|
|
131
129
|
const taggedLogsToAdd = blocks
|
|
132
130
|
.flatMap(block => [this.#extractTaggedLogsFromPrivate(block), this.#extractTaggedLogsFromPublic(block)])
|
|
133
131
|
.reduce((acc, val) => {
|
|
@@ -138,31 +136,32 @@ export class LogStore {
|
|
|
138
136
|
return acc;
|
|
139
137
|
});
|
|
140
138
|
const tagsToUpdate = Array.from(taggedLogsToAdd.keys());
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
139
|
+
|
|
140
|
+
return this.db.transactionAsync(async () => {
|
|
141
|
+
const currentTaggedLogs = await Promise.all(
|
|
142
|
+
tagsToUpdate.map(async tag => ({ tag, logBuffers: await this.#logsByTag.getAsync(tag) })),
|
|
143
|
+
);
|
|
144
|
+
currentTaggedLogs.forEach(taggedLogBuffer => {
|
|
145
|
+
if (taggedLogBuffer.logBuffers && taggedLogBuffer.logBuffers.length > 0) {
|
|
146
|
+
taggedLogsToAdd.set(
|
|
147
|
+
taggedLogBuffer.tag,
|
|
148
|
+
taggedLogBuffer.logBuffers!.concat(taggedLogsToAdd.get(taggedLogBuffer.tag)!),
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
for (const block of blocks) {
|
|
154
153
|
const tagsInBlock = [];
|
|
155
154
|
for (const [tag, logs] of taggedLogsToAdd.entries()) {
|
|
156
|
-
|
|
155
|
+
await this.#logsByTag.set(tag, logs);
|
|
157
156
|
tagsInBlock.push(tag);
|
|
158
157
|
}
|
|
159
|
-
|
|
158
|
+
await this.#logTagsByBlock.set(block.number, tagsInBlock);
|
|
160
159
|
|
|
161
160
|
const privateLogsInBlock = block.body.txEffects
|
|
162
161
|
.map(txEffect => txEffect.privateLogs)
|
|
163
162
|
.flat()
|
|
164
163
|
.map(log => log.toBuffer());
|
|
165
|
-
|
|
164
|
+
await this.#privateLogsByBlock.set(block.number, Buffer.concat(privateLogsInBlock));
|
|
166
165
|
|
|
167
166
|
const publicLogsInBlock = block.body.txEffects
|
|
168
167
|
.map((txEffect, txIndex) =>
|
|
@@ -174,29 +173,36 @@ export class LogStore {
|
|
|
174
173
|
)
|
|
175
174
|
.flat();
|
|
176
175
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
}
|
|
176
|
+
await this.#publicLogsByBlock.set(block.number, Buffer.concat(publicLogsInBlock));
|
|
177
|
+
await this.#contractClassLogsByBlock.set(block.number, block.body.contractClassLogs.toBuffer());
|
|
178
|
+
}
|
|
180
179
|
|
|
181
180
|
return true;
|
|
182
181
|
});
|
|
183
182
|
}
|
|
184
183
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
184
|
+
deleteLogs(blocks: L2Block[]): Promise<boolean> {
|
|
185
|
+
return this.db.transactionAsync(async () => {
|
|
186
|
+
const tagsToDelete = (
|
|
187
|
+
await Promise.all(
|
|
188
|
+
blocks.map(async block => {
|
|
189
|
+
const tags = await this.#logTagsByBlock.getAsync(block.number);
|
|
190
|
+
return tags ?? [];
|
|
191
|
+
}),
|
|
192
|
+
)
|
|
193
|
+
).flat();
|
|
194
|
+
|
|
195
|
+
await Promise.all(
|
|
196
|
+
blocks.map(block =>
|
|
197
|
+
Promise.all([
|
|
198
|
+
this.#privateLogsByBlock.delete(block.number),
|
|
199
|
+
this.#publicLogsByBlock.delete(block.number),
|
|
200
|
+
this.#logTagsByBlock.delete(block.number),
|
|
201
|
+
]),
|
|
202
|
+
),
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
await Promise.all(tagsToDelete.map(tag => this.#logsByTag.delete(tag.toString())));
|
|
200
206
|
return true;
|
|
201
207
|
});
|
|
202
208
|
}
|
|
@@ -207,9 +213,9 @@ export class LogStore {
|
|
|
207
213
|
* @param limit - The maximum number of blocks to retrieve logs from.
|
|
208
214
|
* @returns An array of private logs from the specified range of blocks.
|
|
209
215
|
*/
|
|
210
|
-
getPrivateLogs(start: number, limit: number) {
|
|
216
|
+
async getPrivateLogs(start: number, limit: number): Promise<PrivateLog[]> {
|
|
211
217
|
const logs = [];
|
|
212
|
-
for (const buffer of this.#privateLogsByBlock.
|
|
218
|
+
for await (const buffer of this.#privateLogsByBlock.valuesAsync({ start, limit })) {
|
|
213
219
|
const reader = new BufferReader(buffer);
|
|
214
220
|
while (reader.remainingBytes() > 0) {
|
|
215
221
|
logs.push(reader.readObject(PrivateLog));
|
|
@@ -224,11 +230,10 @@ export class LogStore {
|
|
|
224
230
|
* @returns For each received tag, an array of matching logs is returned. An empty array implies no logs match
|
|
225
231
|
* that tag.
|
|
226
232
|
*/
|
|
227
|
-
getLogsByTags(tags: Fr[]): Promise<TxScopedL2Log[][]> {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
.map(noteLogBuffers => noteLogBuffers?.map(noteLogBuffer => TxScopedL2Log.fromBuffer(noteLogBuffer)) ?? []),
|
|
233
|
+
async getLogsByTags(tags: Fr[]): Promise<TxScopedL2Log[][]> {
|
|
234
|
+
const logs = await Promise.all(tags.map(tag => this.#logsByTag.getAsync(tag.toString())));
|
|
235
|
+
return logs.map(
|
|
236
|
+
noteLogBuffers => noteLogBuffers?.map(noteLogBuffer => TxScopedL2Log.fromBuffer(noteLogBuffer)) ?? [],
|
|
232
237
|
);
|
|
233
238
|
}
|
|
234
239
|
|
|
@@ -237,7 +242,7 @@ export class LogStore {
|
|
|
237
242
|
* @param filter - The filter to apply to the logs.
|
|
238
243
|
* @returns The requested logs.
|
|
239
244
|
*/
|
|
240
|
-
getPublicLogs(filter: LogFilter): GetPublicLogsResponse {
|
|
245
|
+
getPublicLogs(filter: LogFilter): Promise<GetPublicLogsResponse> {
|
|
241
246
|
if (filter.afterLog) {
|
|
242
247
|
return this.#filterPublicLogsBetweenBlocks(filter);
|
|
243
248
|
} else if (filter.txHash) {
|
|
@@ -247,17 +252,17 @@ export class LogStore {
|
|
|
247
252
|
}
|
|
248
253
|
}
|
|
249
254
|
|
|
250
|
-
#filterPublicLogsOfTx(filter: LogFilter): GetPublicLogsResponse {
|
|
255
|
+
async #filterPublicLogsOfTx(filter: LogFilter): Promise<GetPublicLogsResponse> {
|
|
251
256
|
if (!filter.txHash) {
|
|
252
257
|
throw new Error('Missing txHash');
|
|
253
258
|
}
|
|
254
259
|
|
|
255
|
-
const [blockNumber, txIndex] = this.blockStore.getTxLocation(filter.txHash) ?? [];
|
|
260
|
+
const [blockNumber, txIndex] = (await this.blockStore.getTxLocation(filter.txHash)) ?? [];
|
|
256
261
|
if (typeof blockNumber !== 'number' || typeof txIndex !== 'number') {
|
|
257
262
|
return { logs: [], maxLogsHit: false };
|
|
258
263
|
}
|
|
259
264
|
|
|
260
|
-
const buffer = this.#publicLogsByBlock.
|
|
265
|
+
const buffer = (await this.#publicLogsByBlock.getAsync(blockNumber)) ?? Buffer.alloc(0);
|
|
261
266
|
const publicLogsInBlock: [PublicLog[]] = [[]];
|
|
262
267
|
const reader = new BufferReader(buffer);
|
|
263
268
|
while (reader.remainingBytes() > 0) {
|
|
@@ -277,7 +282,7 @@ export class LogStore {
|
|
|
277
282
|
return { logs, maxLogsHit };
|
|
278
283
|
}
|
|
279
284
|
|
|
280
|
-
#filterPublicLogsBetweenBlocks(filter: LogFilter): GetPublicLogsResponse {
|
|
285
|
+
async #filterPublicLogsBetweenBlocks(filter: LogFilter): Promise<GetPublicLogsResponse> {
|
|
281
286
|
const start =
|
|
282
287
|
filter.afterLog?.blockNumber ?? Math.max(filter.fromBlock ?? INITIAL_L2_BLOCK_NUM, INITIAL_L2_BLOCK_NUM);
|
|
283
288
|
const end = filter.toBlock;
|
|
@@ -292,7 +297,7 @@ export class LogStore {
|
|
|
292
297
|
const logs: ExtendedPublicLog[] = [];
|
|
293
298
|
|
|
294
299
|
let maxLogsHit = false;
|
|
295
|
-
loopOverBlocks: for (const [blockNumber, logBuffer] of this.#publicLogsByBlock.
|
|
300
|
+
loopOverBlocks: for await (const [blockNumber, logBuffer] of this.#publicLogsByBlock.entriesAsync({ start, end })) {
|
|
296
301
|
const publicLogsInBlock: [PublicLog[]] = [[]];
|
|
297
302
|
const reader = new BufferReader(logBuffer);
|
|
298
303
|
while (reader.remainingBytes() > 0) {
|
|
@@ -321,7 +326,7 @@ export class LogStore {
|
|
|
321
326
|
* @param filter - The filter to apply to the logs.
|
|
322
327
|
* @returns The requested logs.
|
|
323
328
|
*/
|
|
324
|
-
getContractClassLogs(filter: LogFilter): GetContractClassLogsResponse {
|
|
329
|
+
getContractClassLogs(filter: LogFilter): Promise<GetContractClassLogsResponse> {
|
|
325
330
|
if (filter.afterLog) {
|
|
326
331
|
return this.#filterContractClassLogsBetweenBlocks(filter);
|
|
327
332
|
} else if (filter.txHash) {
|
|
@@ -331,16 +336,16 @@ export class LogStore {
|
|
|
331
336
|
}
|
|
332
337
|
}
|
|
333
338
|
|
|
334
|
-
#filterContractClassLogsOfTx(filter: LogFilter): GetContractClassLogsResponse {
|
|
339
|
+
async #filterContractClassLogsOfTx(filter: LogFilter): Promise<GetContractClassLogsResponse> {
|
|
335
340
|
if (!filter.txHash) {
|
|
336
341
|
throw new Error('Missing txHash');
|
|
337
342
|
}
|
|
338
343
|
|
|
339
|
-
const [blockNumber, txIndex] = this.blockStore.getTxLocation(filter.txHash) ?? [];
|
|
344
|
+
const [blockNumber, txIndex] = (await this.blockStore.getTxLocation(filter.txHash)) ?? [];
|
|
340
345
|
if (typeof blockNumber !== 'number' || typeof txIndex !== 'number') {
|
|
341
346
|
return { logs: [], maxLogsHit: false };
|
|
342
347
|
}
|
|
343
|
-
const contractClassLogsBuffer = this.#contractClassLogsByBlock.
|
|
348
|
+
const contractClassLogsBuffer = await this.#contractClassLogsByBlock.getAsync(blockNumber);
|
|
344
349
|
const contractClassLogsInBlock = contractClassLogsBuffer
|
|
345
350
|
? ContractClass2BlockL2Logs.fromBuffer(contractClassLogsBuffer)
|
|
346
351
|
: new ContractClass2BlockL2Logs([]);
|
|
@@ -352,7 +357,7 @@ export class LogStore {
|
|
|
352
357
|
return { logs, maxLogsHit };
|
|
353
358
|
}
|
|
354
359
|
|
|
355
|
-
#filterContractClassLogsBetweenBlocks(filter: LogFilter): GetContractClassLogsResponse {
|
|
360
|
+
async #filterContractClassLogsBetweenBlocks(filter: LogFilter): Promise<GetContractClassLogsResponse> {
|
|
356
361
|
const start =
|
|
357
362
|
filter.afterLog?.blockNumber ?? Math.max(filter.fromBlock ?? INITIAL_L2_BLOCK_NUM, INITIAL_L2_BLOCK_NUM);
|
|
358
363
|
const end = filter.toBlock;
|
|
@@ -367,7 +372,10 @@ export class LogStore {
|
|
|
367
372
|
const logs: ExtendedUnencryptedL2Log[] = [];
|
|
368
373
|
|
|
369
374
|
let maxLogsHit = false;
|
|
370
|
-
loopOverBlocks: for (const [blockNumber, logBuffer] of this.#contractClassLogsByBlock.
|
|
375
|
+
loopOverBlocks: for await (const [blockNumber, logBuffer] of this.#contractClassLogsByBlock.entriesAsync({
|
|
376
|
+
start,
|
|
377
|
+
end,
|
|
378
|
+
})) {
|
|
371
379
|
const contractClassLogsInBlock = ContractClass2BlockL2Logs.fromBuffer(logBuffer);
|
|
372
380
|
for (let txIndex = filter.afterLog?.txIndex ?? 0; txIndex < contractClassLogsInBlock.txLogs.length; txIndex++) {
|
|
373
381
|
const txLogs = contractClassLogsInBlock.txLogs[txIndex].unrollLogs();
|