@aztec/archiver 0.71.0 → 0.72.1

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 (43) hide show
  1. package/dest/archiver/archiver.d.ts +4 -4
  2. package/dest/archiver/archiver.d.ts.map +1 -1
  3. package/dest/archiver/archiver.js +6 -6
  4. package/dest/archiver/archiver_store.d.ts +4 -4
  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 +97 -59
  8. package/dest/archiver/config.d.ts +1 -1
  9. package/dest/archiver/config.d.ts.map +1 -1
  10. package/dest/archiver/config.js +2 -2
  11. package/dest/archiver/data_retrieval.js +2 -2
  12. package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts +4 -4
  13. package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts.map +1 -1
  14. package/dest/archiver/kv_archiver_store/kv_archiver_store.js +4 -4
  15. package/dest/archiver/kv_archiver_store/log_store.d.ts +5 -5
  16. package/dest/archiver/kv_archiver_store/log_store.d.ts.map +1 -1
  17. package/dest/archiver/kv_archiver_store/log_store.js +83 -51
  18. package/dest/archiver/memory_archiver_store/memory_archiver_store.d.ts +7 -7
  19. package/dest/archiver/memory_archiver_store/memory_archiver_store.d.ts.map +1 -1
  20. package/dest/archiver/memory_archiver_store/memory_archiver_store.js +55 -56
  21. package/dest/factory.js +2 -2
  22. package/dest/rpc/index.d.ts +1 -1
  23. package/dest/rpc/index.d.ts.map +1 -1
  24. package/dest/rpc/index.js +5 -5
  25. package/dest/test/mock_archiver.d.ts +1 -1
  26. package/dest/test/mock_archiver.d.ts.map +1 -1
  27. package/dest/test/mock_archiver.js +2 -1
  28. package/dest/test/mock_l2_block_source.d.ts +1 -1
  29. package/dest/test/mock_l2_block_source.d.ts.map +1 -1
  30. package/dest/test/mock_l2_block_source.js +3 -3
  31. package/package.json +13 -13
  32. package/src/archiver/archiver.ts +9 -8
  33. package/src/archiver/archiver_store.ts +5 -4
  34. package/src/archiver/archiver_store_test_suite.ts +103 -70
  35. package/src/archiver/config.ts +2 -2
  36. package/src/archiver/data_retrieval.ts +1 -1
  37. package/src/archiver/kv_archiver_store/kv_archiver_store.ts +6 -5
  38. package/src/archiver/kv_archiver_store/log_store.ts +108 -61
  39. package/src/archiver/memory_archiver_store/memory_archiver_store.ts +62 -59
  40. package/src/factory.ts +1 -1
  41. package/src/rpc/index.ts +4 -4
  42. package/src/test/mock_archiver.ts +1 -0
  43. package/src/test/mock_l2_block_source.ts +2 -2
@@ -1,18 +1,23 @@
1
1
  import {
2
2
  ContractClass2BlockL2Logs,
3
+ ExtendedPublicLog,
3
4
  ExtendedUnencryptedL2Log,
4
- type GetUnencryptedLogsResponse,
5
+ type GetContractClassLogsResponse,
6
+ type GetPublicLogsResponse,
5
7
  type L2Block,
6
8
  type LogFilter,
7
9
  LogId,
8
10
  TxScopedL2Log,
9
- UnencryptedL2BlockL2Logs,
10
- type UnencryptedL2Log,
11
+ UnencryptedL2Log,
11
12
  } from '@aztec/circuit-types';
12
- import { Fr, PrivateLog } from '@aztec/circuits.js';
13
- import { INITIAL_L2_BLOCK_NUM, MAX_NOTE_HASHES_PER_TX } from '@aztec/circuits.js/constants';
13
+ import { type Fr, PrivateLog, PublicLog } from '@aztec/circuits.js';
14
+ import {
15
+ INITIAL_L2_BLOCK_NUM,
16
+ MAX_NOTE_HASHES_PER_TX,
17
+ PUBLIC_LOG_DATA_SIZE_IN_FIELDS,
18
+ } from '@aztec/circuits.js/constants';
14
19
  import { createLogger } from '@aztec/foundation/log';
15
- import { BufferReader } from '@aztec/foundation/serialize';
20
+ import { BufferReader, numToUInt32BE } from '@aztec/foundation/serialize';
16
21
  import { type AztecKVStore, type AztecMap } from '@aztec/kv-store';
17
22
 
18
23
  import { type BlockStore } from './block_store.js';
@@ -24,7 +29,7 @@ export class LogStore {
24
29
  #logsByTag: AztecMap<string, Buffer[]>;
25
30
  #logTagsByBlock: AztecMap<number, string[]>;
26
31
  #privateLogsByBlock: AztecMap<number, Buffer>;
27
- #unencryptedLogsByBlock: AztecMap<number, Buffer>;
32
+ #publicLogsByBlock: AztecMap<number, Buffer>;
28
33
  #contractClassLogsByBlock: AztecMap<number, Buffer>;
29
34
  #logsMaxPageSize: number;
30
35
  #log = createLogger('archiver:log_store');
@@ -33,7 +38,7 @@ export class LogStore {
33
38
  this.#logsByTag = db.openMap('archiver_tagged_logs_by_tag');
34
39
  this.#logTagsByBlock = db.openMap('archiver_log_tags_by_block');
35
40
  this.#privateLogsByBlock = db.openMap('archiver_private_logs_by_block');
36
- this.#unencryptedLogsByBlock = db.openMap('archiver_unencrypted_logs_by_block');
41
+ this.#publicLogsByBlock = db.openMap('archiver_public_logs_by_block');
37
42
  this.#contractClassLogsByBlock = db.openMap('archiver_contract_class_logs_by_block');
38
43
 
39
44
  this.#logsMaxPageSize = logsMaxPageSize;
@@ -70,39 +75,48 @@ export class LogStore {
70
75
  const dataStartIndexForBlock =
71
76
  block.header.state.partial.noteHashTree.nextAvailableLeafIndex -
72
77
  block.body.txEffects.length * MAX_NOTE_HASHES_PER_TX;
73
- block.body.unencryptedLogs.txLogs.forEach((txLogs, txIndex) => {
74
- const txHash = block.body.txEffects[txIndex].txHash;
78
+ block.body.txEffects.forEach((txEffect, txIndex) => {
79
+ const txHash = txEffect.txHash;
75
80
  const dataStartIndexForTx = dataStartIndexForBlock + txIndex * MAX_NOTE_HASHES_PER_TX;
76
- const logs = txLogs.unrollLogs();
77
- logs.forEach(log => {
78
- if (log.data.length < 32 * 33) {
79
- // TODO remove when #9835 and #9836 are fixed
80
- this.#log.warn(`Skipping unencrypted log with insufficient data length: ${log.data.length}`);
81
+ txEffect.publicLogs.forEach(log => {
82
+ // Check that each log stores 3 lengths in its first field. If not, it's not a tagged log:
83
+ const firstFieldBuf = log.log[0].toBuffer();
84
+ if (
85
+ !firstFieldBuf.subarray(0, 24).equals(Buffer.alloc(24)) ||
86
+ firstFieldBuf[26] !== 0 ||
87
+ firstFieldBuf[29] !== 0
88
+ ) {
89
+ // See parseLogFromPublic - the first field of a tagged log is 8 bytes structured:
90
+ // [ publicLen[0], publicLen[1], 0, privateLen[0], privateLen[1], 0, ciphertextLen[0], ciphertextLen[1]]
91
+ this.#log.warn(`Skipping public log with invalid first field: ${log.log[0]}`);
81
92
  return;
82
93
  }
83
- try {
84
- // TODO remove when #9835 and #9836 are fixed. The partial note logs are emitted as bytes, but encoded as Fields.
85
- // This means that for every 32 bytes of payload, we only have 1 byte of data.
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.
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);
94
- }
95
- const tag = new Fr(correctedBuffer);
96
-
97
- this.#log.debug(`Found tagged unencrypted log with tag ${tag.toString()} in block ${block.number}`);
98
- const currentLogs = taggedLogs.get(tag.toString()) ?? [];
99
- currentLogs.push(
100
- new TxScopedL2Log(txHash, dataStartIndexForTx, block.number, /* isFromPublic */ true, log.data).toBuffer(),
101
- );
102
- taggedLogs.set(tag.toString(), currentLogs);
103
- } catch (err) {
104
- this.#log.warn(`Failed to add tagged log to store: ${err}`);
94
+ // Check that the length values line up with the log contents
95
+ const publicValuesLength = firstFieldBuf.subarray(-8).readUint16BE();
96
+ const privateValuesLength = firstFieldBuf.subarray(-8).readUint16BE(3);
97
+ // Add 1 for the first field holding lengths
98
+ const totalLogLength = 1 + publicValuesLength + privateValuesLength;
99
+ // Note that zeroes can be valid log values, so we can only assert that we do not go over the given length
100
+ if (totalLogLength > PUBLIC_LOG_DATA_SIZE_IN_FIELDS || log.log.slice(totalLogLength).find(f => !f.isZero())) {
101
+ this.#log.warn(`Skipping invalid tagged public log with first field: ${log.log[0]}`);
102
+ return;
105
103
  }
104
+
105
+ // The first elt stores lengths as above => tag is in fields[1]
106
+ const tag = log.log[1];
107
+
108
+ this.#log.debug(`Found tagged public log with tag ${tag.toString()} in block ${block.number}`);
109
+ const currentLogs = taggedLogs.get(tag.toString()) ?? [];
110
+ currentLogs.push(
111
+ new TxScopedL2Log(
112
+ txHash,
113
+ dataStartIndexForTx,
114
+ block.number,
115
+ /* isFromPublic */ true,
116
+ log.toBuffer(),
117
+ ).toBuffer(),
118
+ );
119
+ taggedLogs.set(tag.toString(), currentLogs);
106
120
  });
107
121
  });
108
122
  return taggedLogs;
@@ -150,7 +164,17 @@ export class LogStore {
150
164
  .map(log => log.toBuffer());
151
165
  void this.#privateLogsByBlock.set(block.number, Buffer.concat(privateLogsInBlock));
152
166
 
153
- void this.#unencryptedLogsByBlock.set(block.number, block.body.unencryptedLogs.toBuffer());
167
+ const publicLogsInBlock = block.body.txEffects
168
+ .map((txEffect, txIndex) =>
169
+ [
170
+ numToUInt32BE(txIndex),
171
+ numToUInt32BE(txEffect.publicLogs.length),
172
+ txEffect.publicLogs.map(log => log.toBuffer()),
173
+ ].flat(),
174
+ )
175
+ .flat();
176
+
177
+ void this.#publicLogsByBlock.set(block.number, Buffer.concat(publicLogsInBlock));
154
178
  void this.#contractClassLogsByBlock.set(block.number, block.body.contractClassLogs.toBuffer());
155
179
  });
156
180
 
@@ -165,7 +189,7 @@ export class LogStore {
165
189
  return this.db.transaction(() => {
166
190
  blocks.forEach(block => {
167
191
  void this.#privateLogsByBlock.delete(block.number);
168
- void this.#unencryptedLogsByBlock.delete(block.number);
192
+ void this.#publicLogsByBlock.delete(block.number);
169
193
  void this.#logTagsByBlock.delete(block.number);
170
194
  });
171
195
 
@@ -209,21 +233,21 @@ export class LogStore {
209
233
  }
210
234
 
211
235
  /**
212
- * Gets unencrypted logs based on the provided filter.
236
+ * Gets public logs based on the provided filter.
213
237
  * @param filter - The filter to apply to the logs.
214
238
  * @returns The requested logs.
215
239
  */
216
- getUnencryptedLogs(filter: LogFilter): GetUnencryptedLogsResponse {
240
+ getPublicLogs(filter: LogFilter): GetPublicLogsResponse {
217
241
  if (filter.afterLog) {
218
- return this.#filterUnencryptedLogsBetweenBlocks(filter);
242
+ return this.#filterPublicLogsBetweenBlocks(filter);
219
243
  } else if (filter.txHash) {
220
- return this.#filterUnencryptedLogsOfTx(filter);
244
+ return this.#filterPublicLogsOfTx(filter);
221
245
  } else {
222
- return this.#filterUnencryptedLogsBetweenBlocks(filter);
246
+ return this.#filterPublicLogsBetweenBlocks(filter);
223
247
  }
224
248
  }
225
249
 
226
- #filterUnencryptedLogsOfTx(filter: LogFilter): GetUnencryptedLogsResponse {
250
+ #filterPublicLogsOfTx(filter: LogFilter): GetPublicLogsResponse {
227
251
  if (!filter.txHash) {
228
252
  throw new Error('Missing txHash');
229
253
  }
@@ -233,18 +257,27 @@ export class LogStore {
233
257
  return { logs: [], maxLogsHit: false };
234
258
  }
235
259
 
236
- const buffer = this.#unencryptedLogsByBlock.get(blockNumber) ?? Buffer.alloc(0);
237
- const unencryptedLogsInBlock = UnencryptedL2BlockL2Logs.fromBuffer(buffer);
260
+ const buffer = this.#publicLogsByBlock.get(blockNumber) ?? Buffer.alloc(0);
261
+ const publicLogsInBlock: [PublicLog[]] = [[]];
262
+ const reader = new BufferReader(buffer);
263
+ while (reader.remainingBytes() > 0) {
264
+ const indexOfTx = reader.readNumber();
265
+ const numLogsInTx = reader.readNumber();
266
+ publicLogsInBlock[indexOfTx] = [];
267
+ for (let i = 0; i < numLogsInTx; i++) {
268
+ publicLogsInBlock[indexOfTx].push(reader.readObject(PublicLog));
269
+ }
270
+ }
238
271
 
239
- const txLogs = unencryptedLogsInBlock.txLogs[txIndex].unrollLogs();
272
+ const txLogs = publicLogsInBlock[txIndex];
240
273
 
241
- const logs: ExtendedUnencryptedL2Log[] = [];
274
+ const logs: ExtendedPublicLog[] = [];
242
275
  const maxLogsHit = this.#accumulateLogs(logs, blockNumber, txIndex, txLogs, filter);
243
276
 
244
277
  return { logs, maxLogsHit };
245
278
  }
246
279
 
247
- #filterUnencryptedLogsBetweenBlocks(filter: LogFilter): GetUnencryptedLogsResponse {
280
+ #filterPublicLogsBetweenBlocks(filter: LogFilter): GetPublicLogsResponse {
248
281
  const start =
249
282
  filter.afterLog?.blockNumber ?? Math.max(filter.fromBlock ?? INITIAL_L2_BLOCK_NUM, INITIAL_L2_BLOCK_NUM);
250
283
  const end = filter.toBlock;
@@ -256,13 +289,22 @@ export class LogStore {
256
289
  };
257
290
  }
258
291
 
259
- const logs: ExtendedUnencryptedL2Log[] = [];
292
+ const logs: ExtendedPublicLog[] = [];
260
293
 
261
294
  let maxLogsHit = false;
262
- loopOverBlocks: for (const [blockNumber, logBuffer] of this.#unencryptedLogsByBlock.entries({ start, end })) {
263
- const unencryptedLogsInBlock = UnencryptedL2BlockL2Logs.fromBuffer(logBuffer);
264
- for (let txIndex = filter.afterLog?.txIndex ?? 0; txIndex < unencryptedLogsInBlock.txLogs.length; txIndex++) {
265
- const txLogs = unencryptedLogsInBlock.txLogs[txIndex].unrollLogs();
295
+ loopOverBlocks: for (const [blockNumber, logBuffer] of this.#publicLogsByBlock.entries({ start, end })) {
296
+ const publicLogsInBlock: [PublicLog[]] = [[]];
297
+ const reader = new BufferReader(logBuffer);
298
+ while (reader.remainingBytes() > 0) {
299
+ const indexOfTx = reader.readNumber();
300
+ const numLogsInTx = reader.readNumber();
301
+ publicLogsInBlock[indexOfTx] = [];
302
+ for (let i = 0; i < numLogsInTx; i++) {
303
+ publicLogsInBlock[indexOfTx].push(reader.readObject(PublicLog));
304
+ }
305
+ }
306
+ for (let txIndex = filter.afterLog?.txIndex ?? 0; txIndex < publicLogsInBlock.length; txIndex++) {
307
+ const txLogs = publicLogsInBlock[txIndex];
266
308
  maxLogsHit = this.#accumulateLogs(logs, blockNumber, txIndex, txLogs, filter);
267
309
  if (maxLogsHit) {
268
310
  this.#log.debug(`Max logs hit at block ${blockNumber}`);
@@ -279,7 +321,7 @@ export class LogStore {
279
321
  * @param filter - The filter to apply to the logs.
280
322
  * @returns The requested logs.
281
323
  */
282
- getContractClassLogs(filter: LogFilter): GetUnencryptedLogsResponse {
324
+ getContractClassLogs(filter: LogFilter): GetContractClassLogsResponse {
283
325
  if (filter.afterLog) {
284
326
  return this.#filterContractClassLogsBetweenBlocks(filter);
285
327
  } else if (filter.txHash) {
@@ -289,7 +331,7 @@ export class LogStore {
289
331
  }
290
332
  }
291
333
 
292
- #filterContractClassLogsOfTx(filter: LogFilter): GetUnencryptedLogsResponse {
334
+ #filterContractClassLogsOfTx(filter: LogFilter): GetContractClassLogsResponse {
293
335
  if (!filter.txHash) {
294
336
  throw new Error('Missing txHash');
295
337
  }
@@ -310,7 +352,7 @@ export class LogStore {
310
352
  return { logs, maxLogsHit };
311
353
  }
312
354
 
313
- #filterContractClassLogsBetweenBlocks(filter: LogFilter): GetUnencryptedLogsResponse {
355
+ #filterContractClassLogsBetweenBlocks(filter: LogFilter): GetContractClassLogsResponse {
314
356
  const start =
315
357
  filter.afterLog?.blockNumber ?? Math.max(filter.fromBlock ?? INITIAL_L2_BLOCK_NUM, INITIAL_L2_BLOCK_NUM);
316
358
  const end = filter.toBlock;
@@ -341,10 +383,10 @@ export class LogStore {
341
383
  }
342
384
 
343
385
  #accumulateLogs(
344
- results: ExtendedUnencryptedL2Log[],
386
+ results: (ExtendedUnencryptedL2Log | ExtendedPublicLog)[],
345
387
  blockNumber: number,
346
388
  txIndex: number,
347
- txLogs: UnencryptedL2Log[],
389
+ txLogs: (UnencryptedL2Log | PublicLog)[],
348
390
  filter: LogFilter,
349
391
  ): boolean {
350
392
  let maxLogsHit = false;
@@ -352,7 +394,12 @@ export class LogStore {
352
394
  for (; logIndex < txLogs.length; logIndex++) {
353
395
  const log = txLogs[logIndex];
354
396
  if (!filter.contractAddress || log.contractAddress.equals(filter.contractAddress)) {
355
- results.push(new ExtendedUnencryptedL2Log(new LogId(blockNumber, txIndex, logIndex), log));
397
+ if (log instanceof UnencryptedL2Log) {
398
+ results.push(new ExtendedUnencryptedL2Log(new LogId(blockNumber, txIndex, logIndex), log));
399
+ } else {
400
+ results.push(new ExtendedPublicLog(new LogId(blockNumber, txIndex, logIndex), log));
401
+ }
402
+
356
403
  if (results.length >= this.#logsMaxPageSize) {
357
404
  maxLogsHit = true;
358
405
  break;
@@ -1,7 +1,9 @@
1
1
  import {
2
2
  type ContractClass2BlockL2Logs,
3
+ ExtendedPublicLog,
3
4
  ExtendedUnencryptedL2Log,
4
- type GetUnencryptedLogsResponse,
5
+ type GetContractClassLogsResponse,
6
+ type GetPublicLogsResponse,
5
7
  type InBlock,
6
8
  type InboxLeaf,
7
9
  type L2Block,
@@ -12,7 +14,6 @@ import {
12
14
  type TxHash,
13
15
  TxReceipt,
14
16
  TxScopedL2Log,
15
- type UnencryptedL2BlockL2Logs,
16
17
  wrapInBlock,
17
18
  } from '@aztec/circuit-types';
18
19
  import {
@@ -25,7 +26,9 @@ import {
25
26
  INITIAL_L2_BLOCK_NUM,
26
27
  MAX_NOTE_HASHES_PER_TX,
27
28
  MAX_NULLIFIERS_PER_TX,
29
+ PUBLIC_LOG_DATA_SIZE_IN_FIELDS,
28
30
  type PrivateLog,
31
+ type PublicLog,
29
32
  type UnconstrainedFunctionWithMembershipProof,
30
33
  } from '@aztec/circuits.js';
31
34
  import { FunctionSelector } from '@aztec/foundation/abi';
@@ -57,7 +60,7 @@ export class MemoryArchiverStore implements ArchiverDataStore {
57
60
 
58
61
  private privateLogsPerBlock: Map<number, PrivateLog[]> = new Map();
59
62
 
60
- private unencryptedLogsPerBlock: Map<number, UnencryptedL2BlockL2Logs> = new Map();
63
+ private publicLogsPerBlock: Map<number, PublicLog[]> = new Map();
61
64
 
62
65
  private contractClassLogsPerBlock: Map<number, ContractClass2BlockL2Logs> = new Map();
63
66
 
@@ -89,7 +92,7 @@ export class MemoryArchiverStore implements ArchiverDataStore {
89
92
  #log = createLogger('archiver:data-store');
90
93
 
91
94
  constructor(
92
- /** The max number of logs that can be obtained in 1 "getUnencryptedLogs" call. */
95
+ /** The max number of logs that can be obtained in 1 "getPublicLogs" call. */
93
96
  public readonly maxLogs: number,
94
97
  ) {}
95
98
 
@@ -249,43 +252,43 @@ export class MemoryArchiverStore implements ArchiverDataStore {
249
252
  const dataStartIndexForBlock =
250
253
  block.header.state.partial.noteHashTree.nextAvailableLeafIndex -
251
254
  block.body.txEffects.length * MAX_NOTE_HASHES_PER_TX;
252
- block.body.unencryptedLogs.txLogs.forEach((txLogs, txIndex) => {
253
- const txHash = block.body.txEffects[txIndex].txHash;
255
+ block.body.txEffects.forEach((txEffect, txIndex) => {
256
+ const txHash = txEffect.txHash;
254
257
  const dataStartIndexForTx = dataStartIndexForBlock + txIndex * MAX_NOTE_HASHES_PER_TX;
255
- const logs = txLogs.unrollLogs();
256
- logs.forEach(log => {
258
+ txEffect.publicLogs.forEach(log => {
259
+ // Check that each log stores 3 lengths in its first field. If not, it's not a tagged log:
260
+ const firstFieldBuf = log.log[0].toBuffer();
257
261
  if (
258
- // TODO remove when #9835 and #9836 are fixed
259
- log.data.length <
260
- 32 * 33
262
+ !firstFieldBuf.subarray(0, 24).equals(Buffer.alloc(24)) ||
263
+ firstFieldBuf[26] !== 0 ||
264
+ firstFieldBuf[29] !== 0
261
265
  ) {
262
- this.#log.warn(`Skipping unencrypted log with invalid data length: ${log.data.length}`);
266
+ // See parseLogFromPublic - the first field of a tagged log is 8 bytes structured:
267
+ // [ publicLen[0], publicLen[1], 0, privateLen[0], privateLen[1], 0, ciphertextLen[0], ciphertextLen[1]]
268
+ this.#log.warn(`Skipping public log with invalid first field: ${log.log[0]}`);
263
269
  return;
264
270
  }
265
- try {
266
- // TODO remove when #9835 and #9836 are fixed. The partial note logs are emitted as bytes, but encoded as Fields.
267
- // This means that for every 32 bytes of payload, we only have 1 byte of data.
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.
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);
276
- }
277
- const tag = new Fr(correctedBuffer);
278
- this.#log.verbose(`Storing unencrypted tagged log with tag ${tag.toString()} in block ${block.number}`);
279
- const currentLogs = this.taggedLogs.get(tag.toString()) || [];
280
- this.taggedLogs.set(tag.toString(), [
281
- ...currentLogs,
282
- new TxScopedL2Log(txHash, dataStartIndexForTx, block.number, /* isFromPublic */ true, log.data),
283
- ]);
284
- const currentTagsInBlock = this.logTagsPerBlock.get(block.number) || [];
285
- this.logTagsPerBlock.set(block.number, [...currentTagsInBlock, tag]);
286
- } catch (err) {
287
- this.#log.warn(`Failed to add tagged log to store: ${err}`);
271
+ // Check that the length values line up with the log contents
272
+ const publicValuesLength = firstFieldBuf.subarray(-8).readUint16BE();
273
+ const privateValuesLength = firstFieldBuf.subarray(-8).readUint16BE(3);
274
+ // Add 1 for the first field holding lengths
275
+ const totalLogLength = 1 + publicValuesLength + privateValuesLength;
276
+ // Note that zeroes can be valid log values, so we can only assert that we do not go over the given length
277
+ if (totalLogLength > PUBLIC_LOG_DATA_SIZE_IN_FIELDS || log.log.slice(totalLogLength).find(f => !f.isZero())) {
278
+ this.#log.warn(`Skipping invalid tagged public log with first field: ${log.log[0]}`);
279
+ return;
288
280
  }
281
+
282
+ // The first elt stores lengths => tag is in fields[1]
283
+ const tag = log.log[1];
284
+ this.#log.verbose(`Storing public tagged log with tag ${tag.toString()} in block ${block.number}`);
285
+ const currentLogs = this.taggedLogs.get(tag.toString()) || [];
286
+ this.taggedLogs.set(tag.toString(), [
287
+ ...currentLogs,
288
+ new TxScopedL2Log(txHash, dataStartIndexForTx, block.number, /* isFromPublic */ true, log.toBuffer()),
289
+ ]);
290
+ const currentTagsInBlock = this.logTagsPerBlock.get(block.number) || [];
291
+ this.logTagsPerBlock.set(block.number, [...currentTagsInBlock, tag]);
289
292
  });
290
293
  });
291
294
  }
@@ -300,7 +303,7 @@ export class MemoryArchiverStore implements ArchiverDataStore {
300
303
  void this.#storeTaggedLogsFromPrivate(block);
301
304
  void this.#storeTaggedLogsFromPublic(block);
302
305
  this.privateLogsPerBlock.set(block.number, block.body.txEffects.map(txEffect => txEffect.privateLogs).flat());
303
- this.unencryptedLogsPerBlock.set(block.number, block.body.unencryptedLogs);
306
+ this.publicLogsPerBlock.set(block.number, block.body.txEffects.map(txEffect => txEffect.publicLogs).flat());
304
307
  this.contractClassLogsPerBlock.set(block.number, block.body.contractClassLogs);
305
308
  });
306
309
  return Promise.resolve(true);
@@ -316,7 +319,7 @@ export class MemoryArchiverStore implements ArchiverDataStore {
316
319
 
317
320
  blocks.forEach(block => {
318
321
  this.privateLogsPerBlock.delete(block.number);
319
- this.unencryptedLogsPerBlock.delete(block.number);
322
+ this.publicLogsPerBlock.delete(block.number);
320
323
  this.logTagsPerBlock.delete(block.number);
321
324
  this.contractClassLogsPerBlock.delete(block.number);
322
325
  });
@@ -518,12 +521,12 @@ export class MemoryArchiverStore implements ArchiverDataStore {
518
521
  }
519
522
 
520
523
  /**
521
- * Gets unencrypted logs based on the provided filter.
524
+ * Gets public logs based on the provided filter.
522
525
  * @param filter - The filter to apply to the logs.
523
526
  * @returns The requested logs.
524
527
  * @remarks Works by doing an intersection of all params in the filter.
525
528
  */
526
- getUnencryptedLogs(filter: LogFilter): Promise<GetUnencryptedLogsResponse> {
529
+ getPublicLogs(filter: LogFilter): Promise<GetPublicLogsResponse> {
527
530
  let txHash: TxHash | undefined;
528
531
  let fromBlock = 0;
529
532
  let toBlock = this.l2Blocks.length + INITIAL_L2_BLOCK_NUM;
@@ -564,34 +567,34 @@ export class MemoryArchiverStore implements ArchiverDataStore {
564
567
 
565
568
  const contractAddress = filter.contractAddress;
566
569
 
567
- const logs: ExtendedUnencryptedL2Log[] = [];
570
+ const logs: ExtendedPublicLog[] = [];
568
571
 
569
572
  for (; fromBlock < toBlock; fromBlock++) {
570
573
  const block = this.l2Blocks[fromBlock - INITIAL_L2_BLOCK_NUM];
571
- const blockLogs = this.unencryptedLogsPerBlock.get(fromBlock);
574
+ const blockLogs = this.publicLogsPerBlock.get(fromBlock);
572
575
 
573
576
  if (blockLogs) {
574
- for (; txIndexInBlock < blockLogs.txLogs.length; txIndexInBlock++) {
575
- const txLogs = blockLogs.txLogs[txIndexInBlock].unrollLogs();
576
- for (; logIndexInTx < txLogs.length; logIndexInTx++) {
577
- const log = txLogs[logIndexInTx];
578
- if (
579
- (!txHash || block.data.body.txEffects[txIndexInBlock].txHash.equals(txHash)) &&
580
- (!contractAddress || log.contractAddress.equals(contractAddress))
581
- ) {
582
- logs.push(new ExtendedUnencryptedL2Log(new LogId(block.data.number, txIndexInBlock, logIndexInTx), log));
583
- if (logs.length === this.maxLogs) {
584
- return Promise.resolve({
585
- logs,
586
- maxLogsHit: true,
587
- });
588
- }
577
+ for (let logIndex = 0; logIndex < blockLogs.length; logIndex++) {
578
+ const log = blockLogs[logIndex];
579
+ const thisTxEffect = block.data.body.txEffects.filter(effect => effect.publicLogs.includes(log))[0];
580
+ const thisTxIndexInBlock = block.data.body.txEffects.indexOf(thisTxEffect);
581
+ const thisLogIndexInTx = thisTxEffect.publicLogs.indexOf(log);
582
+ if (
583
+ (!txHash || thisTxEffect.txHash.equals(txHash)) &&
584
+ (!contractAddress || log.contractAddress.equals(contractAddress)) &&
585
+ thisTxIndexInBlock >= txIndexInBlock &&
586
+ thisLogIndexInTx >= logIndexInTx
587
+ ) {
588
+ logs.push(new ExtendedPublicLog(new LogId(block.data.number, thisTxIndexInBlock, thisLogIndexInTx), log));
589
+ if (logs.length === this.maxLogs) {
590
+ return Promise.resolve({
591
+ logs,
592
+ maxLogsHit: true,
593
+ });
589
594
  }
590
595
  }
591
- logIndexInTx = 0;
592
596
  }
593
597
  }
594
- txIndexInBlock = 0;
595
598
  }
596
599
 
597
600
  return Promise.resolve({
@@ -607,7 +610,7 @@ export class MemoryArchiverStore implements ArchiverDataStore {
607
610
  * @returns The requested logs.
608
611
  * @remarks Works by doing an intersection of all params in the filter.
609
612
  */
610
- getContractClassLogs(filter: LogFilter): Promise<GetUnencryptedLogsResponse> {
613
+ getContractClassLogs(filter: LogFilter): Promise<GetContractClassLogsResponse> {
611
614
  let txHash: TxHash | undefined;
612
615
  let fromBlock = 0;
613
616
  let toBlock = this.l2Blocks.length + INITIAL_L2_BLOCK_NUM;
package/src/factory.ts CHANGED
@@ -41,7 +41,7 @@ export async function createArchiver(
41
41
  async function registerProtocolContracts(store: KVArchiverDataStore) {
42
42
  const blockNumber = 0;
43
43
  for (const name of protocolContractNames) {
44
- const contract = getCanonicalProtocolContract(name);
44
+ const contract = await getCanonicalProtocolContract(name);
45
45
  const contractClassPublic: ContractClassPublic = {
46
46
  ...contract.contractClass,
47
47
  privateFunctions: [],
package/src/rpc/index.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  import { type ArchiverApi, ArchiverApiSchema } from '@aztec/circuit-types';
2
- import { createSafeJsonRpcClient, makeFetch } from '@aztec/foundation/json-rpc/client';
3
- import { createSafeJsonRpcServer } from '@aztec/foundation/json-rpc/server';
2
+ import { createSafeJsonRpcClient } from '@aztec/foundation/json-rpc/client';
3
+ import { createTracedJsonRpcServer, makeTracedFetch } from '@aztec/telemetry-client';
4
4
 
5
- export function createArchiverClient(url: string, fetch = makeFetch([1, 2, 3], true)): ArchiverApi {
5
+ export function createArchiverClient(url: string, fetch = makeTracedFetch([1, 2, 3], true)): ArchiverApi {
6
6
  return createSafeJsonRpcClient<ArchiverApi>(url, ArchiverApiSchema, false, 'archiver', fetch);
7
7
  }
8
8
 
9
9
  export function createArchiverRpcServer(handler: ArchiverApi) {
10
- return createSafeJsonRpcServer(handler, ArchiverApiSchema);
10
+ return createTracedJsonRpcServer(handler, ArchiverApiSchema);
11
11
  }
@@ -51,5 +51,6 @@ export class MockPrefilledArchiver extends MockArchiver {
51
51
 
52
52
  const fromBlock = this.l2Blocks.length;
53
53
  this.addBlocks(this.precomputed.slice(fromBlock, fromBlock + numBlocks));
54
+ return Promise.resolve();
54
55
  }
55
56
  }
@@ -24,10 +24,10 @@ export class MockL2BlockSource implements L2BlockSource {
24
24
 
25
25
  private log = createLogger('archiver:mock_l2_block_source');
26
26
 
27
- public createBlocks(numBlocks: number) {
27
+ public async createBlocks(numBlocks: number) {
28
28
  for (let i = 0; i < numBlocks; i++) {
29
29
  const blockNum = this.l2Blocks.length + 1;
30
- const block = L2Block.random(blockNum);
30
+ const block = await L2Block.random(blockNum);
31
31
  this.l2Blocks.push(block);
32
32
  }
33
33