@aztec/pxe 0.59.0 → 0.61.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 (76) hide show
  1. package/dest/contract_data_oracle/index.d.ts +1 -0
  2. package/dest/contract_data_oracle/index.d.ts.map +1 -1
  3. package/dest/contract_data_oracle/private_functions_tree.d.ts +1 -0
  4. package/dest/contract_data_oracle/private_functions_tree.d.ts.map +1 -1
  5. package/dest/database/deferred_note_dao.d.ts +7 -19
  6. package/dest/database/deferred_note_dao.d.ts.map +1 -1
  7. package/dest/database/deferred_note_dao.js +8 -18
  8. package/dest/database/incoming_note_dao.d.ts +2 -1
  9. package/dest/database/incoming_note_dao.d.ts.map +1 -1
  10. package/dest/database/incoming_note_dao.js +3 -3
  11. package/dest/database/kv_pxe_database.d.ts +5 -3
  12. package/dest/database/kv_pxe_database.d.ts.map +1 -1
  13. package/dest/database/kv_pxe_database.js +22 -8
  14. package/dest/database/outgoing_note_dao.d.ts +2 -1
  15. package/dest/database/outgoing_note_dao.d.ts.map +1 -1
  16. package/dest/database/outgoing_note_dao.js +3 -3
  17. package/dest/database/pxe_database.d.ts +6 -4
  18. package/dest/database/pxe_database.d.ts.map +1 -1
  19. package/dest/kernel_prover/hints/build_private_kernel_reset_private_inputs.d.ts.map +1 -1
  20. package/dest/kernel_prover/hints/build_private_kernel_reset_private_inputs.js +9 -9
  21. package/dest/kernel_prover/kernel_prover.js +6 -6
  22. package/dest/kernel_prover/test/test_circuit_prover.d.ts +1 -0
  23. package/dest/kernel_prover/test/test_circuit_prover.d.ts.map +1 -1
  24. package/dest/note_processor/note_processor.d.ts +1 -5
  25. package/dest/note_processor/note_processor.d.ts.map +1 -1
  26. package/dest/note_processor/note_processor.js +56 -58
  27. package/dest/note_processor/utils/add_public_values_to_payload.d.ts +10 -0
  28. package/dest/note_processor/utils/add_public_values_to_payload.d.ts.map +1 -0
  29. package/dest/note_processor/utils/add_public_values_to_payload.js +48 -0
  30. package/dest/note_processor/utils/brute_force_note_info.d.ts +8 -3
  31. package/dest/note_processor/utils/brute_force_note_info.d.ts.map +1 -1
  32. package/dest/note_processor/utils/brute_force_note_info.js +6 -3
  33. package/dest/note_processor/utils/produce_note_daos.d.ts.map +1 -1
  34. package/dest/note_processor/utils/produce_note_daos.js +2 -4
  35. package/dest/note_processor/utils/produce_note_daos_for_key.d.ts +3 -3
  36. package/dest/note_processor/utils/produce_note_daos_for_key.d.ts.map +1 -1
  37. package/dest/note_processor/utils/produce_note_daos_for_key.js +7 -61
  38. package/dest/pxe_http/pxe_http_server.js +3 -3
  39. package/dest/pxe_service/error_enriching.d.ts +11 -0
  40. package/dest/pxe_service/error_enriching.d.ts.map +1 -0
  41. package/dest/pxe_service/error_enriching.js +68 -0
  42. package/dest/pxe_service/index.d.ts +1 -0
  43. package/dest/pxe_service/index.d.ts.map +1 -1
  44. package/dest/pxe_service/index.js +2 -1
  45. package/dest/pxe_service/pxe_service.d.ts +1 -1
  46. package/dest/pxe_service/pxe_service.d.ts.map +1 -1
  47. package/dest/pxe_service/pxe_service.js +27 -66
  48. package/dest/simulator_oracle/index.d.ts +17 -1
  49. package/dest/simulator_oracle/index.d.ts.map +1 -1
  50. package/dest/simulator_oracle/index.js +40 -1
  51. package/dest/synchronizer/synchronizer.d.ts +1 -1
  52. package/dest/synchronizer/synchronizer.d.ts.map +1 -1
  53. package/dest/synchronizer/synchronizer.js +3 -3
  54. package/package.json +14 -14
  55. package/src/database/deferred_note_dao.ts +6 -19
  56. package/src/database/incoming_note_dao.ts +2 -1
  57. package/src/database/kv_pxe_database.ts +26 -6
  58. package/src/database/outgoing_note_dao.ts +2 -1
  59. package/src/database/pxe_database.ts +8 -4
  60. package/src/kernel_prover/hints/build_private_kernel_reset_private_inputs.ts +8 -14
  61. package/src/kernel_prover/kernel_prover.ts +6 -6
  62. package/src/note_processor/note_processor.ts +89 -88
  63. package/src/note_processor/utils/add_public_values_to_payload.ts +63 -0
  64. package/src/note_processor/utils/brute_force_note_info.ts +11 -3
  65. package/src/note_processor/utils/produce_note_daos.ts +5 -7
  66. package/src/note_processor/utils/produce_note_daos_for_key.ts +19 -114
  67. package/src/pxe_http/pxe_http_server.ts +2 -2
  68. package/src/pxe_service/error_enriching.ts +91 -0
  69. package/src/pxe_service/index.ts +1 -0
  70. package/src/pxe_service/pxe_service.ts +29 -78
  71. package/src/simulator_oracle/index.ts +51 -0
  72. package/src/synchronizer/synchronizer.ts +2 -2
  73. package/dest/note_processor/utils/add_nullable_field_to_payload.d.ts +0 -12
  74. package/dest/note_processor/utils/add_nullable_field_to_payload.d.ts.map +0 -1
  75. package/dest/note_processor/utils/add_nullable_field_to_payload.js +0 -46
  76. package/src/note_processor/utils/add_nullable_field_to_payload.ts +0 -67
@@ -1,6 +1,5 @@
1
- import { Note, TxHash, UnencryptedTxL2Logs } from '@aztec/circuit-types';
2
- import { AztecAddress, Fr, Point, type PublicKey, Vector } from '@aztec/circuits.js';
3
- import { NoteSelector } from '@aztec/foundation/abi';
1
+ import { L1NotePayload, TxHash, UnencryptedTxL2Logs } from '@aztec/circuit-types';
2
+ import { Fr, Point, type PublicKey, Vector } from '@aztec/circuits.js';
4
3
  import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';
5
4
 
6
5
  /**
@@ -12,14 +11,8 @@ export class DeferredNoteDao {
12
11
  constructor(
13
12
  /** IvpkM or OvpkM (depending on if incoming or outgoing) the note was encrypted with. */
14
13
  public publicKey: PublicKey,
15
- /** The note as emitted from the Noir contract. */
16
- public note: Note,
17
- /** The contract address this note is created in. */
18
- public contractAddress: AztecAddress,
19
- /** The specific storage location of the note on the contract. */
20
- public storageSlot: Fr,
21
- /** The type ID of the note on the contract. */
22
- public noteTypeId: NoteSelector,
14
+ /** The note payload delivered via L1. */
15
+ public payload: L1NotePayload,
23
16
  /** The hash of the tx the note was created in. Equal to the first nullifier */
24
17
  public txHash: TxHash,
25
18
  /** New note hashes in this transaction, one of which belongs to this note */
@@ -33,10 +26,7 @@ export class DeferredNoteDao {
33
26
  toBuffer(): Buffer {
34
27
  return serializeToBuffer(
35
28
  this.publicKey,
36
- this.note,
37
- this.contractAddress,
38
- this.storageSlot,
39
- this.noteTypeId,
29
+ this.payload,
40
30
  this.txHash,
41
31
  new Vector(this.noteHashes),
42
32
  this.dataStartIndexForTx,
@@ -47,10 +37,7 @@ export class DeferredNoteDao {
47
37
  const reader = BufferReader.asReader(buffer);
48
38
  return new DeferredNoteDao(
49
39
  reader.readObject(Point),
50
- reader.readObject(Note),
51
- reader.readObject(AztecAddress),
52
- reader.readObject(Fr),
53
- reader.readObject(NoteSelector),
40
+ reader.readObject(L1NotePayload),
54
41
  reader.readObject(TxHash),
55
42
  reader.readVector(Fr),
56
43
  reader.readNumber(),
@@ -41,6 +41,7 @@ export class IncomingNoteDao implements NoteData {
41
41
  ) {}
42
42
 
43
43
  static fromPayloadAndNoteInfo(
44
+ note: Note,
44
45
  payload: L1NotePayload,
45
46
  noteInfo: NoteInfo,
46
47
  dataStartIndexForTx: number,
@@ -48,7 +49,7 @@ export class IncomingNoteDao implements NoteData {
48
49
  ) {
49
50
  const noteHashIndexInTheWholeTree = BigInt(dataStartIndexForTx + noteInfo.noteHashIndex);
50
51
  return new IncomingNoteDao(
51
- payload.note,
52
+ note,
52
53
  payload.contractAddress,
53
54
  payload.storageSlot,
54
55
  payload.noteTypeId,
@@ -14,7 +14,7 @@ import {
14
14
  } from '@aztec/circuits.js';
15
15
  import { type ContractArtifact } from '@aztec/foundation/abi';
16
16
  import { toBufferBE } from '@aztec/foundation/bigint-buffer';
17
- import { Fr, type Point } from '@aztec/foundation/fields';
17
+ import { Fr } from '@aztec/foundation/fields';
18
18
  import {
19
19
  type AztecArray,
20
20
  type AztecKVStore,
@@ -66,6 +66,8 @@ export class KVPxeDatabase implements PxeDatabase {
66
66
  #notesByTxHashAndScope: Map<string, AztecMultiMap<string, string>>;
67
67
  #notesByIvpkMAndScope: Map<string, AztecMultiMap<string, string>>;
68
68
 
69
+ #taggingSecretIndexes: AztecMap<string, number>;
70
+
69
71
  constructor(private db: AztecKVStore) {
70
72
  this.#db = db;
71
73
 
@@ -111,6 +113,8 @@ export class KVPxeDatabase implements PxeDatabase {
111
113
  this.#notesByTxHashAndScope.set(scope, db.openMultiMap(`${scope}:notes_by_tx_hash`));
112
114
  this.#notesByIvpkMAndScope.set(scope, db.openMultiMap(`${scope}:notes_by_ivpk_m`));
113
115
  }
116
+
117
+ this.#taggingSecretIndexes = db.openMap('tagging_secret_indices');
114
118
  }
115
119
 
116
120
  public async getContract(
@@ -215,7 +219,7 @@ export class KVPxeDatabase implements PxeDatabase {
215
219
  const newLength = await this.#deferredNotes.push(...deferredNotes.map(note => note.toBuffer()));
216
220
  for (const [index, note] of deferredNotes.entries()) {
217
221
  const noteId = newLength - deferredNotes.length + index;
218
- await this.#deferredNotesByContract.set(note.contractAddress.toString(), noteId);
222
+ await this.#deferredNotesByContract.set(note.payload.contractAddress.toString(), noteId);
219
223
  }
220
224
  }
221
225
 
@@ -545,12 +549,12 @@ export class KVPxeDatabase implements PxeDatabase {
545
549
  return Promise.resolve(Array.from(this.#addresses).map(v => CompleteAddress.fromBuffer(v)));
546
550
  }
547
551
 
548
- getSynchedBlockNumberForPublicKey(publicKey: Point): number | undefined {
549
- return this.#syncedBlockPerPublicKey.get(publicKey.toString());
552
+ getSynchedBlockNumberForAccount(account: AztecAddress): number | undefined {
553
+ return this.#syncedBlockPerPublicKey.get(account.toString());
550
554
  }
551
555
 
552
- setSynchedBlockNumberForPublicKey(publicKey: Point, blockNumber: number): Promise<void> {
553
- return this.#syncedBlockPerPublicKey.set(publicKey.toString(), blockNumber);
556
+ setSynchedBlockNumberForAccount(account: AztecAddress, blockNumber: number): Promise<void> {
557
+ return this.#syncedBlockPerPublicKey.set(account.toString(), blockNumber);
554
558
  }
555
559
 
556
560
  async estimateSize(): Promise<number> {
@@ -572,4 +576,20 @@ export class KVPxeDatabase implements PxeDatabase {
572
576
 
573
577
  return incomingNotesSize + outgoingNotesSize + treeRootsSize + authWitsSize + addressesSize;
574
578
  }
579
+
580
+ async incrementTaggingSecretsIndexes(appTaggingSecrets: Fr[]): Promise<void> {
581
+ const indexes = await this.getTaggingSecretsIndexes(appTaggingSecrets);
582
+ await this.db.transaction(() => {
583
+ indexes.forEach(index => {
584
+ const nextIndex = index ? index + 1 : 1;
585
+ void this.#taggingSecretIndexes.set(appTaggingSecrets.toString(), nextIndex);
586
+ });
587
+ });
588
+ }
589
+
590
+ getTaggingSecretsIndexes(appTaggingSecrets: Fr[]): Promise<number[]> {
591
+ return this.db.transaction(() =>
592
+ appTaggingSecrets.map(secret => this.#taggingSecretIndexes.get(secret.toString()) ?? 0),
593
+ );
594
+ }
575
595
  }
@@ -35,6 +35,7 @@ export class OutgoingNoteDao {
35
35
  ) {}
36
36
 
37
37
  static fromPayloadAndNoteInfo(
38
+ note: Note,
38
39
  payload: L1NotePayload,
39
40
  noteInfo: NoteInfo,
40
41
  dataStartIndexForTx: number,
@@ -42,7 +43,7 @@ export class OutgoingNoteDao {
42
43
  ) {
43
44
  const noteHashIndexInTheWholeTree = BigInt(dataStartIndexForTx + noteInfo.noteHashIndex);
44
45
  return new OutgoingNoteDao(
45
- payload.note,
46
+ note,
46
47
  payload.contractAddress,
47
48
  payload.storageSlot,
48
49
  payload.noteTypeId,
@@ -169,20 +169,24 @@ export interface PxeDatabase extends ContractArtifactDatabase, ContractInstanceD
169
169
 
170
170
  /**
171
171
  * Updates up to which block number we have processed notes for a given public key.
172
- * @param publicKey - The public key to set the synched block number for.
172
+ * @param account - The account to set the synched block number for.
173
173
  * @param blockNumber - The block number to set.
174
174
  */
175
- setSynchedBlockNumberForPublicKey(publicKey: PublicKey, blockNumber: number): Promise<void>;
175
+ setSynchedBlockNumberForAccount(account: AztecAddress, blockNumber: number): Promise<void>;
176
176
 
177
177
  /**
178
178
  * Get the synched block number for a given public key.
179
- * @param publicKey - The public key to get the synched block number for.
179
+ * @param account - The account to get the synched block number for.
180
180
  */
181
- getSynchedBlockNumberForPublicKey(publicKey: PublicKey): number | undefined;
181
+ getSynchedBlockNumberForAccount(account: AztecAddress): number | undefined;
182
182
 
183
183
  /**
184
184
  * Returns the estimated size in bytes of this db.
185
185
  * @returns The estimated size in bytes of this db.
186
186
  */
187
187
  estimateSize(): Promise<number>;
188
+
189
+ getTaggingSecretsIndexes(appTaggingSecrets: Fr[]): Promise<number[]>;
190
+
191
+ incrementTaggingSecretsIndexes(appTaggingSecrets: Fr[]): Promise<void>;
188
192
  }
@@ -48,11 +48,7 @@ function collectNestedReadRequests(
48
48
  return collectNested(executionStack, executionResult => {
49
49
  const nonEmptyReadRequests = getNonEmptyItems(extractReadRequests(executionResult));
50
50
  return nonEmptyReadRequests.map(
51
- readRequest =>
52
- new ScopedReadRequest(
53
- readRequest,
54
- executionResult.callStackItem.publicInputs.callContext.storageContractAddress,
55
- ),
51
+ readRequest => new ScopedReadRequest(readRequest, executionResult.publicInputs.callContext.contractAddress),
56
52
  );
57
53
  });
58
54
  }
@@ -117,7 +113,7 @@ export class PrivateKernelResetPrivateInputsBuilder {
117
113
  MAX_NULLIFIERS_PER_TX,
118
114
  () => new TransientDataIndexHint(MAX_NULLIFIERS_PER_TX, MAX_NOTE_HASHES_PER_TX),
119
115
  );
120
- this.nextIteration = executionStack[this.executionStack.length - 1]?.callStackItem.publicInputs;
116
+ this.nextIteration = executionStack[this.executionStack.length - 1]?.publicInputs;
121
117
  }
122
118
 
123
119
  needsReset(): boolean {
@@ -244,10 +240,9 @@ export class PrivateKernelResetPrivateInputsBuilder {
244
240
  }
245
241
 
246
242
  const futureNoteHashes = collectNested(this.executionStack, executionResult => {
247
- const nonEmptyNoteHashes = getNonEmptyItems(executionResult.callStackItem.publicInputs.noteHashes);
243
+ const nonEmptyNoteHashes = getNonEmptyItems(executionResult.publicInputs.noteHashes);
248
244
  return nonEmptyNoteHashes.map(
249
- noteHash =>
250
- new ScopedNoteHash(noteHash, executionResult.callStackItem.publicInputs.callContext.storageContractAddress),
245
+ noteHash => new ScopedNoteHash(noteHash, executionResult.publicInputs.callContext.contractAddress),
251
246
  );
252
247
  });
253
248
 
@@ -297,10 +292,9 @@ export class PrivateKernelResetPrivateInputsBuilder {
297
292
  }
298
293
 
299
294
  const futureNullifiers = collectNested(this.executionStack, executionResult => {
300
- const nonEmptyNullifiers = getNonEmptyItems(executionResult.callStackItem.publicInputs.nullifiers);
295
+ const nonEmptyNullifiers = getNonEmptyItems(executionResult.publicInputs.nullifiers);
301
296
  return nonEmptyNullifiers.map(
302
- nullifier =>
303
- new ScopedNullifier(nullifier, executionResult.callStackItem.publicInputs.callContext.storageContractAddress),
297
+ nullifier => new ScopedNullifier(nullifier, executionResult.publicInputs.callContext.contractAddress),
304
298
  );
305
299
  });
306
300
 
@@ -376,11 +370,11 @@ export class PrivateKernelResetPrivateInputsBuilder {
376
370
 
377
371
  const futureNoteHashReads = collectNestedReadRequests(
378
372
  this.executionStack,
379
- executionResult => executionResult.callStackItem.publicInputs.noteHashReadRequests,
373
+ executionResult => executionResult.publicInputs.noteHashReadRequests,
380
374
  );
381
375
  const futureNullifierReads = collectNestedReadRequests(
382
376
  this.executionStack,
383
- executionResult => executionResult.callStackItem.publicInputs.nullifierReadRequests,
377
+ executionResult => executionResult.publicInputs.nullifierReadRequests,
384
378
  );
385
379
  if (this.nextIteration) {
386
380
  // If it's not the final reset, only one dimension will be reset at a time.
@@ -114,8 +114,8 @@ export class KernelProver {
114
114
  executionStack.push(...[...currentExecution.nestedExecutions].reverse());
115
115
 
116
116
  const functionName = await this.oracle.getDebugFunctionName(
117
- currentExecution.callStackItem.contractAddress,
118
- currentExecution.callStackItem.functionData.selector,
117
+ currentExecution.publicInputs.callContext.contractAddress,
118
+ currentExecution.publicInputs.callContext.functionSelector,
119
119
  );
120
120
 
121
121
  const appVk = await this.proofCreator.computeAppCircuitVerificationKey(currentExecution.acir, functionName);
@@ -201,12 +201,12 @@ export class KernelProver {
201
201
  return tailOutput;
202
202
  }
203
203
 
204
- private async createPrivateCallData({ callStackItem }: PrivateExecutionResult, vk: VerificationKeyAsFields) {
205
- const { contractAddress, functionData } = callStackItem;
204
+ private async createPrivateCallData({ publicInputs }: PrivateExecutionResult, vk: VerificationKeyAsFields) {
205
+ const { contractAddress, functionSelector } = publicInputs.callContext;
206
206
 
207
207
  const functionLeafMembershipWitness = await this.oracle.getFunctionMembershipWitness(
208
208
  contractAddress,
209
- functionData.selector,
209
+ functionSelector,
210
210
  );
211
211
  const { contractClassId, publicKeys, saltedInitializationHash } = await this.oracle.getContractAddressPreimage(
212
212
  contractAddress,
@@ -223,7 +223,7 @@ export class KernelProver {
223
223
  : makeTuple(PROTOCOL_CONTRACT_TREE_HEIGHT, Fr.zero);
224
224
 
225
225
  return PrivateCallData.from({
226
- callStackItem,
226
+ publicInputs,
227
227
  vk,
228
228
  publicKeys,
229
229
  contractClassArtifactHash,
@@ -1,6 +1,11 @@
1
1
  import { type AztecNode, L1NotePayload, type L2Block } from '@aztec/circuit-types';
2
2
  import { type NoteProcessorStats } from '@aztec/circuit-types/stats';
3
- import { type CompleteAddress, INITIAL_L2_BLOCK_NUM, MAX_NOTE_HASHES_PER_TX, type PublicKey } from '@aztec/circuits.js';
3
+ import {
4
+ type CompleteAddress,
5
+ INITIAL_L2_BLOCK_NUM,
6
+ MAX_NOTE_HASHES_PER_TX,
7
+ computeAddressSecret,
8
+ } from '@aztec/circuits.js';
4
9
  import { type Fr } from '@aztec/foundation/fields';
5
10
  import { type Logger, createDebugLogger } from '@aztec/foundation/log';
6
11
  import { Timer } from '@aztec/foundation/timer';
@@ -48,10 +53,6 @@ export class NoteProcessor {
48
53
 
49
54
  private constructor(
50
55
  public readonly account: CompleteAddress,
51
- /** The public counterpart to the secret key to be used in the decryption of incoming note logs. */
52
- private readonly ivpkM: PublicKey,
53
- /** The public counterpart to the secret key to be used in the decryption of outgoing note logs. */
54
- private readonly ovpkM: PublicKey,
55
56
  private keyStore: KeyStore,
56
57
  private db: PxeDatabase,
57
58
  private node: AztecNode,
@@ -60,7 +61,7 @@ export class NoteProcessor {
60
61
  private log: Logger,
61
62
  ) {}
62
63
 
63
- public static async create(
64
+ public static create(
64
65
  account: CompleteAddress,
65
66
  keyStore: KeyStore,
66
67
  db: PxeDatabase,
@@ -69,10 +70,7 @@ export class NoteProcessor {
69
70
  simulator = getAcirSimulator(db, node, keyStore),
70
71
  log = createDebugLogger('aztec:note_processor'),
71
72
  ) {
72
- const ivpkM = await keyStore.getMasterIncomingViewingPublicKey(account.address);
73
- const ovpkM = await keyStore.getMasterOutgoingViewingPublicKey(account.address);
74
-
75
- return new NoteProcessor(account, ivpkM, ovpkM, keyStore, db, node, startingBlock, simulator, log);
73
+ return new NoteProcessor(account, keyStore, db, node, startingBlock, simulator, log);
76
74
  }
77
75
 
78
76
  /**
@@ -95,7 +93,7 @@ export class NoteProcessor {
95
93
  }
96
94
 
97
95
  private getSyncedToBlock(): number {
98
- return this.db.getSynchedBlockNumberForPublicKey(this.ivpkM) ?? this.startingBlock - 1;
96
+ return this.db.getSynchedBlockNumberForAccount(this.account.address) ?? this.startingBlock - 1;
99
97
  }
100
98
 
101
99
  /**
@@ -114,13 +112,17 @@ export class NoteProcessor {
114
112
  const deferredIncomingNotes: DeferredNoteDao[] = [];
115
113
  const deferredOutgoingNotes: DeferredNoteDao[] = [];
116
114
 
117
- const ivskM = await this.keyStore.getMasterSecretKey(this.ivpkM);
118
- const ovskM = await this.keyStore.getMasterSecretKey(this.ovpkM);
115
+ const ivskM = await this.keyStore.getMasterSecretKey(this.account.publicKeys.masterIncomingViewingPublicKey);
116
+ const addressSecret = computeAddressSecret(this.account.getPreaddress(), ivskM);
117
+
118
+ const ovskM = await this.keyStore.getMasterSecretKey(this.account.publicKeys.masterOutgoingViewingPublicKey);
119
119
 
120
120
  // Iterate over both blocks and encrypted logs.
121
121
  for (const block of blocks) {
122
122
  this.stats.blocks++;
123
- const { txLogs } = block.body.noteEncryptedLogs;
123
+ const { txLogs: encryptedTxLogs } = block.body.noteEncryptedLogs;
124
+ const { txLogs: unencryptedTxLogs } = block.body.unencryptedLogs;
125
+
124
126
  const dataStartIndexForBlock =
125
127
  block.header.state.partial.noteHashTree.nextAvailableLeafIndex -
126
128
  block.body.numberOfTxsIncludingPadded * MAX_NOTE_HASHES_PER_TX;
@@ -131,65 +133,72 @@ export class NoteProcessor {
131
133
  const outgoingNotes: OutgoingNoteDao[] = [];
132
134
 
133
135
  // Iterate over all the encrypted logs and try decrypting them. If successful, store the note.
134
- for (let indexOfTxInABlock = 0; indexOfTxInABlock < txLogs.length; ++indexOfTxInABlock) {
136
+ for (let indexOfTxInABlock = 0; indexOfTxInABlock < encryptedTxLogs.length; ++indexOfTxInABlock) {
135
137
  this.stats.txs++;
136
138
  const dataStartIndexForTx = dataStartIndexForBlock + indexOfTxInABlock * MAX_NOTE_HASHES_PER_TX;
137
139
  const noteHashes = block.body.txEffects[indexOfTxInABlock].noteHashes;
138
140
  // Note: Each tx generates a `TxL2Logs` object and for this reason we can rely on its index corresponding
139
141
  // to the index of a tx in a block.
140
- const txFunctionLogs = txLogs[indexOfTxInABlock].functionLogs;
142
+ const encryptedTxFunctionLogs = encryptedTxLogs[indexOfTxInABlock].functionLogs;
143
+ const unencryptedTxFunctionLogs = unencryptedTxLogs[indexOfTxInABlock].functionLogs;
141
144
  const excludedIndices: Set<number> = new Set();
142
- for (const functionLogs of txFunctionLogs) {
143
- for (const log of functionLogs.logs) {
144
- this.stats.seen++;
145
- const incomingNotePayload = L1NotePayload.decryptAsIncoming(log, ivskM);
146
- const outgoingNotePayload = L1NotePayload.decryptAsOutgoing(log, ovskM);
147
-
148
- if (incomingNotePayload || outgoingNotePayload) {
149
- if (incomingNotePayload && outgoingNotePayload && !incomingNotePayload.equals(outgoingNotePayload)) {
150
- throw new Error(
151
- `Incoming and outgoing note payloads do not match. Incoming: ${JSON.stringify(
152
- incomingNotePayload,
153
- )}, Outgoing: ${JSON.stringify(outgoingNotePayload)}`,
154
- );
155
- }
156
-
157
- const payload = incomingNotePayload || outgoingNotePayload;
158
-
159
- const txEffect = block.body.txEffects[indexOfTxInABlock];
160
- const { incomingNote, outgoingNote, incomingDeferredNote, outgoingDeferredNote } = await produceNoteDaos(
161
- this.simulator,
162
- this.db,
163
- incomingNotePayload ? this.ivpkM : undefined,
164
- outgoingNotePayload ? this.ovpkM : undefined,
165
- payload!,
166
- txEffect.txHash,
167
- noteHashes,
168
- dataStartIndexForTx,
169
- excludedIndices,
170
- this.log,
171
- txEffect.unencryptedLogs,
172
- );
173
-
174
- if (incomingNote) {
175
- incomingNotes.push(incomingNote);
176
- this.stats.decryptedIncoming++;
177
- }
178
- if (outgoingNote) {
179
- outgoingNotes.push(outgoingNote);
180
- this.stats.decryptedOutgoing++;
181
- }
182
- if (incomingDeferredNote) {
183
- deferredIncomingNotes.push(incomingDeferredNote);
184
- this.stats.deferredIncoming++;
185
- }
186
- if (outgoingDeferredNote) {
187
- deferredOutgoingNotes.push(outgoingDeferredNote);
188
- this.stats.deferredOutgoing++;
189
- }
190
145
 
191
- if (incomingNote == undefined && outgoingNote == undefined && incomingDeferredNote == undefined) {
192
- this.stats.failed++;
146
+ // We iterate over both encrypted and unencrypted logs to decrypt the notes since partial notes are passed
147
+ // via the unencrypted logs stream.
148
+ for (const txFunctionLogs of [encryptedTxFunctionLogs, unencryptedTxFunctionLogs]) {
149
+ for (const functionLogs of txFunctionLogs) {
150
+ for (const unprocessedLog of functionLogs.logs) {
151
+ this.stats.seen++;
152
+ const incomingNotePayload = L1NotePayload.decryptAsIncoming(unprocessedLog.data, addressSecret);
153
+ const outgoingNotePayload = L1NotePayload.decryptAsOutgoing(unprocessedLog.data, ovskM);
154
+
155
+ if (incomingNotePayload || outgoingNotePayload) {
156
+ if (incomingNotePayload && outgoingNotePayload && !incomingNotePayload.equals(outgoingNotePayload)) {
157
+ throw new Error(
158
+ `Incoming and outgoing note payloads do not match. Incoming: ${JSON.stringify(
159
+ incomingNotePayload,
160
+ )}, Outgoing: ${JSON.stringify(outgoingNotePayload)}`,
161
+ );
162
+ }
163
+
164
+ const payload = incomingNotePayload || outgoingNotePayload;
165
+
166
+ const txEffect = block.body.txEffects[indexOfTxInABlock];
167
+ const { incomingNote, outgoingNote, incomingDeferredNote, outgoingDeferredNote } =
168
+ await produceNoteDaos(
169
+ this.simulator,
170
+ this.db,
171
+ incomingNotePayload ? this.account.publicKeys.masterIncomingViewingPublicKey : undefined,
172
+ outgoingNotePayload ? this.account.publicKeys.masterOutgoingViewingPublicKey : undefined,
173
+ payload!,
174
+ txEffect.txHash,
175
+ noteHashes,
176
+ dataStartIndexForTx,
177
+ excludedIndices,
178
+ this.log,
179
+ txEffect.unencryptedLogs,
180
+ );
181
+
182
+ if (incomingNote) {
183
+ incomingNotes.push(incomingNote);
184
+ this.stats.decryptedIncoming++;
185
+ }
186
+ if (outgoingNote) {
187
+ outgoingNotes.push(outgoingNote);
188
+ this.stats.decryptedOutgoing++;
189
+ }
190
+ if (incomingDeferredNote) {
191
+ deferredIncomingNotes.push(incomingDeferredNote);
192
+ this.stats.deferredIncoming++;
193
+ }
194
+ if (outgoingDeferredNote) {
195
+ deferredOutgoingNotes.push(outgoingDeferredNote);
196
+ this.stats.deferredOutgoing++;
197
+ }
198
+
199
+ if (incomingNote == undefined && outgoingNote == undefined && incomingDeferredNote == undefined) {
200
+ this.stats.failed++;
201
+ }
193
202
  }
194
203
  }
195
204
  }
@@ -207,7 +216,7 @@ export class NoteProcessor {
207
216
  await this.processDeferredNotes(deferredIncomingNotes, deferredOutgoingNotes);
208
217
 
209
218
  const syncedToBlock = blocks[blocks.length - 1].number;
210
- await this.db.setSynchedBlockNumberForPublicKey(this.ivpkM, syncedToBlock);
219
+ await this.db.setSynchedBlockNumberForAccount(this.account.address, syncedToBlock);
211
220
 
212
221
  this.log.debug(`Synched block ${syncedToBlock}`);
213
222
  }
@@ -241,7 +250,10 @@ export class NoteProcessor {
241
250
  const nullifiers: Fr[] = blocksAndNotes.flatMap(b =>
242
251
  b.block.body.txEffects.flatMap(txEffect => txEffect.nullifiers),
243
252
  );
244
- const removedNotes = await this.db.removeNullifiedNotes(nullifiers, this.ivpkM);
253
+ const removedNotes = await this.db.removeNullifiedNotes(
254
+ nullifiers,
255
+ this.account.publicKeys.masterIncomingViewingPublicKey,
256
+ );
245
257
  removedNotes.forEach(noteDao => {
246
258
  this.log.verbose(
247
259
  `Removed note for contract ${noteDao.contractAddress} at slot ${
@@ -265,15 +277,15 @@ export class NoteProcessor {
265
277
  await this.db.addDeferredNotes([...deferredIncomingNotes, ...deferredOutgoingNotes]);
266
278
  deferredIncomingNotes.forEach(noteDao => {
267
279
  this.log.verbose(
268
- `Deferred incoming note for contract ${noteDao.contractAddress} at slot ${
269
- noteDao.storageSlot
280
+ `Deferred incoming note for contract ${noteDao.payload.contractAddress} at slot ${
281
+ noteDao.payload.storageSlot
270
282
  } in tx ${noteDao.txHash.toString()}`,
271
283
  );
272
284
  });
273
285
  deferredOutgoingNotes.forEach(noteDao => {
274
286
  this.log.verbose(
275
- `Deferred outgoing note for contract ${noteDao.contractAddress} at slot ${
276
- noteDao.storageSlot
287
+ `Deferred outgoing note for contract ${noteDao.payload.contractAddress} at slot ${
288
+ noteDao.payload.storageSlot
277
289
  } in tx ${noteDao.txHash.toString()}`,
278
290
  );
279
291
  });
@@ -298,21 +310,10 @@ export class NoteProcessor {
298
310
  const outgoingNotes: OutgoingNoteDao[] = [];
299
311
 
300
312
  for (const deferredNote of deferredNoteDaos) {
301
- const {
302
- publicKey,
303
- note,
304
- contractAddress,
305
- storageSlot,
306
- noteTypeId,
307
- txHash,
308
- noteHashes,
309
- dataStartIndexForTx,
310
- unencryptedLogs,
311
- } = deferredNote;
312
- const payload = new L1NotePayload(note, contractAddress, storageSlot, noteTypeId);
313
+ const { publicKey, payload, txHash, noteHashes, dataStartIndexForTx, unencryptedLogs } = deferredNote;
313
314
 
314
- const isIncoming = publicKey.equals(this.ivpkM);
315
- const isOutgoing = publicKey.equals(this.ovpkM);
315
+ const isIncoming = publicKey.equals(this.account.publicKeys.masterIncomingViewingPublicKey);
316
+ const isOutgoing = publicKey.equals(this.account.publicKeys.masterOutgoingViewingPublicKey);
316
317
 
317
318
  if (!isIncoming && !isOutgoing) {
318
319
  // The note does not belong to this note processor
@@ -322,8 +323,8 @@ export class NoteProcessor {
322
323
  const { incomingNote, outgoingNote } = await produceNoteDaos(
323
324
  this.simulator,
324
325
  this.db,
325
- isIncoming ? this.ivpkM : undefined,
326
- isOutgoing ? this.ovpkM : undefined,
326
+ isIncoming ? this.account.publicKeys.masterIncomingViewingPublicKey : undefined,
327
+ isOutgoing ? this.account.publicKeys.masterOutgoingViewingPublicKey : undefined,
327
328
  payload,
328
329
  txHash,
329
330
  noteHashes,
@@ -0,0 +1,63 @@
1
+ import { type L1NotePayload, Note } from '@aztec/circuit-types';
2
+ import { ContractNotFoundError } from '@aztec/simulator';
3
+
4
+ import { type PxeDatabase } from '../../database/pxe_database.js';
5
+
6
+ /**
7
+ * Merges privately and publicly delivered note values.
8
+ * @param db - PXE database used to fetch contract instance and artifact.
9
+ * @param payload - Payload corresponding to the note.
10
+ * @returns Note payload with public fields added.
11
+ */
12
+ export async function getOrderedNoteItems(
13
+ db: PxeDatabase,
14
+ { contractAddress, noteTypeId, privateNoteValues, publicNoteValues }: L1NotePayload,
15
+ ): Promise<Note> {
16
+ if (publicNoteValues.length === 0) {
17
+ return new Note(privateNoteValues);
18
+ }
19
+
20
+ const instance = await db.getContractInstance(contractAddress);
21
+ if (!instance) {
22
+ throw new ContractNotFoundError(
23
+ `Could not find instance for ${contractAddress.toString()}. This should never happen here as the partial notes flow should be triggered only for non-deferred notes.`,
24
+ );
25
+ }
26
+
27
+ const artifact = await db.getContractArtifact(instance.contractClassId);
28
+ if (!artifact) {
29
+ throw new Error(
30
+ `Could not find artifact for contract class ${instance.contractClassId.toString()}. This should never happen here as the partial notes flow should be triggered only for non-deferred notes.`,
31
+ );
32
+ }
33
+
34
+ const noteFields = Object.values(artifact.notes).find(note => note.id.equals(noteTypeId))?.fields;
35
+
36
+ if (!noteFields) {
37
+ throw new Error(`Could not find note fields for note type ${noteTypeId.toString()}.`);
38
+ }
39
+
40
+ // We sort note fields by index so that we can iterate over them in order.
41
+ noteFields.sort((a, b) => a.index - b.index);
42
+
43
+ // Now we insert the public fields into the note based on its indices defined in the ABI.
44
+ const modifiedNoteItems = privateNoteValues;
45
+ let indexInPublicValues = 0;
46
+ for (let i = 0; i < noteFields.length; i++) {
47
+ const noteField = noteFields[i];
48
+ if (noteField.nullable) {
49
+ if (i == noteFields.length - 1) {
50
+ // We are processing the last field so we simply insert the rest of the public fields at the end
51
+ modifiedNoteItems.push(...publicNoteValues.slice(indexInPublicValues));
52
+ } else {
53
+ const noteFieldLength = noteFields[i + 1].index - noteField.index;
54
+ const publicValuesToInsert = publicNoteValues.slice(indexInPublicValues, indexInPublicValues + noteFieldLength);
55
+ indexInPublicValues += noteFieldLength;
56
+ // Now we insert the public fields at the note field index
57
+ modifiedNoteItems.splice(noteField.index, 0, ...publicValuesToInsert);
58
+ }
59
+ }
60
+ }
61
+
62
+ return new Note(modifiedNoteItems);
63
+ }
@@ -1,5 +1,7 @@
1
- import { type L1NotePayload, type TxHash } from '@aztec/circuit-types';
1
+ import { type Note, type TxHash } from '@aztec/circuit-types';
2
+ import { type AztecAddress } from '@aztec/circuits.js';
2
3
  import { computeNoteHashNonce, siloNullifier } from '@aztec/circuits.js/hash';
4
+ import { type NoteSelector } from '@aztec/foundation/abi';
3
5
  import { Fr } from '@aztec/foundation/fields';
4
6
  import { type AcirSimulator } from '@aztec/simulator';
5
7
 
@@ -18,7 +20,10 @@ export interface NoteInfo {
18
20
  * @remarks This method assists in identifying spent notes in the note hash tree.
19
21
  * @param siloedNoteHashes - Note hashes in the tx. One of them should correspond to the note we are looking for
20
22
  * @param txHash - Hash of a tx the note was emitted in.
21
- * @param l1NotePayload - The note payload.
23
+ * @param contractAddress - Address of the contract the note was emitted in.
24
+ * @param storageSlot - Storage slot of the note.
25
+ * @param noteTypeId - Type of the note.
26
+ * @param note - Note items.
22
27
  * @param excludedIndices - Indices that have been assigned a note in the same tx. Notes in a tx can have the same
23
28
  * l1NotePayload. We need to find a different index for each replicate.
24
29
  * @param computeNullifier - A flag indicating whether to compute the nullifier or just return 0.
@@ -29,7 +34,10 @@ export async function bruteForceNoteInfo(
29
34
  simulator: AcirSimulator,
30
35
  siloedNoteHashes: Fr[],
31
36
  txHash: TxHash,
32
- { contractAddress, storageSlot, noteTypeId, note }: L1NotePayload,
37
+ contractAddress: AztecAddress,
38
+ storageSlot: Fr,
39
+ noteTypeId: NoteSelector,
40
+ note: Note,
33
41
  excludedIndices: Set<number>,
34
42
  computeNullifier: boolean,
35
43
  ): Promise<NoteInfo> {