@aztec/archiver 0.28.1 → 0.30.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.
Files changed (55) hide show
  1. package/dest/archiver/archiver.d.ts +13 -53
  2. package/dest/archiver/archiver.d.ts.map +1 -1
  3. package/dest/archiver/archiver.js +60 -199
  4. package/dest/archiver/archiver_store.d.ts +21 -67
  5. package/dest/archiver/archiver_store.d.ts.map +1 -1
  6. package/dest/archiver/archiver_store_test_suite.d.ts.map +1 -1
  7. package/dest/archiver/archiver_store_test_suite.js +60 -199
  8. package/dest/archiver/config.d.ts.map +1 -1
  9. package/dest/archiver/config.js +6 -2
  10. package/dest/archiver/data_retrieval.d.ts +10 -32
  11. package/dest/archiver/data_retrieval.d.ts.map +1 -1
  12. package/dest/archiver/data_retrieval.js +13 -67
  13. package/dest/archiver/eth_log_handlers.d.ts +7 -38
  14. package/dest/archiver/eth_log_handlers.d.ts.map +1 -1
  15. package/dest/archiver/eth_log_handlers.js +9 -77
  16. package/dest/archiver/kv_archiver_store/block_store.d.ts +5 -4
  17. package/dest/archiver/kv_archiver_store/block_store.d.ts.map +1 -1
  18. package/dest/archiver/kv_archiver_store/block_store.js +12 -15
  19. package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts +15 -56
  20. package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts.map +1 -1
  21. package/dest/archiver/kv_archiver_store/kv_archiver_store.js +23 -87
  22. package/dest/archiver/kv_archiver_store/message_store.d.ts +12 -43
  23. package/dest/archiver/kv_archiver_store/message_store.d.ts.map +1 -1
  24. package/dest/archiver/kv_archiver_store/message_store.js +32 -141
  25. package/dest/archiver/memory_archiver_store/l1_to_l2_message_store.d.ts +8 -41
  26. package/dest/archiver/memory_archiver_store/l1_to_l2_message_store.d.ts.map +1 -1
  27. package/dest/archiver/memory_archiver_store/l1_to_l2_message_store.js +22 -79
  28. package/dest/archiver/memory_archiver_store/memory_archiver_store.d.ts +20 -81
  29. package/dest/archiver/memory_archiver_store/memory_archiver_store.d.ts.map +1 -1
  30. package/dest/archiver/memory_archiver_store/memory_archiver_store.js +30 -143
  31. package/dest/index.d.ts.map +1 -1
  32. package/dest/index.js +3 -15
  33. package/dest/rpc/archiver_client.d.ts.map +1 -1
  34. package/dest/rpc/archiver_client.js +2 -6
  35. package/dest/rpc/archiver_server.d.ts.map +1 -1
  36. package/dest/rpc/archiver_server.js +2 -6
  37. package/package.json +9 -9
  38. package/src/archiver/archiver.ts +80 -267
  39. package/src/archiver/archiver_store.ts +22 -76
  40. package/src/archiver/archiver_store_test_suite.ts +78 -243
  41. package/src/archiver/config.ts +6 -0
  42. package/src/archiver/data_retrieval.ts +19 -101
  43. package/src/archiver/eth_log_handlers.ts +14 -108
  44. package/src/archiver/kv_archiver_store/block_store.ts +13 -14
  45. package/src/archiver/kv_archiver_store/kv_archiver_store.ts +23 -93
  46. package/src/archiver/kv_archiver_store/message_store.ts +38 -169
  47. package/src/archiver/memory_archiver_store/l1_to_l2_message_store.ts +21 -90
  48. package/src/archiver/memory_archiver_store/memory_archiver_store.ts +33 -161
  49. package/src/index.ts +1 -15
  50. package/src/rpc/archiver_client.ts +0 -8
  51. package/src/rpc/archiver_server.ts +0 -8
  52. package/dest/archiver/kv_archiver_store/contract_store.d.ts +0 -26
  53. package/dest/archiver/kv_archiver_store/contract_store.d.ts.map +0 -1
  54. package/dest/archiver/kv_archiver_store/contract_store.js +0 -49
  55. package/src/archiver/kv_archiver_store/contract_store.ts +0 -55
@@ -1,168 +1,66 @@
1
- import { L1ToL2Message, NewInboxLeaf } from '@aztec/circuit-types';
2
- import { Fr, L1_TO_L2_MSG_SUBTREE_HEIGHT } from '@aztec/circuits.js';
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 { AztecCounter, AztecKVStore, AztecMap, AztecSingleton } from '@aztec/kv-store';
9
+ import { AztecKVStore, AztecMap, AztecSingleton } from '@aztec/kv-store';
5
10
 
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
- };
11
+ import { DataRetrieval } from '../data_retrieval.js';
17
12
 
18
13
  /**
19
14
  * LMDB implementation of the ArchiverDataStore interface.
20
15
  */
21
16
  export class MessageStore {
22
- #newMessages: AztecMap<string, Buffer>;
23
- #lastL1BlockNewMessages: AztecSingleton<bigint>;
24
- // TODO(#4492): Nuke the following when purging the old inbox
25
- #pendingMessagesByFee: AztecCounter<[number, string]>;
26
- #messages: AztecMap<string, Message>;
27
- #lastL1BlockAddingMessages: AztecSingleton<bigint>;
28
- #lastL1BlockCancellingMessages: AztecSingleton<bigint>;
17
+ #l1ToL2Messages: AztecMap<string, Buffer>;
18
+ #l1ToL2MessageIndices: AztecMap<string, bigint>;
19
+ #lastL1BlockMessages: AztecSingleton<bigint>;
29
20
 
30
21
  #log = createDebugLogger('aztec:archiver:message_store');
31
22
 
32
23
  #l1ToL2MessagesSubtreeSize = 2 ** L1_TO_L2_MSG_SUBTREE_HEIGHT;
33
24
 
34
25
  constructor(private db: AztecKVStore) {
35
- this.#newMessages = db.openMap('archiver_l1_to_l2_new_messages');
36
- this.#messages = db.openMap('archiver_l1_to_l2_messages');
37
- this.#pendingMessagesByFee = db.openCounter('archiver_messages_by_fee');
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');
26
+ this.#l1ToL2Messages = db.openMap('archiver_l1_to_l2_messages');
27
+ this.#l1ToL2MessageIndices = db.openMap('archiver_l1_to_l2_message_indices');
28
+ this.#lastL1BlockMessages = db.openSingleton('archiver_last_l1_block_new_messages');
41
29
  }
42
30
 
43
31
  /**
44
- * Gets the last L1 block number that emitted new messages and the block that cancelled messages.
32
+ * Gets the last L1 block number that emitted new messages.
45
33
  * @returns The last L1 block number processed
46
34
  */
47
- getL1BlockNumber() {
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
- };
35
+ getSynchedL1BlockNumber(): bigint {
36
+ return this.#lastL1BlockMessages.get() ?? 0n;
54
37
  }
55
38
 
56
39
  /**
57
- * Append new L1 to L2 messages to the store.
58
- * @param messages - The L1 to L2 messages to be added to the store.
59
- * @param lastMessageL1BlockNumber - The L1 block number in which the last message was emitted.
40
+ * Append L1 to L2 messages to the store.
41
+ * @param messages - The L1 to L2 messages to be added to the store and the last processed L1 block.
60
42
  * @returns True if the operation is successful.
61
43
  */
62
- addNewL1ToL2Messages(messages: NewInboxLeaf[], lastMessageL1BlockNumber: bigint): Promise<boolean> {
44
+ addL1ToL2Messages(messages: DataRetrieval<InboxLeaf>): Promise<boolean> {
63
45
  return this.db.transaction(() => {
64
- const lastL1BlockNumber = this.#lastL1BlockNewMessages.get() ?? 0n;
65
- if (lastL1BlockNumber >= lastMessageL1BlockNumber) {
46
+ const lastL1BlockNumber = this.#lastL1BlockMessages.get() ?? 0n;
47
+ if (lastL1BlockNumber >= messages.lastProcessedL1BlockNumber) {
66
48
  return false;
67
49
  }
68
50
 
69
- void this.#lastL1BlockNewMessages.set(lastMessageL1BlockNumber);
51
+ void this.#lastL1BlockMessages.set(messages.lastProcessedL1BlockNumber);
70
52
 
71
- for (const message of messages) {
53
+ for (const message of messages.retrievedData) {
72
54
  if (message.index >= this.#l1ToL2MessagesSubtreeSize) {
73
55
  throw new Error(`Message index ${message.index} out of subtree range`);
74
56
  }
75
57
  const key = `${message.blockNumber}-${message.index}`;
76
- void this.#newMessages.setIfNotExists(key, message.leaf.toBuffer());
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);
131
-
132
- for (const entryKey of entryKeys) {
133
- const messageCtx = this.#messages.get(entryKey.toString());
134
- if (!messageCtx) {
135
- throw new Error(`Message ${entryKey.toString()} not found`);
136
- }
137
-
138
- void this.#pendingMessagesByFee.update([messageCtx.fee, entryKey.toString()], -1);
139
- }
140
-
141
- return true;
142
- });
143
- }
144
-
145
- /**
146
- * Messages that have been published in an L2 block are confirmed.
147
- * Add them to the confirmed store, also remove them from the pending store.
148
- * @param entryKeys - The entry keys to be removed from the store.
149
- * @returns True if the operation is successful.
150
- */
151
- confirmPendingMessages(entryKeys: Fr[]): Promise<boolean> {
152
- return this.db.transaction(() => {
153
- for (const entryKey of entryKeys) {
154
- if (entryKey.equals(Fr.ZERO)) {
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;
58
+ void this.#l1ToL2Messages.setIfNotExists(key, message.leaf.toBuffer());
163
59
 
164
- void this.#messages.set(entryKey.toString(), messageCtx);
165
- void this.#pendingMessagesByFee.update([messageCtx.fee, entryKey.toString()], -1);
60
+ const indexInTheWholeTree =
61
+ (message.blockNumber - BigInt(INITIAL_L2_BLOCK_NUM)) * BigInt(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP) +
62
+ message.index;
63
+ void this.#l1ToL2MessageIndices.setIfNotExists(message.leaf.toString(), indexInTheWholeTree);
166
64
  }
167
65
 
168
66
  return true;
@@ -170,51 +68,22 @@ export class MessageStore {
170
68
  }
171
69
 
172
70
  /**
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.
71
+ * Gets the L1 to L2 message index in the L1 to L2 message tree.
72
+ * @param l1ToL2Message - The L1 to L2 message.
73
+ * @returns The index of the L1 to L2 message in the L1 to L2 message tree (undefined if not found).
176
74
  */
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`);
181
- }
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;
75
+ public getL1ToL2MessageIndex(l1ToL2Message: Fr): Promise<bigint | undefined> {
76
+ const index = this.#l1ToL2MessageIndices.get(l1ToL2Message.toString());
77
+ return Promise.resolve(index);
209
78
  }
210
79
 
211
- getNewL1ToL2Messages(blockNumber: bigint): Fr[] {
80
+ getL1ToL2Messages(blockNumber: bigint): Fr[] {
212
81
  const messages: Fr[] = [];
213
82
  let undefinedMessageFound = false;
214
83
  for (let messageIndex = 0; messageIndex < this.#l1ToL2MessagesSubtreeSize; messageIndex++) {
215
84
  // This is inefficient but probably fine for now.
216
85
  const key = `${blockNumber}-${messageIndex}`;
217
- const message = this.#newMessages.get(key);
86
+ const message = this.#l1ToL2Messages.get(key);
218
87
  if (message) {
219
88
  if (undefinedMessageFound) {
220
89
  throw new Error(`L1 to L2 message gap found in block ${blockNumber}`);
@@ -1,13 +1,15 @@
1
- import { L1ToL2Message, NewInboxLeaf } from '@aztec/circuit-types';
2
- import { L1_TO_L2_MSG_SUBTREE_HEIGHT } from '@aztec/circuits.js/constants';
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 NewL1ToL2MessageStore {
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: NewInboxLeaf) {
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
- * A map containing the entry key to the corresponding L1 to L2
58
- * messages (and the number of times the message has been seen).
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 (undefined if not found).
59
56
  */
60
- protected store: Map<bigint, L1ToL2MessageAndCount> = new Map();
61
-
62
- constructor() {}
63
-
64
- addMessage(entryKey: Fr, message: L1ToL2Message) {
65
- const entryKeyBigInt = entryKey.toBigInt();
66
- const msgAndCount = this.store.get(entryKeyBigInt);
67
- if (msgAndCount) {
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 | undefined {
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
- return messages;
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
+ return undefined;
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
- };
@@ -1,28 +1,27 @@
1
1
  import {
2
2
  Body,
3
- ExtendedContractData,
4
3
  ExtendedUnencryptedL2Log,
5
4
  GetUnencryptedLogsResponse,
6
- L1ToL2Message,
5
+ InboxLeaf,
7
6
  L2Block,
8
7
  L2BlockContext,
9
8
  L2BlockL2Logs,
10
9
  LogFilter,
11
10
  LogId,
12
11
  LogType,
13
- NewInboxLeaf,
14
12
  TxEffect,
15
13
  TxHash,
16
14
  TxReceipt,
17
15
  TxStatus,
18
16
  UnencryptedL2Log,
19
17
  } from '@aztec/circuit-types';
20
- import { Fr, INITIAL_L2_BLOCK_NUM, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/circuits.js';
18
+ import { Fr, INITIAL_L2_BLOCK_NUM } from '@aztec/circuits.js';
21
19
  import { AztecAddress } from '@aztec/foundation/aztec-address';
22
20
  import { ContractClassPublic, ContractInstanceWithAddress } from '@aztec/types/contracts';
23
21
 
24
- import { ArchiverDataStore } from '../archiver_store.js';
25
- import { L1ToL2MessageStore, NewL1ToL2MessageStore, PendingL1ToL2MessageStore } from './l1_to_l2_message_store.js';
22
+ import { ArchiverDataStore, ArchiverL1SynchPoint } from '../archiver_store.js';
23
+ import { DataRetrieval } from '../data_retrieval.js';
24
+ import { L1ToL2MessageStore } from './l1_to_l2_message_store.js';
26
25
 
27
26
  /**
28
27
  * Simple, in-memory implementation of an archiver data store.
@@ -56,36 +55,16 @@ export class MemoryArchiverStore implements ArchiverDataStore {
56
55
  private unencryptedLogsPerBlock: L2BlockL2Logs[] = [];
57
56
 
58
57
  /**
59
- * A sparse array containing all the extended contract data that have been fetched so far.
58
+ * Contains all L1 to L2 messages.
60
59
  */
61
- private extendedContractDataByBlock: (ExtendedContractData[] | undefined)[] = [];
62
-
63
- /**
64
- * A mapping of contract address to extended contract data.
65
- */
66
- private extendedContractData: Map<string, ExtendedContractData> = new Map();
67
-
68
- // TODO(#4492): Nuke the other message stores
69
- private newL1ToL2Messages = new NewL1ToL2MessageStore();
70
-
71
- /**
72
- * Contains all the confirmed L1 to L2 messages (i.e. messages that were consumed in an L2 block)
73
- * It is a map of entryKey to the corresponding L1 to L2 message and the number of times it has appeared
74
- */
75
- private confirmedL1ToL2Messages: L1ToL2MessageStore = new L1ToL2MessageStore();
76
-
77
- /**
78
- * Contains all the pending L1 to L2 messages (accounts for duplication of messages)
79
- */
80
- private pendingL1ToL2Messages: PendingL1ToL2MessageStore = new PendingL1ToL2MessageStore();
60
+ private l1ToL2Messages = new L1ToL2MessageStore();
81
61
 
82
62
  private contractClasses: Map<string, ContractClassPublic> = new Map();
83
63
 
84
64
  private contractInstances: Map<string, ContractInstanceWithAddress> = new Map();
85
65
 
66
+ private lastL1BlockNewBlocks: bigint = 0n;
86
67
  private lastL1BlockNewMessages: bigint = 0n;
87
- private lastL1BlockAddedMessages: bigint = 0n;
88
- private lastL1BlockCancelledMessages: bigint = 0n;
89
68
 
90
69
  constructor(
91
70
  /** The max number of logs that can be obtained in 1 "getUnencryptedLogs" call. */
@@ -120,12 +99,13 @@ export class MemoryArchiverStore implements ArchiverDataStore {
120
99
 
121
100
  /**
122
101
  * Append new blocks to the store's list.
123
- * @param blocks - The L2 blocks to be added to the store.
124
- * @returns True if the operation is successful (always in this implementation).
102
+ * @param blocks - The L2 blocks to be added to the store and the last processed L1 block.
103
+ * @returns True if the operation is successful.
125
104
  */
126
- public addBlocks(blocks: L2Block[]): Promise<boolean> {
127
- this.l2BlockContexts.push(...blocks.map(block => new L2BlockContext(block)));
128
- this.txEffects.push(...blocks.flatMap(b => b.getTxs()));
105
+ public addBlocks(blocks: DataRetrieval<L2Block>): Promise<boolean> {
106
+ this.lastL1BlockNewBlocks = blocks.lastProcessedL1BlockNumber;
107
+ this.l2BlockContexts.push(...blocks.retrievedData.map(block => new L2BlockContext(block)));
108
+ this.txEffects.push(...blocks.retrievedData.flatMap(b => b.getTxs()));
129
109
  return Promise.resolve(true);
130
110
  }
131
111
 
@@ -178,97 +158,29 @@ export class MemoryArchiverStore implements ArchiverDataStore {
178
158
  }
179
159
 
180
160
  /**
181
- * Append new L1 to L2 messages to the store.
182
- * @param messages - The L1 to L2 messages to be added to the store.
183
- * @param lastMessageL1BlockNumber - The L1 block number in which the last message was emitted.
161
+ * Append L1 to L2 messages to the store.
162
+ * @param messages - The L1 to L2 messages to be added to the store and the last processed L1 block.
184
163
  * @returns True if the operation is successful.
185
164
  */
186
- public addNewL1ToL2Messages(messages: NewInboxLeaf[], lastMessageL1BlockNumber: bigint): Promise<boolean> {
187
- if (lastMessageL1BlockNumber <= this.lastL1BlockNewMessages) {
188
- return Promise.resolve(false);
189
- }
190
-
191
- this.lastL1BlockNewMessages = lastMessageL1BlockNumber;
192
- for (const message of messages) {
193
- this.newL1ToL2Messages.addMessage(message);
194
- }
195
- return Promise.resolve(true);
196
- }
197
-
198
- /**
199
- * Append new pending L1 to L2 messages to the store.
200
- * @param messages - The L1 to L2 messages to be added to the store.
201
- * @param l1BlockNumber - The L1 block number for which to add the messages.
202
- * @returns True if the operation is successful (always in this implementation).
203
- */
204
- public addPendingL1ToL2Messages(messages: L1ToL2Message[], l1BlockNumber: bigint): Promise<boolean> {
205
- if (l1BlockNumber <= this.lastL1BlockAddedMessages) {
165
+ public addL1ToL2Messages(messages: DataRetrieval<InboxLeaf>): Promise<boolean> {
166
+ if (messages.lastProcessedL1BlockNumber <= this.lastL1BlockNewMessages) {
206
167
  return Promise.resolve(false);
207
168
  }
208
169
 
209
- this.lastL1BlockAddedMessages = l1BlockNumber;
210
- for (const message of messages) {
211
- this.pendingL1ToL2Messages.addMessage(message.entryKey!, message);
212
- }
213
- return Promise.resolve(true);
214
- }
215
-
216
- /**
217
- * Remove pending L1 to L2 messages from the store (if they were cancelled).
218
- * @param messages - The entry keys to be removed from the store.
219
- * @param l1BlockNumber - The L1 block number for which to remove the messages.
220
- * @returns True if the operation is successful (always in this implementation).
221
- */
222
- public cancelPendingL1ToL2EntryKeys(messages: Fr[], l1BlockNumber: bigint): Promise<boolean> {
223
- if (l1BlockNumber <= this.lastL1BlockCancelledMessages) {
224
- return Promise.resolve(false);
170
+ this.lastL1BlockNewMessages = messages.lastProcessedL1BlockNumber;
171
+ for (const message of messages.retrievedData) {
172
+ this.l1ToL2Messages.addMessage(message);
225
173
  }
226
-
227
- this.lastL1BlockCancelledMessages = l1BlockNumber;
228
- messages.forEach(entryKey => {
229
- this.pendingL1ToL2Messages.removeMessage(entryKey);
230
- });
231
- return Promise.resolve(true);
232
- }
233
-
234
- /**
235
- * Messages that have been published in an L2 block are confirmed.
236
- * Add them to the confirmed store, also remove them from the pending store.
237
- * @param entryKeys - The entry keys to be removed from the store.
238
- * @returns True if the operation is successful (always in this implementation).
239
- */
240
- public confirmL1ToL2EntryKeys(entryKeys: Fr[]): Promise<boolean> {
241
- entryKeys.forEach(entryKey => {
242
- if (entryKey.equals(Fr.ZERO)) {
243
- return;
244
- }
245
-
246
- this.confirmedL1ToL2Messages.addMessage(entryKey, this.pendingL1ToL2Messages.getMessage(entryKey)!);
247
- this.pendingL1ToL2Messages.removeMessage(entryKey);
248
- });
249
174
  return Promise.resolve(true);
250
175
  }
251
176
 
252
177
  /**
253
- * Store new extended contract data from an L2 block to the store's list.
254
- * @param data - List of contracts' data to be added.
255
- * @param blockNum - Number of the L2 block the contract data was deployed in.
256
- * @returns True if the operation is successful (always in this implementation).
178
+ * Gets the L1 to L2 message index in the L1 to L2 message tree.
179
+ * @param l1ToL2Message - The L1 to L2 message.
180
+ * @returns The index of the L1 to L2 message in the L1 to L2 message tree (undefined if not found).
257
181
  */
258
- public addExtendedContractData(data: ExtendedContractData[], blockNum: number): Promise<boolean> {
259
- // Add to the contracts mapping
260
- for (const contractData of data) {
261
- const key = contractData.contractData.contractAddress.toString();
262
- this.extendedContractData.set(key, contractData);
263
- }
264
-
265
- // Add the index per block
266
- if (this.extendedContractDataByBlock[blockNum]?.length) {
267
- this.extendedContractDataByBlock[blockNum]?.push(...data);
268
- } else {
269
- this.extendedContractDataByBlock[blockNum] = [...data];
270
- }
271
- return Promise.resolve(true);
182
+ public getL1ToL2MessageIndex(l1ToL2Message: Fr): Promise<bigint | undefined> {
183
+ return Promise.resolve(this.l1ToL2Messages.getMessageIndex(l1ToL2Message));
272
184
  }
273
185
 
274
186
  /**
@@ -322,34 +234,12 @@ export class MemoryArchiverStore implements ArchiverDataStore {
322
234
  }
323
235
 
324
236
  /**
325
- * Gets up to `limit` amount of pending L1 to L2 messages, sorted by fee
326
- * @param limit - The number of messages to return (by default NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).
327
- * @returns The requested L1 to L2 entry keys.
328
- */
329
- public getPendingL1ToL2EntryKeys(limit: number = NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP): Promise<Fr[]> {
330
- return Promise.resolve(this.pendingL1ToL2Messages.getEntryKeys(limit));
331
- }
332
-
333
- /**
334
- * Gets the confirmed L1 to L2 message corresponding to the given entry key.
335
- * @param entryKey - The entry key to look up.
336
- * @returns The requested L1 to L2 message or throws if not found.
337
- */
338
- public getConfirmedL1ToL2Message(entryKey: Fr): Promise<L1ToL2Message> {
339
- const message = this.confirmedL1ToL2Messages.getMessage(entryKey);
340
- if (!message) {
341
- throw new Error(`L1 to L2 Message with key ${entryKey.toString()} not found in the confirmed messages store`);
342
- }
343
- return Promise.resolve(message);
344
- }
345
-
346
- /**
347
- * Gets new L1 to L2 message (to be) included in a given block.
237
+ * Gets L1 to L2 message (to be) included in a given block.
348
238
  * @param blockNumber - L2 block number to get messages for.
349
239
  * @returns The L1 to L2 messages/leaves of the messages subtree (throws if not found).
350
240
  */
351
- getNewL1ToL2Messages(blockNumber: bigint): Promise<Fr[]> {
352
- return Promise.resolve(this.newL1ToL2Messages.getMessages(blockNumber));
241
+ getL1ToL2Messages(blockNumber: bigint): Promise<Fr[]> {
242
+ return Promise.resolve(this.l1ToL2Messages.getMessages(blockNumber));
353
243
  }
354
244
 
355
245
  /**
@@ -456,39 +346,21 @@ export class MemoryArchiverStore implements ArchiverDataStore {
456
346
  });
457
347
  }
458
348
 
459
- /**
460
- * Get the extended contract data for this contract.
461
- * TODO(palla/purge-old-contract-deploy): Delete me?
462
- * @param contractAddress - The contract data address.
463
- * @returns The extended contract data or undefined if not found.
464
- */
465
- getExtendedContractData(contractAddress: AztecAddress): Promise<ExtendedContractData | undefined> {
466
- const result = this.extendedContractData.get(contractAddress.toString());
467
- return Promise.resolve(result);
468
- }
469
-
470
349
  /**
471
350
  * Gets the number of the latest L2 block processed.
472
351
  * @returns The number of the latest L2 block processed.
473
352
  */
474
- public getBlockNumber(): Promise<number> {
353
+ public getSynchedL2BlockNumber(): Promise<number> {
475
354
  if (this.l2BlockContexts.length === 0) {
476
355
  return Promise.resolve(INITIAL_L2_BLOCK_NUM - 1);
477
356
  }
478
357
  return Promise.resolve(this.l2BlockContexts[this.l2BlockContexts.length - 1].block.number);
479
358
  }
480
359
 
481
- public getL1BlockNumber() {
482
- const addedBlock = this.l2BlockContexts[this.l2BlockContexts.length - 1]?.block?.getL1BlockNumber() ?? 0n;
483
- const newMessages = this.lastL1BlockNewMessages;
484
- const addedMessages = this.lastL1BlockAddedMessages;
485
- const cancelledMessages = this.lastL1BlockCancelledMessages;
486
-
360
+ public getSynchedL1BlockNumbers(): Promise<ArchiverL1SynchPoint> {
487
361
  return Promise.resolve({
488
- addedBlock,
489
- newMessages,
490
- addedMessages,
491
- cancelledMessages,
362
+ blocks: this.lastL1BlockNewBlocks,
363
+ messages: this.lastL1BlockNewMessages,
492
364
  });
493
365
  }
494
366
  }