@aztec/archiver 0.1.0-alpha11
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/.eslintrc.cjs +1 -0
- package/.tsbuildinfo +1 -0
- package/README.md +17 -0
- package/dest/archiver/archiver.d.ts +147 -0
- package/dest/archiver/archiver.d.ts.map +1 -0
- package/dest/archiver/archiver.js +260 -0
- package/dest/archiver/archiver.test.d.ts +2 -0
- package/dest/archiver/archiver.test.d.ts.map +1 -0
- package/dest/archiver/archiver.test.js +188 -0
- package/dest/archiver/archiver_store.d.ts +269 -0
- package/dest/archiver/archiver_store.d.ts.map +1 -0
- package/dest/archiver/archiver_store.js +259 -0
- package/dest/archiver/config.d.ts +29 -0
- package/dest/archiver/config.d.ts.map +1 -0
- package/dest/archiver/config.js +21 -0
- package/dest/archiver/data_retrieval.d.ts +64 -0
- package/dest/archiver/data_retrieval.d.ts.map +1 -0
- package/dest/archiver/data_retrieval.js +102 -0
- package/dest/archiver/eth_log_handlers.d.ts +77 -0
- package/dest/archiver/eth_log_handlers.d.ts.map +1 -0
- package/dest/archiver/eth_log_handlers.js +178 -0
- package/dest/archiver/index.d.ts +3 -0
- package/dest/archiver/index.d.ts.map +1 -0
- package/dest/archiver/index.js +3 -0
- package/dest/archiver/l1_to_l2_message_store.d.ts +40 -0
- package/dest/archiver/l1_to_l2_message_store.d.ts.map +1 -0
- package/dest/archiver/l1_to_l2_message_store.js +71 -0
- package/dest/archiver/l1_to_l2_message_store.test.d.ts +2 -0
- package/dest/archiver/l1_to_l2_message_store.test.d.ts.map +1 -0
- package/dest/archiver/l1_to_l2_message_store.test.js +77 -0
- package/dest/index.d.ts +2 -0
- package/dest/index.d.ts.map +1 -0
- package/dest/index.js +37 -0
- package/package.json +19 -0
- package/src/archiver/archiver.test.ts +225 -0
- package/src/archiver/archiver.ts +363 -0
- package/src/archiver/archiver_store.ts +425 -0
- package/src/archiver/config.ts +55 -0
- package/src/archiver/data_retrieval.ts +167 -0
- package/src/archiver/eth_log_handlers.ts +238 -0
- package/src/archiver/index.ts +2 -0
- package/src/archiver/l1_to_l2_message_store.test.ts +97 -0
- package/src/archiver/l1_to_l2_message_store.ts +88 -0
- package/src/index.ts +51 -0
- package/tsconfig.json +23 -0
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ContractPublicData,
|
|
3
|
+
L2Block,
|
|
4
|
+
INITIAL_L2_BLOCK_NUM,
|
|
5
|
+
ContractData,
|
|
6
|
+
L1ToL2Message,
|
|
7
|
+
L2BlockL2Logs,
|
|
8
|
+
} from '@aztec/types';
|
|
9
|
+
import { Fr, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/circuits.js';
|
|
10
|
+
import { AztecAddress } from '@aztec/foundation/aztec-address';
|
|
11
|
+
import { L1ToL2MessageStore, PendingL1ToL2MessageStore } from './l1_to_l2_message_store.js';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Interface describing a data store to be used by the archiver to store all its relevant data
|
|
15
|
+
* (blocks, encrypted logs, aztec contract public data).
|
|
16
|
+
*/
|
|
17
|
+
export interface ArchiverDataStore {
|
|
18
|
+
/**
|
|
19
|
+
* Append new blocks to the store's list.
|
|
20
|
+
* @param blocks - The L2 blocks to be added to the store.
|
|
21
|
+
* @returns True if the operation is successful.
|
|
22
|
+
*/
|
|
23
|
+
addL2Blocks(blocks: L2Block[]): Promise<boolean>;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Gets the `take` amount of L2 blocks starting from `from`.
|
|
27
|
+
* @param from - Number of the first block to return (inclusive).
|
|
28
|
+
* @param take - The number of blocks to return.
|
|
29
|
+
* @returns The requested L2 blocks.
|
|
30
|
+
*/
|
|
31
|
+
getL2Blocks(from: number, take: number): Promise<L2Block[]>;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Append new encrypted logs to the store's list.
|
|
35
|
+
* @param data - The encrypted logs to be added to the store.
|
|
36
|
+
* @returns True if the operation is successful.
|
|
37
|
+
*/
|
|
38
|
+
addEncryptedLogs(data: L2BlockL2Logs[]): Promise<boolean>;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Append new unencrypted logs to the store's list.
|
|
42
|
+
* @param data - The unencrypted logs to be added to the store.
|
|
43
|
+
* @returns True if the operation is successful.
|
|
44
|
+
*/
|
|
45
|
+
addUnencryptedLogs(data: L2BlockL2Logs[]): Promise<boolean>;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Append new pending L1 to L2 messages to the store.
|
|
49
|
+
* @param messages - The L1 to L2 messages to be added to the store.
|
|
50
|
+
* @returns True if the operation is successful.
|
|
51
|
+
*/
|
|
52
|
+
addPendingL1ToL2Messages(messages: L1ToL2Message[]): Promise<boolean>;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Remove pending L1 to L2 messages from the store (if they were cancelled).
|
|
56
|
+
* @param messageKeys - The message keys to be removed from the store.
|
|
57
|
+
* @returns True if the operation is successful.
|
|
58
|
+
*/
|
|
59
|
+
cancelPendingL1ToL2Messages(messageKeys: Fr[]): Promise<boolean>;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Messages that have been published in an L2 block are confirmed.
|
|
63
|
+
* Add them to the confirmed store, also remove them from the pending store.
|
|
64
|
+
* @param messageKeys - The message keys to be removed from the store.
|
|
65
|
+
* @returns True if the operation is successful.
|
|
66
|
+
*/
|
|
67
|
+
confirmL1ToL2Messages(messageKeys: Fr[]): Promise<boolean>;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Gets the `take` amount of pending L1 to L2 messages, sorted by fee
|
|
71
|
+
* @param take - The number of messages to return (by default NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).
|
|
72
|
+
* @returns The requested L1 to L2 message keys.
|
|
73
|
+
*/
|
|
74
|
+
getPendingL1ToL2MessageKeys(take: number): Promise<Fr[]>;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Gets the confirmed L1 to L2 message corresponding to the given message key.
|
|
78
|
+
* @param messageKey - The message key to look up.
|
|
79
|
+
* @returns The requested L1 to L2 message or throws if not found.
|
|
80
|
+
*/
|
|
81
|
+
getConfirmedL1ToL2Message(messageKey: Fr): Promise<L1ToL2Message>;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Gets the `take` amount of encrypted logs starting from `from`.
|
|
85
|
+
* @param from - Number of the L2 block to which corresponds the first `encryptedLogs` to be returned.
|
|
86
|
+
* @param take - The number of encrypted logs to return.
|
|
87
|
+
* @returns The requested encrypted logs.
|
|
88
|
+
*/
|
|
89
|
+
getEncryptedLogs(from: number, take: number): Promise<L2BlockL2Logs[]>;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Gets the `take` amount of unencrypted logs starting from `from`.
|
|
93
|
+
* @param from - Number of the L2 block to which corresponds the first `unencryptedLogs` to be returned.
|
|
94
|
+
* @param take - The number of unencrypted logs to return.
|
|
95
|
+
* @returns The requested unencrypted logs.
|
|
96
|
+
*/
|
|
97
|
+
getUnencryptedLogs(from: number, take: number): Promise<L2BlockL2Logs[]>;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Store new Contract Public Data from an L2 block to the store's list.
|
|
101
|
+
* @param data - List of contracts' data to be added.
|
|
102
|
+
* @param blockNum - Number of the L2 block the contract data was deployed in.
|
|
103
|
+
* @returns True if the operation is successful.
|
|
104
|
+
*/
|
|
105
|
+
addL2ContractPublicData(data: ContractPublicData[], blockNum: number): Promise<boolean>;
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Lookup the L2 contract data for a contract address.
|
|
109
|
+
* @param contractAddress - The contract data address.
|
|
110
|
+
* @returns The contract's public data.
|
|
111
|
+
*/
|
|
112
|
+
getL2ContractPublicData(contractAddress: AztecAddress): Promise<ContractPublicData | undefined>;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Lookup all contract data in an L2 block.
|
|
116
|
+
* @param blockNum - The block number to get all contract data from.
|
|
117
|
+
* @returns All contract public data in the block (if found).
|
|
118
|
+
*/
|
|
119
|
+
getL2ContractPublicDataInBlock(blockNum: number): Promise<ContractPublicData[]>;
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Get basic info for an L2 contract.
|
|
123
|
+
* Contains contract address & the ethereum portal address.
|
|
124
|
+
* @param contractAddress - The contract data address.
|
|
125
|
+
* @returns ContractData with the portal address (if we didn't throw an error).
|
|
126
|
+
*/
|
|
127
|
+
getL2ContractInfo(contractAddress: AztecAddress): Promise<ContractData | undefined>;
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Get basic info for an all L2 contracts deployed in a block.
|
|
131
|
+
* Contains contract address & the ethereum portal address.
|
|
132
|
+
* @param l2BlockNum - Number of the L2 block where contracts were deployed.
|
|
133
|
+
* @returns ContractData with the portal address (if we didn't throw an error).
|
|
134
|
+
*/
|
|
135
|
+
getL2ContractInfoInBlock(l2BlockNum: number): Promise<ContractData[] | undefined>;
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Gets the number of the latest L2 block processed.
|
|
139
|
+
* @returns The number of the latest L2 block processed.
|
|
140
|
+
*/
|
|
141
|
+
getBlockHeight(): Promise<number>;
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Gets the length of L2 blocks in store.
|
|
145
|
+
* @returns The length of L2 Blocks stored.
|
|
146
|
+
*/
|
|
147
|
+
getBlocksLength(): number;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Simple, in-memory implementation of an archiver data store.
|
|
152
|
+
*/
|
|
153
|
+
export class MemoryArchiverStore implements ArchiverDataStore {
|
|
154
|
+
/**
|
|
155
|
+
* An array containing all the L2 blocks that have been fetched so far.
|
|
156
|
+
*/
|
|
157
|
+
private l2Blocks: L2Block[] = [];
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* An array containing all the encrypted logs that have been fetched so far.
|
|
161
|
+
* Note: Index in the "outer" array equals to (corresponding L2 block's number - INITIAL_L2_BLOCK_NUM).
|
|
162
|
+
*/
|
|
163
|
+
private encryptedLogs: L2BlockL2Logs[] = [];
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* An array containing all the unencrypted logs that have been fetched so far.
|
|
167
|
+
* Note: Index in the "outer" array equals to (corresponding L2 block's number - INITIAL_L2_BLOCK_NUM).
|
|
168
|
+
*/
|
|
169
|
+
private unencryptedLogs: L2BlockL2Logs[] = [];
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* A sparse array containing all the contract data that have been fetched so far.
|
|
173
|
+
*/
|
|
174
|
+
private contractPublicData: (ContractPublicData[] | undefined)[] = [];
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Contains all the confirmed L1 to L2 messages (i.e. messages that were consumed in an L2 block)
|
|
178
|
+
* It is a map of entryKey to the corresponding L1 to L2 message and the number of times it has appeared
|
|
179
|
+
*/
|
|
180
|
+
private confirmedL1ToL2Messages: L1ToL2MessageStore = new L1ToL2MessageStore();
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Contains all the pending L1 to L2 messages (accounts for duplication of messages)
|
|
184
|
+
*/
|
|
185
|
+
private pendingL1ToL2Messages: PendingL1ToL2MessageStore = new PendingL1ToL2MessageStore();
|
|
186
|
+
|
|
187
|
+
constructor() {}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Append new blocks to the store's list.
|
|
191
|
+
* @param blocks - The L2 blocks to be added to the store.
|
|
192
|
+
* @returns True if the operation is successful (always in this implementation).
|
|
193
|
+
*/
|
|
194
|
+
public addL2Blocks(blocks: L2Block[]): Promise<boolean> {
|
|
195
|
+
this.l2Blocks.push(...blocks);
|
|
196
|
+
return Promise.resolve(true);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Append new encrypted logs data to the store's list.
|
|
201
|
+
* @param data - The encrypted logs to be added to the store.
|
|
202
|
+
* @returns True if the operation is successful (always in this implementation).
|
|
203
|
+
*/
|
|
204
|
+
public addEncryptedLogs(data: L2BlockL2Logs[]): Promise<boolean> {
|
|
205
|
+
this.encryptedLogs.push(...data);
|
|
206
|
+
return Promise.resolve(true);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Append new unencrypted logs data to the store's list.
|
|
211
|
+
* @param data - The unencrypted logs to be added to the store.
|
|
212
|
+
* @returns True if the operation is successful (always in this implementation).
|
|
213
|
+
*/
|
|
214
|
+
public addUnencryptedLogs(data: L2BlockL2Logs[]): Promise<boolean> {
|
|
215
|
+
this.unencryptedLogs.push(...data);
|
|
216
|
+
return Promise.resolve(true);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Append new pending L1 to L2 messages to the store.
|
|
221
|
+
* @param messages - The L1 to L2 messages to be added to the store.
|
|
222
|
+
* @returns True if the operation is successful (always in this implementation).
|
|
223
|
+
*/
|
|
224
|
+
public addPendingL1ToL2Messages(messages: L1ToL2Message[]): Promise<boolean> {
|
|
225
|
+
for (const msg of messages) {
|
|
226
|
+
this.pendingL1ToL2Messages.addMessage(msg.entryKey!, msg);
|
|
227
|
+
}
|
|
228
|
+
return Promise.resolve(true);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Remove pending L1 to L2 messages from the store (if they were cancelled).
|
|
233
|
+
* @param messageKeys - The message keys to be removed from the store.
|
|
234
|
+
* @returns True if the operation is successful (always in this implementation).
|
|
235
|
+
*/
|
|
236
|
+
public cancelPendingL1ToL2Messages(messageKeys: Fr[]): Promise<boolean> {
|
|
237
|
+
messageKeys.forEach(messageKey => {
|
|
238
|
+
this.pendingL1ToL2Messages.removeMessage(messageKey);
|
|
239
|
+
});
|
|
240
|
+
return Promise.resolve(true);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Messages that have been published in an L2 block are confirmed.
|
|
245
|
+
* Add them to the confirmed store, also remove them from the pending store.
|
|
246
|
+
* @param messageKeys - The message keys to be removed from the store.
|
|
247
|
+
* @returns True if the operation is successful (always in this implementation).
|
|
248
|
+
*/
|
|
249
|
+
public confirmL1ToL2Messages(messageKeys: Fr[]): Promise<boolean> {
|
|
250
|
+
messageKeys.forEach(messageKey => {
|
|
251
|
+
this.confirmedL1ToL2Messages.addMessage(messageKey, this.pendingL1ToL2Messages.getMessage(messageKey)!);
|
|
252
|
+
this.pendingL1ToL2Messages.removeMessage(messageKey);
|
|
253
|
+
});
|
|
254
|
+
return Promise.resolve(true);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Store new Contract Public Data from an L2 block to the store's list.
|
|
259
|
+
* @param data - List of contracts' data to be added.
|
|
260
|
+
* @param blockNum - Number of the L2 block the contract data was deployed in.
|
|
261
|
+
* @returns True if the operation is successful (always in this implementation).
|
|
262
|
+
*/
|
|
263
|
+
public addL2ContractPublicData(data: ContractPublicData[], blockNum: number): Promise<boolean> {
|
|
264
|
+
if (this.contractPublicData[blockNum]?.length) {
|
|
265
|
+
this.contractPublicData[blockNum]?.push(...data);
|
|
266
|
+
} else {
|
|
267
|
+
this.contractPublicData[blockNum] = [...data];
|
|
268
|
+
}
|
|
269
|
+
return Promise.resolve(true);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Gets the `take` amount of L2 blocks starting from `from`.
|
|
274
|
+
* @param from - Number of the first block to return (inclusive).
|
|
275
|
+
* @param take - The number of blocks to return.
|
|
276
|
+
* @returns The requested L2 blocks.
|
|
277
|
+
*/
|
|
278
|
+
public getL2Blocks(from: number, take: number): Promise<L2Block[]> {
|
|
279
|
+
if (from < INITIAL_L2_BLOCK_NUM) {
|
|
280
|
+
throw new Error(`Invalid block range ${from}`);
|
|
281
|
+
}
|
|
282
|
+
if (from > this.l2Blocks.length) {
|
|
283
|
+
return Promise.resolve([]);
|
|
284
|
+
}
|
|
285
|
+
const startIndex = from - INITIAL_L2_BLOCK_NUM;
|
|
286
|
+
const endIndex = from + take;
|
|
287
|
+
return Promise.resolve(this.l2Blocks.slice(startIndex, endIndex));
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Gets the `take` amount of pending L1 to L2 messages, sorted by fee
|
|
292
|
+
* @param take - The number of messages to return (by default NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).
|
|
293
|
+
* @returns The requested L1 to L2 message keys.
|
|
294
|
+
*/
|
|
295
|
+
public getPendingL1ToL2MessageKeys(take: number = NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP): Promise<Fr[]> {
|
|
296
|
+
return Promise.resolve(this.pendingL1ToL2Messages.getMessageKeys(take));
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Gets the confirmed L1 to L2 message corresponding to the given message key.
|
|
301
|
+
* @param messageKey - The message key to look up.
|
|
302
|
+
* @returns The requested L1 to L2 message or throws if not found.
|
|
303
|
+
*/
|
|
304
|
+
public getConfirmedL1ToL2Message(messageKey: Fr): Promise<L1ToL2Message> {
|
|
305
|
+
const message = this.confirmedL1ToL2Messages.getMessage(messageKey);
|
|
306
|
+
if (!message) {
|
|
307
|
+
throw new Error(`Message with key ${messageKey.toString()} not found`);
|
|
308
|
+
}
|
|
309
|
+
return Promise.resolve(message);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Gets the `take` amount of encrypted logs starting from `from`.
|
|
314
|
+
* @param from - Number of the L2 block to which corresponds the first encrypted logs to be returned.
|
|
315
|
+
* @param take - The number of encrypted logs to return.
|
|
316
|
+
* @returns The requested encrypted logs.
|
|
317
|
+
*/
|
|
318
|
+
public getEncryptedLogs(from: number, take: number): Promise<L2BlockL2Logs[]> {
|
|
319
|
+
if (from < INITIAL_L2_BLOCK_NUM) {
|
|
320
|
+
throw new Error(`Invalid block range ${from}`);
|
|
321
|
+
}
|
|
322
|
+
if (from > this.encryptedLogs.length) {
|
|
323
|
+
return Promise.resolve([]);
|
|
324
|
+
}
|
|
325
|
+
const startIndex = from - INITIAL_L2_BLOCK_NUM;
|
|
326
|
+
const endIndex = from + take;
|
|
327
|
+
return Promise.resolve(this.encryptedLogs.slice(startIndex, endIndex));
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Gets the 'take' amount of unencrypted logs starting from 'from'.
|
|
332
|
+
* @param from - Number of the L2 block to which corresponds the first unencrypted logs to be returned.
|
|
333
|
+
* @param take - The number of unencrypted logs to return.
|
|
334
|
+
* @returns The requested unencrypted logs.
|
|
335
|
+
*/
|
|
336
|
+
public getUnencryptedLogs(from: number, take: number): Promise<L2BlockL2Logs[]> {
|
|
337
|
+
if (from < INITIAL_L2_BLOCK_NUM) {
|
|
338
|
+
throw new Error(`Invalid block range ${from}`);
|
|
339
|
+
}
|
|
340
|
+
if (from > this.unencryptedLogs.length) {
|
|
341
|
+
return Promise.resolve([]);
|
|
342
|
+
}
|
|
343
|
+
const startIndex = from - INITIAL_L2_BLOCK_NUM;
|
|
344
|
+
const endIndex = from + take;
|
|
345
|
+
return Promise.resolve(this.unencryptedLogs.slice(startIndex, endIndex));
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Lookup the L2 contract data for a contract address.
|
|
350
|
+
* @param contractAddress - The contract data address.
|
|
351
|
+
* @returns The contract's public data.
|
|
352
|
+
*/
|
|
353
|
+
public getL2ContractPublicData(contractAddress: AztecAddress): Promise<ContractPublicData | undefined> {
|
|
354
|
+
let result;
|
|
355
|
+
for (let i = INITIAL_L2_BLOCK_NUM; i < this.contractPublicData.length; i++) {
|
|
356
|
+
const contracts = this.contractPublicData[i];
|
|
357
|
+
const contract = contracts?.find(c => c.contractData.contractAddress.equals(contractAddress));
|
|
358
|
+
if (contract) {
|
|
359
|
+
result = contract;
|
|
360
|
+
break;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
return Promise.resolve(result);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Lookup all contract data in an L2 block.
|
|
368
|
+
* @param blockNum - The block number to get all contract data from.
|
|
369
|
+
* @returns All contract public data in the block (if found).
|
|
370
|
+
*/
|
|
371
|
+
public getL2ContractPublicDataInBlock(blockNum: number): Promise<ContractPublicData[]> {
|
|
372
|
+
if (blockNum > this.l2Blocks.length) {
|
|
373
|
+
return Promise.resolve([]);
|
|
374
|
+
}
|
|
375
|
+
return Promise.resolve(this.contractPublicData[blockNum] || []);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Get basic info for an L2 contract.
|
|
380
|
+
* Contains contract address & the ethereum portal address.
|
|
381
|
+
* @param contractAddress - The contract data address.
|
|
382
|
+
* @returns ContractData with the portal address (if we didn't throw an error).
|
|
383
|
+
*/
|
|
384
|
+
public getL2ContractInfo(contractAddress: AztecAddress): Promise<ContractData | undefined> {
|
|
385
|
+
for (const block of this.l2Blocks) {
|
|
386
|
+
for (const contractData of block.newContractData) {
|
|
387
|
+
if (contractData.contractAddress.equals(contractAddress)) {
|
|
388
|
+
return Promise.resolve(contractData);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
return Promise.resolve(undefined);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* Get basic info for an all L2 contracts deployed in a block.
|
|
397
|
+
* Contains contract address & the ethereum portal address.
|
|
398
|
+
* @param l2BlockNum - Number of the L2 block where contracts were deployed.
|
|
399
|
+
* @returns ContractData with the portal address (if we didn't throw an error).
|
|
400
|
+
*/
|
|
401
|
+
public getL2ContractInfoInBlock(l2BlockNum: number): Promise<ContractData[] | undefined> {
|
|
402
|
+
if (l2BlockNum > this.l2Blocks.length) {
|
|
403
|
+
return Promise.resolve([]);
|
|
404
|
+
}
|
|
405
|
+
const block = this.l2Blocks[l2BlockNum];
|
|
406
|
+
return Promise.resolve(block.newContractData);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Gets the number of the latest L2 block processed.
|
|
411
|
+
* @returns The number of the latest L2 block processed.
|
|
412
|
+
*/
|
|
413
|
+
public getBlockHeight(): Promise<number> {
|
|
414
|
+
if (this.l2Blocks.length === 0) return Promise.resolve(INITIAL_L2_BLOCK_NUM - 1);
|
|
415
|
+
return Promise.resolve(this.l2Blocks[this.l2Blocks.length - 1].number);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* Gets the length of L2 blocks in store.
|
|
420
|
+
* @returns The length of L2 Blocks array.
|
|
421
|
+
*/
|
|
422
|
+
public getBlocksLength(): number {
|
|
423
|
+
return this.l2Blocks.length;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
2
|
+
import { L1Addresses } from '@aztec/types';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The archiver configuration.
|
|
6
|
+
*/
|
|
7
|
+
export interface ArchiverConfig extends L1Addresses {
|
|
8
|
+
/**
|
|
9
|
+
* The url of the Ethereum RPC node.
|
|
10
|
+
*/
|
|
11
|
+
rpcUrl: string;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* The key for the ethereum node.
|
|
15
|
+
*/
|
|
16
|
+
apiKey?: string;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The polling interval in ms for retrieving new L2 blocks and encrypted logs.
|
|
20
|
+
*/
|
|
21
|
+
archiverPollingInterval?: number;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Eth block from which we start scanning for L2Blocks.
|
|
25
|
+
*/
|
|
26
|
+
searchStartBlock: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Returns the archiver configuration from the environment variables.
|
|
31
|
+
* Note: If an environment variable is not set, the default value is used.
|
|
32
|
+
* @returns The archiver configuration.
|
|
33
|
+
*/
|
|
34
|
+
export function getConfigEnvVars(): ArchiverConfig {
|
|
35
|
+
const {
|
|
36
|
+
ETHEREUM_HOST,
|
|
37
|
+
ARCHIVER_POLLING_INTERVAL,
|
|
38
|
+
ROLLUP_CONTRACT_ADDRESS,
|
|
39
|
+
CONTRACT_DEPLOYMENT_EMITTER_ADDRESS,
|
|
40
|
+
SEARCH_START_BLOCK,
|
|
41
|
+
API_KEY,
|
|
42
|
+
INBOX_CONTRACT_ADDRESS,
|
|
43
|
+
} = process.env;
|
|
44
|
+
return {
|
|
45
|
+
rpcUrl: ETHEREUM_HOST || 'http://127.0.0.1:8545/',
|
|
46
|
+
archiverPollingInterval: ARCHIVER_POLLING_INTERVAL ? +ARCHIVER_POLLING_INTERVAL : 1_000,
|
|
47
|
+
rollupContract: ROLLUP_CONTRACT_ADDRESS ? EthAddress.fromString(ROLLUP_CONTRACT_ADDRESS) : EthAddress.ZERO,
|
|
48
|
+
inboxContract: INBOX_CONTRACT_ADDRESS ? EthAddress.fromString(INBOX_CONTRACT_ADDRESS) : EthAddress.ZERO,
|
|
49
|
+
contractDeploymentEmitterContract: CONTRACT_DEPLOYMENT_EMITTER_ADDRESS
|
|
50
|
+
? EthAddress.fromString(CONTRACT_DEPLOYMENT_EMITTER_ADDRESS)
|
|
51
|
+
: EthAddress.ZERO,
|
|
52
|
+
searchStartBlock: SEARCH_START_BLOCK ? +SEARCH_START_BLOCK : 0,
|
|
53
|
+
apiKey: API_KEY,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { PublicClient } from 'viem';
|
|
2
|
+
import {
|
|
3
|
+
getContractDeploymentLogs,
|
|
4
|
+
getL2BlockProcessedLogs,
|
|
5
|
+
getPendingL1ToL2MessageLogs,
|
|
6
|
+
getL1ToL2MessageCancelledLogs,
|
|
7
|
+
processBlockLogs,
|
|
8
|
+
processContractDeploymentLogs,
|
|
9
|
+
processPendingL1ToL2MessageAddedLogs,
|
|
10
|
+
processCancelledL1ToL2MessagesLogs,
|
|
11
|
+
} from './eth_log_handlers.js';
|
|
12
|
+
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
13
|
+
import { ContractPublicData, L1ToL2Message, L2Block } from '@aztec/types';
|
|
14
|
+
import { Fr } from '@aztec/foundation/fields';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Data retrieved from logs
|
|
18
|
+
*/
|
|
19
|
+
type DataRetrieval<T> = {
|
|
20
|
+
/**
|
|
21
|
+
* The next block number.
|
|
22
|
+
*/
|
|
23
|
+
nextEthBlockNumber: bigint;
|
|
24
|
+
/**
|
|
25
|
+
* The data returned.
|
|
26
|
+
*/
|
|
27
|
+
retrievedData: T[];
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Fetches new L2 Blocks.
|
|
32
|
+
* @param publicClient - The viem public client to use for transaction retrieval.
|
|
33
|
+
* @param rollupAddress - The address of the rollup contract.
|
|
34
|
+
* @param blockUntilSynced - If true, blocks until the archiver has fully synced.
|
|
35
|
+
* @param currentL1BlockNum - Latest available block number in the ETH node.
|
|
36
|
+
* @param searchStartBlock - The block number to use for starting the search.
|
|
37
|
+
* @param expectedNextL2BlockNum - The next L2 block number that we expect to find.
|
|
38
|
+
* @returns An array of L2 Blocks and the next eth block to search from
|
|
39
|
+
*/
|
|
40
|
+
export async function retrieveBlocks(
|
|
41
|
+
publicClient: PublicClient,
|
|
42
|
+
rollupAddress: EthAddress,
|
|
43
|
+
blockUntilSynced: boolean,
|
|
44
|
+
currentL1BlockNum: bigint,
|
|
45
|
+
searchStartBlock: bigint,
|
|
46
|
+
expectedNextL2BlockNum: bigint,
|
|
47
|
+
): Promise<DataRetrieval<L2Block>> {
|
|
48
|
+
const retrievedBlocks: L2Block[] = [];
|
|
49
|
+
do {
|
|
50
|
+
if (searchStartBlock > currentL1BlockNum) {
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
const l2BlockProcessedLogs = await getL2BlockProcessedLogs(publicClient, rollupAddress, searchStartBlock);
|
|
54
|
+
if (l2BlockProcessedLogs.length === 0) {
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const newBlocks = await processBlockLogs(publicClient, expectedNextL2BlockNum, l2BlockProcessedLogs);
|
|
59
|
+
retrievedBlocks.push(...newBlocks);
|
|
60
|
+
searchStartBlock = l2BlockProcessedLogs[l2BlockProcessedLogs.length - 1].blockNumber! + 1n;
|
|
61
|
+
expectedNextL2BlockNum += BigInt(newBlocks.length);
|
|
62
|
+
} while (blockUntilSynced && searchStartBlock <= currentL1BlockNum);
|
|
63
|
+
return { nextEthBlockNumber: searchStartBlock, retrievedData: retrievedBlocks };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Fetches new contract data.
|
|
68
|
+
* @param publicClient - The viem public client to use for transaction retrieval.
|
|
69
|
+
* @param contractDeploymentEmitterAddress - The address of the contract deployment emitter contract.
|
|
70
|
+
* @param blockUntilSynced - If true, blocks until the archiver has fully synced.
|
|
71
|
+
* @param currentBlockNumber - Latest available block number in the ETH node.
|
|
72
|
+
* @param searchStartBlock - The block number to use for starting the search.
|
|
73
|
+
* @param blockHashMapping - A mapping from block number to relevant block hash.
|
|
74
|
+
* @returns An array of ContractPublicData and their equivalent L2 Block number along with the next eth block to search from..
|
|
75
|
+
*/
|
|
76
|
+
export async function retrieveNewContractData(
|
|
77
|
+
publicClient: PublicClient,
|
|
78
|
+
contractDeploymentEmitterAddress: EthAddress,
|
|
79
|
+
blockUntilSynced: boolean,
|
|
80
|
+
currentBlockNumber: bigint,
|
|
81
|
+
searchStartBlock: bigint,
|
|
82
|
+
blockHashMapping: { [key: number]: Buffer | undefined },
|
|
83
|
+
): Promise<DataRetrieval<[ContractPublicData[], number]>> {
|
|
84
|
+
let retrievedNewContracts: [ContractPublicData[], number][] = [];
|
|
85
|
+
do {
|
|
86
|
+
if (searchStartBlock > currentBlockNumber) {
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
const contractDataLogs = await getContractDeploymentLogs(
|
|
90
|
+
publicClient,
|
|
91
|
+
contractDeploymentEmitterAddress,
|
|
92
|
+
searchStartBlock,
|
|
93
|
+
);
|
|
94
|
+
if (contractDataLogs.length === 0) {
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
const newContracts = processContractDeploymentLogs(blockHashMapping, contractDataLogs);
|
|
98
|
+
retrievedNewContracts = retrievedNewContracts.concat(newContracts);
|
|
99
|
+
searchStartBlock = (contractDataLogs.findLast(cd => !!cd)?.blockNumber || searchStartBlock) + 1n;
|
|
100
|
+
} while (blockUntilSynced && searchStartBlock <= currentBlockNumber);
|
|
101
|
+
return { nextEthBlockNumber: searchStartBlock, retrievedData: retrievedNewContracts };
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Fetch new pending L1 to L2 messages.
|
|
106
|
+
* @param publicClient - The viem public client to use for transaction retrieval.
|
|
107
|
+
* @param inboxAddress - The address of the inbox contract to fetch messages from.
|
|
108
|
+
* @param blockUntilSynced - If true, blocks until the archiver has fully synced.
|
|
109
|
+
* @param currentBlockNumber - Latest available block number in the ETH node.
|
|
110
|
+
* @param searchStartBlock - The block number to use for starting the search.
|
|
111
|
+
* @returns An array of L1ToL2Message and next eth block to search from.
|
|
112
|
+
*/
|
|
113
|
+
export async function retrieveNewPendingL1ToL2Messages(
|
|
114
|
+
publicClient: PublicClient,
|
|
115
|
+
inboxAddress: EthAddress,
|
|
116
|
+
blockUntilSynced: boolean,
|
|
117
|
+
currentBlockNumber: bigint,
|
|
118
|
+
searchStartBlock: bigint,
|
|
119
|
+
): Promise<DataRetrieval<L1ToL2Message>> {
|
|
120
|
+
const retrievedNewL1ToL2Messages: L1ToL2Message[] = [];
|
|
121
|
+
do {
|
|
122
|
+
if (searchStartBlock > currentBlockNumber) {
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
const newL1ToL2MessageLogs = await getPendingL1ToL2MessageLogs(publicClient, inboxAddress, searchStartBlock);
|
|
126
|
+
const newL1ToL2Messages = processPendingL1ToL2MessageAddedLogs(newL1ToL2MessageLogs);
|
|
127
|
+
retrievedNewL1ToL2Messages.push(...newL1ToL2Messages);
|
|
128
|
+
// handles the case when there are no new messages:
|
|
129
|
+
searchStartBlock = (newL1ToL2MessageLogs.findLast(msgLog => !!msgLog)?.blockNumber || searchStartBlock) + 1n;
|
|
130
|
+
} while (blockUntilSynced && searchStartBlock <= currentBlockNumber);
|
|
131
|
+
return { nextEthBlockNumber: searchStartBlock, retrievedData: retrievedNewL1ToL2Messages };
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Fetch newly cancelled L1 to L2 messages.
|
|
136
|
+
* @param publicClient - The viem public client to use for transaction retrieval.
|
|
137
|
+
* @param inboxAddress - The address of the inbox contract to fetch messages from.
|
|
138
|
+
* @param blockUntilSynced - If true, blocks until the archiver has fully synced.
|
|
139
|
+
* @param currentBlockNumber - Latest available block number in the ETH node.
|
|
140
|
+
* @param searchStartBlock - The block number to use for starting the search.
|
|
141
|
+
* @returns An array of message keys that were cancelled and next eth block to search from.
|
|
142
|
+
*/
|
|
143
|
+
export async function retrieveNewCancelledL1ToL2Messages(
|
|
144
|
+
publicClient: PublicClient,
|
|
145
|
+
inboxAddress: EthAddress,
|
|
146
|
+
blockUntilSynced: boolean,
|
|
147
|
+
currentBlockNumber: bigint,
|
|
148
|
+
searchStartBlock: bigint,
|
|
149
|
+
): Promise<DataRetrieval<Fr>> {
|
|
150
|
+
const retrievedNewCancelledL1ToL2Messages: Fr[] = [];
|
|
151
|
+
do {
|
|
152
|
+
if (searchStartBlock > currentBlockNumber) {
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
const newL1ToL2MessageCancelledLogs = await getL1ToL2MessageCancelledLogs(
|
|
156
|
+
publicClient,
|
|
157
|
+
inboxAddress,
|
|
158
|
+
searchStartBlock,
|
|
159
|
+
);
|
|
160
|
+
const newCancelledL1ToL2Messages = processCancelledL1ToL2MessagesLogs(newL1ToL2MessageCancelledLogs);
|
|
161
|
+
retrievedNewCancelledL1ToL2Messages.push(...newCancelledL1ToL2Messages);
|
|
162
|
+
// handles the case when there are no new messages:
|
|
163
|
+
searchStartBlock =
|
|
164
|
+
(newL1ToL2MessageCancelledLogs.findLast(msgLog => !!msgLog)?.blockNumber || searchStartBlock) + 1n;
|
|
165
|
+
} while (blockUntilSynced && searchStartBlock <= currentBlockNumber);
|
|
166
|
+
return { nextEthBlockNumber: searchStartBlock, retrievedData: retrievedNewCancelledL1ToL2Messages };
|
|
167
|
+
}
|