@aztec/pxe 1.2.1 → 2.0.0-nightly.20250813

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 (88) hide show
  1. package/dest/config/package_info.js +1 -1
  2. package/dest/contract_function_simulator/contract_function_simulator.d.ts +5 -2
  3. package/dest/contract_function_simulator/contract_function_simulator.d.ts.map +1 -1
  4. package/dest/contract_function_simulator/contract_function_simulator.js +48 -29
  5. package/dest/contract_function_simulator/index.d.ts +1 -0
  6. package/dest/contract_function_simulator/index.d.ts.map +1 -1
  7. package/dest/contract_function_simulator/index.js +1 -0
  8. package/dest/contract_function_simulator/noir-structs/event_validation_request.d.ts +1 -1
  9. package/dest/contract_function_simulator/noir-structs/event_validation_request.js +1 -1
  10. package/dest/contract_function_simulator/noir-structs/log_retrieval_request.d.ts +1 -1
  11. package/dest/contract_function_simulator/noir-structs/log_retrieval_request.js +1 -1
  12. package/dest/contract_function_simulator/noir-structs/log_retrieval_response.d.ts +1 -1
  13. package/dest/contract_function_simulator/noir-structs/log_retrieval_response.js +1 -1
  14. package/dest/contract_function_simulator/noir-structs/note_validation_request.d.ts +1 -1
  15. package/dest/contract_function_simulator/noir-structs/note_validation_request.js +1 -1
  16. package/dest/contract_function_simulator/oracle/note_packing_utils.d.ts +22 -0
  17. package/dest/contract_function_simulator/oracle/note_packing_utils.d.ts.map +1 -0
  18. package/dest/contract_function_simulator/oracle/note_packing_utils.js +49 -0
  19. package/dest/contract_function_simulator/oracle/oracle.d.ts +44 -43
  20. package/dest/contract_function_simulator/oracle/oracle.d.ts.map +1 -1
  21. package/dest/contract_function_simulator/oracle/oracle.js +127 -106
  22. package/dest/contract_function_simulator/oracle/private_execution.d.ts +7 -2
  23. package/dest/contract_function_simulator/oracle/private_execution.d.ts.map +1 -1
  24. package/dest/contract_function_simulator/oracle/private_execution.js +16 -11
  25. package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts +41 -17
  26. package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts.map +1 -1
  27. package/dest/contract_function_simulator/oracle/private_execution_oracle.js +51 -23
  28. package/dest/contract_function_simulator/oracle/typed_oracle.d.ts +48 -47
  29. package/dest/contract_function_simulator/oracle/typed_oracle.d.ts.map +1 -1
  30. package/dest/contract_function_simulator/oracle/typed_oracle.js +89 -87
  31. package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts +31 -30
  32. package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts.map +1 -1
  33. package/dest/contract_function_simulator/oracle/utility_execution_oracle.js +33 -30
  34. package/dest/contract_function_simulator/pxe_oracle_interface.d.ts.map +1 -1
  35. package/dest/contract_function_simulator/pxe_oracle_interface.js +6 -7
  36. package/dest/entrypoints/server/utils.d.ts +4 -2
  37. package/dest/entrypoints/server/utils.d.ts.map +1 -1
  38. package/dest/entrypoints/server/utils.js +4 -2
  39. package/dest/private_kernel/hints/build_private_kernel_reset_private_inputs.d.ts +4 -4
  40. package/dest/private_kernel/hints/build_private_kernel_reset_private_inputs.d.ts.map +1 -1
  41. package/dest/private_kernel/hints/build_private_kernel_reset_private_inputs.js +58 -59
  42. package/dest/private_kernel/hints/compute_tx_include_by_timestamp.d.ts +4 -0
  43. package/dest/private_kernel/hints/compute_tx_include_by_timestamp.d.ts.map +1 -0
  44. package/dest/private_kernel/hints/compute_tx_include_by_timestamp.js +41 -0
  45. package/dest/private_kernel/hints/index.d.ts +1 -0
  46. package/dest/private_kernel/hints/index.d.ts.map +1 -1
  47. package/dest/private_kernel/hints/index.js +1 -0
  48. package/dest/private_kernel/private_kernel_execution_prover.d.ts +1 -1
  49. package/dest/private_kernel/private_kernel_execution_prover.d.ts.map +1 -1
  50. package/dest/private_kernel/private_kernel_execution_prover.js +13 -4
  51. package/dest/private_kernel/private_kernel_oracle.d.ts +1 -1
  52. package/dest/private_kernel/private_kernel_oracle.d.ts.map +1 -1
  53. package/dest/private_kernel/private_kernel_oracle_impl.d.ts.map +1 -1
  54. package/dest/private_kernel/private_kernel_oracle_impl.js +6 -6
  55. package/dest/pxe_service/error_enriching.d.ts.map +1 -1
  56. package/dest/pxe_service/error_enriching.js +1 -0
  57. package/dest/pxe_service/pxe_service.d.ts +3 -2
  58. package/dest/pxe_service/pxe_service.d.ts.map +1 -1
  59. package/dest/pxe_service/pxe_service.js +28 -19
  60. package/dest/storage/capsule_data_provider/capsule_data_provider.js +1 -1
  61. package/dest/storage/note_data_provider/note_data_provider.d.ts.map +1 -1
  62. package/dest/storage/note_data_provider/note_data_provider.js +16 -4
  63. package/package.json +16 -16
  64. package/src/config/package_info.ts +1 -1
  65. package/src/contract_function_simulator/contract_function_simulator.ts +67 -37
  66. package/src/contract_function_simulator/index.ts +1 -0
  67. package/src/contract_function_simulator/noir-structs/event_validation_request.ts +1 -1
  68. package/src/contract_function_simulator/noir-structs/log_retrieval_request.ts +1 -1
  69. package/src/contract_function_simulator/noir-structs/log_retrieval_response.ts +1 -1
  70. package/src/contract_function_simulator/noir-structs/note_validation_request.ts +1 -1
  71. package/src/contract_function_simulator/oracle/note_packing_utils.ts +52 -0
  72. package/src/contract_function_simulator/oracle/oracle.ts +149 -111
  73. package/src/contract_function_simulator/oracle/private_execution.ts +17 -12
  74. package/src/contract_function_simulator/oracle/private_execution_oracle.ts +60 -24
  75. package/src/contract_function_simulator/oracle/typed_oracle.ts +108 -92
  76. package/src/contract_function_simulator/oracle/utility_execution_oracle.ts +34 -30
  77. package/src/contract_function_simulator/pxe_oracle_interface.ts +6 -8
  78. package/src/entrypoints/server/utils.ts +17 -6
  79. package/src/private_kernel/hints/build_private_kernel_reset_private_inputs.ts +106 -104
  80. package/src/private_kernel/hints/compute_tx_include_by_timestamp.ts +58 -0
  81. package/src/private_kernel/hints/index.ts +1 -0
  82. package/src/private_kernel/private_kernel_execution_prover.ts +21 -4
  83. package/src/private_kernel/private_kernel_oracle.ts +1 -1
  84. package/src/private_kernel/private_kernel_oracle_impl.ts +12 -9
  85. package/src/pxe_service/error_enriching.ts +1 -0
  86. package/src/pxe_service/pxe_service.ts +30 -32
  87. package/src/storage/capsule_data_provider/capsule_data_provider.ts +1 -1
  88. package/src/storage/note_data_provider/note_data_provider.ts +27 -16
@@ -109,7 +109,7 @@ import { enrichPublicSimulationError, enrichSimulationError } from './error_enri
109
109
  throw new Error(`L2 to L1 message not found in block ${blockNumber}`);
110
110
  }
111
111
  return [
112
- result.l2MessageIndex,
112
+ result.leafIndex,
113
113
  result.siblingPath
114
114
  ];
115
115
  }
@@ -180,7 +180,7 @@ import { enrichPublicSimulationError, enrichSimulationError } from './error_enri
180
180
  async #isContractClassPubliclyRegistered(id) {
181
181
  return !!await this.node.getContractClass(id);
182
182
  }
183
- async #isContractPubliclyDeployed(address) {
183
+ async #isContractPublished(address) {
184
184
  return !!await this.node.getContract(address);
185
185
  }
186
186
  async #isContractInitialized(address) {
@@ -206,10 +206,14 @@ import { enrichPublicSimulationError, enrichSimulationError } from './error_enri
206
206
  returnTypes: functionDao.returnTypes
207
207
  };
208
208
  }
209
- async #executePrivate(contractFunctionSimulator, txRequest, msgSender, scopes) {
209
+ // Executes the entrypoint private function, as well as all nested private
210
+ // functions that might arise.
211
+ async #executePrivate(contractFunctionSimulator, txRequest, scopes) {
210
212
  const { origin: contractAddress, functionSelector } = txRequest;
211
213
  try {
212
- const result = await contractFunctionSimulator.run(txRequest, contractAddress, functionSelector, msgSender, scopes);
214
+ const result = await contractFunctionSimulator.run(txRequest, contractAddress, functionSelector, undefined, // The sender for tags is set by contracts, typically by an account
215
+ // contract entrypoint
216
+ undefined, scopes);
213
217
  this.log.debug(`Private simulation completed for ${contractAddress.toString()}:${functionSelector}`);
214
218
  return result;
215
219
  } catch (err) {
@@ -319,7 +323,7 @@ import { enrichPublicSimulationError, enrichSimulationError } from './error_enri
319
323
  return {
320
324
  contractInstance: instance,
321
325
  isContractInitialized: await this.#isContractInitialized(address),
322
- isContractPubliclyDeployed: await this.#isContractPubliclyDeployed(address)
326
+ isContractPublished: await this.#isContractPublished(address)
323
327
  };
324
328
  }
325
329
  async registerAccount(secretKey, partialAddress) {
@@ -427,6 +431,8 @@ import { enrichPublicSimulationError, enrichSimulationError } from './error_enri
427
431
  return this.contractDataProvider.getContractsAddresses();
428
432
  }
429
433
  async getNotes(filter) {
434
+ // We need to manually trigger private state sync to have a guarantee that all the events are available.
435
+ await this.simulateUtility('sync_private_state', [], filter.contractAddress);
430
436
  const noteDaos = await this.noteDataProvider.getNotes(filter);
431
437
  const extendedNotes = noteDaos.map(async (dao)=>{
432
438
  let recipient = filter.recipient;
@@ -486,7 +492,7 @@ import { enrichPublicSimulationError, enrichSimulationError } from './error_enri
486
492
  perFunction,
487
493
  unaccounted: totalTime - ((syncTime ?? 0) + (proving ?? 0) + perFunction.reduce((acc, { time })=>acc + time, 0))
488
494
  };
489
- this.log.info(`Proving completed in ${totalTime}ms`, {
495
+ this.log.debug(`Proving completed in ${totalTime}ms`, {
490
496
  timings
491
497
  });
492
498
  return new TxProvingResult(privateExecutionResult, publicInputs, clientIvcProof, {
@@ -498,7 +504,7 @@ import { enrichPublicSimulationError, enrichSimulationError } from './error_enri
498
504
  }
499
505
  });
500
506
  }
501
- profileTx(txRequest, profileMode, skipProofGeneration = true, msgSender) {
507
+ profileTx(txRequest, profileMode, skipProofGeneration = true) {
502
508
  // We disable concurrent profiles for consistency with simulateTx.
503
509
  return this.#putInJobQueue(async ()=>{
504
510
  const totalTimer = new Timer();
@@ -507,7 +513,6 @@ import { enrichPublicSimulationError, enrichSimulationError } from './error_enri
507
513
  origin: txRequest.origin,
508
514
  functionSelector: txRequest.functionSelector,
509
515
  simulatePublic: false,
510
- msgSender,
511
516
  chainId: txRequest.txContext.chainId,
512
517
  version: txRequest.txContext.version,
513
518
  authWitnesses: txRequest.authWitnesses.map((w)=>w.requestHash)
@@ -517,7 +522,7 @@ import { enrichPublicSimulationError, enrichSimulationError } from './error_enri
517
522
  await this.synchronizer.sync();
518
523
  const syncTime = syncTimer.ms();
519
524
  const contractFunctionSimulator = this.#getSimulatorForTx();
520
- const privateExecutionResult = await this.#executePrivate(contractFunctionSimulator, txRequest, msgSender);
525
+ const privateExecutionResult = await this.#executePrivate(contractFunctionSimulator, txRequest);
521
526
  const { executionSteps, timings: { proving } = {} } = await this.#prove(txRequest, this.proofCreator, privateExecutionResult, {
522
527
  simulate: skipProofGeneration,
523
528
  skipFeeEnforcement: false,
@@ -547,7 +552,7 @@ import { enrichPublicSimulationError, enrichSimulationError } from './error_enri
547
552
  nodeRPCCalls: simulatorStats.nodeRPCCalls
548
553
  });
549
554
  } catch (err) {
550
- throw this.#contextualizeError(err, inspect(txRequest), `profileMode=${profileMode}`, `msgSender=${msgSender?.toString() ?? 'undefined'}`);
555
+ throw this.#contextualizeError(err, inspect(txRequest), `profileMode=${profileMode}`);
551
556
  }
552
557
  });
553
558
  }
@@ -563,7 +568,6 @@ import { enrichPublicSimulationError, enrichSimulationError } from './error_enri
563
568
  origin: txRequest.origin,
564
569
  functionSelector: txRequest.functionSelector,
565
570
  simulatePublic,
566
- msgSender: overrides?.msgSender,
567
571
  chainId: txRequest.txContext.chainId,
568
572
  version: txRequest.txContext.version,
569
573
  authWitnesses: txRequest.authWitnesses.map((w)=>w.requestHash)
@@ -577,7 +581,8 @@ import { enrichPublicSimulationError, enrichSimulationError } from './error_enri
577
581
  // will fail. Consider handing control to the user/wallet on whether they want to run them
578
582
  // or not.
579
583
  const skipKernels = overrides?.contracts !== undefined && Object.keys(overrides.contracts ?? {}).length > 0;
580
- const privateExecutionResult = await this.#executePrivate(contractFunctionSimulator, txRequest, overrides?.msgSender, scopes);
584
+ // Execution of private functions only; no proving, and no kernel logic.
585
+ const privateExecutionResult = await this.#executePrivate(contractFunctionSimulator, txRequest, scopes);
581
586
  let publicInputs;
582
587
  let executionSteps = [];
583
588
  if (skipKernels) {
@@ -587,6 +592,7 @@ import { enrichPublicSimulationError, enrichSimulationError } from './error_enri
587
592
  const nonceGenerator = privateExecutionResult.firstNullifier.equals(Fr.ZERO) ? await txRequest.toTxRequest().hash() : privateExecutionResult.firstNullifier;
588
593
  ({ publicInputs, executionSteps } = await generateSimulatedProvingResult(privateExecutionResult, nonceGenerator, this.contractDataProvider));
589
594
  } else {
595
+ // Kernel logic, plus proving of all private functions and kernels.
590
596
  ({ publicInputs, executionSteps } = await this.#prove(txRequest, this.proofCreator, privateExecutionResult, {
591
597
  simulate: true,
592
598
  skipFeeEnforcement,
@@ -594,7 +600,7 @@ import { enrichPublicSimulationError, enrichSimulationError } from './error_enri
594
600
  }));
595
601
  }
596
602
  const privateSimulationResult = new PrivateSimulationResult(privateExecutionResult, publicInputs);
597
- const simulatedTx = privateSimulationResult.toSimulatedTx();
603
+ const simulatedTx = await privateSimulationResult.toSimulatedTx();
598
604
  let publicSimulationTime;
599
605
  let publicOutput;
600
606
  if (simulatePublic && publicInputs.forPublic) {
@@ -603,7 +609,7 @@ import { enrichPublicSimulationError, enrichSimulationError } from './error_enri
603
609
  publicSimulationTime = publicSimulationTimer.ms();
604
610
  }
605
611
  let validationTime;
606
- if (!skipTxValidation && !skipKernels) {
612
+ if (!skipTxValidation) {
607
613
  const validationTimer = new Timer();
608
614
  const validationResult = await this.node.isValidTx(simulatedTx, {
609
615
  isSimulation: true,
@@ -614,7 +620,7 @@ import { enrichPublicSimulationError, enrichSimulationError } from './error_enri
614
620
  throw new Error('The simulated transaction is unable to be added to state and is invalid.');
615
621
  }
616
622
  }
617
- const txHash = await simulatedTx.getTxHash();
623
+ const txHash = simulatedTx.getTxHash();
618
624
  const totalTime = totalTimer.ms();
619
625
  const perFunction = executionSteps.map(({ functionName, timings: { witgen, oracles } })=>({
620
626
  functionName,
@@ -644,12 +650,12 @@ import { enrichPublicSimulationError, enrichSimulationError } from './error_enri
644
650
  nodeRPCCalls: simulatorStats.nodeRPCCalls
645
651
  });
646
652
  } catch (err) {
647
- throw this.#contextualizeError(err, inspect(txRequest), `simulatePublic=${simulatePublic}`, `msgSender=${overrides?.msgSender?.toString() ?? 'undefined'}`, `skipTxValidation=${skipTxValidation}`, `scopes=${scopes?.map((s)=>s.toString()).join(', ') ?? 'undefined'}`);
653
+ throw this.#contextualizeError(err, inspect(txRequest), `simulatePublic=${simulatePublic}`, `skipTxValidation=${skipTxValidation}`, `scopes=${scopes?.map((s)=>s.toString()).join(', ') ?? 'undefined'}`);
648
654
  }
649
655
  });
650
656
  }
651
657
  async sendTx(tx) {
652
- const txHash = await tx.getTxHash();
658
+ const txHash = tx.getTxHash();
653
659
  if (await this.node.getTxEffect(txHash)) {
654
660
  throw new Error(`A settled tx with equal hash ${txHash.toString()} exists.`);
655
661
  }
@@ -731,9 +737,9 @@ import { enrichPublicSimulationError, enrichSimulationError } from './error_enri
731
737
  return Promise.resolve({
732
738
  pxeVersion: this.packageVersion,
733
739
  protocolContractAddresses: {
734
- classRegisterer: ProtocolContractAddress.ContractClassRegisterer,
740
+ classRegistry: ProtocolContractAddress.ContractClassRegistry,
735
741
  feeJuice: ProtocolContractAddress.FeeJuice,
736
- instanceDeployer: ProtocolContractAddress.ContractInstanceDeployer,
742
+ instanceRegistry: ProtocolContractAddress.ContractInstanceRegistry,
737
743
  multiCallEntrypoint: ProtocolContractAddress.MultiCallEntrypoint
738
744
  }
739
745
  });
@@ -776,4 +782,7 @@ import { enrichPublicSimulationError, enrichSimulationError } from './error_enri
776
782
  async resetNoteSyncData() {
777
783
  return await this.taggingDataProvider.resetNoteSyncData();
778
784
  }
785
+ stop() {
786
+ return this.jobQueue.end();
787
+ }
779
788
  }
@@ -17,7 +17,7 @@ export class CapsuleDataProvider {
17
17
  async loadCapsule(contractAddress, slot) {
18
18
  const dataBuffer = await this.#capsules.getAsync(dbSlotToKey(contractAddress, slot));
19
19
  if (!dataBuffer) {
20
- this.logger.debug(`Data not found for contract ${contractAddress.toString()} and slot ${slot.toString()}`);
20
+ this.logger.trace(`Data not found for contract ${contractAddress.toString()} and slot ${slot.toString()}`);
21
21
  return null;
22
22
  }
23
23
  const capsule = [];
@@ -1 +1 @@
1
- {"version":3,"file":"note_data_provider.d.ts","sourceRoot":"","sources":["../../../src/storage/note_data_provider/note_data_provider.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;AAEnD,OAAO,KAAK,EAAE,iBAAiB,EAAqC,MAAM,iBAAiB,CAAC;AAC5F,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAc,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAElE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAExC,qBAAa,gBAAiB,YAAW,YAAY;;IAsBnD,OAAO;WAsBa,MAAM,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAWlE,QAAQ,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC;IAgB5D,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,GAAE,YAAgC,GAAG,OAAO,CAAC,IAAI,CAAC;IAwB3E,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAsB9C,mBAAmB,CAAC,WAAW,EAAE,MAAM,EAAE,kBAAkB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkD3F,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAkGvD,oBAAoB,CAAC,UAAU,EAAE,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,SAAS,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IA2DtF,OAAO;CAGd"}
1
+ {"version":3,"file":"note_data_provider.d.ts","sourceRoot":"","sources":["../../../src/storage/note_data_provider/note_data_provider.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;AAEnD,OAAO,KAAK,EAAE,iBAAiB,EAAqC,MAAM,iBAAiB,CAAC;AAC5F,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAc,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAElE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAExC,qBAAa,gBAAiB,YAAW,YAAY;;IAsBnD,OAAO;WAsBa,MAAM,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAWlE,QAAQ,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC;IAgB5D,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,GAAE,YAAgC,GAAG,OAAO,CAAC,IAAI,CAAC;IAwB3E,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAsB9C,mBAAmB,CAAC,WAAW,EAAE,MAAM,EAAE,kBAAkB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkD3F,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IA8FvD,oBAAoB,CAAC,UAAU,EAAE,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,SAAS,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IA2DtF,OAAO;CAkBd"}
@@ -154,7 +154,7 @@ export class NoteDataProvider {
154
154
  if (!await this.#scopes.hasAsync(formattedScopeString)) {
155
155
  throw new Error('Trying to get incoming notes of an scope that is not in the PXE database');
156
156
  }
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()));
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.storageSlot ? await toArray(this.#notesByStorageSlotAndScope.get(formattedScopeString).getValuesAsync(filter.storageSlot.toString())) : await toArray(this.#notesByContractAndScope.get(formattedScopeString).getValuesAsync(filter.contractAddress.toString())));
158
158
  }
159
159
  candidateNoteSources.push({
160
160
  ids: new Set(activeNoteIdsPerScope.flat()),
@@ -162,7 +162,7 @@ export class NoteDataProvider {
162
162
  });
163
163
  if (filter.status == NoteStatus.ACTIVE_OR_NULLIFIED) {
164
164
  candidateNoteSources.push({
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()),
165
+ ids: filter.recipient ? await toArray(this.#nullifiedNotesByRecipient.getValuesAsync(filter.recipient.toString())) : filter.txHash ? await toArray(this.#nullifiedNotesByTxHash.getValuesAsync(filter.txHash.toString())) : filter.storageSlot ? await toArray(this.#nullifiedNotesByStorageSlot.getValuesAsync(filter.storageSlot.toString())) : await toArray(this.#nullifiedNotesByContract.getValuesAsync(filter.contractAddress.toString())),
166
166
  notes: this.#nullifiedNotes
167
167
  });
168
168
  }
@@ -174,7 +174,7 @@ export class NoteDataProvider {
174
174
  continue;
175
175
  }
176
176
  const note = NoteDao.fromBuffer(serializedNote);
177
- if (filter.contractAddress && !note.contractAddress.equals(filter.contractAddress)) {
177
+ if (!note.contractAddress.equals(filter.contractAddress)) {
178
178
  continue;
179
179
  }
180
180
  if (filter.txHash && !note.txHash.equals(filter.txHash)) {
@@ -243,6 +243,18 @@ export class NoteDataProvider {
243
243
  });
244
244
  }
245
245
  async getSize() {
246
- return (await this.getNotes({})).reduce((sum, note)=>sum + note.getSize(), 0);
246
+ const scopes = await toArray(this.#scopes.keysAsync());
247
+ const contractAddresses = new Set();
248
+ // Collect all unique contract addresses across all scopes
249
+ for (const scope of scopes){
250
+ const addresses = await toArray(this.#notesByContractAndScope.get(scope).keysAsync());
251
+ addresses.forEach((addr)=>contractAddresses.add(addr));
252
+ }
253
+ // Get all notes for each contract address
254
+ const allNotes = await Promise.all(Array.from(contractAddresses).map((addr)=>this.getNotes({
255
+ contractAddress: AztecAddress.fromString(addr)
256
+ })));
257
+ // Reduce all notes to get total size
258
+ return allNotes.flat().reduce((sum, note)=>sum + note.getSize(), 0);
247
259
  }
248
260
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/pxe",
3
- "version": "1.2.1",
3
+ "version": "2.0.0-nightly.20250813",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  "./server": "./dest/entrypoints/server/index.js",
@@ -62,19 +62,19 @@
62
62
  ]
63
63
  },
64
64
  "dependencies": {
65
- "@aztec/bb-prover": "1.2.1",
66
- "@aztec/bb.js": "1.2.1",
67
- "@aztec/builder": "1.2.1",
68
- "@aztec/constants": "1.2.1",
69
- "@aztec/ethereum": "1.2.1",
70
- "@aztec/foundation": "1.2.1",
71
- "@aztec/key-store": "1.2.1",
72
- "@aztec/kv-store": "1.2.1",
73
- "@aztec/noir-protocol-circuits-types": "1.2.1",
74
- "@aztec/noir-types": "1.2.1",
75
- "@aztec/protocol-contracts": "1.2.1",
76
- "@aztec/simulator": "1.2.1",
77
- "@aztec/stdlib": "1.2.1",
65
+ "@aztec/bb-prover": "2.0.0-nightly.20250813",
66
+ "@aztec/bb.js": "2.0.0-nightly.20250813",
67
+ "@aztec/builder": "2.0.0-nightly.20250813",
68
+ "@aztec/constants": "2.0.0-nightly.20250813",
69
+ "@aztec/ethereum": "2.0.0-nightly.20250813",
70
+ "@aztec/foundation": "2.0.0-nightly.20250813",
71
+ "@aztec/key-store": "2.0.0-nightly.20250813",
72
+ "@aztec/kv-store": "2.0.0-nightly.20250813",
73
+ "@aztec/noir-protocol-circuits-types": "2.0.0-nightly.20250813",
74
+ "@aztec/noir-types": "2.0.0-nightly.20250813",
75
+ "@aztec/protocol-contracts": "2.0.0-nightly.20250813",
76
+ "@aztec/simulator": "2.0.0-nightly.20250813",
77
+ "@aztec/stdlib": "2.0.0-nightly.20250813",
78
78
  "koa": "^2.16.1",
79
79
  "koa-router": "^12.0.0",
80
80
  "lodash.omit": "^4.5.0",
@@ -83,8 +83,8 @@
83
83
  "viem": "2.23.7"
84
84
  },
85
85
  "devDependencies": {
86
- "@aztec/merkle-tree": "1.2.1",
87
- "@aztec/noir-test-contracts.js": "1.2.1",
86
+ "@aztec/merkle-tree": "2.0.0-nightly.20250813",
87
+ "@aztec/noir-test-contracts.js": "2.0.0-nightly.20250813",
88
88
  "@jest/globals": "^30.0.0",
89
89
  "@types/jest": "^30.0.0",
90
90
  "@types/lodash.omit": "^4.5.7",
@@ -1,3 +1,3 @@
1
1
  export function getPackageInfo() {
2
- return { version: '1.2.0', name: '@aztec/pxe' };
2
+ return { version: '1.2.1', name: '@aztec/pxe' };
3
3
  }
@@ -37,7 +37,6 @@ import {
37
37
  PrivateToPublicAccumulatedData,
38
38
  PrivateToRollupAccumulatedData,
39
39
  PublicCallRequest,
40
- RollupValidationRequests,
41
40
  ScopedLogHash,
42
41
  } from '@aztec/stdlib/kernel';
43
42
  import { PrivateLog } from '@aztec/stdlib/logs';
@@ -79,7 +78,10 @@ export class ContractFunctionSimulator {
79
78
  * @param request - The transaction request.
80
79
  * @param entryPointArtifact - The artifact of the entry point function.
81
80
  * @param contractAddress - The address of the contract (should match request.origin)
82
- * @param msgSender - The address calling the function. This can be replaced to simulate a call from another contract or a specific account.
81
+ * @param msgSender - The address calling the function. This can be replaced to simulate a call from another contract
82
+ * or a specific account.
83
+ * @param senderForTags - The address that is used as a tagging sender when emitting private logs. Returned from
84
+ * the `privateGetSenderForTags` oracle.
83
85
  * @param scopes - The accounts whose notes we can access in this call. Currently optional and will default to all.
84
86
  * @returns The result of the execution.
85
87
  */
@@ -88,6 +90,7 @@ export class ContractFunctionSimulator {
88
90
  contractAddress: AztecAddress,
89
91
  selector: FunctionSelector,
90
92
  msgSender = AztecAddress.fromField(Fr.MAX_FIELD_VALUE),
93
+ senderForTags?: AztecAddress,
91
94
  scopes?: AztecAddress[],
92
95
  ): Promise<PrivateExecutionResult> {
93
96
  const simulatorSetupTimer = new Timer();
@@ -131,15 +134,20 @@ export class ContractFunctionSimulator {
131
134
  noteCache,
132
135
  this.executionDataProvider,
133
136
  this.simulator,
134
- /*totalPublicArgsCount=*/ 0,
137
+ 0, // totalPublicArgsCount
135
138
  startSideEffectCounter,
136
- undefined,
139
+ undefined, // log
137
140
  scopes,
141
+ senderForTags,
138
142
  );
139
143
 
140
144
  const setupTime = simulatorSetupTimer.ms();
141
145
 
142
146
  try {
147
+ // Note: any nested private function calls are made recursively within this
148
+ // function call. So this execution result is the result of executing _all_
149
+ // private functions of this tx (the results of those executions are contained
150
+ // within executionResult.nestedExecutionResults).
143
151
  const executionResult = await executePrivateFunction(
144
152
  this.simulator,
145
153
  privateExecutionOracle,
@@ -151,13 +159,15 @@ export class ContractFunctionSimulator {
151
159
  const { usedTxRequestHashForNonces } = noteCache.finish();
152
160
  const firstNullifierHint = usedTxRequestHashForNonces ? Fr.ZERO : noteCache.getAllNullifiers()[0];
153
161
 
154
- const publicCallRequests = collectNested([executionResult], r => [
155
- ...r.publicInputs.publicCallRequests.map(r => r.inner),
156
- r.publicInputs.publicTeardownCallRequest,
157
- ]).filter(r => !r.isEmpty());
162
+ const publicCallRequests = collectNested([executionResult], r =>
163
+ r.publicInputs.publicCallRequests
164
+ .getActiveItems()
165
+ .map(r => r.inner)
166
+ .concat(r.publicInputs.publicTeardownCallRequest.isEmpty() ? [] : [r.publicInputs.publicTeardownCallRequest]),
167
+ );
158
168
  const publicFunctionsCalldata = await Promise.all(
159
169
  publicCallRequests.map(async r => {
160
- const calldata = await privateExecutionOracle.loadFromExecutionCache(r.calldataHash);
170
+ const calldata = await privateExecutionOracle.privateLoadFromExecutionCache(r.calldataHash);
161
171
  return new HashedValues(calldata, r.calldataHash);
162
172
  }),
163
173
  );
@@ -169,6 +179,9 @@ export class ContractFunctionSimulator {
169
179
  executionResult.profileResult.timings.witgen += setupTime + teardownTime;
170
180
  }
171
181
 
182
+ // Not to be confused with a PrivateCallExecutionResult. This is a superset
183
+ // of the PrivateCallExecutionResult, containing also firstNullifierHint
184
+ // and publicFunctionsCalldata.
172
185
  return new PrivateExecutionResult(executionResult, firstNullifierHint, publicFunctionsCalldata);
173
186
  } catch (err) {
174
187
  throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during private execution'));
@@ -258,7 +271,7 @@ export async function generateSimulatedProvingResult(
258
271
  nonceGenerator: Fr,
259
272
  contractDataProvider: ContractDataProvider,
260
273
  ): Promise<PrivateKernelExecutionProofOutput<PrivateKernelTailCircuitPublicInputs>> {
261
- const uniqueNoteHashes: OrderedSideEffect<Fr>[] = [];
274
+ const siloedNoteHashes: OrderedSideEffect<Fr>[] = [];
262
275
  const nullifiers: OrderedSideEffect<Fr>[] = [];
263
276
  const taggedPrivateLogs: OrderedSideEffect<PrivateLog>[] = [];
264
277
  const l2ToL1Messages: OrderedSideEffect<ScopedL2ToL1Message>[] = [];
@@ -268,29 +281,27 @@ export async function generateSimulatedProvingResult(
268
281
 
269
282
  let publicTeardownCallRequest;
270
283
 
271
- let noteHashIndexInTx = 0;
272
284
  const executions = [privateExecutionResult.entrypoint];
273
285
 
274
286
  while (executions.length !== 0) {
275
287
  const execution = executions.shift()!;
276
- executions.unshift(...execution!.nestedExecutions);
288
+ executions.unshift(...execution!.nestedExecutionResults);
277
289
 
278
290
  const { contractAddress } = execution.publicInputs.callContext;
279
291
 
280
292
  const noteHashesFromExecution = await Promise.all(
281
293
  execution.publicInputs.noteHashes
294
+ .getActiveItems()
282
295
  .filter(noteHash => !noteHash.isEmpty())
283
- .map(async noteHash => {
284
- const nonce = await computeNoteHashNonce(nonceGenerator, noteHashIndexInTx++);
285
- const siloedNoteHash = await siloNoteHash(contractAddress, noteHash.value);
286
- // We could defer this to the public processor, and pass this in as non-revertible.
287
- return new OrderedSideEffect(await computeUniqueNoteHash(nonce, siloedNoteHash), noteHash.counter);
288
- }),
296
+ .map(
297
+ async noteHash =>
298
+ new OrderedSideEffect(await siloNoteHash(contractAddress, noteHash.value), noteHash.counter),
299
+ ),
289
300
  );
290
301
 
291
302
  const nullifiersFromExecution = await Promise.all(
292
303
  execution.publicInputs.nullifiers
293
- .filter(nullifier => !nullifier.isEmpty())
304
+ .getActiveItems()
294
305
  .map(
295
306
  async nullifier =>
296
307
  new OrderedSideEffect(await siloNullifier(contractAddress, nullifier.value), nullifier.counter),
@@ -298,25 +309,23 @@ export async function generateSimulatedProvingResult(
298
309
  );
299
310
 
300
311
  const privateLogsFromExecution = await Promise.all(
301
- execution.publicInputs.privateLogs
302
- .filter(privateLog => !privateLog.isEmpty())
303
- .map(async metadata => {
304
- metadata.log.fields[0] = await poseidon2Hash([contractAddress, metadata.log.fields[0]]);
305
- return new OrderedSideEffect(metadata.log, metadata.counter);
306
- }),
312
+ execution.publicInputs.privateLogs.getActiveItems().map(async metadata => {
313
+ metadata.log.fields[0] = await poseidon2Hash([contractAddress, metadata.log.fields[0]]);
314
+ return new OrderedSideEffect(metadata.log, metadata.counter);
315
+ }),
307
316
  );
308
317
 
309
- uniqueNoteHashes.push(...noteHashesFromExecution);
318
+ siloedNoteHashes.push(...noteHashesFromExecution);
310
319
  taggedPrivateLogs.push(...privateLogsFromExecution);
311
320
  nullifiers.push(...nullifiersFromExecution);
312
321
  l2ToL1Messages.push(
313
322
  ...execution.publicInputs.l2ToL1Msgs
314
- .filter(l2ToL1Message => !l2ToL1Message.isEmpty())
323
+ .getActiveItems()
315
324
  .map(message => new OrderedSideEffect(message.message.scope(contractAddress), message.counter)),
316
325
  );
317
326
  contractClassLogsHashes.push(
318
327
  ...execution.publicInputs.contractClassLogsHashes
319
- .filter(contractClassLogsHash => !contractClassLogsHash.isEmpty())
328
+ .getActiveItems()
320
329
  .map(
321
330
  contractClassLogHash =>
322
331
  new OrderedSideEffect(contractClassLogHash.logHash.scope(contractAddress), contractClassLogHash.counter),
@@ -324,7 +333,7 @@ export async function generateSimulatedProvingResult(
324
333
  );
325
334
  publicCallRequests.push(
326
335
  ...execution.publicInputs.publicCallRequests
327
- .filter(publicCallRequest => !publicCallRequest.isEmpty())
336
+ .getActiveItems()
328
337
  .map(callRequest => new OrderedSideEffect(callRequest.inner, callRequest.counter)),
329
338
  );
330
339
 
@@ -363,14 +372,27 @@ export async function generateSimulatedProvingResult(
363
372
  const getEffect = <T>(orderedSideEffect: OrderedSideEffect<T>) => orderedSideEffect.sideEffect;
364
373
 
365
374
  const sortedNullifiers = nullifiers.sort(sortByCounter).map(getEffect);
375
+
376
+ // If the tx generated no nullifiers, the nonce generator (txRequest hash)
377
+ // is injected as the first nullifier as per protocol rules.
366
378
  if (sortedNullifiers.length === 0) {
367
379
  sortedNullifiers.push(nonceGenerator);
368
380
  }
369
381
 
370
382
  // Private only
371
383
  if (privateExecutionResult.publicFunctionCalldata.length === 0) {
384
+ // In case the tx only contains private functions, we must make the note hashes unique by using the
385
+ // nonce generator and their index in the tx.
386
+ const uniqueNoteHashes = await Promise.all(
387
+ siloedNoteHashes.sort(sortByCounter).map(async (orderedSideEffect, i) => {
388
+ const siloedNoteHash = orderedSideEffect.sideEffect;
389
+ const nonce = await computeNoteHashNonce(nonceGenerator, i);
390
+ const uniqueNoteHash = await computeUniqueNoteHash(nonce, siloedNoteHash);
391
+ return uniqueNoteHash;
392
+ }),
393
+ );
372
394
  const accumulatedDataForRollup = new PrivateToRollupAccumulatedData(
373
- padArrayEnd(uniqueNoteHashes.sort(sortByCounter).map(getEffect), Fr.ZERO, MAX_NOTE_HASHES_PER_TX),
395
+ padArrayEnd(uniqueNoteHashes, Fr.ZERO, MAX_NOTE_HASHES_PER_TX),
374
396
  padArrayEnd(sortedNullifiers, Fr.ZERO, MAX_NULLIFIERS_PER_TX),
375
397
  padArrayEnd(
376
398
  l2ToL1Messages.sort(sortByCounter).map(getEffect),
@@ -387,8 +409,18 @@ export async function generateSimulatedProvingResult(
387
409
 
388
410
  inputsForRollup = new PartialPrivateTailPublicInputsForRollup(accumulatedDataForRollup);
389
411
  } else {
390
- const accumulatedDataForPublic = new PrivateToPublicAccumulatedData(
391
- padArrayEnd(uniqueNoteHashes.sort(sortByCounter).map(getEffect), Fr.ZERO, MAX_NOTE_HASHES_PER_TX),
412
+ const nonRevertibleData = PrivateToPublicAccumulatedData.empty();
413
+
414
+ // The nullifier array contains the nonce generator in position 0
415
+ // Here we remove it from the revertible data and
416
+ // add it as the first non-revertible nullifier (we can't have dupes!)
417
+ // This is because public processor will use that first non-revertible nullifier
418
+ // as the nonce generator for the note hashes in the revertible part of the tx.
419
+ const [firstNullifier] = sortedNullifiers.splice(0, 1);
420
+ nonRevertibleData.nullifiers[0] = firstNullifier;
421
+
422
+ const revertibleData = new PrivateToPublicAccumulatedData(
423
+ padArrayEnd(siloedNoteHashes.sort(sortByCounter).map(getEffect), Fr.ZERO, MAX_NOTE_HASHES_PER_TX),
392
424
  padArrayEnd(sortedNullifiers, Fr.ZERO, MAX_NULLIFIERS_PER_TX),
393
425
  padArrayEnd(
394
426
  l2ToL1Messages.sort(sortByCounter).map(getEffect),
@@ -409,19 +441,17 @@ export async function generateSimulatedProvingResult(
409
441
  );
410
442
 
411
443
  inputsForPublic = new PartialPrivateTailPublicInputsForPublic(
412
- // nonrevertible
413
- accumulatedDataForPublic,
414
- // revertible
415
- PrivateToPublicAccumulatedData.empty(),
444
+ nonRevertibleData,
445
+ revertibleData,
416
446
  publicTeardownCallRequest ?? PublicCallRequest.empty(),
417
447
  );
418
448
  }
419
449
 
420
450
  const publicInputs = new PrivateKernelTailCircuitPublicInputs(
421
451
  constantData,
422
- RollupValidationRequests.empty(),
423
452
  /*gasUsed=*/ new Gas(0, 0),
424
453
  /*feePayer=*/ AztecAddress.zero(),
454
+ /*includeByTimestamp=*/ 0n,
425
455
  hasPublicCalls ? inputsForPublic : undefined,
426
456
  !hasPublicCalls ? inputsForRollup : undefined,
427
457
  );
@@ -8,3 +8,4 @@ export { PrivateExecutionOracle } from './oracle/private_execution_oracle.js';
8
8
  export { Oracle } from './oracle/oracle.js';
9
9
  export { executePrivateFunction, extractPrivateCircuitPublicInputs } from './oracle/private_execution.js';
10
10
  export { generateSimulatedProvingResult } from './contract_function_simulator.js';
11
+ export { packAsRetrievedNote } from './oracle/note_packing_utils.js';
@@ -8,7 +8,7 @@ import { TxHash } from '@aztec/stdlib/tx';
8
8
  const MAX_EVENT_SERIALIZED_LEN = 12;
9
9
 
10
10
  /**
11
- * Intermediate struct used to perform batch event validation by PXE. The `validateEnqueuedNotesAndEvents` oracle
11
+ * Intermediate struct used to perform batch event validation by PXE. The `utilityValidateEnqueuedNotesAndEvents` oracle
12
12
  * expects for values of this type to be stored in a `CapsuleArray`.
13
13
  */
14
14
  export class EventValidationRequest {
@@ -3,7 +3,7 @@ import { FieldReader } from '@aztec/foundation/serialize';
3
3
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
4
4
 
5
5
  /**
6
- * Intermediate struct used to perform batch log retrieval by PXE. The `bulkRetrieveLogs` oracle expects values of this
6
+ * Intermediate struct used to perform batch log retrieval by PXE. The `utilityBulkRetrieveLogs` oracle expects values of this
7
7
  * type to be stored in a `CapsuleArray`.
8
8
  */
9
9
  export class LogRetrievalRequest {
@@ -6,7 +6,7 @@ import type { TxHash } from '@aztec/stdlib/tx';
6
6
  const MAX_LOG_CONTENT_LEN = Math.max(PUBLIC_LOG_PLAINTEXT_LEN, PRIVATE_LOG_CIPHERTEXT_LEN);
7
7
 
8
8
  /**
9
- * Intermediate struct used to perform batch log retrieval by PXE. The `bulkRetrieveLogs` oracle stores values of this
9
+ * Intermediate struct used to perform batch log retrieval by PXE. The `utilityBulkRetrieveLogs` oracle stores values of this
10
10
  * type in a `CapsuleArray`.
11
11
  */
12
12
  export class LogRetrievalResponse {
@@ -7,7 +7,7 @@ import { TxHash } from '@aztec/stdlib/tx';
7
7
  const MAX_NOTE_PACKED_LEN = 12;
8
8
 
9
9
  /**
10
- * Intermediate struct used to perform batch note validation by PXE. The `validateEnqueuedNotesAndEvents` oracle
10
+ * Intermediate struct used to perform batch note validation by PXE. The `utilityValidateEnqueuedNotesAndEvents` oracle
11
11
  * expects for values of this type to be stored in a `CapsuleArray`.
12
12
  */
13
13
  export class NoteValidationRequest {
@@ -0,0 +1,52 @@
1
+ import { Fr } from '@aztec/foundation/fields';
2
+ import type { AztecAddress } from '@aztec/stdlib/aztec-address';
3
+ import type { Note } from '@aztec/stdlib/note';
4
+
5
+ // TS equivalent of the `NoteMetadata::from_raw_data` function in `aztec/src/note/note_metadata.nr`
6
+ function fromRawData(nonzeroNoteHashCounter: boolean, maybeNoteNonce: Fr): { stage: number; maybeNoteNonce: Fr } {
7
+ if (nonzeroNoteHashCounter) {
8
+ if (maybeNoteNonce.equals(Fr.ZERO)) {
9
+ return { stage: 1, maybeNoteNonce }; // PENDING_SAME_PHASE
10
+ } else {
11
+ return { stage: 2, maybeNoteNonce }; // PENDING_PREVIOUS_PHASE
12
+ }
13
+ } else if (!maybeNoteNonce.equals(Fr.ZERO)) {
14
+ return { stage: 3, maybeNoteNonce }; // SETTLED
15
+ } else {
16
+ throw new Error('Note has a zero note hash counter and no nonce - existence cannot be proven');
17
+ }
18
+ }
19
+
20
+ /**
21
+ * Packs a note in a format that is compatible with the default Packable implementation of the retrieved note.
22
+ *
23
+ * @dev Unlike the default Packable implementation, this function first constructs the note metadata from the inputs
24
+ * and only after that it packs the retrieved note. Hence it doesn't map one to one with `RetrievedNote::pack()`.
25
+ *
26
+ * @param contractAddress - The address of the contract that owns the note
27
+ * @param noteNonce - The nonce injected into the note hash preimage by kernels.
28
+ * @param index - Optional index in the note hash tree. If undefined, indicates a transient note
29
+ * @param note - The note content containing the actual note data
30
+ * @returns The packed note as an array of field elements
31
+ */
32
+ export function packAsRetrievedNote({
33
+ contractAddress,
34
+ noteNonce,
35
+ index,
36
+ note,
37
+ }: {
38
+ contractAddress: AztecAddress;
39
+ noteNonce: Fr;
40
+ index?: bigint;
41
+ note: Note;
42
+ }) {
43
+ // If index is undefined, the note is transient which implies that the nonzero_note_hash_counter has to be true
44
+ const noteIsTransient = index === undefined;
45
+ const nonzeroNoteHashCounter = noteIsTransient ? true : false;
46
+
47
+ // To pack the note as retrieved note we first need to reconstruct the note metadata.
48
+ const noteMetadata = fromRawData(nonzeroNoteHashCounter, noteNonce);
49
+
50
+ // Pack metadata first (stage and maybe_note_nonce), followed by the rest
51
+ return [...note.items, contractAddress, new Fr(noteMetadata.stage), noteMetadata.maybeNoteNonce];
52
+ }