@aztec/archiver 0.28.0 → 0.29.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 +13 -53
- package/dest/archiver/archiver.d.ts.map +1 -1
- package/dest/archiver/archiver.js +42 -180
- package/dest/archiver/archiver_store.d.ts +17 -63
- 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 +26 -168
- package/dest/archiver/data_retrieval.d.ts +5 -26
- package/dest/archiver/data_retrieval.d.ts.map +1 -1
- package/dest/archiver/data_retrieval.js +10 -64
- package/dest/archiver/eth_log_handlers.d.ts +5 -36
- package/dest/archiver/eth_log_handlers.d.ts.map +1 -1
- package/dest/archiver/eth_log_handlers.js +7 -75
- package/dest/archiver/kv_archiver_store/block_store.d.ts +2 -2
- package/dest/archiver/kv_archiver_store/block_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/block_store.js +3 -3
- package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts +11 -52
- package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/kv_archiver_store.js +21 -84
- package/dest/archiver/kv_archiver_store/message_store.d.ts +10 -41
- package/dest/archiver/kv_archiver_store/message_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/message_store.js +31 -136
- package/dest/archiver/memory_archiver_store/l1_to_l2_message_store.d.ts +8 -41
- package/dest/archiver/memory_archiver_store/l1_to_l2_message_store.d.ts.map +1 -1
- package/dest/archiver/memory_archiver_store/l1_to_l2_message_store.js +22 -79
- package/dest/archiver/memory_archiver_store/memory_archiver_store.d.ts +14 -76
- package/dest/archiver/memory_archiver_store/memory_archiver_store.d.ts.map +1 -1
- package/dest/archiver/memory_archiver_store/memory_archiver_store.js +22 -134
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +3 -15
- package/dest/rpc/archiver_client.d.ts.map +1 -1
- package/dest/rpc/archiver_client.js +2 -6
- package/dest/rpc/archiver_server.d.ts.map +1 -1
- package/dest/rpc/archiver_server.js +2 -6
- package/package.json +9 -9
- package/src/archiver/archiver.ts +47 -230
- package/src/archiver/archiver_store.ts +17 -72
- package/src/archiver/archiver_store_test_suite.ts +25 -208
- package/src/archiver/data_retrieval.ts +11 -93
- package/src/archiver/eth_log_handlers.ts +10 -104
- package/src/archiver/kv_archiver_store/block_store.ts +2 -2
- package/src/archiver/kv_archiver_store/kv_archiver_store.ts +19 -89
- package/src/archiver/kv_archiver_store/message_store.ts +36 -165
- package/src/archiver/memory_archiver_store/l1_to_l2_message_store.ts +21 -90
- package/src/archiver/memory_archiver_store/memory_archiver_store.ts +23 -150
- package/src/index.ts +1 -15
- package/src/rpc/archiver_client.ts +0 -8
- package/src/rpc/archiver_server.ts +0 -8
- package/dest/archiver/kv_archiver_store/contract_store.d.ts +0 -26
- package/dest/archiver/kv_archiver_store/contract_store.d.ts.map +0 -1
- package/dest/archiver/kv_archiver_store/contract_store.js +0 -49
- package/src/archiver/kv_archiver_store/contract_store.ts +0 -55
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Body,
|
|
3
|
-
ExtendedContractData,
|
|
4
3
|
GetUnencryptedLogsResponse,
|
|
5
|
-
|
|
4
|
+
InboxLeaf,
|
|
6
5
|
L2Block,
|
|
7
6
|
L2BlockL2Logs,
|
|
8
7
|
LogFilter,
|
|
9
8
|
LogType,
|
|
10
|
-
NewInboxLeaf,
|
|
11
9
|
TxEffect,
|
|
12
10
|
TxHash,
|
|
13
11
|
TxReceipt,
|
|
@@ -23,7 +21,6 @@ import { BlockBodyStore } from './block_body_store.js';
|
|
|
23
21
|
import { BlockStore } from './block_store.js';
|
|
24
22
|
import { ContractClassStore } from './contract_class_store.js';
|
|
25
23
|
import { ContractInstanceStore } from './contract_instance_store.js';
|
|
26
|
-
import { ContractStore } from './contract_store.js';
|
|
27
24
|
import { LogStore } from './log_store.js';
|
|
28
25
|
import { MessageStore } from './message_store.js';
|
|
29
26
|
|
|
@@ -34,7 +31,6 @@ export class KVArchiverDataStore implements ArchiverDataStore {
|
|
|
34
31
|
#blockStore: BlockStore;
|
|
35
32
|
#blockBodyStore: BlockBodyStore;
|
|
36
33
|
#logStore: LogStore;
|
|
37
|
-
#contractStore: ContractStore;
|
|
38
34
|
#messageStore: MessageStore;
|
|
39
35
|
#contractClassStore: ContractClassStore;
|
|
40
36
|
#contractInstanceStore: ContractInstanceStore;
|
|
@@ -45,7 +41,6 @@ export class KVArchiverDataStore implements ArchiverDataStore {
|
|
|
45
41
|
this.#blockBodyStore = new BlockBodyStore(db);
|
|
46
42
|
this.#blockStore = new BlockStore(db, this.#blockBodyStore);
|
|
47
43
|
this.#logStore = new LogStore(db, this.#blockStore, logsMaxPageSize);
|
|
48
|
-
this.#contractStore = new ContractStore(db, this.#blockStore);
|
|
49
44
|
this.#messageStore = new MessageStore(db);
|
|
50
45
|
this.#contractClassStore = new ContractClassStore(db);
|
|
51
46
|
this.#contractInstanceStore = new ContractInstanceStore(db);
|
|
@@ -149,76 +144,32 @@ export class KVArchiverDataStore implements ArchiverDataStore {
|
|
|
149
144
|
}
|
|
150
145
|
|
|
151
146
|
/**
|
|
152
|
-
* Append
|
|
147
|
+
* Append L1 to L2 messages to the store.
|
|
153
148
|
* @param messages - The L1 to L2 messages to be added to the store.
|
|
154
149
|
* @param lastMessageL1BlockNumber - The L1 block number in which the last message was emitted.
|
|
155
150
|
* @returns True if the operation is successful.
|
|
156
151
|
*/
|
|
157
|
-
|
|
158
|
-
return Promise.resolve(this.#messageStore.
|
|
152
|
+
addL1ToL2Messages(messages: InboxLeaf[], lastMessageL1BlockNumber: bigint): Promise<boolean> {
|
|
153
|
+
return Promise.resolve(this.#messageStore.addL1ToL2Messages(messages, lastMessageL1BlockNumber));
|
|
159
154
|
}
|
|
160
155
|
|
|
161
156
|
/**
|
|
162
|
-
*
|
|
163
|
-
* @param
|
|
164
|
-
* @
|
|
165
|
-
* @returns True if the operation is successful.
|
|
157
|
+
* Gets the L1 to L2 message index in the L1 to L2 message tree.
|
|
158
|
+
* @param l1ToL2Message - The L1 to L2 message.
|
|
159
|
+
* @returns The index of the L1 to L2 message in the L1 to L2 message tree.
|
|
166
160
|
*/
|
|
167
|
-
|
|
168
|
-
return Promise.resolve(this.#messageStore.
|
|
161
|
+
public getL1ToL2MessageIndex(l1ToL2Message: Fr): Promise<bigint> {
|
|
162
|
+
return Promise.resolve(this.#messageStore.getL1ToL2MessageIndex(l1ToL2Message));
|
|
169
163
|
}
|
|
170
164
|
|
|
171
165
|
/**
|
|
172
|
-
*
|
|
173
|
-
* @param messages - The entry keys to be removed from the store.
|
|
174
|
-
* @param l1BlockNumber - The L1 block number for which to remove the messages.
|
|
175
|
-
* @returns True if the operation is successful.
|
|
176
|
-
*/
|
|
177
|
-
cancelPendingL1ToL2EntryKeys(messages: Fr[], l1BlockNumber: bigint): Promise<boolean> {
|
|
178
|
-
return Promise.resolve(this.#messageStore.cancelPendingMessages(messages, l1BlockNumber));
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
/**
|
|
182
|
-
* Messages that have been published in an L2 block are confirmed.
|
|
183
|
-
* Add them to the confirmed store, also remove them from the pending store.
|
|
184
|
-
* @param entryKeys - The entry keys to be removed from the store.
|
|
185
|
-
* @param blockNumber - The block for which to add the messages.
|
|
186
|
-
* @returns True if the operation is successful.
|
|
187
|
-
*/
|
|
188
|
-
confirmL1ToL2EntryKeys(entryKeys: Fr[]): Promise<boolean> {
|
|
189
|
-
return this.#messageStore.confirmPendingMessages(entryKeys);
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* Gets up to `limit` amount of pending L1 to L2 messages, sorted by fee
|
|
194
|
-
* @param limit - The number of messages to return (by default NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).
|
|
195
|
-
* @returns The requested L1 to L2 entry keys.
|
|
196
|
-
*/
|
|
197
|
-
getPendingL1ToL2EntryKeys(limit: number): Promise<Fr[]> {
|
|
198
|
-
return Promise.resolve(this.#messageStore.getPendingEntryKeysByFee(limit));
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* Gets the confirmed L1 to L2 message corresponding to the given entry key.
|
|
203
|
-
* @param entryKey - The entry key to look up.
|
|
204
|
-
* @returns The requested L1 to L2 message or throws if not found.
|
|
205
|
-
*/
|
|
206
|
-
getConfirmedL1ToL2Message(entryKey: Fr): Promise<L1ToL2Message> {
|
|
207
|
-
try {
|
|
208
|
-
return Promise.resolve(this.#messageStore.getConfirmedMessage(entryKey));
|
|
209
|
-
} catch (err) {
|
|
210
|
-
return Promise.reject(err);
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
/**
|
|
215
|
-
* Gets new L1 to L2 message (to be) included in a given block.
|
|
166
|
+
* Gets L1 to L2 message (to be) included in a given block.
|
|
216
167
|
* @param blockNumber - L2 block number to get messages for.
|
|
217
168
|
* @returns The L1 to L2 messages/leaves of the messages subtree (throws if not found).
|
|
218
169
|
*/
|
|
219
|
-
|
|
170
|
+
getL1ToL2Messages(blockNumber: bigint): Promise<Fr[]> {
|
|
220
171
|
try {
|
|
221
|
-
return Promise.resolve(this.#messageStore.
|
|
172
|
+
return Promise.resolve(this.#messageStore.getL1ToL2Messages(blockNumber));
|
|
222
173
|
} catch (err) {
|
|
223
174
|
return Promise.reject(err);
|
|
224
175
|
}
|
|
@@ -252,44 +203,23 @@ export class KVArchiverDataStore implements ArchiverDataStore {
|
|
|
252
203
|
}
|
|
253
204
|
}
|
|
254
205
|
|
|
255
|
-
/**
|
|
256
|
-
* Add new extended contract data from an L2 block to the store's list.
|
|
257
|
-
* @param data - List of contracts' data to be added.
|
|
258
|
-
* @param blockNum - Number of the L2 block the contract data was deployed in.
|
|
259
|
-
* @returns True if the operation is successful.
|
|
260
|
-
*/
|
|
261
|
-
addExtendedContractData(data: ExtendedContractData[], blockNum: number): Promise<boolean> {
|
|
262
|
-
return this.#contractStore.addExtendedContractData(data, blockNum);
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
/**
|
|
266
|
-
* Get the extended contract data for this contract.
|
|
267
|
-
* @param contractAddress - The contract data address.
|
|
268
|
-
* @returns The extended contract data or undefined if not found.
|
|
269
|
-
*/
|
|
270
|
-
getExtendedContractData(contractAddress: AztecAddress): Promise<ExtendedContractData | undefined> {
|
|
271
|
-
return Promise.resolve(this.#contractStore.getExtendedContractData(contractAddress));
|
|
272
|
-
}
|
|
273
|
-
|
|
274
206
|
/**
|
|
275
207
|
* Gets the number of the latest L2 block processed.
|
|
276
208
|
* @returns The number of the latest L2 block processed.
|
|
277
209
|
*/
|
|
278
|
-
|
|
279
|
-
return Promise.resolve(this.#blockStore.
|
|
210
|
+
getSynchedL2BlockNumber(): Promise<number> {
|
|
211
|
+
return Promise.resolve(this.#blockStore.getSynchedL2BlockNumber());
|
|
280
212
|
}
|
|
281
213
|
|
|
282
214
|
/**
|
|
283
215
|
* Gets the last L1 block number processed by the archiver
|
|
284
216
|
*/
|
|
285
|
-
|
|
286
|
-
const
|
|
287
|
-
const
|
|
217
|
+
getSynchedL1BlockNumbers(): Promise<ArchiverL1SynchPoint> {
|
|
218
|
+
const blocks = this.#blockStore.getSynchedL1BlockNumber();
|
|
219
|
+
const messages = this.#messageStore.getSynchedL1BlockNumber();
|
|
288
220
|
return Promise.resolve({
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
newMessages,
|
|
292
|
-
cancelledMessages,
|
|
221
|
+
blocks,
|
|
222
|
+
messages,
|
|
293
223
|
});
|
|
294
224
|
}
|
|
295
225
|
}
|
|
@@ -1,141 +1,65 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { InboxLeaf } from '@aztec/circuit-types';
|
|
2
|
+
import {
|
|
3
|
+
Fr,
|
|
4
|
+
INITIAL_L2_BLOCK_NUM,
|
|
5
|
+
L1_TO_L2_MSG_SUBTREE_HEIGHT,
|
|
6
|
+
NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
|
|
7
|
+
} from '@aztec/circuits.js';
|
|
3
8
|
import { createDebugLogger } from '@aztec/foundation/log';
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* A message stored in the database
|
|
8
|
-
*/
|
|
9
|
-
type Message = {
|
|
10
|
-
/** The L1ToL2Message */
|
|
11
|
-
message: Buffer;
|
|
12
|
-
/** The message's fee */
|
|
13
|
-
fee: number;
|
|
14
|
-
/** Has it _ever_ been confirmed? */
|
|
15
|
-
confirmed: boolean;
|
|
16
|
-
};
|
|
9
|
+
import { AztecKVStore, AztecMap, AztecSingleton } from '@aztec/kv-store';
|
|
17
10
|
|
|
18
11
|
/**
|
|
19
12
|
* LMDB implementation of the ArchiverDataStore interface.
|
|
20
13
|
*/
|
|
21
14
|
export class MessageStore {
|
|
22
|
-
#
|
|
23
|
-
#
|
|
24
|
-
|
|
25
|
-
#pendingMessagesByFee: AztecCounter<[number, string]>;
|
|
26
|
-
#messages: AztecMap<string, Message>;
|
|
27
|
-
#lastL1BlockAddingMessages: AztecSingleton<bigint>;
|
|
28
|
-
#lastL1BlockCancellingMessages: AztecSingleton<bigint>;
|
|
15
|
+
#l1ToL2Messages: AztecMap<string, Buffer>;
|
|
16
|
+
#l1ToL2MessageIndices: AztecMap<string, bigint>;
|
|
17
|
+
#lastL1BlockMessages: AztecSingleton<bigint>;
|
|
29
18
|
|
|
30
19
|
#log = createDebugLogger('aztec:archiver:message_store');
|
|
31
20
|
|
|
32
21
|
#l1ToL2MessagesSubtreeSize = 2 ** L1_TO_L2_MSG_SUBTREE_HEIGHT;
|
|
33
22
|
|
|
34
23
|
constructor(private db: AztecKVStore) {
|
|
35
|
-
this.#
|
|
36
|
-
this.#
|
|
37
|
-
this.#
|
|
38
|
-
this.#lastL1BlockNewMessages = db.openSingleton('archiver_last_l1_block_new_messages');
|
|
39
|
-
this.#lastL1BlockAddingMessages = db.openSingleton('archiver_last_l1_block_adding_messages');
|
|
40
|
-
this.#lastL1BlockCancellingMessages = db.openSingleton('archiver_last_l1_block_cancelling_messages');
|
|
24
|
+
this.#l1ToL2Messages = db.openMap('archiver_l1_to_l2_messages');
|
|
25
|
+
this.#l1ToL2MessageIndices = db.openMap('archiver_l1_to_l2_message_indices');
|
|
26
|
+
this.#lastL1BlockMessages = db.openSingleton('archiver_last_l1_block_new_messages');
|
|
41
27
|
}
|
|
42
28
|
|
|
43
29
|
/**
|
|
44
|
-
* Gets the last L1 block number that emitted new messages
|
|
30
|
+
* Gets the last L1 block number that emitted new messages.
|
|
45
31
|
* @returns The last L1 block number processed
|
|
46
32
|
*/
|
|
47
|
-
|
|
48
|
-
return
|
|
49
|
-
newMessages: this.#lastL1BlockNewMessages.get() ?? 0n,
|
|
50
|
-
// TODO(#4492): Nuke the following when purging the old inbox
|
|
51
|
-
addedMessages: this.#lastL1BlockAddingMessages.get() ?? 0n,
|
|
52
|
-
cancelledMessages: this.#lastL1BlockCancellingMessages.get() ?? 0n,
|
|
53
|
-
};
|
|
33
|
+
getSynchedL1BlockNumber(): bigint {
|
|
34
|
+
return this.#lastL1BlockMessages.get() ?? 0n;
|
|
54
35
|
}
|
|
55
36
|
|
|
56
37
|
/**
|
|
57
|
-
* Append
|
|
38
|
+
* Append L1 to L2 messages to the store.
|
|
58
39
|
* @param messages - The L1 to L2 messages to be added to the store.
|
|
59
40
|
* @param lastMessageL1BlockNumber - The L1 block number in which the last message was emitted.
|
|
60
41
|
* @returns True if the operation is successful.
|
|
61
42
|
*/
|
|
62
|
-
|
|
43
|
+
addL1ToL2Messages(messages: InboxLeaf[], lastMessageL1BlockNumber: bigint): Promise<boolean> {
|
|
63
44
|
return this.db.transaction(() => {
|
|
64
|
-
const lastL1BlockNumber = this.#
|
|
45
|
+
const lastL1BlockNumber = this.#lastL1BlockMessages.get() ?? 0n;
|
|
65
46
|
if (lastL1BlockNumber >= lastMessageL1BlockNumber) {
|
|
66
47
|
return false;
|
|
67
48
|
}
|
|
68
49
|
|
|
69
|
-
void this.#
|
|
50
|
+
void this.#lastL1BlockMessages.set(lastMessageL1BlockNumber);
|
|
70
51
|
|
|
71
52
|
for (const message of messages) {
|
|
72
53
|
if (message.index >= this.#l1ToL2MessagesSubtreeSize) {
|
|
73
54
|
throw new Error(`Message index ${message.index} out of subtree range`);
|
|
74
55
|
}
|
|
75
56
|
const key = `${message.blockNumber}-${message.index}`;
|
|
76
|
-
void this.#
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
return true;
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Append new pending L1 to L2 messages to the store.
|
|
85
|
-
* @param messages - The L1 to L2 messages to be added to the store.
|
|
86
|
-
* @param l1BlockNumber - The L1 block number for which to add the messages.
|
|
87
|
-
* @returns True if the operation is successful.
|
|
88
|
-
*/
|
|
89
|
-
addPendingMessages(messages: L1ToL2Message[], l1BlockNumber: bigint): Promise<boolean> {
|
|
90
|
-
return this.db.transaction(() => {
|
|
91
|
-
const lastL1BlockNumber = this.#lastL1BlockAddingMessages.get() ?? 0n;
|
|
92
|
-
if (lastL1BlockNumber >= l1BlockNumber) {
|
|
93
|
-
return false;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
void this.#lastL1BlockAddingMessages.set(l1BlockNumber);
|
|
97
|
-
|
|
98
|
-
for (const message of messages) {
|
|
99
|
-
const entryKey = message.entryKey?.toString();
|
|
100
|
-
if (!entryKey) {
|
|
101
|
-
throw new Error('Message does not have an entry key');
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
void this.#messages.setIfNotExists(entryKey, {
|
|
105
|
-
message: message.toBuffer(),
|
|
106
|
-
fee: message.fee,
|
|
107
|
-
confirmed: false,
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
void this.#pendingMessagesByFee.update([message.fee, entryKey], 1);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
return true;
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Remove pending L1 to L2 messages from the store (if they were cancelled).
|
|
119
|
-
* @param entryKeys - The entry keys to be removed from the store.
|
|
120
|
-
* @param l1BlockNumber - The L1 block number for which to remove the messages.
|
|
121
|
-
* @returns True if the operation is successful.
|
|
122
|
-
*/
|
|
123
|
-
cancelPendingMessages(entryKeys: Fr[], l1BlockNumber: bigint): Promise<boolean> {
|
|
124
|
-
return this.db.transaction(() => {
|
|
125
|
-
const lastL1BlockNumber = this.#lastL1BlockCancellingMessages.get() ?? 0n;
|
|
126
|
-
if (lastL1BlockNumber >= l1BlockNumber) {
|
|
127
|
-
return false;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
void this.#lastL1BlockCancellingMessages.set(l1BlockNumber);
|
|
57
|
+
void this.#l1ToL2Messages.setIfNotExists(key, message.leaf.toBuffer());
|
|
131
58
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
void this.#pendingMessagesByFee.update([messageCtx.fee, entryKey.toString()], -1);
|
|
59
|
+
const indexInTheWholeTree =
|
|
60
|
+
(message.blockNumber - BigInt(INITIAL_L2_BLOCK_NUM)) * BigInt(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP) +
|
|
61
|
+
message.index;
|
|
62
|
+
void this.#l1ToL2MessageIndices.setIfNotExists(message.leaf.toString(), indexInTheWholeTree);
|
|
139
63
|
}
|
|
140
64
|
|
|
141
65
|
return true;
|
|
@@ -143,78 +67,25 @@ export class MessageStore {
|
|
|
143
67
|
}
|
|
144
68
|
|
|
145
69
|
/**
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
* @
|
|
149
|
-
* @returns True if the operation is successful.
|
|
70
|
+
* Gets the L1 to L2 message index in the L1 to L2 message tree.
|
|
71
|
+
* @param l1ToL2Message - The L1 to L2 message.
|
|
72
|
+
* @returns The index of the L1 to L2 message in the L1 to L2 message tree.
|
|
150
73
|
*/
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
continue;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
const messageCtx = this.#messages.get(entryKey.toString());
|
|
159
|
-
if (!messageCtx) {
|
|
160
|
-
throw new Error(`Message ${entryKey.toString()} not found`);
|
|
161
|
-
}
|
|
162
|
-
messageCtx.confirmed = true;
|
|
163
|
-
|
|
164
|
-
void this.#messages.set(entryKey.toString(), messageCtx);
|
|
165
|
-
void this.#pendingMessagesByFee.update([messageCtx.fee, entryKey.toString()], -1);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
return true;
|
|
169
|
-
});
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* Gets the confirmed L1 to L2 message corresponding to the given entry key.
|
|
174
|
-
* @param entryKey - The entry key to look up.
|
|
175
|
-
* @returns The requested L1 to L2 message or throws if not found.
|
|
176
|
-
*/
|
|
177
|
-
getConfirmedMessage(entryKey: Fr): L1ToL2Message {
|
|
178
|
-
const messageCtx = this.#messages.get(entryKey.toString());
|
|
179
|
-
if (!messageCtx) {
|
|
180
|
-
throw new Error(`Message ${entryKey.toString()} not found`);
|
|
74
|
+
public getL1ToL2MessageIndex(l1ToL2Message: Fr): Promise<bigint> {
|
|
75
|
+
const index = this.#l1ToL2MessageIndices.get(l1ToL2Message.toString());
|
|
76
|
+
if (index === undefined) {
|
|
77
|
+
throw new Error(`L1 to L2 message index not found in the store for message ${l1ToL2Message.toString()}`);
|
|
181
78
|
}
|
|
182
|
-
|
|
183
|
-
if (!messageCtx.confirmed) {
|
|
184
|
-
throw new Error(`Message ${entryKey.toString()} not confirmed`);
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
return L1ToL2Message.fromBuffer(messageCtx.message);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* Gets up to `limit` amount of pending L1 to L2 messages, sorted by fee
|
|
192
|
-
* @param limit - The number of messages to return (by default NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).
|
|
193
|
-
* @returns The requested L1 to L2 entry keys.
|
|
194
|
-
*/
|
|
195
|
-
getPendingEntryKeysByFee(limit: number): Fr[] {
|
|
196
|
-
const entryKeys: Fr[] = [];
|
|
197
|
-
|
|
198
|
-
for (const [[_, entryKey], count] of this.#pendingMessagesByFee.entries({
|
|
199
|
-
reverse: true,
|
|
200
|
-
})) {
|
|
201
|
-
// put `count` copies of this message in the result list
|
|
202
|
-
entryKeys.push(...Array(count).fill(Fr.fromString(entryKey)));
|
|
203
|
-
if (entryKeys.length >= limit) {
|
|
204
|
-
break;
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
return entryKeys;
|
|
79
|
+
return Promise.resolve(index);
|
|
209
80
|
}
|
|
210
81
|
|
|
211
|
-
|
|
82
|
+
getL1ToL2Messages(blockNumber: bigint): Fr[] {
|
|
212
83
|
const messages: Fr[] = [];
|
|
213
84
|
let undefinedMessageFound = false;
|
|
214
85
|
for (let messageIndex = 0; messageIndex < this.#l1ToL2MessagesSubtreeSize; messageIndex++) {
|
|
215
86
|
// This is inefficient but probably fine for now.
|
|
216
87
|
const key = `${blockNumber}-${messageIndex}`;
|
|
217
|
-
const message = this.#
|
|
88
|
+
const message = this.#l1ToL2Messages.get(key);
|
|
218
89
|
if (message) {
|
|
219
90
|
if (undefinedMessageFound) {
|
|
220
91
|
throw new Error(`L1 to L2 message gap found in block ${blockNumber}`);
|
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { InboxLeaf } from '@aztec/circuit-types';
|
|
2
|
+
import {
|
|
3
|
+
INITIAL_L2_BLOCK_NUM,
|
|
4
|
+
L1_TO_L2_MSG_SUBTREE_HEIGHT,
|
|
5
|
+
NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
|
|
6
|
+
} from '@aztec/circuits.js/constants';
|
|
3
7
|
import { Fr } from '@aztec/foundation/fields';
|
|
4
8
|
|
|
5
9
|
/**
|
|
6
|
-
* A simple in-memory implementation of an L1 to L2 message store
|
|
7
|
-
* that handles message duplication.
|
|
8
|
-
* TODO(#4492): Clean this up
|
|
10
|
+
* A simple in-memory implementation of an L1 to L2 message store.
|
|
9
11
|
*/
|
|
10
|
-
export class
|
|
12
|
+
export class L1ToL2MessageStore {
|
|
11
13
|
/**
|
|
12
14
|
* A map containing the entry key to the corresponding L1 to L2
|
|
13
15
|
* messages (and the number of times the message has been seen).
|
|
@@ -18,7 +20,7 @@ export class NewL1ToL2MessageStore {
|
|
|
18
20
|
|
|
19
21
|
constructor() {}
|
|
20
22
|
|
|
21
|
-
addMessage(message:
|
|
23
|
+
addMessage(message: InboxLeaf) {
|
|
22
24
|
if (message.index >= this.#l1ToL2MessagesSubtreeSize) {
|
|
23
25
|
throw new Error(`Message index ${message.index} out of subtree range`);
|
|
24
26
|
}
|
|
@@ -46,93 +48,22 @@ export class NewL1ToL2MessageStore {
|
|
|
46
48
|
}
|
|
47
49
|
return messages;
|
|
48
50
|
}
|
|
49
|
-
}
|
|
50
51
|
|
|
51
|
-
/**
|
|
52
|
-
* A simple in-memory implementation of an L1 to L2 message store
|
|
53
|
-
* that handles message duplication.
|
|
54
|
-
*/
|
|
55
|
-
export class L1ToL2MessageStore {
|
|
56
52
|
/**
|
|
57
|
-
*
|
|
58
|
-
*
|
|
53
|
+
* Gets the L1 to L2 message index in the L1 to L2 message tree.
|
|
54
|
+
* @param l1ToL2Message - The L1 to L2 message.
|
|
55
|
+
* @returns The index of the L1 to L2 message in the L1 to L2 message tree.
|
|
59
56
|
*/
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
msgAndCount.count++;
|
|
69
|
-
} else {
|
|
70
|
-
this.store.set(entryKeyBigInt, { message, count: 1 });
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
getMessage(entryKey: Fr): L1ToL2Message | undefined {
|
|
75
|
-
return this.store.get(entryKey.value)?.message;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
getMessageAndCount(entryKey: Fr): L1ToL2MessageAndCount | undefined {
|
|
79
|
-
return this.store.get(entryKey.value);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Specifically for the store that will hold pending messages
|
|
85
|
-
* for removing messages or fetching multiple messages.
|
|
86
|
-
*/
|
|
87
|
-
export class PendingL1ToL2MessageStore extends L1ToL2MessageStore {
|
|
88
|
-
getEntryKeys(limit: number): Fr[] {
|
|
89
|
-
if (limit < 1) {
|
|
90
|
-
return [];
|
|
91
|
-
}
|
|
92
|
-
// fetch `limit` number of messages from the store with the highest fee.
|
|
93
|
-
// Note the store has multiple of the same message. So if a message has count 2, include both of them in the result:
|
|
94
|
-
const messages: Fr[] = [];
|
|
95
|
-
const sortedMessages = Array.from(this.store.values()).sort((a, b) => b.message.fee - a.message.fee);
|
|
96
|
-
for (const messageAndCount of sortedMessages) {
|
|
97
|
-
for (let i = 0; i < messageAndCount.count; i++) {
|
|
98
|
-
messages.push(messageAndCount.message.entryKey!);
|
|
99
|
-
if (messages.length === limit) {
|
|
100
|
-
return messages;
|
|
101
|
-
}
|
|
57
|
+
getMessageIndex(l1ToL2Message: Fr): bigint {
|
|
58
|
+
for (const [key, message] of this.store.entries()) {
|
|
59
|
+
if (message.equals(l1ToL2Message)) {
|
|
60
|
+
const [blockNumber, messageIndex] = key.split('-');
|
|
61
|
+
const indexInTheWholeTree =
|
|
62
|
+
(BigInt(blockNumber) - BigInt(INITIAL_L2_BLOCK_NUM)) * BigInt(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP) +
|
|
63
|
+
BigInt(messageIndex);
|
|
64
|
+
return indexInTheWholeTree;
|
|
102
65
|
}
|
|
103
66
|
}
|
|
104
|
-
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
removeMessage(entryKey: Fr) {
|
|
108
|
-
// ignore 0 - entryKey is a hash, so a 0 can probabilistically never occur. It is best to skip it.
|
|
109
|
-
if (entryKey.equals(Fr.ZERO)) {
|
|
110
|
-
return;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
const entryKeyBigInt = entryKey.value;
|
|
114
|
-
const msgAndCount = this.store.get(entryKeyBigInt);
|
|
115
|
-
if (!msgAndCount) {
|
|
116
|
-
throw new Error(`Unable to remove message: L1 to L2 Message with key ${entryKeyBigInt} not found in store`);
|
|
117
|
-
}
|
|
118
|
-
if (msgAndCount.count > 1) {
|
|
119
|
-
msgAndCount.count--;
|
|
120
|
-
} else {
|
|
121
|
-
this.store.delete(entryKeyBigInt);
|
|
122
|
-
}
|
|
67
|
+
throw new Error(`L1 to L2 message index not found in the store for message ${l1ToL2Message.toString()}`);
|
|
123
68
|
}
|
|
124
69
|
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Useful to keep track of the number of times a message has been seen.
|
|
128
|
-
*/
|
|
129
|
-
type L1ToL2MessageAndCount = {
|
|
130
|
-
/**
|
|
131
|
-
* The message.
|
|
132
|
-
*/
|
|
133
|
-
message: L1ToL2Message;
|
|
134
|
-
/**
|
|
135
|
-
* The number of times the message has been seen.
|
|
136
|
-
*/
|
|
137
|
-
count: number;
|
|
138
|
-
};
|