@aztec/pxe 0.61.0 → 0.62.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 (49) hide show
  1. package/dest/database/deferred_note_dao.d.ts +2 -2
  2. package/dest/database/deferred_note_dao.d.ts.map +1 -1
  3. package/dest/database/deferred_note_dao.js +2 -2
  4. package/dest/database/incoming_note_dao.d.ts +3 -3
  5. package/dest/database/incoming_note_dao.d.ts.map +1 -1
  6. package/dest/database/incoming_note_dao.js +6 -6
  7. package/dest/database/kv_pxe_database.d.ts +8 -5
  8. package/dest/database/kv_pxe_database.d.ts.map +1 -1
  9. package/dest/database/kv_pxe_database.js +63 -44
  10. package/dest/database/outgoing_note_dao.d.ts +1 -1
  11. package/dest/database/outgoing_note_dao.js +2 -2
  12. package/dest/database/pxe_database.d.ts +33 -3
  13. package/dest/database/pxe_database.d.ts.map +1 -1
  14. package/dest/database/pxe_database_test_suite.d.ts.map +1 -1
  15. package/dest/database/pxe_database_test_suite.js +11 -11
  16. package/dest/index.d.ts +1 -1
  17. package/dest/index.d.ts.map +1 -1
  18. package/dest/index.js +1 -1
  19. package/dest/note_processor/note_processor.d.ts.map +1 -1
  20. package/dest/note_processor/note_processor.js +9 -8
  21. package/dest/note_processor/utils/produce_note_daos.d.ts +2 -2
  22. package/dest/note_processor/utils/produce_note_daos.d.ts.map +1 -1
  23. package/dest/note_processor/utils/produce_note_daos.js +7 -7
  24. package/dest/pxe_http/pxe_http_server.d.ts.map +1 -1
  25. package/dest/pxe_http/pxe_http_server.js +23 -21
  26. package/dest/pxe_service/pxe_service.d.ts +15 -7
  27. package/dest/pxe_service/pxe_service.d.ts.map +1 -1
  28. package/dest/pxe_service/pxe_service.js +42 -39
  29. package/dest/pxe_service/test/pxe_test_suite.d.ts.map +1 -1
  30. package/dest/pxe_service/test/pxe_test_suite.js +2 -32
  31. package/dest/simulator_oracle/index.d.ts +24 -1
  32. package/dest/simulator_oracle/index.d.ts.map +1 -1
  33. package/dest/simulator_oracle/index.js +81 -18
  34. package/dest/synchronizer/synchronizer.js +6 -6
  35. package/package.json +16 -14
  36. package/src/database/deferred_note_dao.ts +1 -1
  37. package/src/database/incoming_note_dao.ts +4 -4
  38. package/src/database/kv_pxe_database.ts +72 -46
  39. package/src/database/outgoing_note_dao.ts +2 -2
  40. package/src/database/pxe_database.ts +36 -2
  41. package/src/database/pxe_database_test_suite.ts +12 -20
  42. package/src/index.ts +1 -1
  43. package/src/note_processor/note_processor.ts +12 -9
  44. package/src/note_processor/utils/produce_note_daos.ts +6 -6
  45. package/src/pxe_http/pxe_http_server.ts +22 -19
  46. package/src/pxe_service/pxe_service.ts +50 -44
  47. package/src/pxe_service/test/pxe_test_suite.ts +1 -53
  48. package/src/simulator_oracle/index.ts +93 -14
  49. package/src/synchronizer/synchronizer.ts +5 -5
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  type AuthWitness,
3
3
  type AztecNode,
4
- type EventMetadata,
4
+ EventMetadata,
5
5
  EventType,
6
6
  type ExtendedNote,
7
7
  type FunctionCall,
@@ -44,11 +44,13 @@ import {
44
44
  computeAddressSecret,
45
45
  computeContractAddressFromInstance,
46
46
  computeContractClassId,
47
+ computePoint,
47
48
  getContractClassFromArtifact,
48
49
  } from '@aztec/circuits.js';
49
50
  import { computeNoteHashNonce, siloNullifier } from '@aztec/circuits.js/hash';
50
51
  import {
51
52
  type AbiDecoded,
53
+ type AbiType,
52
54
  type ContractArtifact,
53
55
  EventSelector,
54
56
  FunctionSelector,
@@ -124,19 +126,18 @@ export class PXEService implements PXE {
124
126
 
125
127
  private async restoreNoteProcessors() {
126
128
  const accounts = await this.keyStore.getAccounts();
127
- const publicKeys = accounts.map(async account => await this.keyStore.getMasterIncomingViewingPublicKey(account));
128
- const publicKeysSet = new Set(publicKeys.map(k => k.toString()));
129
+ const accountsSet = new Set(accounts.map(k => k.toString()));
129
130
 
130
131
  const registeredAddresses = await this.db.getCompleteAddresses();
131
132
 
132
133
  let count = 0;
133
- for (const address of registeredAddresses) {
134
- if (!publicKeysSet.has(address.publicKeys.masterIncomingViewingPublicKey.toString())) {
134
+ for (const completeAddress of registeredAddresses) {
135
+ if (!accountsSet.has(completeAddress.address.toString())) {
135
136
  continue;
136
137
  }
137
138
 
138
139
  count++;
139
- this.synchronizer.addAccount(address, this.keyStore, this.config.l2StartingBlock);
140
+ this.synchronizer.addAccount(completeAddress, this.keyStore, this.config.l2StartingBlock);
140
141
  }
141
142
 
142
143
  if (count > 0) {
@@ -204,47 +205,56 @@ export class PXEService implements PXE {
204
205
  return accountCompleteAddress;
205
206
  }
206
207
 
207
- public async getRegisteredAccounts(): Promise<CompleteAddress[]> {
208
- // Get complete addresses of both the recipients and the accounts
209
- const completeAddresses = await this.db.getCompleteAddresses();
210
- // Filter out the addresses not corresponding to accounts
208
+ public async registerContact(address: AztecAddress): Promise<AztecAddress> {
211
209
  const accounts = await this.keyStore.getAccounts();
212
- return completeAddresses.filter(completeAddress =>
213
- accounts.find(address => address.equals(completeAddress.address)),
214
- );
210
+ if (accounts.includes(address)) {
211
+ this.log.info(`Account:\n "${address.toString()}"\n already registered.`);
212
+ return address;
213
+ }
214
+
215
+ const wasAdded = await this.db.addContactAddress(address);
216
+
217
+ if (wasAdded) {
218
+ this.log.info(`Added contact:\n ${address.toString()}`);
219
+ } else {
220
+ this.log.info(`Contact:\n "${address.toString()}"\n already registered.`);
221
+ }
222
+
223
+ return address;
215
224
  }
216
225
 
217
- public async getRegisteredAccount(address: AztecAddress): Promise<CompleteAddress | undefined> {
218
- const result = await this.getRegisteredAccounts();
219
- const account = result.find(r => r.address.equals(address));
220
- return Promise.resolve(account);
226
+ public getContacts(): Promise<AztecAddress[]> {
227
+ const contacts = this.db.getContactAddresses();
228
+
229
+ return Promise.resolve(contacts);
221
230
  }
222
231
 
223
- public async registerRecipient(recipient: CompleteAddress): Promise<void> {
224
- const wasAdded = await this.db.addCompleteAddress(recipient);
232
+ public async removeContact(address: AztecAddress): Promise<void> {
233
+ const wasRemoved = await this.db.removeContactAddress(address);
225
234
 
226
- if (wasAdded) {
227
- this.log.info(`Added recipient:\n ${recipient.toReadableString()}`);
235
+ if (wasRemoved) {
236
+ this.log.info(`Removed contact:\n ${address.toString()}`);
228
237
  } else {
229
- this.log.info(`Recipient:\n "${recipient.toReadableString()}"\n already registered.`);
238
+ this.log.info(`Contact:\n "${address.toString()}"\n not in address book.`);
230
239
  }
240
+
241
+ return Promise.resolve();
231
242
  }
232
243
 
233
- public async getRecipients(): Promise<CompleteAddress[]> {
244
+ public async getRegisteredAccounts(): Promise<CompleteAddress[]> {
234
245
  // Get complete addresses of both the recipients and the accounts
235
246
  const completeAddresses = await this.db.getCompleteAddresses();
236
- // Filter out the addresses corresponding to accounts
247
+ // Filter out the addresses not corresponding to accounts
237
248
  const accounts = await this.keyStore.getAccounts();
238
- const recipients = completeAddresses.filter(
239
- completeAddress => !accounts.find(account => account.equals(completeAddress.address)),
249
+ return completeAddresses.filter(completeAddress =>
250
+ accounts.find(address => address.equals(completeAddress.address)),
240
251
  );
241
- return recipients;
242
252
  }
243
253
 
244
- public async getRecipient(address: AztecAddress): Promise<CompleteAddress | undefined> {
245
- const result = await this.getRecipients();
246
- const recipient = result.find(r => r.address.equals(address));
247
- return Promise.resolve(recipient);
254
+ public async getRegisteredAccount(address: AztecAddress): Promise<CompleteAddress | undefined> {
255
+ const result = await this.getRegisteredAccounts();
256
+ const account = result.find(r => r.address.equals(address));
257
+ return Promise.resolve(account);
248
258
  }
249
259
 
250
260
  public async registerContractClass(artifact: ContractArtifact): Promise<void> {
@@ -306,11 +316,11 @@ export class PXEService implements PXE {
306
316
  const extendedNotes = noteDaos.map(async dao => {
307
317
  let owner = filter.owner;
308
318
  if (owner === undefined) {
309
- const completeAddresses = (await this.db.getCompleteAddresses()).find(address =>
310
- address.publicKeys.masterIncomingViewingPublicKey.equals(dao.ivpkM),
319
+ const completeAddresses = (await this.db.getCompleteAddresses()).find(completeAddress =>
320
+ computePoint(completeAddress.address).equals(dao.addressPoint),
311
321
  );
312
322
  if (completeAddresses === undefined) {
313
- throw new Error(`Cannot find complete address for IvpkM ${dao.ivpkM.toString()}`);
323
+ throw new Error(`Cannot find complete address for addressPoint ${dao.addressPoint.toString()}`);
314
324
  }
315
325
  owner = completeAddresses.address;
316
326
  }
@@ -405,7 +415,7 @@ export class PXEService implements PXE {
405
415
  noteHash,
406
416
  siloedNullifier,
407
417
  index,
408
- owner.publicKeys.masterIncomingViewingPublicKey,
418
+ computePoint(owner.address),
409
419
  ),
410
420
  scope,
411
421
  );
@@ -413,11 +423,6 @@ export class PXEService implements PXE {
413
423
  }
414
424
 
415
425
  public async addNullifiedNote(note: ExtendedNote) {
416
- const owner = await this.db.getCompleteAddress(note.owner);
417
- if (!owner) {
418
- throw new Error(`Unknown account: ${note.owner.toString()}`);
419
- }
420
-
421
426
  const nonces = await this.#getNoteNonces(note);
422
427
  if (nonces.length === 0) {
423
428
  throw new Error(`Cannot find the note in tx: ${note.txHash}.`);
@@ -453,7 +458,7 @@ export class PXEService implements PXE {
453
458
  noteHash,
454
459
  Fr.ZERO, // We are not able to derive
455
460
  index,
456
- owner.publicKeys.masterIncomingViewingPublicKey,
461
+ computePoint(note.owner),
457
462
  ),
458
463
  );
459
464
  }
@@ -830,24 +835,25 @@ export class PXEService implements PXE {
830
835
 
831
836
  public getEvents<T>(
832
837
  type: EventType.Encrypted,
833
- eventMetadata: EventMetadata<T>,
838
+ event: { eventSelector: EventSelector; abiType: AbiType; fieldNames: string[] },
834
839
  from: number,
835
840
  limit: number,
836
841
  vpks: Point[],
837
842
  ): Promise<T[]>;
838
843
  public getEvents<T>(
839
844
  type: EventType.Unencrypted,
840
- eventMetadata: EventMetadata<T>,
845
+ event: { eventSelector: EventSelector; abiType: AbiType; fieldNames: string[] },
841
846
  from: number,
842
847
  limit: number,
843
848
  ): Promise<T[]>;
844
849
  public getEvents<T>(
845
850
  type: EventType,
846
- eventMetadata: EventMetadata<T>,
851
+ event: { eventSelector: EventSelector; abiType: AbiType; fieldNames: string[] },
847
852
  from: number,
848
853
  limit: number,
849
854
  vpks: Point[] = [],
850
855
  ): Promise<T[]> {
856
+ const eventMetadata = new EventMetadata<T>(type, event);
851
857
  if (type.includes(EventType.Encrypted)) {
852
858
  return this.getEncryptedEvents(from, limit, eventMetadata, vpks);
853
859
  }
@@ -4,15 +4,7 @@ import {
4
4
  randomContractInstanceWithAddress,
5
5
  randomDeployedContract,
6
6
  } from '@aztec/circuit-types';
7
- import {
8
- AztecAddress,
9
- CompleteAddress,
10
- Fr,
11
- INITIAL_L2_BLOCK_NUM,
12
- Point,
13
- PublicKeys,
14
- getContractClassFromArtifact,
15
- } from '@aztec/circuits.js';
7
+ import { AztecAddress, Fr, INITIAL_L2_BLOCK_NUM, getContractClassFromArtifact } from '@aztec/circuits.js';
16
8
 
17
9
  export const pxeTestSuite = (testName: string, pxeSetup: () => Promise<PXE>) => {
18
10
  describe(testName, () => {
@@ -29,33 +21,11 @@ export const pxeTestSuite = (testName: string, pxeSetup: () => Promise<PXE>) =>
29
21
 
30
22
  // Check that the account is correctly registered using the getAccounts and getRecipients methods
31
23
  const accounts = await pxe.getRegisteredAccounts();
32
- const recipients = await pxe.getRecipients();
33
24
  expect(accounts).toContainEqual(completeAddress);
34
- expect(recipients).not.toContainEqual(completeAddress);
35
25
 
36
26
  // Check that the account is correctly registered using the getAccount and getRecipient methods
37
27
  const account = await pxe.getRegisteredAccount(completeAddress.address);
38
- const recipient = await pxe.getRecipient(completeAddress.address);
39
28
  expect(account).toEqual(completeAddress);
40
- expect(recipient).toBeUndefined();
41
- });
42
-
43
- it('registers a recipient and returns it as a recipient only and not as an account', async () => {
44
- const completeAddress = CompleteAddress.random();
45
-
46
- await pxe.registerRecipient(completeAddress);
47
-
48
- // Check that the recipient is correctly registered using the getAccounts and getRecipients methods
49
- const accounts = await pxe.getRegisteredAccounts();
50
- const recipients = await pxe.getRecipients();
51
- expect(accounts).not.toContainEqual(completeAddress);
52
- expect(recipients).toContainEqual(completeAddress);
53
-
54
- // Check that the recipient is correctly registered using the getAccount and getRecipient methods
55
- const account = await pxe.getRegisteredAccount(completeAddress.address);
56
- const recipient = await pxe.getRecipient(completeAddress.address);
57
- expect(account).toBeUndefined();
58
- expect(recipient).toEqual(completeAddress);
59
29
  });
60
30
 
61
31
  it('does not throw when registering the same account twice (just ignores the second attempt)', async () => {
@@ -66,28 +36,6 @@ export const pxeTestSuite = (testName: string, pxeSetup: () => Promise<PXE>) =>
66
36
  await pxe.registerAccount(randomSecretKey, randomPartialAddress);
67
37
  });
68
38
 
69
- // Disabled as CompleteAddress constructor now performs preimage validation.
70
- it.skip('cannot register a recipient with the same aztec address but different pub key or partial address', async () => {
71
- const recipient1 = CompleteAddress.random();
72
- const recipient2 = new CompleteAddress(
73
- recipient1.address,
74
- new PublicKeys(Point.random(), Point.random(), Point.random(), Point.random()),
75
- Fr.random(),
76
- );
77
-
78
- await pxe.registerRecipient(recipient1);
79
- await expect(() => pxe.registerRecipient(recipient2)).rejects.toThrow(
80
- `Complete address with aztec address ${recipient1.address}`,
81
- );
82
- });
83
-
84
- it('does not throw when registering the same recipient twice (just ignores the second attempt)', async () => {
85
- const completeAddress = CompleteAddress.random();
86
-
87
- await pxe.registerRecipient(completeAddress);
88
- await pxe.registerRecipient(completeAddress);
89
- });
90
-
91
39
  it('successfully adds a contract', async () => {
92
40
  const contracts = [randomDeployedContract(), randomDeployedContract()];
93
41
  for (const contract of contracts) {
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  type AztecNode,
3
+ type EncryptedL2NoteLog,
3
4
  type L2Block,
4
5
  MerkleTreeId,
5
6
  type NoteStatus,
@@ -17,6 +18,7 @@ import {
17
18
  IndexedTaggingSecret,
18
19
  type KeyValidationRequest,
19
20
  type L1_TO_L2_MSG_TREE_HEIGHT,
21
+ TaggingSecret,
20
22
  computeTaggingSecret,
21
23
  } from '@aztec/circuits.js';
22
24
  import { type FunctionArtifact, getFunctionArtifact } from '@aztec/foundation/abi';
@@ -49,7 +51,7 @@ export class SimulatorOracle implements DBOracle {
49
51
  if (!completeAddress) {
50
52
  throw new Error(
51
53
  `No public key registered for address ${account}.
52
- Register it by calling pxe.registerRecipient(...) or pxe.registerAccount(...).\nSee docs for context: https://docs.aztec.network/reference/common_errors/aztecnr-errors#simulation-error-no-public-key-registered-for-address-0x0-register-it-by-calling-pxeregisterrecipient-or-pxeregisteraccount`,
54
+ Register it by calling pxe.registerAccount(...).\nSee docs for context: https://docs.aztec.network/reference/common_errors/aztecnr-errors#simulation-error-no-public-key-registered-for-address-0x0-register-it-by-calling-pxeregisterrecipient-or-pxeregisteraccount`,
53
55
  );
54
56
  }
55
57
  return completeAddress;
@@ -230,6 +232,16 @@ export class SimulatorOracle implements DBOracle {
230
232
  return this.contractDataOracle.getDebugFunctionName(contractAddress, selector);
231
233
  }
232
234
 
235
+ /**
236
+ * Returns the full contents of your address book.
237
+ * This is used when calculating tags for incoming notes by deriving the shared secret, the contract-siloed tagging secret, and
238
+ * finally the index specified tag. We will then query the node with this tag for each address in the address book.
239
+ * @returns The full list of the users contact addresses.
240
+ */
241
+ public getContacts(): AztecAddress[] {
242
+ return this.db.getContactAddresses();
243
+ }
244
+
233
245
  /**
234
246
  * Returns the tagging secret for a given sender and recipient pair. For this to work, the ivpsk_m of the sender must be known.
235
247
  * Includes the last known index used for tagging with this secret.
@@ -243,13 +255,35 @@ export class SimulatorOracle implements DBOracle {
243
255
  sender: AztecAddress,
244
256
  recipient: AztecAddress,
245
257
  ): Promise<IndexedTaggingSecret> {
258
+ const directionalSecret = await this.#calculateDirectionalSecret(contractAddress, sender, recipient);
259
+ const [index] = await this.db.getTaggingSecretsIndexes([directionalSecret]);
260
+ return IndexedTaggingSecret.fromTaggingSecret(directionalSecret, index);
261
+ }
262
+
263
+ /**
264
+ * Increments the tagging secret for a given sender and recipient pair. For this to work, the ivpsk_m of the sender must be known.
265
+ * @param contractAddress - The contract address to silo the secret for
266
+ * @param sender - The address sending the note
267
+ * @param recipient - The address receiving the note
268
+ */
269
+ public async incrementAppTaggingSecret(
270
+ contractAddress: AztecAddress,
271
+ sender: AztecAddress,
272
+ recipient: AztecAddress,
273
+ ): Promise<void> {
274
+ const directionalSecret = await this.#calculateDirectionalSecret(contractAddress, sender, recipient);
275
+ await this.db.incrementTaggingSecretsIndexes([directionalSecret]);
276
+ }
277
+
278
+ async #calculateDirectionalSecret(contractAddress: AztecAddress, sender: AztecAddress, recipient: AztecAddress) {
246
279
  const senderCompleteAddress = await this.getCompleteAddress(sender);
247
280
  const senderIvsk = await this.keyStore.getMasterIncomingViewingSecretKey(sender);
248
281
  const sharedSecret = computeTaggingSecret(senderCompleteAddress, senderIvsk, recipient);
249
282
  // Silo the secret to the app so it can't be used to track other app's notes
250
- const secret = poseidon2Hash([sharedSecret.x, sharedSecret.y, contractAddress]);
251
- const [index] = await this.db.getTaggingSecretsIndexes([secret]);
252
- return new IndexedTaggingSecret(secret, index);
283
+ const siloedSecret = poseidon2Hash([sharedSecret.x, sharedSecret.y, contractAddress]);
284
+ // Get the index of the secret, ensuring the directionality (sender -> recipient)
285
+ const directionalSecret = new TaggingSecret(siloedSecret, recipient);
286
+ return directionalSecret;
253
287
  }
254
288
 
255
289
  /**
@@ -263,18 +297,63 @@ export class SimulatorOracle implements DBOracle {
263
297
  recipient: AztecAddress,
264
298
  ): Promise<IndexedTaggingSecret[]> {
265
299
  const recipientCompleteAddress = await this.getCompleteAddress(recipient);
266
- const completeAddresses = await this.db.getCompleteAddresses();
267
- // Filter out the addresses corresponding to accounts
268
- const accounts = await this.keyStore.getAccounts();
269
- const senders = completeAddresses.filter(
270
- completeAddress => !accounts.find(account => account.equals(completeAddress.address)),
271
- );
272
300
  const recipientIvsk = await this.keyStore.getMasterIncomingViewingSecretKey(recipient);
273
- const secrets = senders.map(({ address: sender }) => {
274
- const sharedSecret = computeTaggingSecret(recipientCompleteAddress, recipientIvsk, sender);
301
+
302
+ // We implicitly add the recipient as a contact, this helps us decrypt tags on notes that we send to ourselves (recipient = us, sender = us)
303
+ const contacts = [...this.db.getContactAddresses(), recipient];
304
+ const appTaggingSecrets = contacts.map(contact => {
305
+ const sharedSecret = computeTaggingSecret(recipientCompleteAddress, recipientIvsk, contact);
275
306
  return poseidon2Hash([sharedSecret.x, sharedSecret.y, contractAddress]);
276
307
  });
277
- const indexes = await this.db.getTaggingSecretsIndexes(secrets);
278
- return secrets.map((secret, i) => new IndexedTaggingSecret(secret, indexes[i]));
308
+ // Ensure the directionality (sender -> recipient)
309
+ const directionalSecrets = appTaggingSecrets.map(secret => new TaggingSecret(secret, recipient));
310
+ const indexes = await this.db.getTaggingSecretsIndexes(directionalSecrets);
311
+ return directionalSecrets.map((directionalSecret, i) =>
312
+ IndexedTaggingSecret.fromTaggingSecret(directionalSecret, indexes[i]),
313
+ );
314
+ }
315
+
316
+ /**
317
+ * Synchronizes the logs tagged with the recipient's address and all the senders in the addressbook.
318
+ * Returns the unsynched logs and updates the indexes of the secrets used to tag them until there are no more logs to sync.
319
+ * @param contractAddress - The address of the contract that the logs are tagged for
320
+ * @param recipient - The address of the recipient
321
+ * @returns A list of encrypted logs tagged with the recipient's address
322
+ */
323
+ public async syncTaggedLogs(contractAddress: AztecAddress, recipient: AztecAddress): Promise<EncryptedL2NoteLog[]> {
324
+ // Ideally this algorithm would be implemented in noir, exposing its building blocks as oracles.
325
+ // However it is impossible at the moment due to the language not supporting nested slices.
326
+ // This nesting is necessary because for a given set of tags we don't
327
+ // know how many logs we will get back. Furthermore, these logs are of undetermined
328
+ // length, since we don't really know the note they correspond to until we decrypt them.
329
+
330
+ // 1. Get all the secrets for the recipient and sender pairs (#9365)
331
+ let appTaggingSecrets = await this.getAppTaggingSecretsForSenders(contractAddress, recipient);
332
+
333
+ const logs: EncryptedL2NoteLog[] = [];
334
+ while (appTaggingSecrets.length > 0) {
335
+ // 2. Compute tags using the secrets, recipient and index. Obtain logs for each tag (#9380)
336
+ const currentTags = appTaggingSecrets.map(({ secret, recipient, index }) =>
337
+ poseidon2Hash([secret, recipient, index]),
338
+ );
339
+ const logsByTags = await this.aztecNode.getLogsByTags(currentTags);
340
+ const newTaggingSecrets: IndexedTaggingSecret[] = [];
341
+ logsByTags.forEach((logsByTag, index) => {
342
+ // 3.1. Append logs to the list and increment the index for the tags that have logs (#9380)
343
+ if (logsByTag.length > 0) {
344
+ logs.push(...logsByTag);
345
+ // 3.2. Increment the index for the tags that have logs (#9380)
346
+ newTaggingSecrets.push(
347
+ new IndexedTaggingSecret(appTaggingSecrets[index].secret, recipient, appTaggingSecrets[index].index + 1),
348
+ );
349
+ }
350
+ });
351
+ // 4. Consolidate in db and replace initial appTaggingSecrets with the new ones (updated indexes)
352
+ await this.db.incrementTaggingSecretsIndexes(
353
+ newTaggingSecrets.map(secret => new TaggingSecret(secret.secret, recipient)),
354
+ );
355
+ appTaggingSecrets = newTaggingSecrets;
356
+ }
357
+ return logs;
279
358
  }
280
359
  }
@@ -371,15 +371,15 @@ export class Synchronizer {
371
371
 
372
372
  async #removeNullifiedNotes(notes: IncomingNoteDao[]) {
373
373
  // now group the decoded incoming notes by public key
374
- const publicKeyToIncomingNotes: Map<PublicKey, IncomingNoteDao[]> = new Map();
374
+ const addressPointToIncomingNotes: Map<PublicKey, IncomingNoteDao[]> = new Map();
375
375
  for (const noteDao of notes) {
376
- const notesForPublicKey = publicKeyToIncomingNotes.get(noteDao.ivpkM) ?? [];
377
- notesForPublicKey.push(noteDao);
378
- publicKeyToIncomingNotes.set(noteDao.ivpkM, notesForPublicKey);
376
+ const notesForAddressPoint = addressPointToIncomingNotes.get(noteDao.addressPoint) ?? [];
377
+ notesForAddressPoint.push(noteDao);
378
+ addressPointToIncomingNotes.set(noteDao.addressPoint, notesForAddressPoint);
379
379
  }
380
380
 
381
381
  // now for each group, look for the nullifiers in the nullifier tree
382
- for (const [publicKey, notes] of publicKeyToIncomingNotes.entries()) {
382
+ for (const [publicKey, notes] of addressPointToIncomingNotes.entries()) {
383
383
  const nullifiers = notes.map(n => n.siloedNullifier);
384
384
  const relevantNullifiers: Fr[] = [];
385
385
  for (const nullifier of nullifiers) {