@aztec/pxe 0.41.0 → 0.43.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 (85) hide show
  1. package/dest/config/index.d.ts.map +1 -1
  2. package/dest/config/index.js +5 -2
  3. package/dest/contract_data_oracle/index.d.ts +1 -0
  4. package/dest/contract_data_oracle/index.d.ts.map +1 -1
  5. package/dest/contract_data_oracle/index.js +7 -1
  6. package/dest/contract_data_oracle/private_functions_tree.d.ts.map +1 -1
  7. package/dest/contract_data_oracle/private_functions_tree.js +2 -2
  8. package/dest/database/deferred_note_dao.d.ts +2 -2
  9. package/dest/database/deferred_note_dao.d.ts.map +1 -1
  10. package/dest/database/deferred_note_dao.js +2 -2
  11. package/dest/database/incoming_note_dao.d.ts +73 -0
  12. package/dest/database/incoming_note_dao.d.ts.map +1 -0
  13. package/dest/database/incoming_note_dao.js +92 -0
  14. package/dest/database/kv_pxe_database.d.ts +10 -7
  15. package/dest/database/kv_pxe_database.d.ts.map +1 -1
  16. package/dest/database/kv_pxe_database.js +149 -78
  17. package/dest/database/{note_dao.d.ts → outgoing_note_dao.d.ts} +7 -12
  18. package/dest/database/outgoing_note_dao.d.ts.map +1 -0
  19. package/dest/database/outgoing_note_dao.js +83 -0
  20. package/dest/database/pxe_database.d.ts +21 -9
  21. package/dest/database/pxe_database.d.ts.map +1 -1
  22. package/dest/database/pxe_database_test_suite.d.ts.map +1 -1
  23. package/dest/database/pxe_database_test_suite.js +71 -24
  24. package/dest/kernel_oracle/index.d.ts +4 -4
  25. package/dest/kernel_oracle/index.d.ts.map +1 -1
  26. package/dest/kernel_oracle/index.js +6 -17
  27. package/dest/kernel_prover/kernel_prover.d.ts +3 -0
  28. package/dest/kernel_prover/kernel_prover.d.ts.map +1 -1
  29. package/dest/kernel_prover/kernel_prover.js +44 -8
  30. package/dest/kernel_prover/private_inputs_builders/build_private_kernel_reset_hints.d.ts +2 -1
  31. package/dest/kernel_prover/private_inputs_builders/build_private_kernel_reset_hints.d.ts.map +1 -1
  32. package/dest/kernel_prover/private_inputs_builders/build_private_kernel_reset_hints.js +32 -12
  33. package/dest/kernel_prover/private_inputs_builders/build_private_kernel_reset_outputs.d.ts +1 -1
  34. package/dest/kernel_prover/private_inputs_builders/build_private_kernel_reset_outputs.d.ts.map +1 -1
  35. package/dest/kernel_prover/private_inputs_builders/build_private_kernel_reset_outputs.js +9 -7
  36. package/dest/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.d.ts.map +1 -1
  37. package/dest/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.js +7 -3
  38. package/dest/kernel_prover/proving_data_oracle.d.ts +6 -6
  39. package/dest/kernel_prover/proving_data_oracle.d.ts.map +1 -1
  40. package/dest/note_processor/note_processor.d.ts +23 -20
  41. package/dest/note_processor/note_processor.d.ts.map +1 -1
  42. package/dest/note_processor/note_processor.js +123 -76
  43. package/dest/note_processor/produce_note_dao.d.ts +13 -4
  44. package/dest/note_processor/produce_note_dao.d.ts.map +1 -1
  45. package/dest/note_processor/produce_note_dao.js +88 -31
  46. package/dest/pxe_http/pxe_http_server.js +3 -3
  47. package/dest/pxe_service/create_pxe_service.d.ts.map +1 -1
  48. package/dest/pxe_service/create_pxe_service.js +4 -2
  49. package/dest/pxe_service/pxe_service.d.ts +14 -6
  50. package/dest/pxe_service/pxe_service.d.ts.map +1 -1
  51. package/dest/pxe_service/pxe_service.js +139 -87
  52. package/dest/pxe_service/test/pxe_test_suite.d.ts.map +1 -1
  53. package/dest/pxe_service/test/pxe_test_suite.js +3 -16
  54. package/dest/simulator_oracle/index.d.ts +1 -0
  55. package/dest/simulator_oracle/index.d.ts.map +1 -1
  56. package/dest/simulator_oracle/index.js +5 -2
  57. package/dest/synchronizer/synchronizer.d.ts +9 -2
  58. package/dest/synchronizer/synchronizer.d.ts.map +1 -1
  59. package/dest/synchronizer/synchronizer.js +43 -34
  60. package/package.json +14 -14
  61. package/src/config/index.ts +11 -1
  62. package/src/contract_data_oracle/index.ts +7 -0
  63. package/src/contract_data_oracle/private_functions_tree.ts +3 -1
  64. package/src/database/deferred_note_dao.ts +1 -1
  65. package/src/database/{note_dao.ts → incoming_note_dao.ts} +10 -7
  66. package/src/database/kv_pxe_database.ts +127 -29
  67. package/src/database/outgoing_note_dao.ts +90 -0
  68. package/src/database/pxe_database.ts +23 -9
  69. package/src/database/pxe_database_test_suite.ts +93 -29
  70. package/src/kernel_oracle/index.ts +4 -17
  71. package/src/kernel_prover/kernel_prover.ts +76 -16
  72. package/src/kernel_prover/private_inputs_builders/build_private_kernel_reset_hints.ts +79 -8
  73. package/src/kernel_prover/private_inputs_builders/build_private_kernel_reset_outputs.ts +9 -5
  74. package/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.ts +13 -1
  75. package/src/kernel_prover/proving_data_oracle.ts +5 -6
  76. package/src/note_processor/note_processor.ts +191 -121
  77. package/src/note_processor/produce_note_dao.ts +164 -50
  78. package/src/pxe_http/pxe_http_server.ts +2 -2
  79. package/src/pxe_service/create_pxe_service.ts +3 -1
  80. package/src/pxe_service/pxe_service.ts +210 -149
  81. package/src/pxe_service/test/pxe_test_suite.ts +0 -20
  82. package/src/simulator_oracle/index.ts +5 -1
  83. package/src/synchronizer/synchronizer.ts +55 -50
  84. package/dest/database/note_dao.d.ts.map +0 -1
  85. package/dest/database/note_dao.js +0 -89
@@ -1,36 +1,34 @@
1
- import {
2
- type AztecNode,
3
- type EncryptedL2BlockL2Logs,
4
- L1NotePayload,
5
- type L2Block,
6
- TaggedNote,
7
- } from '@aztec/circuit-types';
1
+ import { type AztecNode, L1NotePayload, type L2Block, TaggedLog } from '@aztec/circuit-types';
8
2
  import { type NoteProcessorStats } from '@aztec/circuit-types/stats';
9
- import { INITIAL_L2_BLOCK_NUM, MAX_NEW_NOTE_HASHES_PER_TX, type PublicKey } from '@aztec/circuits.js';
3
+ import {
4
+ type AztecAddress,
5
+ INITIAL_L2_BLOCK_NUM,
6
+ MAX_NEW_NOTE_HASHES_PER_TX,
7
+ type PublicKey,
8
+ } from '@aztec/circuits.js';
10
9
  import { type Fr } from '@aztec/foundation/fields';
11
- import { createDebugLogger } from '@aztec/foundation/log';
10
+ import { type Logger, createDebugLogger } from '@aztec/foundation/log';
12
11
  import { Timer } from '@aztec/foundation/timer';
13
12
  import { type KeyStore } from '@aztec/key-store';
14
- import { ContractNotFoundError } from '@aztec/simulator';
13
+ import { type AcirSimulator } from '@aztec/simulator';
15
14
 
16
- import { DeferredNoteDao } from '../database/deferred_note_dao.js';
15
+ import { type DeferredNoteDao } from '../database/deferred_note_dao.js';
16
+ import { type IncomingNoteDao } from '../database/incoming_note_dao.js';
17
17
  import { type PxeDatabase } from '../database/index.js';
18
- import { type NoteDao } from '../database/note_dao.js';
18
+ import { type OutgoingNoteDao } from '../database/outgoing_note_dao.js';
19
19
  import { getAcirSimulator } from '../simulator/index.js';
20
- import { produceNoteDao } from './produce_note_dao.js';
20
+ import { produceNoteDaos } from './produce_note_dao.js';
21
21
 
22
22
  /**
23
23
  * Contains all the decrypted data in this array so that we can later batch insert it all into the database.
24
24
  */
25
25
  interface ProcessedData {
26
- /**
27
- * Holds L2 block.
28
- */
26
+ /** Holds L2 block. */
29
27
  block: L2Block;
30
- /**
31
- * DAOs of processed notes.
32
- */
33
- noteDaos: NoteDao[];
28
+ /** DAOs of processed incoming notes. */
29
+ incomingNotes: IncomingNoteDao[];
30
+ /** DAOs of processed outgoing notes. */
31
+ outgoingNotes: OutgoingNoteDao[];
34
32
  }
35
33
 
36
34
  /**
@@ -42,21 +40,46 @@ export class NoteProcessor {
42
40
  public readonly timer: Timer = new Timer();
43
41
 
44
42
  /** Stats accumulated for this processor. */
45
- public readonly stats: NoteProcessorStats = { seen: 0, decrypted: 0, deferred: 0, failed: 0, blocks: 0, txs: 0 };
43
+ public readonly stats: NoteProcessorStats = {
44
+ seen: 0,
45
+ decryptedIncoming: 0,
46
+ decryptedOutgoing: 0,
47
+ deferredIncoming: 0,
48
+ deferredOutgoing: 0,
49
+ failed: 0,
50
+ blocks: 0,
51
+ txs: 0,
52
+ };
46
53
 
47
- constructor(
48
- /**
49
- * The public counterpart to the private key to be used in note decryption.
50
- */
51
- public readonly masterIncomingViewingPublicKey: PublicKey,
54
+ private constructor(
55
+ public readonly account: AztecAddress,
56
+ /** The public counterpart to the secret key to be used in the decryption of incoming note logs. */
57
+ private readonly ivpkM: PublicKey,
58
+ /** The public counterpart to the secret key to be used in the decryption of outgoing note logs. */
59
+ private readonly ovpkM: PublicKey,
52
60
  private keyStore: KeyStore,
53
61
  private db: PxeDatabase,
54
62
  private node: AztecNode,
55
- private startingBlock: number = INITIAL_L2_BLOCK_NUM,
56
- private simulator = getAcirSimulator(db, node, keyStore),
57
- private log = createDebugLogger('aztec:note_processor'),
63
+ private startingBlock: number,
64
+ private simulator: AcirSimulator,
65
+ private log: Logger,
58
66
  ) {}
59
67
 
68
+ public static async create(
69
+ account: AztecAddress,
70
+ keyStore: KeyStore,
71
+ db: PxeDatabase,
72
+ node: AztecNode,
73
+ startingBlock: number = INITIAL_L2_BLOCK_NUM,
74
+ simulator = getAcirSimulator(db, node, keyStore),
75
+ log = createDebugLogger('aztec:note_processor'),
76
+ ) {
77
+ const ivpkM = await keyStore.getMasterIncomingViewingPublicKey(account);
78
+ const ovpkM = await keyStore.getMasterOutgoingViewingPublicKey(account);
79
+
80
+ return new NoteProcessor(account, ivpkM, ovpkM, keyStore, db, node, startingBlock, simulator, log);
81
+ }
82
+
60
83
  /**
61
84
  * Check if the NoteProcessor is synchronized with the remote block number.
62
85
  * The function queries the remote block number from the AztecNode and compares it with the syncedToBlock value in the NoteProcessor.
@@ -77,46 +100,40 @@ export class NoteProcessor {
77
100
  }
78
101
 
79
102
  private getSyncedToBlock(): number {
80
- return this.db.getSynchedBlockNumberForPublicKey(this.masterIncomingViewingPublicKey) ?? this.startingBlock - 1;
103
+ return this.db.getSynchedBlockNumberForPublicKey(this.ivpkM) ?? this.startingBlock - 1;
81
104
  }
82
105
 
83
106
  /**
84
107
  * Extracts new user-relevant notes from the information contained in the provided L2 blocks and encrypted logs.
85
108
  *
86
- * @throws If the number of blocks and encrypted logs do not match.
87
- * @param l2Blocks - L2 blocks to be processed.
88
- * @param encryptedL2BlockLogs - Encrypted logs associated with the L2 blocks.
109
+ * @param blocks - L2 blocks to be processed.
89
110
  * @returns A promise that resolves once the processing is completed.
90
111
  */
91
- public async process(l2Blocks: L2Block[], encryptedL2BlockLogs: EncryptedL2BlockL2Logs[]): Promise<void> {
92
- if (l2Blocks.length !== encryptedL2BlockLogs.length) {
93
- throw new Error(
94
- `Number of blocks and EncryptedLogs is not equal. Received ${l2Blocks.length} blocks, ${encryptedL2BlockLogs.length} encrypted logs.`,
95
- );
96
- }
97
- if (l2Blocks.length === 0) {
112
+ public async process(blocks: L2Block[]): Promise<void> {
113
+ if (blocks.length === 0) {
98
114
  return;
99
115
  }
100
116
 
101
117
  const blocksAndNotes: ProcessedData[] = [];
102
118
  // Keep track of notes that we couldn't process because the contract was not found.
103
- const deferredNoteDaos: DeferredNoteDao[] = [];
119
+ const deferredIncomingNotes: DeferredNoteDao[] = [];
120
+ const deferredOutgoingNotes: DeferredNoteDao[] = [];
121
+
122
+ const ivskM = await this.keyStore.getMasterSecretKey(this.ivpkM);
123
+ const ovskM = await this.keyStore.getMasterSecretKey(this.ovpkM);
104
124
 
105
125
  // Iterate over both blocks and encrypted logs.
106
- for (let blockIndex = 0; blockIndex < encryptedL2BlockLogs.length; ++blockIndex) {
126
+ for (const block of blocks) {
107
127
  this.stats.blocks++;
108
- const { txLogs } = encryptedL2BlockLogs[blockIndex];
109
- const block = l2Blocks[blockIndex];
128
+ const { txLogs } = block.body.noteEncryptedLogs;
110
129
  const dataStartIndexForBlock =
111
130
  block.header.state.partial.noteHashTree.nextAvailableLeafIndex -
112
131
  block.body.numberOfTxsIncludingPadded * MAX_NEW_NOTE_HASHES_PER_TX;
113
132
 
114
133
  // We are using set for `userPertainingTxIndices` to avoid duplicates. This would happen in case there were
115
134
  // multiple encrypted logs in a tx pertaining to a user.
116
- const noteDaos: NoteDao[] = [];
117
- const secretKey = await this.keyStore.getMasterIncomingViewingSecretKeyForPublicKey(
118
- this.masterIncomingViewingPublicKey,
119
- );
135
+ const incomingNotes: IncomingNoteDao[] = [];
136
+ const outgoingNotes: OutgoingNoteDao[] = [];
120
137
 
121
138
  // Iterate over all the encrypted logs and try decrypting them. If successful, store the note.
122
139
  for (let indexOfTxInABlock = 0; indexOfTxInABlock < txLogs.length; ++indexOfTxInABlock) {
@@ -130,43 +147,57 @@ export class NoteProcessor {
130
147
  for (const functionLogs of txFunctionLogs) {
131
148
  for (const log of functionLogs.logs) {
132
149
  this.stats.seen++;
133
- // @todo Issue(#6410) We should also try decrypting as outgoing if this fails.
134
- const taggedNote = TaggedNote.decryptAsIncoming(log.data, secretKey);
135
- if (taggedNote?.notePayload) {
136
- const { notePayload: payload } = taggedNote;
137
- // We have successfully decrypted the data.
150
+ const incomingTaggedNote = TaggedLog.decryptAsIncoming(log.data, ivskM)!;
151
+ const outgoingTaggedNote = TaggedLog.decryptAsOutgoing(log.data, ovskM)!;
152
+
153
+ if (incomingTaggedNote || outgoingTaggedNote) {
154
+ // TODO(#7053): Re-enable this check
155
+ // if (
156
+ // incomingTaggedNote &&
157
+ // outgoingTaggedNote &&
158
+ // !incomingTaggedNote.payload.equals(outgoingTaggedNote.payload)
159
+ // ) {
160
+ // throw new Error(
161
+ // `Incoming and outgoing note payloads do not match. Incoming: ${JSON.stringify(
162
+ // incomingTaggedNote.payload,
163
+ // )}, Outgoing: ${JSON.stringify(outgoingTaggedNote.payload)}`,
164
+ // );
165
+ // }
166
+
167
+ const payload = incomingTaggedNote?.payload || outgoingTaggedNote?.payload;
168
+
138
169
  const txHash = block.body.txEffects[indexOfTxInABlock].txHash;
139
- try {
140
- const noteDao = await produceNoteDao(
141
- this.simulator,
142
- this.masterIncomingViewingPublicKey,
143
- payload,
144
- txHash,
145
- newNoteHashes,
146
- dataStartIndexForTx,
147
- excludedIndices,
148
- );
149
- noteDaos.push(noteDao);
150
- this.stats.decrypted++;
151
- } catch (e) {
152
- if (e instanceof ContractNotFoundError) {
153
- this.stats.deferred++;
154
- this.log.warn(e.message);
155
- const deferredNoteDao = new DeferredNoteDao(
156
- this.masterIncomingViewingPublicKey,
157
- payload.note,
158
- payload.contractAddress,
159
- payload.storageSlot,
160
- payload.noteTypeId,
161
- txHash,
162
- newNoteHashes,
163
- dataStartIndexForTx,
164
- );
165
- deferredNoteDaos.push(deferredNoteDao);
166
- } else {
167
- this.stats.failed++;
168
- this.log.error(`Could not process note because of "${e}". Discarding note...`);
169
- }
170
+ const { incomingNote, outgoingNote, incomingDeferredNote, outgoingDeferredNote } = await produceNoteDaos(
171
+ this.simulator,
172
+ incomingTaggedNote ? this.ivpkM : undefined,
173
+ outgoingTaggedNote ? this.ovpkM : undefined,
174
+ payload,
175
+ txHash,
176
+ newNoteHashes,
177
+ dataStartIndexForTx,
178
+ excludedIndices,
179
+ this.log,
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++;
170
201
  }
171
202
  }
172
203
  }
@@ -174,16 +205,17 @@ export class NoteProcessor {
174
205
  }
175
206
 
176
207
  blocksAndNotes.push({
177
- block: l2Blocks[blockIndex],
178
- noteDaos,
208
+ block,
209
+ incomingNotes,
210
+ outgoingNotes,
179
211
  });
180
212
  }
181
213
 
182
214
  await this.processBlocksAndNotes(blocksAndNotes);
183
- await this.processDeferredNotes(deferredNoteDaos);
215
+ await this.processDeferredNotes(deferredIncomingNotes, deferredOutgoingNotes);
184
216
 
185
- const syncedToBlock = l2Blocks[l2Blocks.length - 1].number;
186
- await this.db.setSynchedBlockNumberForPublicKey(this.masterIncomingViewingPublicKey, syncedToBlock);
217
+ const syncedToBlock = blocks[blocks.length - 1].number;
218
+ await this.db.setSynchedBlockNumberForPublicKey(this.ivpkM, syncedToBlock);
187
219
 
188
220
  this.log.debug(`Synched block ${syncedToBlock}`);
189
221
  }
@@ -198,22 +230,26 @@ export class NoteProcessor {
198
230
  * @param blocksAndNotes - Array of objects containing L2 blocks, user-pertaining transaction indices, and NoteDaos.
199
231
  */
200
232
  private async processBlocksAndNotes(blocksAndNotes: ProcessedData[]) {
201
- const noteDaos = blocksAndNotes.flatMap(b => b.noteDaos);
202
- if (noteDaos.length) {
203
- await this.db.addNotes(noteDaos);
204
- noteDaos.forEach(noteDao => {
233
+ const incomingNotes = blocksAndNotes.flatMap(b => b.incomingNotes);
234
+ const outgoingNotes = blocksAndNotes.flatMap(b => b.outgoingNotes);
235
+ if (incomingNotes.length || outgoingNotes.length) {
236
+ await this.db.addNotes(incomingNotes, outgoingNotes);
237
+ incomingNotes.forEach(noteDao => {
205
238
  this.log.verbose(
206
- `Added note for contract ${noteDao.contractAddress} at slot ${
239
+ `Added incoming note for contract ${noteDao.contractAddress} at slot ${
207
240
  noteDao.storageSlot
208
241
  } with nullifier ${noteDao.siloedNullifier.toString()}`,
209
242
  );
210
243
  });
244
+ outgoingNotes.forEach(noteDao => {
245
+ this.log.verbose(`Added outgoing note for contract ${noteDao.contractAddress} at slot ${noteDao.storageSlot}`);
246
+ });
211
247
  }
212
248
 
213
249
  const newNullifiers: Fr[] = blocksAndNotes.flatMap(b =>
214
250
  b.block.body.txEffects.flatMap(txEffect => txEffect.nullifiers),
215
251
  );
216
- const removedNotes = await this.db.removeNullifiedNotes(newNullifiers, this.masterIncomingViewingPublicKey);
252
+ const removedNotes = await this.db.removeNullifiedNotes(newNullifiers, this.ivpkM);
217
253
  removedNotes.forEach(noteDao => {
218
254
  this.log.verbose(
219
255
  `Removed note for contract ${noteDao.contractAddress} at slot ${
@@ -226,14 +262,25 @@ export class NoteProcessor {
226
262
  /**
227
263
  * Store the given deferred notes in the database for later decoding.
228
264
  *
229
- * @param deferredNoteDaos - notes that are intended for us but we couldn't process because the contract was not found.
265
+ * @param deferredIncomingNotes - incoming notes that are intended for us but we couldn't process because the contract was not found.
266
+ * @param deferredOutgoingNotes - outgoing notes that we couldn't process because the contract was not found.
230
267
  */
231
- private async processDeferredNotes(deferredNoteDaos: DeferredNoteDao[]) {
232
- if (deferredNoteDaos.length) {
233
- await this.db.addDeferredNotes(deferredNoteDaos);
234
- deferredNoteDaos.forEach(noteDao => {
268
+ private async processDeferredNotes(
269
+ deferredIncomingNotes: DeferredNoteDao[],
270
+ deferredOutgoingNotes: DeferredNoteDao[],
271
+ ) {
272
+ if (deferredIncomingNotes.length || deferredOutgoingNotes.length) {
273
+ await this.db.addDeferredNotes([...deferredIncomingNotes, ...deferredOutgoingNotes]);
274
+ deferredIncomingNotes.forEach(noteDao => {
275
+ this.log.verbose(
276
+ `Deferred incoming note for contract ${noteDao.contractAddress} at slot ${
277
+ noteDao.storageSlot
278
+ } in tx ${noteDao.txHash.toString()}`,
279
+ );
280
+ });
281
+ deferredOutgoingNotes.forEach(noteDao => {
235
282
  this.log.verbose(
236
- `Deferred note for contract ${noteDao.contractAddress} at slot ${
283
+ `Deferred outgoing note for contract ${noteDao.contractAddress} at slot ${
237
284
  noteDao.storageSlot
238
285
  } in tx ${noteDao.txHash.toString()}`,
239
286
  );
@@ -245,37 +292,60 @@ export class NoteProcessor {
245
292
  * Retry decoding the given deferred notes because we now have the contract code.
246
293
  *
247
294
  * @param deferredNoteDaos - notes that we have previously deferred because the contract was not found
248
- * @returns An array of NoteDaos that were successfully decoded.
295
+ * @returns An object containing arrays of incoming and outgoing notes that were successfully decoded.
249
296
  *
250
297
  * @remarks Caller is responsible for making sure that we have the contract for the
251
298
  * deferred notes provided: we will not retry notes that fail again.
252
299
  */
253
- public async decodeDeferredNotes(deferredNoteDaos: DeferredNoteDao[]): Promise<NoteDao[]> {
300
+ public async decodeDeferredNotes(deferredNoteDaos: DeferredNoteDao[]): Promise<{
301
+ incomingNotes: IncomingNoteDao[];
302
+ outgoingNotes: OutgoingNoteDao[];
303
+ }> {
254
304
  const excludedIndices: Set<number> = new Set();
255
- const noteDaos: NoteDao[] = [];
305
+ const incomingNotes: IncomingNoteDao[] = [];
306
+ const outgoingNotes: OutgoingNoteDao[] = [];
307
+
256
308
  for (const deferredNote of deferredNoteDaos) {
257
- const { note, contractAddress, storageSlot, noteTypeId, txHash, newNoteHashes, dataStartIndexForTx } =
309
+ const { publicKey, note, contractAddress, storageSlot, noteTypeId, txHash, newNoteHashes, dataStartIndexForTx } =
258
310
  deferredNote;
259
311
  const payload = new L1NotePayload(note, contractAddress, storageSlot, noteTypeId);
260
312
 
261
- try {
262
- const noteDao = await produceNoteDao(
263
- this.simulator,
264
- this.masterIncomingViewingPublicKey,
265
- payload,
266
- txHash,
267
- newNoteHashes,
268
- dataStartIndexForTx,
269
- excludedIndices,
270
- );
271
- noteDaos.push(noteDao);
272
- this.stats.decrypted++;
273
- } catch (e) {
274
- this.stats.failed++;
275
- this.log.warn(`Could not process deferred note because of "${e}". Discarding note...`);
313
+ const isIncoming = publicKey.equals(this.ivpkM);
314
+ const isOutgoing = publicKey.equals(this.ovpkM);
315
+
316
+ if (!isIncoming && !isOutgoing) {
317
+ // The note does not belong to this note processor
318
+ continue;
319
+ }
320
+
321
+ const { incomingNote, outgoingNote } = await produceNoteDaos(
322
+ this.simulator,
323
+ isIncoming ? this.ivpkM : undefined,
324
+ isOutgoing ? this.ovpkM : undefined,
325
+ payload,
326
+ txHash,
327
+ newNoteHashes,
328
+ dataStartIndexForTx,
329
+ excludedIndices,
330
+ this.log,
331
+ );
332
+
333
+ if (isIncoming) {
334
+ if (!incomingNote) {
335
+ throw new Error('Deferred incoming note could not be decoded');
336
+ }
337
+ incomingNotes.push(incomingNote);
338
+ this.stats.decryptedIncoming++;
339
+ }
340
+ if (outgoingNote) {
341
+ if (!outgoingNote) {
342
+ throw new Error('Deferred outgoing note could not be decoded');
343
+ }
344
+ outgoingNotes.push(outgoingNote);
345
+ this.stats.decryptedOutgoing++;
276
346
  }
277
347
  }
278
348
 
279
- return noteDaos;
349
+ return { incomingNotes, outgoingNotes };
280
350
  }
281
351
  }