@aztec/archiver 0.65.2 → 0.66.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 (46) hide show
  1. package/dest/archiver/archiver.d.ts +18 -22
  2. package/dest/archiver/archiver.d.ts.map +1 -1
  3. package/dest/archiver/archiver.js +143 -99
  4. package/dest/archiver/archiver_store.d.ts +7 -8
  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 +126 -150
  8. package/dest/archiver/config.d.ts +6 -12
  9. package/dest/archiver/config.d.ts.map +1 -1
  10. package/dest/archiver/config.js +6 -1
  11. package/dest/archiver/data_retrieval.d.ts +2 -3
  12. package/dest/archiver/data_retrieval.d.ts.map +1 -1
  13. package/dest/archiver/data_retrieval.js +14 -15
  14. package/dest/archiver/instrumentation.d.ts +2 -7
  15. package/dest/archiver/instrumentation.d.ts.map +1 -1
  16. package/dest/archiver/instrumentation.js +3 -6
  17. package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts +7 -8
  18. package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts.map +1 -1
  19. package/dest/archiver/kv_archiver_store/kv_archiver_store.js +7 -8
  20. package/dest/archiver/kv_archiver_store/log_store.d.ts +7 -8
  21. package/dest/archiver/kv_archiver_store/log_store.d.ts.map +1 -1
  22. package/dest/archiver/kv_archiver_store/log_store.js +55 -95
  23. package/dest/archiver/memory_archiver_store/memory_archiver_store.d.ts +8 -10
  24. package/dest/archiver/memory_archiver_store/memory_archiver_store.d.ts.map +1 -1
  25. package/dest/archiver/memory_archiver_store/memory_archiver_store.js +50 -57
  26. package/dest/index.d.ts +2 -2
  27. package/dest/index.d.ts.map +1 -1
  28. package/dest/index.js +3 -42
  29. package/dest/test/mock_l2_block_source.d.ts.map +1 -1
  30. package/dest/test/mock_l2_block_source.js +2 -2
  31. package/package.json +11 -13
  32. package/src/archiver/archiver.ts +199 -191
  33. package/src/archiver/archiver_store.ts +6 -13
  34. package/src/archiver/archiver_store_test_suite.ts +160 -186
  35. package/src/archiver/config.ts +12 -12
  36. package/src/archiver/data_retrieval.ts +12 -17
  37. package/src/archiver/instrumentation.ts +3 -5
  38. package/src/archiver/kv_archiver_store/kv_archiver_store.ts +7 -14
  39. package/src/archiver/kv_archiver_store/log_store.ts +68 -118
  40. package/src/archiver/memory_archiver_store/memory_archiver_store.ts +51 -65
  41. package/src/index.ts +5 -59
  42. package/src/test/mock_l2_block_source.ts +1 -2
  43. package/dest/archiver/epoch_helpers.d.ts +0 -20
  44. package/dest/archiver/epoch_helpers.d.ts.map +0 -1
  45. package/dest/archiver/epoch_helpers.js +0 -34
  46. package/src/archiver/epoch_helpers.ts +0 -54
@@ -1,12 +1,9 @@
1
1
  import {
2
- type FromLogType,
3
2
  type GetUnencryptedLogsResponse,
4
3
  type InBlock,
5
4
  type InboxLeaf,
6
5
  type L2Block,
7
- type L2BlockL2Logs,
8
6
  type LogFilter,
9
- type LogType,
10
7
  type TxHash,
11
8
  type TxReceipt,
12
9
  type TxScopedL2Log,
@@ -17,6 +14,7 @@ import {
17
14
  type ExecutablePrivateFunctionWithMembershipProof,
18
15
  type Fr,
19
16
  type Header,
17
+ type PrivateLog,
20
18
  type UnconstrainedFunctionWithMembershipProof,
21
19
  } from '@aztec/circuits.js';
22
20
  import { type ContractArtifact, FunctionSelector } from '@aztec/foundation/abi';
@@ -266,19 +264,14 @@ export class KVArchiverDataStore implements ArchiverDataStore {
266
264
  }
267
265
 
268
266
  /**
269
- * Gets up to `limit` amount of logs starting from `from`.
270
- * @param start - Number of the L2 block to which corresponds the first logs to be returned.
271
- * @param limit - The number of logs to return.
272
- * @param logType - Specifies whether to return encrypted or unencrypted logs.
273
- * @returns The requested logs.
267
+ * Retrieves all private logs from up to `limit` blocks, starting from the block number `from`.
268
+ * @param from - The block number from which to begin retrieving logs.
269
+ * @param limit - The maximum number of blocks to retrieve logs from.
270
+ * @returns An array of private logs from the specified range of blocks.
274
271
  */
275
- getLogs<TLogType extends LogType>(
276
- start: number,
277
- limit: number,
278
- logType: TLogType,
279
- ): Promise<L2BlockL2Logs<FromLogType<TLogType>>[]> {
272
+ getPrivateLogs(from: number, limit: number): Promise<PrivateLog[]> {
280
273
  try {
281
- return Promise.resolve(Array.from(this.#logStore.getLogs(start, limit, logType)));
274
+ return Promise.resolve(Array.from(this.#logStore.getPrivateLogs(from, limit)));
282
275
  } catch (err) {
283
276
  return Promise.reject(err);
284
277
  }
@@ -1,23 +1,18 @@
1
1
  import {
2
- type Body,
3
2
  ContractClass2BlockL2Logs,
4
- EncryptedL2BlockL2Logs,
5
- EncryptedNoteL2BlockL2Logs,
6
3
  ExtendedUnencryptedL2Log,
7
- type FromLogType,
8
4
  type GetUnencryptedLogsResponse,
9
5
  type L2Block,
10
- type L2BlockL2Logs,
11
6
  type LogFilter,
12
7
  LogId,
13
- LogType,
14
8
  TxScopedL2Log,
15
9
  UnencryptedL2BlockL2Logs,
16
10
  type UnencryptedL2Log,
17
11
  } from '@aztec/circuit-types';
18
- import { Fr } from '@aztec/circuits.js';
12
+ import { Fr, PrivateLog } from '@aztec/circuits.js';
19
13
  import { INITIAL_L2_BLOCK_NUM, MAX_NOTE_HASHES_PER_TX } from '@aztec/circuits.js/constants';
20
14
  import { createDebugLogger } from '@aztec/foundation/log';
15
+ import { BufferReader } from '@aztec/foundation/serialize';
21
16
  import { type AztecKVStore, type AztecMap } from '@aztec/kv-store';
22
17
 
23
18
  import { type BlockStore } from './block_store.js';
@@ -26,72 +21,83 @@ import { type BlockStore } from './block_store.js';
26
21
  * A store for logs
27
22
  */
28
23
  export class LogStore {
29
- #noteEncryptedLogsByBlock: AztecMap<number, Buffer>;
30
24
  #logsByTag: AztecMap<string, Buffer[]>;
31
25
  #logTagsByBlock: AztecMap<number, string[]>;
32
- #encryptedLogsByBlock: AztecMap<number, Buffer>;
26
+ #privateLogsByBlock: AztecMap<number, Buffer>;
33
27
  #unencryptedLogsByBlock: AztecMap<number, Buffer>;
34
28
  #contractClassLogsByBlock: AztecMap<number, Buffer>;
35
29
  #logsMaxPageSize: number;
36
30
  #log = createDebugLogger('aztec:archiver:log_store');
37
31
 
38
32
  constructor(private db: AztecKVStore, private blockStore: BlockStore, logsMaxPageSize: number = 1000) {
39
- this.#noteEncryptedLogsByBlock = db.openMap('archiver_note_encrypted_logs_by_block');
40
33
  this.#logsByTag = db.openMap('archiver_tagged_logs_by_tag');
41
34
  this.#logTagsByBlock = db.openMap('archiver_log_tags_by_block');
42
- this.#encryptedLogsByBlock = db.openMap('archiver_encrypted_logs_by_block');
35
+ this.#privateLogsByBlock = db.openMap('archiver_private_logs_by_block');
43
36
  this.#unencryptedLogsByBlock = db.openMap('archiver_unencrypted_logs_by_block');
44
37
  this.#contractClassLogsByBlock = db.openMap('archiver_contract_class_logs_by_block');
45
38
 
46
39
  this.#logsMaxPageSize = logsMaxPageSize;
47
40
  }
48
41
 
49
- #extractTaggedLogs(block: L2Block, logType: keyof Pick<Body, 'noteEncryptedLogs' | 'unencryptedLogs'>) {
42
+ #extractTaggedLogsFromPrivate(block: L2Block) {
50
43
  const taggedLogs = new Map<string, Buffer[]>();
51
44
  const dataStartIndexForBlock =
52
45
  block.header.state.partial.noteHashTree.nextAvailableLeafIndex -
53
46
  block.body.numberOfTxsIncludingPadded * MAX_NOTE_HASHES_PER_TX;
54
- block.body[logType].txLogs.forEach((txLogs, txIndex) => {
47
+ block.body.txEffects.forEach((txEffect, txIndex) => {
48
+ const txHash = txEffect.txHash;
49
+ const dataStartIndexForTx = dataStartIndexForBlock + txIndex * MAX_NOTE_HASHES_PER_TX;
50
+ txEffect.privateLogs.forEach(log => {
51
+ const tag = log.fields[0];
52
+ const currentLogs = taggedLogs.get(tag.toString()) ?? [];
53
+ currentLogs.push(
54
+ new TxScopedL2Log(
55
+ txHash,
56
+ dataStartIndexForTx,
57
+ block.number,
58
+ /* isFromPublic */ false,
59
+ log.toBuffer(),
60
+ ).toBuffer(),
61
+ );
62
+ taggedLogs.set(tag.toString(), currentLogs);
63
+ });
64
+ });
65
+ return taggedLogs;
66
+ }
67
+
68
+ #extractTaggedLogsFromPublic(block: L2Block) {
69
+ const taggedLogs = new Map<string, Buffer[]>();
70
+ const dataStartIndexForBlock =
71
+ block.header.state.partial.noteHashTree.nextAvailableLeafIndex -
72
+ block.body.numberOfTxsIncludingPadded * MAX_NOTE_HASHES_PER_TX;
73
+ block.body.unencryptedLogs.txLogs.forEach((txLogs, txIndex) => {
55
74
  const txHash = block.body.txEffects[txIndex].txHash;
56
75
  const dataStartIndexForTx = dataStartIndexForBlock + txIndex * MAX_NOTE_HASHES_PER_TX;
57
76
  const logs = txLogs.unrollLogs();
58
77
  logs.forEach(log => {
59
- if (
60
- (logType == 'noteEncryptedLogs' && log.data.length < 32) ||
78
+ if (log.data.length < 32 * 33) {
61
79
  // TODO remove when #9835 and #9836 are fixed
62
- (logType === 'unencryptedLogs' && log.data.length < 32 * 33)
63
- ) {
64
- this.#log.warn(`Skipping log (${logType}) with invalid data length: ${log.data.length}`);
80
+ this.#log.warn(`Skipping unencrypted log with insufficient data length: ${log.data.length}`);
65
81
  return;
66
82
  }
67
83
  try {
68
- let tag = Fr.ZERO;
69
84
  // TODO remove when #9835 and #9836 are fixed. The partial note logs are emitted as bytes, but encoded as Fields.
70
85
  // This means that for every 32 bytes of payload, we only have 1 byte of data.
71
86
  // Also, the tag is not stored in the first 32 bytes of the log, (that's the length of public fields now) but in the next 32.
72
- if (logType === 'unencryptedLogs') {
73
- const correctedBuffer = Buffer.alloc(32);
74
- const initialOffset = 32;
75
- for (let i = 0; i < 32; i++) {
76
- const byte = Fr.fromBuffer(
77
- log.data.subarray(i * 32 + initialOffset, i * 32 + 32 + initialOffset),
78
- ).toNumber();
79
- correctedBuffer.writeUInt8(byte, i);
80
- }
81
- tag = new Fr(correctedBuffer);
82
- } else {
83
- tag = new Fr(log.data.subarray(0, 32));
87
+ const correctedBuffer = Buffer.alloc(32);
88
+ const initialOffset = 32;
89
+ for (let i = 0; i < 32; i++) {
90
+ const byte = Fr.fromBuffer(
91
+ log.data.subarray(i * 32 + initialOffset, i * 32 + 32 + initialOffset),
92
+ ).toNumber();
93
+ correctedBuffer.writeUInt8(byte, i);
84
94
  }
85
- this.#log.verbose(`Found tagged (${logType}) log with tag ${tag.toString()} in block ${block.number}`);
95
+ const tag = new Fr(correctedBuffer);
96
+
97
+ this.#log.debug(`Found tagged unencrypted log with tag ${tag.toString()} in block ${block.number}`);
86
98
  const currentLogs = taggedLogs.get(tag.toString()) ?? [];
87
99
  currentLogs.push(
88
- new TxScopedL2Log(
89
- txHash,
90
- dataStartIndexForTx,
91
- block.number,
92
- logType === 'unencryptedLogs',
93
- log.data,
94
- ).toBuffer(),
100
+ new TxScopedL2Log(txHash, dataStartIndexForTx, block.number, /* isFromPublic */ true, log.data).toBuffer(),
95
101
  );
96
102
  taggedLogs.set(tag.toString(), currentLogs);
97
103
  } catch (err) {
@@ -109,10 +115,7 @@ export class LogStore {
109
115
  */
110
116
  async addLogs(blocks: L2Block[]): Promise<boolean> {
111
117
  const taggedLogsToAdd = blocks
112
- .flatMap(block => [
113
- this.#extractTaggedLogs(block, 'noteEncryptedLogs'),
114
- this.#extractTaggedLogs(block, 'unencryptedLogs'),
115
- ])
118
+ .flatMap(block => [this.#extractTaggedLogsFromPrivate(block), this.#extractTaggedLogsFromPublic(block)])
116
119
  .reduce((acc, val) => {
117
120
  for (const [tag, logs] of val.entries()) {
118
121
  const currentLogs = acc.get(tag) ?? [];
@@ -140,8 +143,13 @@ export class LogStore {
140
143
  tagsInBlock.push(tag);
141
144
  }
142
145
  void this.#logTagsByBlock.set(block.number, tagsInBlock);
143
- void this.#noteEncryptedLogsByBlock.set(block.number, block.body.noteEncryptedLogs.toBuffer());
144
- void this.#encryptedLogsByBlock.set(block.number, block.body.encryptedLogs.toBuffer());
146
+
147
+ const privateLogsInBlock = block.body.txEffects
148
+ .map(txEffect => txEffect.privateLogs)
149
+ .flat()
150
+ .map(log => log.toBuffer());
151
+ void this.#privateLogsByBlock.set(block.number, Buffer.concat(privateLogsInBlock));
152
+
145
153
  void this.#unencryptedLogsByBlock.set(block.number, block.body.unencryptedLogs.toBuffer());
146
154
  void this.#contractClassLogsByBlock.set(block.number, block.body.contractClassLogs.toBuffer());
147
155
  });
@@ -156,8 +164,7 @@ export class LogStore {
156
164
  });
157
165
  return this.db.transaction(() => {
158
166
  blocks.forEach(block => {
159
- void this.#noteEncryptedLogsByBlock.delete(block.number);
160
- void this.#encryptedLogsByBlock.delete(block.number);
167
+ void this.#privateLogsByBlock.delete(block.number);
161
168
  void this.#unencryptedLogsByBlock.delete(block.number);
162
169
  void this.#logTagsByBlock.delete(block.number);
163
170
  });
@@ -171,43 +178,20 @@ export class LogStore {
171
178
  }
172
179
 
173
180
  /**
174
- * Gets up to `limit` amount of logs starting from `from`.
175
- * @param start - Number of the L2 block to which corresponds the first logs to be returned.
176
- * @param limit - The number of logs to return.
177
- * @param logType - Specifies whether to return encrypted or unencrypted logs.
178
- * @returns The requested logs.
181
+ * Retrieves all private logs from up to `limit` blocks, starting from the block number `start`.
182
+ * @param start - The block number from which to begin retrieving logs.
183
+ * @param limit - The maximum number of blocks to retrieve logs from.
184
+ * @returns An array of private logs from the specified range of blocks.
179
185
  */
180
- *getLogs<TLogType extends LogType>(
181
- start: number,
182
- limit: number,
183
- logType: TLogType,
184
- ): IterableIterator<L2BlockL2Logs<FromLogType<TLogType>>> {
185
- const logMap = (() => {
186
- switch (logType) {
187
- case LogType.ENCRYPTED:
188
- return this.#encryptedLogsByBlock;
189
- case LogType.NOTEENCRYPTED:
190
- return this.#noteEncryptedLogsByBlock;
191
- case LogType.UNENCRYPTED:
192
- default:
193
- return this.#unencryptedLogsByBlock;
194
- }
195
- })();
196
- const logTypeMap = (() => {
197
- switch (logType) {
198
- case LogType.ENCRYPTED:
199
- return EncryptedL2BlockL2Logs;
200
- case LogType.NOTEENCRYPTED:
201
- return EncryptedNoteL2BlockL2Logs;
202
- case LogType.UNENCRYPTED:
203
- default:
204
- return UnencryptedL2BlockL2Logs;
186
+ getPrivateLogs(start: number, limit: number) {
187
+ const logs = [];
188
+ for (const buffer of this.#privateLogsByBlock.values({ start, limit })) {
189
+ const reader = new BufferReader(buffer);
190
+ while (reader.remainingBytes() > 0) {
191
+ logs.push(reader.readObject(PrivateLog));
205
192
  }
206
- })();
207
- const L2BlockL2Logs = logTypeMap;
208
- for (const buffer of logMap.values({ start, limit })) {
209
- yield L2BlockL2Logs.fromBuffer(buffer) as L2BlockL2Logs<FromLogType<TLogType>>;
210
193
  }
194
+ return logs;
211
195
  }
212
196
 
213
197
  /**
@@ -249,7 +233,9 @@ export class LogStore {
249
233
  return { logs: [], maxLogsHit: false };
250
234
  }
251
235
 
252
- const unencryptedLogsInBlock = this.#getBlockLogs(blockNumber, LogType.UNENCRYPTED);
236
+ const buffer = this.#unencryptedLogsByBlock.get(blockNumber) ?? Buffer.alloc(0);
237
+ const unencryptedLogsInBlock = UnencryptedL2BlockL2Logs.fromBuffer(buffer);
238
+
253
239
  const txLogs = unencryptedLogsInBlock.txLogs[txIndex].unrollLogs();
254
240
 
255
241
  const logs: ExtendedUnencryptedL2Log[] = [];
@@ -376,40 +362,4 @@ export class LogStore {
376
362
 
377
363
  return maxLogsHit;
378
364
  }
379
-
380
- #getBlockLogs<TLogType extends LogType>(
381
- blockNumber: number,
382
- logType: TLogType,
383
- ): L2BlockL2Logs<FromLogType<TLogType>> {
384
- const logMap = (() => {
385
- switch (logType) {
386
- case LogType.ENCRYPTED:
387
- return this.#encryptedLogsByBlock;
388
- case LogType.NOTEENCRYPTED:
389
- return this.#noteEncryptedLogsByBlock;
390
- case LogType.UNENCRYPTED:
391
- default:
392
- return this.#unencryptedLogsByBlock;
393
- }
394
- })();
395
- const logTypeMap = (() => {
396
- switch (logType) {
397
- case LogType.ENCRYPTED:
398
- return EncryptedL2BlockL2Logs;
399
- case LogType.NOTEENCRYPTED:
400
- return EncryptedNoteL2BlockL2Logs;
401
- case LogType.UNENCRYPTED:
402
- default:
403
- return UnencryptedL2BlockL2Logs;
404
- }
405
- })();
406
- const L2BlockL2Logs = logTypeMap;
407
- const buffer = logMap.get(blockNumber);
408
-
409
- if (!buffer) {
410
- return new L2BlockL2Logs([]) as L2BlockL2Logs<FromLogType<TLogType>>;
411
- }
412
-
413
- return L2BlockL2Logs.fromBuffer(buffer) as L2BlockL2Logs<FromLogType<TLogType>>;
414
- }
415
365
  }
@@ -1,19 +1,13 @@
1
1
  import {
2
- type Body,
3
2
  type ContractClass2BlockL2Logs,
4
- type EncryptedL2BlockL2Logs,
5
- type EncryptedNoteL2BlockL2Logs,
6
3
  ExtendedUnencryptedL2Log,
7
- type FromLogType,
8
4
  type GetUnencryptedLogsResponse,
9
5
  type InBlock,
10
6
  type InboxLeaf,
11
7
  type L2Block,
12
8
  L2BlockHash,
13
- type L2BlockL2Logs,
14
9
  type LogFilter,
15
10
  LogId,
16
- LogType,
17
11
  type TxEffect,
18
12
  type TxHash,
19
13
  TxReceipt,
@@ -31,6 +25,7 @@ import {
31
25
  INITIAL_L2_BLOCK_NUM,
32
26
  MAX_NOTE_HASHES_PER_TX,
33
27
  MAX_NULLIFIERS_PER_TX,
28
+ type PrivateLog,
34
29
  type UnconstrainedFunctionWithMembershipProof,
35
30
  } from '@aztec/circuits.js';
36
31
  import { type ContractArtifact, FunctionSelector } from '@aztec/foundation/abi';
@@ -56,13 +51,11 @@ export class MemoryArchiverStore implements ArchiverDataStore {
56
51
  */
57
52
  private txEffects: InBlock<TxEffect>[] = [];
58
53
 
59
- private noteEncryptedLogsPerBlock: Map<number, EncryptedNoteL2BlockL2Logs> = new Map();
60
-
61
54
  private taggedLogs: Map<string, TxScopedL2Log[]> = new Map();
62
55
 
63
56
  private logTagsPerBlock: Map<number, Fr[]> = new Map();
64
57
 
65
- private encryptedLogsPerBlock: Map<number, EncryptedL2BlockL2Logs> = new Map();
58
+ private privateLogsPerBlock: Map<number, PrivateLog[]> = new Map();
66
59
 
67
60
  private unencryptedLogsPerBlock: Map<number, UnencryptedL2BlockL2Logs> = new Map();
68
61
 
@@ -232,46 +225,61 @@ export class MemoryArchiverStore implements ArchiverDataStore {
232
225
  return Promise.resolve(true);
233
226
  }
234
227
 
235
- #storeTaggedLogs(block: L2Block, logType: keyof Pick<Body, 'noteEncryptedLogs' | 'unencryptedLogs'>): void {
228
+ #storeTaggedLogsFromPrivate(block: L2Block): void {
229
+ const dataStartIndexForBlock =
230
+ block.header.state.partial.noteHashTree.nextAvailableLeafIndex -
231
+ block.body.numberOfTxsIncludingPadded * MAX_NOTE_HASHES_PER_TX;
232
+ block.body.txEffects.forEach((txEffect, txIndex) => {
233
+ const txHash = txEffect.txHash;
234
+ const dataStartIndexForTx = dataStartIndexForBlock + txIndex * MAX_NOTE_HASHES_PER_TX;
235
+ txEffect.privateLogs.forEach(log => {
236
+ const tag = log.fields[0];
237
+ const currentLogs = this.taggedLogs.get(tag.toString()) || [];
238
+ this.taggedLogs.set(tag.toString(), [
239
+ ...currentLogs,
240
+ new TxScopedL2Log(txHash, dataStartIndexForTx, block.number, /* isFromPublic */ false, log.toBuffer()),
241
+ ]);
242
+ const currentTagsInBlock = this.logTagsPerBlock.get(block.number) || [];
243
+ this.logTagsPerBlock.set(block.number, [...currentTagsInBlock, tag]);
244
+ });
245
+ });
246
+ }
247
+
248
+ #storeTaggedLogsFromPublic(block: L2Block): void {
236
249
  const dataStartIndexForBlock =
237
250
  block.header.state.partial.noteHashTree.nextAvailableLeafIndex -
238
251
  block.body.numberOfTxsIncludingPadded * MAX_NOTE_HASHES_PER_TX;
239
- block.body[logType].txLogs.forEach((txLogs, txIndex) => {
252
+ block.body.unencryptedLogs.txLogs.forEach((txLogs, txIndex) => {
240
253
  const txHash = block.body.txEffects[txIndex].txHash;
241
254
  const dataStartIndexForTx = dataStartIndexForBlock + txIndex * MAX_NOTE_HASHES_PER_TX;
242
255
  const logs = txLogs.unrollLogs();
243
256
  logs.forEach(log => {
244
257
  if (
245
- (logType == 'noteEncryptedLogs' && log.data.length < 32) ||
246
258
  // TODO remove when #9835 and #9836 are fixed
247
- (logType === 'unencryptedLogs' && log.data.length < 32 * 33)
259
+ log.data.length <
260
+ 32 * 33
248
261
  ) {
249
- this.#log.warn(`Skipping log (${logType}) with invalid data length: ${log.data.length}`);
262
+ this.#log.warn(`Skipping unencrypted log with invalid data length: ${log.data.length}`);
250
263
  return;
251
264
  }
252
265
  try {
253
- let tag = Fr.ZERO;
254
266
  // TODO remove when #9835 and #9836 are fixed. The partial note logs are emitted as bytes, but encoded as Fields.
255
267
  // This means that for every 32 bytes of payload, we only have 1 byte of data.
256
268
  // Also, the tag is not stored in the first 32 bytes of the log, (that's the length of public fields now) but in the next 32.
257
- if (logType === 'unencryptedLogs') {
258
- const correctedBuffer = Buffer.alloc(32);
259
- const initialOffset = 32;
260
- for (let i = 0; i < 32; i++) {
261
- const byte = Fr.fromBuffer(
262
- log.data.subarray(i * 32 + initialOffset, i * 32 + 32 + initialOffset),
263
- ).toNumber();
264
- correctedBuffer.writeUInt8(byte, i);
265
- }
266
- tag = new Fr(correctedBuffer);
267
- } else {
268
- tag = new Fr(log.data.subarray(0, 32));
269
+ const correctedBuffer = Buffer.alloc(32);
270
+ const initialOffset = 32;
271
+ for (let i = 0; i < 32; i++) {
272
+ const byte = Fr.fromBuffer(
273
+ log.data.subarray(i * 32 + initialOffset, i * 32 + 32 + initialOffset),
274
+ ).toNumber();
275
+ correctedBuffer.writeUInt8(byte, i);
269
276
  }
270
- this.#log.verbose(`Storing tagged (${logType}) log with tag ${tag.toString()} in block ${block.number}`);
277
+ const tag = new Fr(correctedBuffer);
278
+ this.#log.verbose(`Storing unencrypted tagged log with tag ${tag.toString()} in block ${block.number}`);
271
279
  const currentLogs = this.taggedLogs.get(tag.toString()) || [];
272
280
  this.taggedLogs.set(tag.toString(), [
273
281
  ...currentLogs,
274
- new TxScopedL2Log(txHash, dataStartIndexForTx, block.number, logType === 'unencryptedLogs', log.data),
282
+ new TxScopedL2Log(txHash, dataStartIndexForTx, block.number, /* isFromPublic */ true, log.data),
275
283
  ]);
276
284
  const currentTagsInBlock = this.logTagsPerBlock.get(block.number) || [];
277
285
  this.logTagsPerBlock.set(block.number, [...currentTagsInBlock, tag]);
@@ -289,10 +297,9 @@ export class MemoryArchiverStore implements ArchiverDataStore {
289
297
  */
290
298
  addLogs(blocks: L2Block[]): Promise<boolean> {
291
299
  blocks.forEach(block => {
292
- void this.#storeTaggedLogs(block, 'noteEncryptedLogs');
293
- void this.#storeTaggedLogs(block, 'unencryptedLogs');
294
- this.noteEncryptedLogsPerBlock.set(block.number, block.body.noteEncryptedLogs);
295
- this.encryptedLogsPerBlock.set(block.number, block.body.encryptedLogs);
300
+ void this.#storeTaggedLogsFromPrivate(block);
301
+ void this.#storeTaggedLogsFromPublic(block);
302
+ this.privateLogsPerBlock.set(block.number, block.body.txEffects.map(txEffect => txEffect.privateLogs).flat());
296
303
  this.unencryptedLogsPerBlock.set(block.number, block.body.unencryptedLogs);
297
304
  this.contractClassLogsPerBlock.set(block.number, block.body.contractClassLogs);
298
305
  });
@@ -308,8 +315,7 @@ export class MemoryArchiverStore implements ArchiverDataStore {
308
315
  });
309
316
 
310
317
  blocks.forEach(block => {
311
- this.encryptedLogsPerBlock.delete(block.number);
312
- this.noteEncryptedLogsPerBlock.delete(block.number);
318
+ this.privateLogsPerBlock.delete(block.number);
313
319
  this.unencryptedLogsPerBlock.delete(block.number);
314
320
  this.logTagsPerBlock.delete(block.number);
315
321
  this.contractClassLogsPerBlock.delete(block.number);
@@ -471,17 +477,12 @@ export class MemoryArchiverStore implements ArchiverDataStore {
471
477
  }
472
478
 
473
479
  /**
474
- * Gets up to `limit` amount of logs starting from `from`.
475
- * @param from - Number of the L2 block to which corresponds the first logs to be returned.
476
- * @param limit - The number of logs to return.
477
- * @param logType - Specifies whether to return encrypted or unencrypted logs.
478
- * @returns The requested logs.
480
+ * Retrieves all private logs from up to `limit` blocks, starting from the block number `from`.
481
+ * @param from - The block number from which to begin retrieving logs.
482
+ * @param limit - The maximum number of blocks to retrieve logs from.
483
+ * @returns An array of private logs from the specified range of blocks.
479
484
  */
480
- getLogs<TLogType extends LogType>(
481
- from: number,
482
- limit: number,
483
- logType: TLogType,
484
- ): Promise<L2BlockL2Logs<FromLogType<TLogType>>[]> {
485
+ getPrivateLogs(from: number, limit: number): Promise<PrivateLog[]> {
485
486
  if (from < INITIAL_L2_BLOCK_NUM || limit < 1) {
486
487
  return Promise.resolve([]);
487
488
  }
@@ -490,34 +491,19 @@ export class MemoryArchiverStore implements ArchiverDataStore {
490
491
  return Promise.resolve([]);
491
492
  }
492
493
 
493
- const logMap = (() => {
494
- switch (logType) {
495
- case LogType.ENCRYPTED:
496
- return this.encryptedLogsPerBlock;
497
- case LogType.NOTEENCRYPTED:
498
- return this.noteEncryptedLogsPerBlock;
499
- case LogType.UNENCRYPTED:
500
- default:
501
- return this.unencryptedLogsPerBlock;
502
- }
503
- })() as Map<number, L2BlockL2Logs<FromLogType<TLogType>>>;
504
-
505
494
  const startIndex = from;
506
495
  const endIndex = startIndex + limit;
507
496
  const upper = Math.min(endIndex, this.l2Blocks.length + INITIAL_L2_BLOCK_NUM);
508
497
 
509
- const l = [];
498
+ const logsInBlocks = [];
510
499
  for (let i = startIndex; i < upper; i++) {
511
- const log = logMap.get(i);
512
- if (log) {
513
- l.push(log);
514
- } else {
515
- // I hate typescript sometimes
516
- l.push(undefined as unknown as L2BlockL2Logs<FromLogType<TLogType>>);
500
+ const logs = this.privateLogsPerBlock.get(i);
501
+ if (logs) {
502
+ logsInBlocks.push(logs);
517
503
  }
518
504
  }
519
505
 
520
- return Promise.resolve(l);
506
+ return Promise.resolve(logsInBlocks.flat());
521
507
  }
522
508
 
523
509
  /**
package/src/index.ts CHANGED
@@ -1,62 +1,8 @@
1
- import { jsonStringify } from '@aztec/foundation/json-rpc';
2
- import { createDebugLogger } from '@aztec/foundation/log';
3
- import { fileURLToPath } from '@aztec/foundation/url';
4
- import { NoopTelemetryClient } from '@aztec/telemetry-client/noop';
5
-
6
- import { createPublicClient, http } from 'viem';
7
- import { localhost } from 'viem/chains';
8
-
9
- import { Archiver, getArchiverConfigFromEnv } from './archiver/index.js';
10
- import { ArchiverInstrumentation } from './archiver/instrumentation.js';
11
- import { MemoryArchiverStore } from './archiver/memory_archiver_store/memory_archiver_store.js';
12
-
13
1
  export * from './archiver/index.js';
14
- export * from './rpc/index.js';
15
2
  export * from './factory.js';
3
+ export * from './rpc/index.js';
16
4
 
17
- export { retrieveL2ProofVerifiedEvents, retrieveBlockFromRollup } from './archiver/data_retrieval.js';
18
-
19
- const log = createDebugLogger('aztec:archiver');
20
-
21
- /**
22
- * A function which instantiates and starts Archiver.
23
- */
24
- // eslint-disable-next-line require-await
25
- async function main() {
26
- const config = getArchiverConfigFromEnv();
27
- const { l1RpcUrl: rpcUrl, l1Contracts } = config;
28
-
29
- log.info(`Starting archiver in main(): ${jsonStringify(config)}`);
30
- const publicClient = createPublicClient({
31
- chain: localhost,
32
- transport: http(rpcUrl),
33
- });
34
-
35
- const archiverStore = new MemoryArchiverStore(1000);
36
-
37
- const archiver = new Archiver(
38
- publicClient,
39
- l1Contracts.rollupAddress,
40
- l1Contracts.inboxAddress,
41
- l1Contracts.registryAddress,
42
- archiverStore,
43
- 1000,
44
- new ArchiverInstrumentation(new NoopTelemetryClient()),
45
- );
46
-
47
- const shutdown = async () => {
48
- await archiver.stop();
49
- process.exit(0);
50
- };
51
- process.once('SIGINT', shutdown);
52
- process.once('SIGTERM', shutdown);
53
- }
54
-
55
- // See https://twitter.com/Rich_Harris/status/1355289863130673153
56
- if (process.argv[1] === fileURLToPath(import.meta.url).replace(/\/index\.js$/, '')) {
57
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
58
- main().catch(err => {
59
- log.error(err);
60
- process.exit(1);
61
- });
62
- }
5
+ export {
6
+ retrieveBlocksFromRollup as retrieveBlockFromRollup,
7
+ retrieveL2ProofVerifiedEvents,
8
+ } from './archiver/data_retrieval.js';
@@ -7,12 +7,11 @@ import {
7
7
  TxReceipt,
8
8
  TxStatus,
9
9
  } from '@aztec/circuit-types';
10
+ import { getSlotRangeForEpoch } from '@aztec/circuit-types';
10
11
  import { EthAddress, type Header } from '@aztec/circuits.js';
11
12
  import { DefaultL1ContractsConfig } from '@aztec/ethereum';
12
13
  import { createDebugLogger } from '@aztec/foundation/log';
13
14
 
14
- import { getSlotRangeForEpoch } from '../archiver/epoch_helpers.js';
15
-
16
15
  /**
17
16
  * A mocked implementation of L2BlockSource to be used in tests.
18
17
  */
@@ -1,20 +0,0 @@
1
- export type EpochConstants = {
2
- l1GenesisBlock: bigint;
3
- l1GenesisTime: bigint;
4
- epochDuration: number;
5
- slotDuration: number;
6
- };
7
- /** Returns the slot number for a given timestamp. */
8
- export declare function getSlotAtTimestamp(ts: bigint, constants: Pick<EpochConstants, 'l1GenesisTime' | 'slotDuration'>): bigint;
9
- /** Returns the epoch number for a given timestamp. */
10
- export declare function getEpochNumberAtTimestamp(ts: bigint, constants: Pick<EpochConstants, 'epochDuration' | 'slotDuration' | 'l1GenesisTime'>): bigint;
11
- /** Returns the range of L2 slots (inclusive) for a given epoch number. */
12
- export declare function getSlotRangeForEpoch(epochNumber: bigint, constants: Pick<EpochConstants, 'epochDuration'>): bigint[];
13
- /** Returns the range of L1 timestamps (inclusive) for a given epoch number. */
14
- export declare function getTimestampRangeForEpoch(epochNumber: bigint, constants: Pick<EpochConstants, 'l1GenesisTime' | 'slotDuration' | 'epochDuration'>): bigint[];
15
- /**
16
- * Returns the range of L1 blocks (inclusive) for a given epoch number.
17
- * @remarks This assumes no time warp has happened.
18
- */
19
- export declare function getL1BlockRangeForEpoch(epochNumber: bigint, constants: Pick<EpochConstants, 'l1GenesisBlock' | 'epochDuration' | 'slotDuration'>): bigint[];
20
- //# sourceMappingURL=epoch_helpers.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"epoch_helpers.d.ts","sourceRoot":"","sources":["../../src/archiver/epoch_helpers.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,cAAc,GAAG;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,qDAAqD;AACrD,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,cAAc,EAAE,eAAe,GAAG,cAAc,CAAC,UAE/G;AAED,sDAAsD;AACtD,wBAAgB,yBAAyB,CACvC,EAAE,EAAE,MAAM,EACV,SAAS,EAAE,IAAI,CAAC,cAAc,EAAE,eAAe,GAAG,cAAc,GAAG,eAAe,CAAC,UAGpF;AAED,0EAA0E;AAC1E,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,cAAc,EAAE,eAAe,CAAC,YAGzG;AAED,+EAA+E;AAC/E,wBAAgB,yBAAyB,CACvC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,IAAI,CAAC,cAAc,EAAE,eAAe,GAAG,cAAc,GAAG,eAAe,CAAC,YAOpF;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,IAAI,CAAC,cAAc,EAAE,gBAAgB,GAAG,eAAe,GAAG,cAAc,CAAC,YAOrF"}