@aztec/pxe 0.80.0 → 0.81.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.
@@ -13,14 +13,14 @@ export class NoteDataProvider {
13
13
  #nullifiedNotesByContract;
14
14
  #nullifiedNotesByStorageSlot;
15
15
  #nullifiedNotesByTxHash;
16
- #nullifiedNotesByAddressPoint;
16
+ #nullifiedNotesByRecipient;
17
17
  #nullifiedNotesByNullifier;
18
18
  #scopes;
19
19
  #notesToScope;
20
20
  #notesByContractAndScope;
21
21
  #notesByStorageSlotAndScope;
22
22
  #notesByTxHashAndScope;
23
- #notesByAddressPointAndScope;
23
+ #notesByRecipientAndScope;
24
24
  constructor(store){
25
25
  this.#store = store;
26
26
  this.#notes = store.openMap('notes');
@@ -31,14 +31,14 @@ export class NoteDataProvider {
31
31
  this.#nullifiedNotesByContract = store.openMultiMap('nullified_notes_by_contract');
32
32
  this.#nullifiedNotesByStorageSlot = store.openMultiMap('nullified_notes_by_storage_slot');
33
33
  this.#nullifiedNotesByTxHash = store.openMultiMap('nullified_notes_by_tx_hash');
34
- this.#nullifiedNotesByAddressPoint = store.openMultiMap('nullified_notes_by_address_point');
34
+ this.#nullifiedNotesByRecipient = store.openMultiMap('nullified_notes_by_recipient');
35
35
  this.#nullifiedNotesByNullifier = store.openMap('nullified_notes_by_nullifier');
36
36
  this.#scopes = store.openMap('scopes');
37
37
  this.#notesToScope = store.openMultiMap('notes_to_scope');
38
38
  this.#notesByContractAndScope = new Map();
39
39
  this.#notesByStorageSlotAndScope = new Map();
40
40
  this.#notesByTxHashAndScope = new Map();
41
- this.#notesByAddressPointAndScope = new Map();
41
+ this.#notesByRecipientAndScope = new Map();
42
42
  }
43
43
  static async create(store) {
44
44
  const pxeDB = new NoteDataProvider(store);
@@ -46,7 +46,7 @@ export class NoteDataProvider {
46
46
  pxeDB.#notesByContractAndScope.set(scope, store.openMultiMap(`${scope}:notes_by_contract`));
47
47
  pxeDB.#notesByStorageSlotAndScope.set(scope, store.openMultiMap(`${scope}:notes_by_storage_slot`));
48
48
  pxeDB.#notesByTxHashAndScope.set(scope, store.openMultiMap(`${scope}:notes_by_tx_hash`));
49
- pxeDB.#notesByAddressPointAndScope.set(scope, store.openMultiMap(`${scope}:notes_by_address_point`));
49
+ pxeDB.#notesByRecipientAndScope.set(scope, store.openMultiMap(`${scope}:notes_by_recipient`));
50
50
  }
51
51
  return pxeDB;
52
52
  }
@@ -59,7 +59,7 @@ export class NoteDataProvider {
59
59
  this.#notesByContractAndScope.set(scopeString, this.#store.openMultiMap(`${scopeString}:notes_by_contract`));
60
60
  this.#notesByStorageSlotAndScope.set(scopeString, this.#store.openMultiMap(`${scopeString}:notes_by_storage_slot`));
61
61
  this.#notesByTxHashAndScope.set(scopeString, this.#store.openMultiMap(`${scopeString}:notes_by_tx_hash`));
62
- this.#notesByAddressPointAndScope.set(scopeString, this.#store.openMultiMap(`${scopeString}:notes_by_address_point`));
62
+ this.#notesByRecipientAndScope.set(scopeString, this.#store.openMultiMap(`${scopeString}:notes_by_recipient`));
63
63
  return true;
64
64
  }
65
65
  async addNotes(notes, scope = AztecAddress.ZERO) {
@@ -79,7 +79,7 @@ export class NoteDataProvider {
79
79
  await this.#notesByContractAndScope.get(scope.toString()).set(dao.contractAddress.toString(), noteIndex);
80
80
  await this.#notesByStorageSlotAndScope.get(scope.toString()).set(dao.storageSlot.toString(), noteIndex);
81
81
  await this.#notesByTxHashAndScope.get(scope.toString()).set(dao.txHash.toString(), noteIndex);
82
- await this.#notesByAddressPointAndScope.get(scope.toString()).set(dao.addressPoint.toString(), noteIndex);
82
+ await this.#notesByRecipientAndScope.get(scope.toString()).set(dao.recipient.toString(), noteIndex);
83
83
  }
84
84
  });
85
85
  }
@@ -95,7 +95,7 @@ export class NoteDataProvider {
95
95
  await this.#nullifierToNoteId.delete(noteDao.siloedNullifier.toString());
96
96
  const scopes = await toArray(this.#scopes.keysAsync());
97
97
  for (const scope of scopes){
98
- await this.#notesByAddressPointAndScope.get(scope).deleteValue(noteDao.addressPoint.toString(), noteIndex);
98
+ await this.#notesByRecipientAndScope.get(scope).deleteValue(noteDao.recipient.toString(), noteIndex);
99
99
  await this.#notesByTxHashAndScope.get(scope).deleteValue(noteDao.txHash.toString(), noteIndex);
100
100
  await this.#notesByContractAndScope.get(scope).deleteValue(noteDao.contractAddress.toString(), noteIndex);
101
101
  await this.#notesByStorageSlotAndScope.get(scope).deleteValue(noteDao.storageSlot.toString(), noteIndex);
@@ -123,14 +123,14 @@ export class NoteDataProvider {
123
123
  let scopes = await toArray(this.#nullifiedNotesToScope.getValuesAsync(noteIndex)) ?? [];
124
124
  if (scopes.length === 0) {
125
125
  scopes = [
126
- new AztecAddress(dao.addressPoint.x).toString()
126
+ dao.recipient.toString()
127
127
  ];
128
128
  }
129
129
  for (const scope of scopes){
130
130
  await this.#notesByContractAndScope.get(scope.toString()).set(dao.contractAddress.toString(), noteIndex);
131
131
  await this.#notesByStorageSlotAndScope.get(scope.toString()).set(dao.storageSlot.toString(), noteIndex);
132
132
  await this.#notesByTxHashAndScope.get(scope.toString()).set(dao.txHash.toString(), noteIndex);
133
- await this.#notesByAddressPointAndScope.get(scope.toString()).set(dao.addressPoint.toString(), noteIndex);
133
+ await this.#notesByRecipientAndScope.get(scope.toString()).set(dao.recipient.toString(), noteIndex);
134
134
  await this.#notesToScope.set(noteIndex, scope);
135
135
  }
136
136
  await this.#nullifiedNotes.delete(noteIndex);
@@ -139,13 +139,12 @@ export class NoteDataProvider {
139
139
  await this.#nullifiedNotesByContract.deleteValue(dao.contractAddress.toString(), noteIndex);
140
140
  await this.#nullifiedNotesByStorageSlot.deleteValue(dao.storageSlot.toString(), noteIndex);
141
141
  await this.#nullifiedNotesByTxHash.deleteValue(dao.txHash.toString(), noteIndex);
142
- await this.#nullifiedNotesByAddressPoint.deleteValue(dao.addressPoint.toString(), noteIndex);
142
+ await this.#nullifiedNotesByRecipient.deleteValue(dao.recipient.toString(), noteIndex);
143
143
  await this.#nullifiedNotesByNullifier.delete(dao.siloedNullifier.toString());
144
144
  }
145
145
  });
146
146
  }
147
147
  async getNotes(filter) {
148
- const publicKey = filter.owner ? await filter.owner.toAddressPoint() : undefined;
149
148
  filter.status = filter.status ?? NoteStatus.ACTIVE;
150
149
  const candidateNoteSources = [];
151
150
  filter.scopes ??= (await toArray(this.#scopes.keysAsync())).map((addressString)=>AztecAddress.fromString(addressString));
@@ -155,7 +154,7 @@ export class NoteDataProvider {
155
154
  if (!await this.#scopes.hasAsync(formattedScopeString)) {
156
155
  throw new Error('Trying to get incoming notes of an scope that is not in the PXE database');
157
156
  }
158
- activeNoteIdsPerScope.push(publicKey ? await toArray(this.#notesByAddressPointAndScope.get(formattedScopeString).getValuesAsync(publicKey.toString())) : filter.txHash ? await toArray(this.#notesByTxHashAndScope.get(formattedScopeString).getValuesAsync(filter.txHash.toString())) : filter.contractAddress ? await toArray(this.#notesByContractAndScope.get(formattedScopeString).getValuesAsync(filter.contractAddress.toString())) : filter.storageSlot ? await toArray(this.#notesByStorageSlotAndScope.get(formattedScopeString).getValuesAsync(filter.storageSlot.toString())) : await toArray(this.#notesByAddressPointAndScope.get(formattedScopeString).valuesAsync()));
157
+ activeNoteIdsPerScope.push(filter.recipient ? await toArray(this.#notesByRecipientAndScope.get(formattedScopeString).getValuesAsync(filter.recipient.toString())) : filter.txHash ? await toArray(this.#notesByTxHashAndScope.get(formattedScopeString).getValuesAsync(filter.txHash.toString())) : filter.contractAddress ? await toArray(this.#notesByContractAndScope.get(formattedScopeString).getValuesAsync(filter.contractAddress.toString())) : filter.storageSlot ? await toArray(this.#notesByStorageSlotAndScope.get(formattedScopeString).getValuesAsync(filter.storageSlot.toString())) : await toArray(this.#notesByRecipientAndScope.get(formattedScopeString).valuesAsync()));
159
158
  }
160
159
  candidateNoteSources.push({
161
160
  ids: new Set(activeNoteIdsPerScope.flat()),
@@ -163,7 +162,7 @@ export class NoteDataProvider {
163
162
  });
164
163
  if (filter.status == NoteStatus.ACTIVE_OR_NULLIFIED) {
165
164
  candidateNoteSources.push({
166
- ids: publicKey ? await toArray(this.#nullifiedNotesByAddressPoint.getValuesAsync(publicKey.toString())) : filter.txHash ? await toArray(this.#nullifiedNotesByTxHash.getValuesAsync(filter.txHash.toString())) : filter.contractAddress ? await toArray(this.#nullifiedNotesByContract.getValuesAsync(filter.contractAddress.toString())) : filter.storageSlot ? await toArray(this.#nullifiedNotesByStorageSlot.getValuesAsync(filter.storageSlot.toString())) : await toArray(this.#nullifiedNotes.keysAsync()),
165
+ ids: filter.recipient ? await toArray(this.#nullifiedNotesByRecipient.getValuesAsync(filter.recipient.toString())) : filter.txHash ? await toArray(this.#nullifiedNotesByTxHash.getValuesAsync(filter.txHash.toString())) : filter.contractAddress ? await toArray(this.#nullifiedNotesByContract.getValuesAsync(filter.contractAddress.toString())) : filter.storageSlot ? await toArray(this.#nullifiedNotesByStorageSlot.getValuesAsync(filter.storageSlot.toString())) : await toArray(this.#nullifiedNotes.keysAsync()),
167
166
  notes: this.#nullifiedNotes
168
167
  });
169
168
  }
@@ -184,7 +183,7 @@ export class NoteDataProvider {
184
183
  if (filter.storageSlot && !note.storageSlot.equals(filter.storageSlot)) {
185
184
  continue;
186
185
  }
187
- if (publicKey && !note.addressPoint.equals(publicKey)) {
186
+ if (filter.recipient && !note.recipient.equals(filter.recipient)) {
188
187
  continue;
189
188
  }
190
189
  if (filter.siloedNullifier && !note.siloedNullifier.equals(filter.siloedNullifier)) {
@@ -195,7 +194,7 @@ export class NoteDataProvider {
195
194
  }
196
195
  return result;
197
196
  }
198
- removeNullifiedNotes(nullifiers, accountAddressPoint) {
197
+ removeNullifiedNotes(nullifiers, recipient) {
199
198
  if (nullifiers.length === 0) {
200
199
  return Promise.resolve([]);
201
200
  }
@@ -213,7 +212,7 @@ export class NoteDataProvider {
213
212
  }
214
213
  const noteScopes = await toArray(this.#notesToScope.getValuesAsync(noteIndex)) ?? [];
215
214
  const note = NoteDao.fromBuffer(noteBuffer);
216
- if (!note.addressPoint.equals(accountAddressPoint)) {
215
+ if (!note.recipient.equals(recipient)) {
217
216
  continue;
218
217
  }
219
218
  nullifiedNotes.push(note);
@@ -221,7 +220,7 @@ export class NoteDataProvider {
221
220
  await this.#notesToScope.delete(noteIndex);
222
221
  const scopes = await toArray(this.#scopes.keysAsync());
223
222
  for (const scope of scopes){
224
- await this.#notesByAddressPointAndScope.get(scope).deleteValue(accountAddressPoint.toString(), noteIndex);
223
+ await this.#notesByRecipientAndScope.get(scope).deleteValue(note.recipient.toString(), noteIndex);
225
224
  await this.#notesByTxHashAndScope.get(scope).deleteValue(note.txHash.toString(), noteIndex);
226
225
  await this.#notesByContractAndScope.get(scope).deleteValue(note.contractAddress.toString(), noteIndex);
227
226
  await this.#notesByStorageSlotAndScope.get(scope).deleteValue(note.storageSlot.toString(), noteIndex);
@@ -236,7 +235,7 @@ export class NoteDataProvider {
236
235
  await this.#nullifiedNotesByContract.set(note.contractAddress.toString(), noteIndex);
237
236
  await this.#nullifiedNotesByStorageSlot.set(note.storageSlot.toString(), noteIndex);
238
237
  await this.#nullifiedNotesByTxHash.set(note.txHash.toString(), noteIndex);
239
- await this.#nullifiedNotesByAddressPoint.set(note.addressPoint.toString(), noteIndex);
238
+ await this.#nullifiedNotesByRecipient.set(note.recipient.toString(), noteIndex);
240
239
  await this.#nullifiedNotesByNullifier.set(nullifier.toString(), noteIndex);
241
240
  await this.#nullifierToNoteId.delete(nullifier.toString());
242
241
  }
@@ -36,7 +36,7 @@ import { L2BlockStream } from '@aztec/stdlib/block';
36
36
  switch(event.type){
37
37
  case 'blocks-added':
38
38
  {
39
- const lastBlock = event.blocks.at(-1);
39
+ const lastBlock = event.blocks.at(-1).block;
40
40
  this.log.verbose(`Updated pxe last block to ${lastBlock.number}`, {
41
41
  blockHash: lastBlock.hash(),
42
42
  archive: lastBlock.archive.root.toString(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/pxe",
3
- "version": "0.80.0",
3
+ "version": "0.81.0",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  "./server": "./dest/entrypoints/server/index.js",
@@ -59,19 +59,19 @@
59
59
  ]
60
60
  },
61
61
  "dependencies": {
62
- "@aztec/bb-prover": "0.80.0",
63
- "@aztec/bb.js": "0.80.0",
64
- "@aztec/builder": "0.80.0",
65
- "@aztec/constants": "0.80.0",
66
- "@aztec/ethereum": "0.80.0",
67
- "@aztec/foundation": "0.80.0",
68
- "@aztec/key-store": "0.80.0",
69
- "@aztec/kv-store": "0.80.0",
70
- "@aztec/noir-protocol-circuits-types": "0.80.0",
71
- "@aztec/noir-types": "0.80.0",
72
- "@aztec/protocol-contracts": "0.80.0",
73
- "@aztec/simulator": "0.80.0",
74
- "@aztec/stdlib": "0.80.0",
62
+ "@aztec/bb-prover": "0.81.0",
63
+ "@aztec/bb.js": "0.81.0",
64
+ "@aztec/builder": "0.81.0",
65
+ "@aztec/constants": "0.81.0",
66
+ "@aztec/ethereum": "0.81.0",
67
+ "@aztec/foundation": "0.81.0",
68
+ "@aztec/key-store": "0.81.0",
69
+ "@aztec/kv-store": "0.81.0",
70
+ "@aztec/noir-protocol-circuits-types": "0.81.0",
71
+ "@aztec/noir-types": "0.81.0",
72
+ "@aztec/protocol-contracts": "0.81.0",
73
+ "@aztec/simulator": "0.81.0",
74
+ "@aztec/stdlib": "0.81.0",
75
75
  "@msgpack/msgpack": "^3.0.0-beta2",
76
76
  "koa": "^2.14.2",
77
77
  "koa-router": "^12.0.0",
@@ -81,7 +81,7 @@
81
81
  "viem": "2.23.7"
82
82
  },
83
83
  "devDependencies": {
84
- "@aztec/noir-contracts.js": "0.80.0",
84
+ "@aztec/noir-contracts.js": "0.81.0",
85
85
  "@jest/globals": "^29.5.0",
86
86
  "@types/jest": "^29.5.0",
87
87
  "@types/lodash.omit": "^4.5.7",
@@ -1,48 +1,37 @@
1
- import {
2
- type L1_TO_L2_MSG_TREE_HEIGHT,
3
- MAX_NOTE_HASHES_PER_TX,
4
- PRIVATE_LOG_SIZE_IN_FIELDS,
5
- PUBLIC_LOG_DATA_SIZE_IN_FIELDS,
6
- } from '@aztec/constants';
1
+ import { type L1_TO_L2_MSG_TREE_HEIGHT, MAX_NOTE_HASHES_PER_TX, PRIVATE_LOG_SIZE_IN_FIELDS } from '@aztec/constants';
7
2
  import { timesParallel } from '@aztec/foundation/collection';
8
3
  import { poseidon2Hash } from '@aztec/foundation/crypto';
9
- import { Fr } from '@aztec/foundation/fields';
4
+ import { Fr, Point } from '@aztec/foundation/fields';
10
5
  import { createLogger } from '@aztec/foundation/log';
11
- import { BufferReader } from '@aztec/foundation/serialize';
12
6
  import type { KeyStore } from '@aztec/key-store';
13
- import { AcirSimulator, type ExecutionDataProvider, type SimulationProvider } from '@aztec/simulator/client';
14
- import { MessageLoadOracleInputs } from '@aztec/simulator/client';
7
+ import {
8
+ AcirSimulator,
9
+ type ExecutionDataProvider,
10
+ MessageLoadOracleInputs,
11
+ type SimulationProvider,
12
+ } from '@aztec/simulator/client';
15
13
  import {
16
14
  type FunctionArtifact,
17
15
  FunctionCall,
18
16
  FunctionSelector,
19
17
  FunctionType,
20
- NoteSelector,
21
18
  encodeArguments,
22
19
  getFunctionArtifact,
23
20
  } from '@aztec/stdlib/abi';
24
- import type { AztecAddress } from '@aztec/stdlib/aztec-address';
21
+ import { AztecAddress } from '@aztec/stdlib/aztec-address';
25
22
  import type { InBlock, L2Block, L2BlockNumber } from '@aztec/stdlib/block';
26
23
  import type { CompleteAddress, ContractInstance } from '@aztec/stdlib/contract';
27
24
  import { computeUniqueNoteHash, siloNoteHash, siloNullifier } from '@aztec/stdlib/hash';
28
25
  import type { AztecNode } from '@aztec/stdlib/interfaces/client';
29
26
  import type { KeyValidationRequest } from '@aztec/stdlib/kernel';
30
27
  import { computeAddressSecret, computeTaggingSecretPoint } from '@aztec/stdlib/keys';
31
- import {
32
- IndexedTaggingSecret,
33
- L1NotePayload,
34
- LogWithTxData,
35
- PrivateLog,
36
- PublicLog,
37
- TxScopedL2Log,
38
- } from '@aztec/stdlib/logs';
28
+ import { IndexedTaggingSecret, LogWithTxData, TxScopedL2Log, deriveEcdhSharedSecret } from '@aztec/stdlib/logs';
39
29
  import { getNonNullifiedL1ToL2MessageWitness } from '@aztec/stdlib/messaging';
40
30
  import { Note, type NoteStatus } from '@aztec/stdlib/note';
41
31
  import { MerkleTreeId, type NullifierMembershipWitness, PublicDataWitness } from '@aztec/stdlib/trees';
42
32
  import type { BlockHeader } from '@aztec/stdlib/tx';
43
33
  import { TxHash } from '@aztec/stdlib/tx';
44
34
 
45
- import { getOrderedNoteItems } from '../note_decryption_utils/add_public_values_to_payload.js';
46
35
  import type { AddressDataProvider } from '../storage/address_data_provider/address_data_provider.js';
47
36
  import type { AuthWitnessDataProvider } from '../storage/auth_witness_data_provider/auth_witness_data_provider.js';
48
37
  import type { CapsuleDataProvider } from '../storage/capsule_data_provider/capsule_data_provider.js';
@@ -470,7 +459,7 @@ export class PXEOracleInterface implements ExecutionDataProvider {
470
459
  const recipients = scopes ? scopes : await this.keyStore.getAccounts();
471
460
  // A map of logs going from recipient address to logs. Note that the logs might have been processed before
472
461
  // due to us having a sliding window that "looks back" for logs as well. (We look back as there is no guarantee
473
- // that a logs will be received ordered by a given tax index and that the tags won't be reused).
462
+ // that a logs will be received ordered by a given tag index and that the tags won't be reused).
474
463
  const logsMap = new Map<string, TxScopedL2Log[]>();
475
464
  const contractName = await this.contractDataProvider.getDebugContractName(contractAddress);
476
465
  for (const recipient of recipients) {
@@ -516,31 +505,21 @@ export class PXEOracleInterface implements ExecutionDataProvider {
516
505
 
517
506
  logsByTags.forEach((logsByTag, logIndex) => {
518
507
  if (logsByTag.length > 0) {
519
- // Check that public logs have the correct contract address
520
- const checkedLogsbyTag = logsByTag.filter(
521
- l => !l.isFromPublic || PublicLog.fromBuffer(l.logData).contractAddress.equals(contractAddress),
522
- );
523
- if (checkedLogsbyTag.length < logsByTag.length) {
524
- const discarded = logsByTag.filter(
525
- log => checkedLogsbyTag.find(filteredLog => filteredLog.equals(log)) === undefined,
526
- );
527
- this.log.warn(
528
- `Discarded ${
529
- logsByTag.length - checkedLogsbyTag.length
530
- } public logs with mismatched contract address ${contractAddress}:`,
531
- discarded.map(l => PublicLog.fromBuffer(l.logData)),
532
- );
508
+ // Discard public logs
509
+ const filteredLogsByTag = logsByTag.filter(l => !l.isFromPublic);
510
+ if (filteredLogsByTag.length < logsByTag.length) {
511
+ this.log.warn(`Discarded ${logsByTag.filter(l => l.isFromPublic).length} public logs with matching tags`);
533
512
  }
534
513
 
535
514
  // The logs for the given tag exist so we store them for later processing
536
- logsForRecipient.push(...checkedLogsbyTag);
515
+ logsForRecipient.push(...filteredLogsByTag);
537
516
 
538
517
  // We retrieve the indexed tagging secret corresponding to the log as I need that to evaluate whether
539
518
  // a new largest index have been found.
540
519
  const secretCorrespondingToLog = secretsForTheWholeWindow[logIndex];
541
520
  const initialIndex = initialIndexesMap[secretCorrespondingToLog.appTaggingSecret.toString()];
542
521
 
543
- this.log.debug(`Found ${checkedLogsbyTag.length} logs as recipient ${recipient}`, {
522
+ this.log.debug(`Found ${filteredLogsByTag.length} logs as recipient ${recipient}`, {
544
523
  recipient,
545
524
  secret: secretCorrespondingToLog.appTaggingSecret,
546
525
  contractName,
@@ -610,77 +589,36 @@ export class PXEOracleInterface implements ExecutionDataProvider {
610
589
  return logsMap;
611
590
  }
612
591
 
613
- /**
614
- * Decrypts logs tagged for a recipient and returns them.
615
- * @param scopedLogs - The logs to decrypt.
616
- * @param recipient - The recipient of the logs.
617
- * @returns The decrypted notes.
618
- */
619
- async #decryptTaggedLogs(scopedLogs: TxScopedL2Log[], recipient: AztecAddress) {
620
- const recipientCompleteAddress = await this.getCompleteAddress(recipient);
621
- const ivskM = await this.keyStore.getMasterSecretKey(
622
- recipientCompleteAddress.publicKeys.masterIncomingViewingPublicKey,
623
- );
624
- const addressSecret = await computeAddressSecret(await recipientCompleteAddress.getPreaddress(), ivskM);
625
-
626
- // Since we could have notes with the same index for different txs, we need
627
- // to keep track of them scoping by txHash
628
- const excludedIndices: Map<string, Set<number>> = new Map();
629
- const decrypted = [];
630
-
631
- for (const scopedLog of scopedLogs) {
632
- const payload = scopedLog.isFromPublic
633
- ? await L1NotePayload.decryptAsIncomingFromPublic(PublicLog.fromBuffer(scopedLog.logData), addressSecret)
634
- : await L1NotePayload.decryptAsIncoming(PrivateLog.fromBuffer(scopedLog.logData), addressSecret);
635
-
636
- if (!payload) {
637
- this.log.verbose('Unable to decrypt log');
638
- continue;
639
- }
640
-
641
- if (!excludedIndices.has(scopedLog.txHash.toString())) {
642
- excludedIndices.set(scopedLog.txHash.toString(), new Set());
643
- }
644
-
645
- const note = await getOrderedNoteItems(this.contractDataProvider, payload);
646
- const plaintext = [payload.storageSlot, payload.noteTypeId.toField(), ...note.items];
647
-
648
- decrypted.push({ plaintext, txHash: scopedLog.txHash, contractAddress: payload.contractAddress });
649
- }
650
-
651
- return decrypted;
652
- }
653
-
654
592
  /**
655
593
  * Processes the tagged logs returned by syncTaggedLogs by decrypting them and storing them in the database.
594
+ * @param contractAddress - The address of the contract that the logs are tagged for.
656
595
  * @param logs - The logs to process.
657
596
  * @param recipient - The recipient of the logs.
658
597
  */
659
598
  public async processTaggedLogs(
599
+ contractAddress: AztecAddress,
660
600
  logs: TxScopedL2Log[],
661
601
  recipient: AztecAddress,
662
602
  simulator?: AcirSimulator,
663
603
  ): Promise<void> {
664
- const decryptedLogs = await this.#decryptTaggedLogs(logs, recipient);
604
+ for (const scopedLog of logs) {
605
+ if (scopedLog.isFromPublic) {
606
+ throw new Error('Attempted to decrypt public log');
607
+ }
665
608
 
666
- // We've produced the full NoteDao, which we'd be able to simply insert into the database. However, this is
667
- // only a temporary measure as we migrate from the PXE-driven discovery into the new contract-driven approach. We
668
- // discard most of the work done up to this point and reconstruct the note plaintext to then hand over to the
669
- // contract for further processing.
670
- for (const decryptedLog of decryptedLogs) {
671
609
  // Log processing requires the note hashes in the tx in which the note was created. We are now assuming that the
672
610
  // note was included in the same block in which the log was delivered - note that partial notes will not work this
673
611
  // way.
674
- const txEffect = await this.aztecNode.getTxEffect(decryptedLog.txHash);
612
+ const txEffect = await this.aztecNode.getTxEffect(scopedLog.txHash);
675
613
  if (!txEffect) {
676
- throw new Error(`Could not find tx effect for tx hash ${decryptedLog.txHash}`);
614
+ throw new Error(`Could not find tx effect for tx hash ${scopedLog.txHash}`);
677
615
  }
678
616
 
679
617
  // This will trigger calls to the deliverNote oracle
680
618
  await this.callProcessLog(
681
- decryptedLog.contractAddress,
682
- decryptedLog.plaintext,
683
- decryptedLog.txHash,
619
+ contractAddress,
620
+ scopedLog.log.toFields(),
621
+ scopedLog.txHash,
684
622
  txEffect.data.noteHashes,
685
623
  txEffect.data.nullifiers[0],
686
624
  recipient,
@@ -749,8 +687,6 @@ export class PXEOracleInterface implements ExecutionDataProvider {
749
687
  throw new Error(`Failed to fetch tx receipt for tx hash ${txHash} when searching for note hashes`);
750
688
  }
751
689
 
752
- // TODO(#12549): does it make sense to store the recipient's address point instead of just its address?
753
- const recipientAddressPoint = await recipient.toAddressPoint();
754
690
  const noteDao = new NoteDao(
755
691
  new Note(content),
756
692
  contractAddress,
@@ -762,8 +698,7 @@ export class PXEOracleInterface implements ExecutionDataProvider {
762
698
  txReceipt.blockNumber!,
763
699
  txReceipt.blockHash!.toString(),
764
700
  uniqueNoteHashTreeIndex,
765
- recipientAddressPoint,
766
- NoteSelector.empty(), // TODO(#12013): remove
701
+ recipient,
767
702
  );
768
703
 
769
704
  await this.noteDataProvider.addNotes([noteDao], recipient);
@@ -777,10 +712,7 @@ export class PXEOracleInterface implements ExecutionDataProvider {
777
712
  const [nullifierIndex] = await this.aztecNode.findNullifiersIndexesWithBlock(syncedBlockNumber, [siloedNullifier]);
778
713
  if (nullifierIndex !== undefined) {
779
714
  const { data: _, ...blockHashAndNum } = nullifierIndex;
780
- await this.noteDataProvider.removeNullifiedNotes(
781
- [{ data: siloedNullifier, ...blockHashAndNum }],
782
- recipientAddressPoint,
783
- );
715
+ await this.noteDataProvider.removeNullifiedNotes([{ data: siloedNullifier, ...blockHashAndNum }], recipient);
784
716
 
785
717
  this.log.verbose(`Removed just-added note`, {
786
718
  contract: contractAddress,
@@ -806,33 +738,33 @@ export class PXEOracleInterface implements ExecutionDataProvider {
806
738
  );
807
739
  }
808
740
 
809
- const log = logsForTag[0];
741
+ const scopedLog = logsForTag[0];
810
742
 
811
743
  // getLogsByTag doesn't have all of the information that we need (notably note hashes and the first nullifier), so
812
744
  // we need to make a second call to the node for `getTxEffect`.
813
745
  // TODO(#9789): bundle this information in the `getLogsByTag` call.
814
- const txEffect = await this.aztecNode.getTxEffect(log.txHash);
746
+ const txEffect = await this.aztecNode.getTxEffect(scopedLog.txHash);
815
747
  if (txEffect == undefined) {
816
- throw new Error(`Unexpected: failed to retrieve tx effects for tx ${log.txHash} which is known to exist`);
748
+ throw new Error(`Unexpected: failed to retrieve tx effects for tx ${scopedLog.txHash} which is known to exist`);
817
749
  }
818
750
 
819
- const reader = BufferReader.asReader(log.logData);
820
- const logArray = reader.readArray(PUBLIC_LOG_DATA_SIZE_IN_FIELDS, Fr);
821
-
822
751
  // Public logs always take up all available fields by padding with zeroes, and the length of the originally emitted
823
752
  // log is lost. Until this is improved, we simply remove all of the zero elements (which are expected to be at the
824
753
  // end).
825
754
  // TODO(#11636): use the actual log length.
826
- const trimmedLog = logArray.filter(x => !x.isZero());
755
+ const trimmedLog = scopedLog.log.toFields().filter(x => !x.isZero());
827
756
 
828
- return new LogWithTxData(trimmedLog, log.txHash.hash, txEffect.data.noteHashes, txEffect.data.nullifiers[0]);
757
+ return new LogWithTxData(trimmedLog, scopedLog.txHash.hash, txEffect.data.noteHashes, txEffect.data.nullifiers[0]);
829
758
  }
830
759
 
760
+ // TODO(#12553): nuke this as part of tackling that issue. This function is no longer unit tested as I had to remove
761
+ // it from pxe_oracle_interface.test.ts when moving decryption to Noir (at that point we could not get a hold of
762
+ // the decrypted note in the test as TS decryption no longer existed).
831
763
  public async removeNullifiedNotes(contractAddress: AztecAddress) {
832
764
  this.log.verbose('Searching for nullifiers of known notes', { contract: contractAddress });
833
765
 
834
766
  for (const recipient of await this.keyStore.getAccounts()) {
835
- const currentNotesForRecipient = await this.noteDataProvider.getNotes({ contractAddress, owner: recipient });
767
+ const currentNotesForRecipient = await this.noteDataProvider.getNotes({ contractAddress, recipient });
836
768
  const nullifiersToCheck = currentNotesForRecipient.map(note => note.siloedNullifier);
837
769
  const nullifierIndexes = await this.aztecNode.findNullifiersIndexesWithBlock('latest', nullifiersToCheck);
838
770
 
@@ -844,10 +776,7 @@ export class PXEOracleInterface implements ExecutionDataProvider {
844
776
  })
845
777
  .filter(nullifier => nullifier !== undefined) as InBlock<Fr>[];
846
778
 
847
- const nullifiedNotes = await this.noteDataProvider.removeNullifiedNotes(
848
- foundNullifiers,
849
- await recipient.toAddressPoint(),
850
- );
779
+ const nullifiedNotes = await this.noteDataProvider.removeNullifiedNotes(foundNullifiers, recipient);
851
780
  nullifiedNotes.forEach(noteDao => {
852
781
  this.log.verbose(`Removed note for contract ${noteDao.contractAddress} at slot ${noteDao.storageSlot}`, {
853
782
  contract: noteDao.contractAddress,
@@ -860,7 +789,7 @@ export class PXEOracleInterface implements ExecutionDataProvider {
860
789
 
861
790
  async callProcessLog(
862
791
  contractAddress: AztecAddress,
863
- logPlaintext: Fr[],
792
+ logCiphertext: Fr[],
864
793
  txHash: TxHash,
865
794
  noteHashes: Fr[],
866
795
  firstNullifier: Fr,
@@ -885,7 +814,7 @@ export class PXEOracleInterface implements ExecutionDataProvider {
885
814
  type: FunctionType.UNCONSTRAINED,
886
815
  isStatic: artifact.isStatic,
887
816
  args: encodeArguments(artifact, [
888
- toBoundedVec(logPlaintext, PRIVATE_LOG_SIZE_IN_FIELDS),
817
+ toBoundedVec(logCiphertext, PRIVATE_LOG_SIZE_IN_FIELDS),
889
818
  txHash.toString(),
890
819
  toBoundedVec(noteHashes, MAX_NOTE_HASHES_PER_TX),
891
820
  firstNullifier,
@@ -917,6 +846,16 @@ export class PXEOracleInterface implements ExecutionDataProvider {
917
846
  copyCapsule(contractAddress: AztecAddress, srcSlot: Fr, dstSlot: Fr, numEntries: number): Promise<void> {
918
847
  return this.capsuleDataProvider.copyCapsule(contractAddress, srcSlot, dstSlot, numEntries);
919
848
  }
849
+
850
+ async getSharedSecret(address: AztecAddress, ephPk: Point): Promise<Point> {
851
+ // TODO(#12656): return an app-siloed secret
852
+ const recipientCompleteAddress = await this.getCompleteAddress(address);
853
+ const ivskM = await this.keyStore.getMasterSecretKey(
854
+ recipientCompleteAddress.publicKeys.masterIncomingViewingPublicKey,
855
+ );
856
+ const addressSecret = await computeAddressSecret(await recipientCompleteAddress.getPreaddress(), ivskM);
857
+ return deriveEcdhSharedSecret(addressSecret, ephPk);
858
+ }
920
859
  }
921
860
 
922
861
  function toBoundedVec(array: Fr[], maxLength: number) {
@@ -32,8 +32,9 @@ import {
32
32
  type ContractInstanceWithAddress,
33
33
  type NodeInfo,
34
34
  type PartialAddress,
35
+ computeContractAddressFromInstance,
36
+ getContractClassFromArtifact,
35
37
  } from '@aztec/stdlib/contract';
36
- import { computeContractAddressFromInstance, getContractClassFromArtifact } from '@aztec/stdlib/contract';
37
38
  import { SimulationError } from '@aztec/stdlib/errors';
38
39
  import { EventMetadata, L1EventPayload } from '@aztec/stdlib/event';
39
40
  import type { GasFees } from '@aztec/stdlib/gas';
@@ -436,27 +437,19 @@ export class PXEService implements PXE {
436
437
  const noteDaos = await this.noteDataProvider.getNotes(filter);
437
438
 
438
439
  const extendedNotes = noteDaos.map(async dao => {
439
- let owner = filter.owner;
440
- if (owner === undefined) {
440
+ let recipient = filter.recipient;
441
+ if (recipient === undefined) {
441
442
  const completeAddresses = await this.addressDataProvider.getCompleteAddresses();
442
- const completeAddressIndex = (
443
- await Promise.all(completeAddresses.map(completeAddresses => completeAddresses.address.toAddressPoint()))
444
- ).findIndex(addressPoint => addressPoint.equals(dao.addressPoint));
443
+ const completeAddressIndex = completeAddresses.findIndex(completeAddress =>
444
+ completeAddress.address.equals(dao.recipient),
445
+ );
445
446
  const completeAddress = completeAddresses[completeAddressIndex];
446
447
  if (completeAddress === undefined) {
447
- throw new Error(`Cannot find complete address for addressPoint ${dao.addressPoint.toString()}`);
448
+ throw new Error(`Cannot find complete address for recipient ${dao.recipient.toString()}`);
448
449
  }
449
- owner = completeAddress.address;
450
+ recipient = completeAddress.address;
450
451
  }
451
- return new UniqueNote(
452
- dao.note,
453
- owner,
454
- dao.contractAddress,
455
- dao.storageSlot,
456
- dao.noteTypeId,
457
- dao.txHash,
458
- dao.nonce,
459
- );
452
+ return new UniqueNote(dao.note, recipient, dao.contractAddress, dao.storageSlot, dao.txHash, dao.nonce);
460
453
  });
461
454
  return Promise.all(extendedNotes);
462
455
  }