@aztec/pxe 0.0.1-commit.1142ef1 → 0.0.1-commit.1bea0213

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 (190) hide show
  1. package/dest/bin/check_oracle_version.js +1 -1
  2. package/dest/block_synchronizer/block_synchronizer.d.ts +8 -4
  3. package/dest/block_synchronizer/block_synchronizer.d.ts.map +1 -1
  4. package/dest/block_synchronizer/block_synchronizer.js +64 -19
  5. package/dest/config/index.d.ts +3 -1
  6. package/dest/config/index.d.ts.map +1 -1
  7. package/dest/config/index.js +17 -0
  8. package/dest/contract_function_simulator/benchmarked_node.d.ts +9 -0
  9. package/dest/contract_function_simulator/benchmarked_node.d.ts.map +1 -0
  10. package/dest/contract_function_simulator/benchmarked_node.js +77 -0
  11. package/dest/contract_function_simulator/contract_function_simulator.d.ts +5 -7
  12. package/dest/contract_function_simulator/contract_function_simulator.d.ts.map +1 -1
  13. package/dest/contract_function_simulator/contract_function_simulator.js +26 -16
  14. package/dest/contract_function_simulator/execution_note_cache.d.ts +18 -9
  15. package/dest/contract_function_simulator/execution_note_cache.d.ts.map +1 -1
  16. package/dest/contract_function_simulator/execution_note_cache.js +45 -28
  17. package/dest/contract_function_simulator/index.d.ts +2 -2
  18. package/dest/contract_function_simulator/index.d.ts.map +1 -1
  19. package/dest/contract_function_simulator/index.js +1 -1
  20. package/dest/contract_function_simulator/noir-structs/event_validation_request.d.ts +1 -1
  21. package/dest/contract_function_simulator/noir-structs/event_validation_request.js +1 -1
  22. package/dest/contract_function_simulator/noir-structs/note_validation_request.d.ts +1 -1
  23. package/dest/contract_function_simulator/noir-structs/note_validation_request.js +1 -1
  24. package/dest/contract_function_simulator/noir-structs/utility_context.d.ts +4 -10
  25. package/dest/contract_function_simulator/noir-structs/utility_context.d.ts.map +1 -1
  26. package/dest/contract_function_simulator/noir-structs/utility_context.js +7 -18
  27. package/dest/contract_function_simulator/oracle/interfaces.d.ts +15 -11
  28. package/dest/contract_function_simulator/oracle/interfaces.d.ts.map +1 -1
  29. package/dest/contract_function_simulator/oracle/message_load_oracle_inputs.d.ts +3 -1
  30. package/dest/contract_function_simulator/oracle/message_load_oracle_inputs.d.ts.map +1 -1
  31. package/dest/contract_function_simulator/oracle/note_packing_utils.d.ts +6 -6
  32. package/dest/contract_function_simulator/oracle/note_packing_utils.d.ts.map +1 -1
  33. package/dest/contract_function_simulator/oracle/note_packing_utils.js +8 -8
  34. package/dest/contract_function_simulator/oracle/oracle.d.ts +10 -8
  35. package/dest/contract_function_simulator/oracle/oracle.d.ts.map +1 -1
  36. package/dest/contract_function_simulator/oracle/oracle.js +43 -32
  37. package/dest/contract_function_simulator/oracle/private_execution.d.ts +2 -26
  38. package/dest/contract_function_simulator/oracle/private_execution.d.ts.map +1 -1
  39. package/dest/contract_function_simulator/oracle/private_execution.js +0 -35
  40. package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts +10 -1
  41. package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts.map +1 -1
  42. package/dest/contract_function_simulator/oracle/private_execution_oracle.js +19 -7
  43. package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts +25 -16
  44. package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts.map +1 -1
  45. package/dest/contract_function_simulator/oracle/utility_execution_oracle.js +69 -71
  46. package/dest/contract_sync/index.d.ts +23 -0
  47. package/dest/contract_sync/index.d.ts.map +1 -0
  48. package/dest/contract_sync/index.js +54 -0
  49. package/dest/debug/pxe_debug_utils.d.ts +1 -1
  50. package/dest/debug/pxe_debug_utils.d.ts.map +1 -1
  51. package/dest/debug/pxe_debug_utils.js +3 -2
  52. package/dest/entrypoints/server/index.d.ts +3 -1
  53. package/dest/entrypoints/server/index.d.ts.map +1 -1
  54. package/dest/entrypoints/server/index.js +2 -0
  55. package/dest/events/event_service.d.ts +4 -3
  56. package/dest/events/event_service.d.ts.map +1 -1
  57. package/dest/events/event_service.js +17 -19
  58. package/dest/events/private_event_filter_validator.d.ts +5 -5
  59. package/dest/events/private_event_filter_validator.d.ts.map +1 -1
  60. package/dest/events/private_event_filter_validator.js +5 -6
  61. package/dest/logs/log_service.d.ts +3 -2
  62. package/dest/logs/log_service.d.ts.map +1 -1
  63. package/dest/logs/log_service.js +21 -13
  64. package/dest/notes/note_service.d.ts +5 -4
  65. package/dest/notes/note_service.d.ts.map +1 -1
  66. package/dest/notes/note_service.js +30 -34
  67. package/dest/oracle_version.d.ts +3 -3
  68. package/dest/oracle_version.d.ts.map +1 -1
  69. package/dest/oracle_version.js +4 -3
  70. package/dest/private_kernel/hints/index.d.ts +2 -2
  71. package/dest/private_kernel/hints/index.d.ts.map +1 -1
  72. package/dest/private_kernel/hints/index.js +1 -1
  73. package/dest/private_kernel/hints/private_kernel_reset_private_inputs_builder.d.ts +28 -0
  74. package/dest/private_kernel/hints/private_kernel_reset_private_inputs_builder.d.ts.map +1 -0
  75. package/dest/private_kernel/hints/{build_private_kernel_reset_private_inputs.js → private_kernel_reset_private_inputs_builder.js} +12 -6
  76. package/dest/private_kernel/private_kernel_execution_prover.js +1 -1
  77. package/dest/private_kernel/private_kernel_oracle.d.ts +23 -28
  78. package/dest/private_kernel/private_kernel_oracle.d.ts.map +1 -1
  79. package/dest/private_kernel/private_kernel_oracle.js +90 -2
  80. package/dest/pxe.d.ts +7 -36
  81. package/dest/pxe.d.ts.map +1 -1
  82. package/dest/pxe.js +37 -79
  83. package/dest/storage/capsule_store/capsule_store.d.ts +24 -9
  84. package/dest/storage/capsule_store/capsule_store.d.ts.map +1 -1
  85. package/dest/storage/capsule_store/capsule_store.js +132 -23
  86. package/dest/storage/contract_store/contract_store.d.ts +1 -2
  87. package/dest/storage/contract_store/contract_store.d.ts.map +1 -1
  88. package/dest/storage/contract_store/contract_store.js +0 -12
  89. package/dest/storage/note_store/note_store.d.ts +45 -56
  90. package/dest/storage/note_store/note_store.d.ts.map +1 -1
  91. package/dest/storage/note_store/note_store.js +244 -263
  92. package/dest/storage/note_store/stored_note.d.ts +16 -0
  93. package/dest/storage/note_store/stored_note.d.ts.map +1 -0
  94. package/dest/storage/note_store/stored_note.js +43 -0
  95. package/dest/storage/private_event_store/private_event_store.d.ts +43 -8
  96. package/dest/storage/private_event_store/private_event_store.d.ts.map +1 -1
  97. package/dest/storage/private_event_store/private_event_store.js +196 -104
  98. package/dest/storage/private_event_store/stored_private_event.d.ts +23 -0
  99. package/dest/storage/private_event_store/stored_private_event.d.ts.map +1 -0
  100. package/dest/storage/private_event_store/stored_private_event.js +56 -0
  101. package/dest/storage/tagging_store/recipient_tagging_store.d.ts +15 -8
  102. package/dest/storage/tagging_store/recipient_tagging_store.d.ts.map +1 -1
  103. package/dest/storage/tagging_store/recipient_tagging_store.js +69 -12
  104. package/dest/storage/tagging_store/sender_tagging_store.d.ts +19 -9
  105. package/dest/storage/tagging_store/sender_tagging_store.d.ts.map +1 -1
  106. package/dest/storage/tagging_store/sender_tagging_store.js +109 -27
  107. package/dest/tagging/get_all_logs_by_tags.d.ts +24 -0
  108. package/dest/tagging/get_all_logs_by_tags.d.ts.map +1 -0
  109. package/dest/tagging/get_all_logs_by_tags.js +46 -0
  110. package/dest/tagging/index.d.ts +2 -1
  111. package/dest/tagging/index.d.ts.map +1 -1
  112. package/dest/tagging/index.js +1 -0
  113. package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.d.ts +3 -2
  114. package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.d.ts.map +1 -1
  115. package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.js +6 -6
  116. package/dest/tagging/recipient_sync/utils/load_logs_for_range.d.ts +3 -2
  117. package/dest/tagging/recipient_sync/utils/load_logs_for_range.d.ts.map +1 -1
  118. package/dest/tagging/recipient_sync/utils/load_logs_for_range.js +5 -2
  119. package/dest/tagging/sender_sync/sync_sender_tagging_indexes.d.ts +3 -2
  120. package/dest/tagging/sender_sync/sync_sender_tagging_indexes.d.ts.map +1 -1
  121. package/dest/tagging/sender_sync/sync_sender_tagging_indexes.js +7 -7
  122. package/dest/tagging/sender_sync/utils/get_status_change_of_pending.d.ts +1 -1
  123. package/dest/tagging/sender_sync/utils/get_status_change_of_pending.d.ts.map +1 -1
  124. package/dest/tagging/sender_sync/utils/get_status_change_of_pending.js +5 -8
  125. package/dest/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.d.ts +5 -2
  126. package/dest/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.d.ts.map +1 -1
  127. package/dest/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.js +10 -5
  128. package/package.json +18 -18
  129. package/src/bin/check_oracle_version.ts +1 -0
  130. package/src/block_synchronizer/block_synchronizer.ts +70 -21
  131. package/src/config/index.ts +14 -0
  132. package/src/contract_function_simulator/benchmarked_node.ts +103 -0
  133. package/src/contract_function_simulator/contract_function_simulator.ts +28 -22
  134. package/src/contract_function_simulator/execution_note_cache.ts +44 -25
  135. package/src/contract_function_simulator/index.ts +1 -1
  136. package/src/contract_function_simulator/noir-structs/event_validation_request.ts +1 -1
  137. package/src/contract_function_simulator/noir-structs/note_validation_request.ts +1 -1
  138. package/src/contract_function_simulator/noir-structs/utility_context.ts +6 -25
  139. package/src/contract_function_simulator/oracle/interfaces.ts +20 -10
  140. package/src/contract_function_simulator/oracle/note_packing_utils.ts +10 -10
  141. package/src/contract_function_simulator/oracle/oracle.ts +56 -41
  142. package/src/contract_function_simulator/oracle/private_execution.ts +1 -67
  143. package/src/contract_function_simulator/oracle/private_execution_oracle.ts +35 -8
  144. package/src/contract_function_simulator/oracle/utility_execution_oracle.ts +88 -76
  145. package/src/contract_sync/index.ts +98 -0
  146. package/src/debug/pxe_debug_utils.ts +3 -2
  147. package/src/entrypoints/server/index.ts +2 -0
  148. package/src/events/event_service.ts +15 -21
  149. package/src/events/private_event_filter_validator.ts +3 -5
  150. package/src/logs/log_service.ts +27 -9
  151. package/src/notes/note_service.ts +37 -40
  152. package/src/oracle_version.ts +4 -3
  153. package/src/private_kernel/hints/index.ts +1 -1
  154. package/src/private_kernel/hints/{build_private_kernel_reset_private_inputs.ts → private_kernel_reset_private_inputs_builder.ts} +32 -20
  155. package/src/private_kernel/private_kernel_execution_prover.ts +1 -1
  156. package/src/private_kernel/private_kernel_oracle.ts +116 -37
  157. package/src/pxe.ts +63 -112
  158. package/src/storage/capsule_store/capsule_store.ts +159 -23
  159. package/src/storage/contract_store/contract_store.ts +0 -20
  160. package/src/storage/note_store/note_store.ts +286 -317
  161. package/src/storage/note_store/stored_note.ts +48 -0
  162. package/src/storage/private_event_store/private_event_store.ts +266 -119
  163. package/src/storage/private_event_store/stored_private_event.ts +73 -0
  164. package/src/storage/tagging_store/recipient_tagging_store.ts +89 -13
  165. package/src/storage/tagging_store/sender_tagging_store.ts +128 -27
  166. package/src/tagging/get_all_logs_by_tags.ts +68 -0
  167. package/src/tagging/index.ts +1 -0
  168. package/src/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.ts +16 -5
  169. package/src/tagging/recipient_sync/utils/load_logs_for_range.ts +7 -1
  170. package/src/tagging/sender_sync/sync_sender_tagging_indexes.ts +9 -6
  171. package/src/tagging/sender_sync/utils/get_status_change_of_pending.ts +5 -17
  172. package/src/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.ts +16 -4
  173. package/dest/contract_function_simulator/proxied_node.d.ts +0 -9
  174. package/dest/contract_function_simulator/proxied_node.d.ts.map +0 -1
  175. package/dest/contract_function_simulator/proxied_node.js +0 -27
  176. package/dest/private_kernel/hints/build_private_kernel_reset_private_inputs.d.ts +0 -28
  177. package/dest/private_kernel/hints/build_private_kernel_reset_private_inputs.d.ts.map +0 -1
  178. package/dest/private_kernel/private_kernel_oracle_impl.d.ts +0 -46
  179. package/dest/private_kernel/private_kernel_oracle_impl.d.ts.map +0 -1
  180. package/dest/private_kernel/private_kernel_oracle_impl.js +0 -85
  181. package/dest/public_storage/public_storage_service.d.ts +0 -24
  182. package/dest/public_storage/public_storage_service.d.ts.map +0 -1
  183. package/dest/public_storage/public_storage_service.js +0 -26
  184. package/dest/tree_membership/tree_membership_service.d.ts +0 -52
  185. package/dest/tree_membership/tree_membership_service.d.ts.map +0 -1
  186. package/dest/tree_membership/tree_membership_service.js +0 -84
  187. package/src/contract_function_simulator/proxied_node.ts +0 -33
  188. package/src/private_kernel/private_kernel_oracle_impl.ts +0 -127
  189. package/src/public_storage/public_storage_service.ts +0 -33
  190. package/src/tree_membership/tree_membership_service.ts +0 -112
package/src/pxe.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { PrivateEventFilter } from '@aztec/aztec.js/wallet';
2
+ import { BlockNumber } from '@aztec/foundation/branded-types';
2
3
  import { Fr } from '@aztec/foundation/curves/bn254';
3
4
  import { type Logger, createLogger } from '@aztec/foundation/log';
4
5
  import { SerialQueue } from '@aztec/foundation/queue';
@@ -19,14 +20,12 @@ import type { AuthWitness } from '@aztec/stdlib/auth-witness';
19
20
  import type { AztecAddress } from '@aztec/stdlib/aztec-address';
20
21
  import {
21
22
  CompleteAddress,
22
- type ContractClassWithId,
23
23
  type ContractInstanceWithAddress,
24
24
  type PartialAddress,
25
25
  computeContractAddressFromInstance,
26
26
  getContractClassFromArtifact,
27
27
  } from '@aztec/stdlib/contract';
28
28
  import { SimulationError } from '@aztec/stdlib/errors';
29
- import { computeProtocolNullifier, siloNullifier } from '@aztec/stdlib/hash';
30
29
  import type { AztecNode, PrivateKernelProver } from '@aztec/stdlib/interfaces/client';
31
30
  import type {
32
31
  PrivateExecutionStep,
@@ -54,13 +53,13 @@ import { inspect } from 'util';
54
53
 
55
54
  import { BlockSynchronizer } from './block_synchronizer/index.js';
56
55
  import type { PXEConfig } from './config/index.js';
56
+ import { BenchmarkedNodeFactory } from './contract_function_simulator/benchmarked_node.js';
57
57
  import {
58
58
  ContractFunctionSimulator,
59
59
  generateSimulatedProvingResult,
60
60
  } from './contract_function_simulator/contract_function_simulator.js';
61
- import { readCurrentClassId } from './contract_function_simulator/oracle/private_execution.js';
62
61
  import { ProxiedContractStoreFactory } from './contract_function_simulator/proxied_contract_data_source.js';
63
- import { ProxiedNodeFactory } from './contract_function_simulator/proxied_node.js';
62
+ import { ensureContractSynced, readCurrentClassId } from './contract_sync/index.js';
64
63
  import { PXEDebugUtils } from './debug/pxe_debug_utils.js';
65
64
  import { enrichPublicSimulationError, enrichSimulationError } from './error_enriching.js';
66
65
  import { PrivateEventFilterValidator } from './events/private_event_filter_validator.js';
@@ -69,7 +68,7 @@ import {
69
68
  PrivateKernelExecutionProver,
70
69
  type PrivateKernelExecutionProverConfig,
71
70
  } from './private_kernel/private_kernel_execution_prover.js';
72
- import { PrivateKernelOracleImpl } from './private_kernel/private_kernel_oracle_impl.js';
71
+ import { PrivateKernelOracle } from './private_kernel/private_kernel_oracle.js';
73
72
  import { AddressStore } from './storage/address_store/address_store.js';
74
73
  import { AnchorBlockStore } from './storage/anchor_block_store/anchor_block_store.js';
75
74
  import { CapsuleStore } from './storage/capsule_store/capsule_store.js';
@@ -138,7 +137,7 @@ export class PXE {
138
137
  const addressStore = new AddressStore(store);
139
138
  const privateEventStore = new PrivateEventStore(store);
140
139
  const contractStore = new ContractStore(store);
141
- const noteStore = await NoteStore.create(store);
140
+ const noteStore = new NoteStore(store);
142
141
  const anchorBlockStore = new AnchorBlockStore(store);
143
142
  const senderTaggingStore = new SenderTaggingStore(store);
144
143
  const senderAddressBookStore = new SenderAddressBookStore(store);
@@ -148,6 +147,7 @@ export class PXE {
148
147
  const tipsStore = new L2TipsKVStore(store, 'pxe');
149
148
  const synchronizer = new BlockSynchronizer(
150
149
  node,
150
+ store,
151
151
  anchorBlockStore,
152
152
  noteStore,
153
153
  privateEventStore,
@@ -157,6 +157,13 @@ export class PXE {
157
157
  );
158
158
 
159
159
  const jobCoordinator = new JobCoordinator(store);
160
+ jobCoordinator.registerStores([
161
+ capsuleStore,
162
+ senderTaggingStore,
163
+ recipientTaggingStore,
164
+ privateEventStore,
165
+ noteStore,
166
+ ]);
160
167
 
161
168
  const debugUtils = new PXEDebugUtils(contractStore, noteStore);
162
169
 
@@ -205,7 +212,7 @@ export class PXE {
205
212
  this.noteStore,
206
213
  this.keyStore,
207
214
  this.addressStore,
208
- ProxiedNodeFactory.create(this.node),
215
+ BenchmarkedNodeFactory.create(this.node),
209
216
  this.anchorBlockStore,
210
217
  this.senderTaggingStore,
211
218
  this.recipientTaggingStore,
@@ -274,19 +281,6 @@ export class PXE {
274
281
  this.log.verbose(`Registered protocol contracts in pxe`, registered);
275
282
  }
276
283
 
277
- async #isContractClassPubliclyRegistered(id: Fr): Promise<boolean> {
278
- return !!(await this.node.getContractClass(id));
279
- }
280
-
281
- async #isContractPublished(address: AztecAddress): Promise<boolean> {
282
- return !!(await this.node.getContract(address));
283
- }
284
-
285
- async #isContractInitialized(address: AztecAddress): Promise<boolean> {
286
- const initNullifier = await siloNullifier(address, address.toField());
287
- return !!(await this.node.getNullifierMembershipWitness('latest', initNullifier));
288
- }
289
-
290
284
  // Executes the entrypoint private function, as well as all nested private
291
285
  // functions that might arise.
292
286
  async #executePrivate(
@@ -300,6 +294,15 @@ export class PXE {
300
294
  try {
301
295
  const anchorBlockHeader = await this.anchorBlockStore.getBlockHeader();
302
296
 
297
+ await ensureContractSynced(
298
+ contractAddress,
299
+ functionSelector,
300
+ privateSyncCall => this.#simulateUtility(contractFunctionSimulator, privateSyncCall, [], undefined, jobId),
301
+ this.node,
302
+ this.contractStore,
303
+ anchorBlockHeader,
304
+ );
305
+
303
306
  const result = await contractFunctionSimulator.run(
304
307
  txRequest,
305
308
  contractAddress,
@@ -394,13 +397,9 @@ export class PXE {
394
397
  privateExecutionResult: PrivateExecutionResult,
395
398
  config: PrivateKernelExecutionProverConfig,
396
399
  ): Promise<PrivateKernelExecutionProofOutput<PrivateKernelTailCircuitPublicInputs>> {
397
- const simulationAnchorBlock = privateExecutionResult.getSimulationAnchorBlockNumber();
398
- const kernelOracle = new PrivateKernelOracleImpl(
399
- this.contractStore,
400
- this.keyStore,
401
- this.node,
402
- simulationAnchorBlock,
403
- );
400
+ const anchorBlockHeader = await this.anchorBlockStore.getBlockHeader();
401
+ const anchorBlockHash = await anchorBlockHeader.hash();
402
+ const kernelOracle = new PrivateKernelOracle(this.contractStore, this.keyStore, this.node, anchorBlockHash);
404
403
  const kernelTraceProver = new PrivateKernelExecutionProver(kernelOracle, proofCreator, !this.proverEnabled);
405
404
  this.log.debug(`Executing kernel trace prover (${JSON.stringify(config)})...`);
406
405
  return await kernelTraceProver.proveWithKernels(txExecutionRequest.toTxRequest(), privateExecutionResult, config);
@@ -413,66 +412,12 @@ export class PXE {
413
412
  }
414
413
 
415
414
  /**
416
- * Returns the contract class metadata given a contract class id.
417
- * The metadata consists of its contract class, whether it has been publicly registered, and its artifact.
418
- * @remark - it queries the node to check whether the contract class with the given id has been publicly registered.
419
- * @param id - Identifier of the class.
420
- * @param includeArtifact - Identifier of the class.
421
- * @returns - It returns the contract class metadata, with the artifact field being optional, and will only be returned if true is passed in
422
- * for `includeArtifact`
423
- * TODO(@spalladino): The PXE actually holds artifacts and not classes, what should we return? Also,
424
- * should the pxe query the node for contract public info, and merge it with its own definitions?
425
- * TODO(@spalladino): This method is strictly needed to decide whether to publicly register a class or not
426
- * during a public deployment. We probably want a nicer and more general API for this, but it'll have to
427
- * do for the time being.
415
+ * Returns the contract artifact for a given contract class id, if it's registered in the PXE.
416
+ * @param id - Identifier of the contract class.
417
+ * @returns The contract artifact if found, undefined otherwise.
428
418
  */
429
- public async getContractClassMetadata(
430
- id: Fr,
431
- includeArtifact: boolean = false,
432
- ): Promise<{
433
- contractClass: ContractClassWithId | undefined;
434
- isContractClassPubliclyRegistered: boolean;
435
- artifact: ContractArtifact | undefined;
436
- }> {
437
- const artifact = await this.contractStore.getContractArtifact(id);
438
- if (!artifact) {
439
- this.log.warn(`No artifact found for contract class ${id.toString()} when looking for its metadata`);
440
- }
441
-
442
- return {
443
- contractClass: artifact && (await getContractClassFromArtifact(artifact)),
444
- isContractClassPubliclyRegistered: await this.#isContractClassPubliclyRegistered(id),
445
- artifact: includeArtifact ? artifact : undefined,
446
- };
447
- }
448
-
449
- /**
450
- * Returns the contract metadata given an address.
451
- * The metadata consists of its contract instance, which includes the contract class identifier,
452
- * initialization hash, deployment salt, and public keys hash; whether the contract instance has been initialized;
453
- * and whether the contract instance with the given address has been publicly deployed.
454
- * @remark - it queries the node to check whether the contract instance has been initialized / publicly deployed through a node.
455
- * This query is not dependent on the PXE.
456
- * @param address - The address that the contract instance resides at.
457
- * @returns - It returns the contract metadata
458
- * TODO(@spalladino): Should we return the public keys in plain as well here?
459
- */
460
- public async getContractMetadata(address: AztecAddress): Promise<{
461
- contractInstance: ContractInstanceWithAddress | undefined;
462
- isContractInitialized: boolean;
463
- isContractPublished: boolean;
464
- }> {
465
- let instance;
466
- try {
467
- instance = await this.contractStore.getContractInstance(address);
468
- } catch {
469
- this.log.warn(`No instance found for contract ${address.toString()} when looking for its metadata`);
470
- }
471
- return {
472
- contractInstance: instance,
473
- isContractInitialized: await this.#isContractInitialized(address),
474
- isContractPublished: await this.#isContractPublished(address),
475
- };
419
+ public async getContractArtifact(id: Fr): Promise<ContractArtifact | undefined> {
420
+ return await this.contractStore.getContractArtifact(id);
476
421
  }
477
422
 
478
423
  /**
@@ -497,7 +442,6 @@ export class PXE {
497
442
  }
498
443
 
499
444
  await this.addressStore.addCompleteAddress(accountCompleteAddress);
500
- await this.noteStore.addScope(accountCompleteAddress.address);
501
445
  return accountCompleteAddress;
502
446
  }
503
447
 
@@ -645,13 +589,7 @@ export class PXE {
645
589
 
646
590
  const header = await this.anchorBlockStore.getBlockHeader();
647
591
 
648
- const currentClassId = await readCurrentClassId(
649
- contractAddress,
650
- currentInstance,
651
- this.node,
652
- header.globalVariables.blockNumber,
653
- header.globalVariables.timestamp,
654
- );
592
+ const currentClassId = await readCurrentClassId(contractAddress, currentInstance, this.node, header);
655
593
  if (!contractClass.id.equals(currentClassId)) {
656
594
  throw new Error('Could not update contract to a class different from the current one.');
657
595
  }
@@ -744,7 +682,7 @@ export class PXE {
744
682
  // TODO(benesjan): The following is an expensive operation. Figure out a way to avoid it.
745
683
  const txHash = (await txProvingResult.toTx()).txHash;
746
684
 
747
- await this.senderTaggingStore.storePendingIndexes(preTagsUsedInTheTx, txHash);
685
+ await this.senderTaggingStore.storePendingIndexes(preTagsUsedInTheTx, txHash, jobId);
748
686
  this.log.debug(`Stored used pre-tags as sender for the tx`, {
749
687
  preTagsUsedInTheTx,
750
688
  });
@@ -911,14 +849,8 @@ export class PXE {
911
849
  let executionSteps: PrivateExecutionStep[] = [];
912
850
 
913
851
  if (skipKernels) {
914
- // According to the protocol rules, the nonce generator for the note hashes
915
- // can either be the first nullifier in the tx or the protocol nullifier if there are none.
916
- const nonceGenerator = privateExecutionResult.firstNullifier.equals(Fr.ZERO)
917
- ? await computeProtocolNullifier(await txRequest.toTxRequest().hash())
918
- : privateExecutionResult.firstNullifier;
919
852
  ({ publicInputs, executionSteps } = await generateSimulatedProvingResult(
920
853
  privateExecutionResult,
921
- nonceGenerator,
922
854
  this.contractStore,
923
855
  ));
924
856
  } else {
@@ -1029,8 +961,14 @@ export class PXE {
1029
961
  const functionTimer = new Timer();
1030
962
  const contractFunctionSimulator = this.#getSimulatorForTx();
1031
963
 
1032
- await this.contractStore.syncPrivateState(call.to, call.selector, privateSyncCall =>
1033
- this.#simulateUtility(contractFunctionSimulator, privateSyncCall, [], undefined, jobId),
964
+ const anchorBlockHeader = await this.anchorBlockStore.getBlockHeader();
965
+ await ensureContractSynced(
966
+ call.to,
967
+ call.selector,
968
+ privateSyncCall => this.#simulateUtility(contractFunctionSimulator, privateSyncCall, [], undefined, jobId),
969
+ this.node,
970
+ this.contractStore,
971
+ anchorBlockHeader,
1034
972
  );
1035
973
 
1036
974
  const executionResult = await this.#simulateUtility(
@@ -1080,26 +1018,39 @@ export class PXE {
1080
1018
  * Defaults to the latest known block to PXE + 1.
1081
1019
  * @returns - The packed events with block and tx metadata.
1082
1020
  */
1083
- public getPrivateEvents(eventSelector: EventSelector, filter: PrivateEventFilter): Promise<PackedPrivateEvent[]> {
1084
- return this.#putInJobQueue(async jobId => {
1021
+ public async getPrivateEvents(
1022
+ eventSelector: EventSelector,
1023
+ filter: PrivateEventFilter,
1024
+ ): Promise<PackedPrivateEvent[]> {
1025
+ let anchorBlockNumber: BlockNumber;
1026
+
1027
+ await this.#putInJobQueue(async jobId => {
1085
1028
  await this.blockStateSynchronizer.sync();
1029
+
1030
+ const anchorBlockHeader = await this.anchorBlockStore.getBlockHeader();
1031
+ anchorBlockNumber = anchorBlockHeader.getBlockNumber();
1032
+
1086
1033
  const contractFunctionSimulator = this.#getSimulatorForTx();
1087
1034
 
1088
- await this.contractStore.syncPrivateState(
1035
+ await ensureContractSynced(
1089
1036
  filter.contractAddress,
1090
1037
  null,
1091
1038
  async privateSyncCall =>
1092
1039
  await this.#simulateUtility(contractFunctionSimulator, privateSyncCall, [], undefined, jobId),
1040
+ this.node,
1041
+ this.contractStore,
1042
+ anchorBlockHeader,
1093
1043
  );
1044
+ });
1094
1045
 
1095
- const sanitizedFilter = await new PrivateEventFilterValidator(this.anchorBlockStore).validate(filter);
1046
+ // anchorBlockNumber is set during the job and fixed to whatever it is after a block sync
1047
+ const sanitizedFilter = new PrivateEventFilterValidator(anchorBlockNumber!).validate(filter);
1096
1048
 
1097
- this.log.debug(
1098
- `Getting private events for ${sanitizedFilter.contractAddress.toString()} from ${sanitizedFilter.fromBlock} to ${sanitizedFilter.toBlock}`,
1099
- );
1049
+ this.log.debug(
1050
+ `Getting private events for ${sanitizedFilter.contractAddress.toString()} from ${sanitizedFilter.fromBlock} to ${sanitizedFilter.toBlock}`,
1051
+ );
1100
1052
 
1101
- return this.privateEventStore.getPrivateEvents(eventSelector, sanitizedFilter);
1102
- });
1053
+ return this.privateEventStore.getPrivateEvents(eventSelector, sanitizedFilter);
1103
1054
  }
1104
1055
 
1105
1056
  /**
@@ -3,12 +3,21 @@ import { type Logger, createLogger } from '@aztec/foundation/log';
3
3
  import type { AztecAsyncKVStore, AztecAsyncMap } from '@aztec/kv-store';
4
4
  import type { AztecAddress } from '@aztec/stdlib/aztec-address';
5
5
 
6
- export class CapsuleStore {
6
+ import type { StagedStore } from '../../job_coordinator/job_coordinator.js';
7
+
8
+ export class CapsuleStore implements StagedStore {
9
+ readonly storeName = 'capsule';
10
+
7
11
  #store: AztecAsyncKVStore;
8
12
 
9
13
  // Arbitrary data stored by contracts. Key is computed as `${contractAddress}:${key}`
10
14
  #capsules: AztecAsyncMap<string, Buffer>;
11
15
 
16
+ // jobId => `${contractAddress}:${key}` => capsule data
17
+ // when `#stagedCapsules.get('some-job-id').get('${some-contract-address:some-key') === null`,
18
+ // it signals that the capsule was deleted during the job, so it needs to be deleted on commit
19
+ #stagedCapsules: Map<string, Map<string, Buffer | null>>;
20
+
12
21
  logger: Logger;
13
22
 
14
23
  constructor(store: AztecAsyncKVStore) {
@@ -16,21 +25,120 @@ export class CapsuleStore {
16
25
 
17
26
  this.#capsules = this.#store.openMap('capsules');
18
27
 
28
+ this.#stagedCapsules = new Map();
29
+
19
30
  this.logger = createLogger('pxe:capsule-data-provider');
20
31
  }
21
32
 
33
+ /**
34
+ * Given a job denoted by `jobId`, it returns the
35
+ * capsules that said job has interacted with.
36
+ *
37
+ * Capsules that haven't been committed to persistence KV storage
38
+ * are kept in-memory in `#stagedCapsules`, this method provides a convenient
39
+ * way to access that in-memory collection of data.
40
+ *
41
+ * @param jobId
42
+ * @returns
43
+ */
44
+ #getJobStagedCapsules(jobId: string): Map<string, Buffer | null> {
45
+ let jobStagedCapsules = this.#stagedCapsules.get(jobId);
46
+ if (!jobStagedCapsules) {
47
+ jobStagedCapsules = new Map();
48
+ this.#stagedCapsules.set(jobId, jobStagedCapsules);
49
+ }
50
+ return jobStagedCapsules;
51
+ }
52
+
53
+ /**
54
+ * Reads a capsule's slot from the staged version of the data associated to the given jobId.
55
+ *
56
+ * If it is not there, it reads it from the KV store.
57
+ */
58
+ async #getFromStage(jobId: string, dbSlotKey: string): Promise<Buffer | null | undefined> {
59
+ const jobStagedCapsules = this.#getJobStagedCapsules(jobId);
60
+ let staged: Buffer | null | undefined = jobStagedCapsules.get(dbSlotKey);
61
+ // Note that if staged === null, we marked it for deletion, so we don't want to
62
+ // re-read it from DB
63
+ if (staged === undefined) {
64
+ // If we don't have a staged version of this dbSlotKey, first we check if there's one in DB
65
+ staged = await this.#loadCapsuleFromDb(dbSlotKey);
66
+ }
67
+ return staged;
68
+ }
69
+
70
+ /**
71
+ * Writes a capsule to the stage of a job.
72
+ */
73
+ #setOnStage(jobId: string, dbSlotKey: string, capsuleData: Buffer) {
74
+ this.#getJobStagedCapsules(jobId).set(dbSlotKey, capsuleData);
75
+ }
76
+
77
+ /**
78
+ * Deletes a capsule on the stage of a job. Note the capsule will still
79
+ * exist in storage until the job is committed.
80
+ */
81
+ #deleteOnStage(jobId: string, dbSlotKey: string) {
82
+ this.#getJobStagedCapsules(jobId).set(dbSlotKey, null);
83
+ }
84
+
85
+ async #loadCapsuleFromDb(dbSlotKey: string): Promise<Buffer | null> {
86
+ const dataBuffer = await this.#capsules.getAsync(dbSlotKey);
87
+ if (!dataBuffer) {
88
+ return null;
89
+ }
90
+
91
+ return dataBuffer;
92
+ }
93
+
94
+ /**
95
+ * Commits staged data to main storage.
96
+ * Called by JobCoordinator when a job completes successfully.
97
+ * Note: JobCoordinator wraps all commits in a single transaction, so we don't
98
+ * need our own transactionAsync here (and using one would deadlock on IndexedDB).
99
+ * @param jobId - The jobId identifying which staged data to commit
100
+ */
101
+ async commit(jobId: string): Promise<void> {
102
+ const jobStagedCapsules = this.#getJobStagedCapsules(jobId);
103
+
104
+ for (const [key, value] of jobStagedCapsules) {
105
+ // In the write stage, we represent deleted capsules with null
106
+ // (as opposed to undefined, which denotes there was never a capsule there to begin with).
107
+ // So we delete from actual KV store here.
108
+ if (value === null) {
109
+ await this.#capsules.delete(key);
110
+ } else {
111
+ await this.#capsules.set(key, value);
112
+ }
113
+ }
114
+
115
+ this.#stagedCapsules.delete(jobId);
116
+ }
117
+
118
+ /**
119
+ * Discards staged data without committing.
120
+ */
121
+ discardStaged(jobId: string): Promise<void> {
122
+ this.#stagedCapsules.delete(jobId);
123
+ return Promise.resolve();
124
+ }
125
+
22
126
  /**
23
127
  * Stores arbitrary information in a per-contract non-volatile database, which can later be retrieved with `loadCapsule`.
24
128
  * * If data was already stored at this slot, it is overwritten.
25
129
  * @param contractAddress - The contract address to scope the data under.
26
130
  * @param slot - The slot in the database in which to store the value. Slots need not be contiguous.
27
131
  * @param capsule - An array of field elements representing the capsule.
132
+ * @param jobId - The context in which this store will be visible until PXE decides to persist it to underlying KV store
28
133
  * @remarks A capsule is a "blob" of data that is passed to the contract through an oracle. It works similarly
29
134
  * to public contract storage in that it's indexed by the contract address and storage slot but instead of the global
30
135
  * network state it's backed by local PXE db.
31
136
  */
32
- async storeCapsule(contractAddress: AztecAddress, slot: Fr, capsule: Fr[]): Promise<void> {
33
- await this.#capsules.set(dbSlotToKey(contractAddress, slot), Buffer.concat(capsule.map(value => value.toBuffer())));
137
+ storeCapsule(contractAddress: AztecAddress, slot: Fr, capsule: Fr[], jobId: string) {
138
+ const dbSlotKey = dbSlotToKey(contractAddress, slot);
139
+
140
+ // A store overrides any pre-existing data on the slot
141
+ this.#setOnStage(jobId, dbSlotKey, Buffer.concat(capsule.map(value => value.toBuffer())));
34
142
  }
35
143
 
36
144
  /**
@@ -39,8 +147,8 @@ export class CapsuleStore {
39
147
  * @param slot - The slot in the database to read.
40
148
  * @returns The stored data or `null` if no data is stored under the slot.
41
149
  */
42
- async loadCapsule(contractAddress: AztecAddress, slot: Fr): Promise<Fr[] | null> {
43
- const dataBuffer = await this.#capsules.getAsync(dbSlotToKey(contractAddress, slot));
150
+ async loadCapsule(contractAddress: AztecAddress, slot: Fr, jobId: string): Promise<Fr[] | null> {
151
+ const dataBuffer = await this.#getFromStage(jobId, dbSlotToKey(contractAddress, slot));
44
152
  if (!dataBuffer) {
45
153
  this.logger.trace(`Data not found for contract ${contractAddress.toString()} and slot ${slot.toString()}`);
46
154
  return null;
@@ -57,8 +165,9 @@ export class CapsuleStore {
57
165
  * @param contractAddress - The contract address under which the data is scoped.
58
166
  * @param slot - The slot in the database to delete.
59
167
  */
60
- async deleteCapsule(contractAddress: AztecAddress, slot: Fr): Promise<void> {
61
- await this.#capsules.delete(dbSlotToKey(contractAddress, slot));
168
+ deleteCapsule(contractAddress: AztecAddress, slot: Fr, jobId: string) {
169
+ // When we commit this, we will interpret null as a deletion, so we'll propagate the delete to the KV store
170
+ this.#deleteOnStage(jobId, dbSlotToKey(contractAddress, slot));
62
171
  }
63
172
 
64
173
  /**
@@ -72,13 +181,22 @@ export class CapsuleStore {
72
181
  * @param dstSlot - The first slot to copy to.
73
182
  * @param numEntries - The number of entries to copy.
74
183
  */
75
- copyCapsule(contractAddress: AztecAddress, srcSlot: Fr, dstSlot: Fr, numEntries: number): Promise<void> {
184
+ copyCapsule(
185
+ contractAddress: AztecAddress,
186
+ srcSlot: Fr,
187
+ dstSlot: Fr,
188
+ numEntries: number,
189
+ jobId: string,
190
+ ): Promise<void> {
191
+ // This transactional context gives us "copy atomicity":
192
+ // there shouldn't be concurrent writes to what's being copied here.
193
+ // Equally important: this in practice is expected to perform thousands of DB operations
194
+ // and not using a transaction here would heavily impact performance.
76
195
  return this.#store.transactionAsync(async () => {
77
196
  // In order to support overlapping source and destination regions, we need to check the relative positions of source
78
197
  // and destination. If destination is ahead of source, then by the time we overwrite source elements using forward
79
198
  // indexes we'll have already read those. On the contrary, if source is ahead of destination we need to use backward
80
199
  // indexes to avoid reading elements that've been overwritten.
81
-
82
200
  const indexes = Array.from(Array(numEntries).keys());
83
201
  if (srcSlot.lt(dstSlot)) {
84
202
  indexes.reverse();
@@ -88,12 +206,12 @@ export class CapsuleStore {
88
206
  const currentSrcSlot = dbSlotToKey(contractAddress, srcSlot.add(new Fr(i)));
89
207
  const currentDstSlot = dbSlotToKey(contractAddress, dstSlot.add(new Fr(i)));
90
208
 
91
- const toCopy = await this.#capsules.getAsync(currentSrcSlot);
209
+ const toCopy = await this.#getFromStage(jobId, currentSrcSlot);
92
210
  if (!toCopy) {
93
211
  throw new Error(`Attempted to copy empty slot ${currentSrcSlot} for contract ${contractAddress.toString()}`);
94
212
  }
95
213
 
96
- await this.#capsules.set(currentDstSlot, toCopy);
214
+ this.#setOnStage(jobId, currentDstSlot, toCopy);
97
215
  }
98
216
  });
99
217
  }
@@ -106,35 +224,45 @@ export class CapsuleStore {
106
224
  * @param baseSlot - The slot where the array length is stored
107
225
  * @param content - Array of capsule data to append
108
226
  */
109
- appendToCapsuleArray(contractAddress: AztecAddress, baseSlot: Fr, content: Fr[][]): Promise<void> {
227
+ appendToCapsuleArray(contractAddress: AztecAddress, baseSlot: Fr, content: Fr[][], jobId: string): Promise<void> {
228
+ // We wrap this in a transaction to serialize concurrent calls from Promise.all.
229
+ // Without this, concurrent appends to the same array could race: both read length=0,
230
+ // both write at the same slots, one overwrites the other.
231
+ // Equally important: this in practice is expected to perform thousands of DB operations
232
+ // and not using a transaction here would heavily impact performance.
110
233
  return this.#store.transactionAsync(async () => {
111
234
  // Load current length, defaulting to 0 if not found
112
- const lengthData = await this.loadCapsule(contractAddress, baseSlot);
235
+ const lengthData = await this.loadCapsule(contractAddress, baseSlot, jobId);
113
236
  const currentLength = lengthData ? lengthData[0].toNumber() : 0;
114
237
 
115
238
  // Store each capsule at consecutive slots after baseSlot + 1 + currentLength
116
239
  for (let i = 0; i < content.length; i++) {
117
240
  const nextSlot = arraySlot(baseSlot, currentLength + i);
118
- await this.storeCapsule(contractAddress, nextSlot, content[i]);
241
+ this.storeCapsule(contractAddress, nextSlot, content[i], jobId);
119
242
  }
120
243
 
121
244
  // Update length to include all new capsules
122
245
  const newLength = currentLength + content.length;
123
- await this.storeCapsule(contractAddress, baseSlot, [new Fr(newLength)]);
246
+ this.storeCapsule(contractAddress, baseSlot, [new Fr(newLength)], jobId);
124
247
  });
125
248
  }
126
249
 
127
- readCapsuleArray(contractAddress: AztecAddress, baseSlot: Fr): Promise<Fr[][]> {
250
+ readCapsuleArray(contractAddress: AztecAddress, baseSlot: Fr, jobId: string): Promise<Fr[][]> {
251
+ // I'm leaving this transactional context here though because I'm assuming this
252
+ // gives us "read array atomicity": there shouldn't be concurrent writes to what's being copied
253
+ // here.
254
+ // This is one point we should revisit in the future if we want to relax the concurrency
255
+ // of jobs: different calls running concurrently on the same contract may cause trouble.
128
256
  return this.#store.transactionAsync(async () => {
129
257
  // Load length, defaulting to 0 if not found
130
- const maybeLength = await this.loadCapsule(contractAddress, baseSlot);
258
+ const maybeLength = await this.loadCapsule(contractAddress, baseSlot, jobId);
131
259
  const length = maybeLength ? maybeLength[0].toBigInt() : 0n;
132
260
 
133
261
  const values: Fr[][] = [];
134
262
 
135
263
  // Read each capsule at consecutive slots after baseSlot
136
264
  for (let i = 0; i < length; i++) {
137
- const currentValue = await this.loadCapsule(contractAddress, arraySlot(baseSlot, i));
265
+ const currentValue = await this.loadCapsule(contractAddress, arraySlot(baseSlot, i), jobId);
138
266
  if (currentValue == undefined) {
139
267
  throw new Error(
140
268
  `Expected non-empty value at capsule array in base slot ${baseSlot} at index ${i} for contract ${contractAddress}`,
@@ -148,23 +276,31 @@ export class CapsuleStore {
148
276
  });
149
277
  }
150
278
 
151
- setCapsuleArray(contractAddress: AztecAddress, baseSlot: Fr, content: Fr[][]) {
279
+ setCapsuleArray(contractAddress: AztecAddress, baseSlot: Fr, content: Fr[][], jobId: string) {
280
+ // This transactional context in theory isn't so critical now because we aren't
281
+ // writing to DB so if there's exceptions midway and it blows up, no visible impact
282
+ // to persistent storage will happen.
283
+ // I'm leaving this transactional context here though because I'm assuming this
284
+ // gives us "write array atomicity": there shouldn't be concurrent writes to what's being copied
285
+ // here.
286
+ // This is one point we should revisit in the future if we want to relax the concurrency
287
+ // of jobs: different calls running concurrently on the same contract may cause trouble.
152
288
  return this.#store.transactionAsync(async () => {
153
289
  // Load current length, defaulting to 0 if not found
154
- const maybeLength = await this.loadCapsule(contractAddress, baseSlot);
290
+ const maybeLength = await this.loadCapsule(contractAddress, baseSlot, jobId);
155
291
  const originalLength = maybeLength ? maybeLength[0].toNumber() : 0;
156
292
 
157
293
  // Set the new length
158
- await this.storeCapsule(contractAddress, baseSlot, [new Fr(content.length)]);
294
+ this.storeCapsule(contractAddress, baseSlot, [new Fr(content.length)], jobId);
159
295
 
160
296
  // Store the new content, possibly overwriting existing values
161
297
  for (let i = 0; i < content.length; i++) {
162
- await this.storeCapsule(contractAddress, arraySlot(baseSlot, i), content[i]);
298
+ this.storeCapsule(contractAddress, arraySlot(baseSlot, i), content[i], jobId);
163
299
  }
164
300
 
165
301
  // Clear any stragglers
166
302
  for (let i = content.length; i < originalLength; i++) {
167
- await this.deleteCapsule(contractAddress, arraySlot(baseSlot, i));
303
+ this.deleteCapsule(contractAddress, arraySlot(baseSlot, i), jobId);
168
304
  }
169
305
  });
170
306
  }
@@ -3,7 +3,6 @@ import type { Fr } from '@aztec/foundation/curves/bn254';
3
3
  import { toArray } from '@aztec/foundation/iterable';
4
4
  import type { MembershipWitness } from '@aztec/foundation/trees';
5
5
  import type { AztecAsyncKVStore, AztecAsyncMap } from '@aztec/kv-store';
6
- import { isProtocolContract } from '@aztec/protocol-contracts';
7
6
  import {
8
7
  type ContractArtifact,
9
8
  type FunctionAbi,
@@ -317,23 +316,4 @@ export class ContractStore {
317
316
  returnTypes: functionDao.returnTypes,
318
317
  };
319
318
  }
320
-
321
- // Synchronize target contract data
322
- public async syncPrivateState(
323
- contractAddress: AztecAddress,
324
- functionToInvokeAfterSync: FunctionSelector | null,
325
- utilityExecutor: (privateSyncCall: FunctionCall) => Promise<any>,
326
- ) {
327
- // Protocol contracts don't have private state to sync
328
- if (!isProtocolContract(contractAddress)) {
329
- const syncPrivateStateFunctionCall = await this.getFunctionCall('sync_private_state', [], contractAddress);
330
- if (functionToInvokeAfterSync && functionToInvokeAfterSync.equals(syncPrivateStateFunctionCall.selector)) {
331
- throw new Error(
332
- 'Forbidden `sync_private_state` invocation. `sync_private_state` can only be invoked by PXE, manual execution can lead to inconsistencies.',
333
- );
334
- }
335
-
336
- return utilityExecutor(syncPrivateStateFunctionCall);
337
- }
338
- }
339
319
  }