@aztec/pxe 0.0.1-commit.5de5ca79e → 0.0.1-commit.6201a7b05

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 (191) hide show
  1. package/dest/bin/check_oracle_version.js +4 -4
  2. package/dest/block_synchronizer/block_stream_source.d.ts +10 -0
  3. package/dest/block_synchronizer/block_stream_source.d.ts.map +1 -0
  4. package/dest/block_synchronizer/block_stream_source.js +37 -0
  5. package/dest/block_synchronizer/block_synchronizer.d.ts +6 -2
  6. package/dest/block_synchronizer/block_synchronizer.d.ts.map +1 -1
  7. package/dest/block_synchronizer/block_synchronizer.js +30 -10
  8. package/dest/config/index.d.ts +1 -1
  9. package/dest/config/index.d.ts.map +1 -1
  10. package/dest/config/index.js +7 -14
  11. package/dest/contract_function_simulator/contract_function_simulator.d.ts +6 -4
  12. package/dest/contract_function_simulator/contract_function_simulator.d.ts.map +1 -1
  13. package/dest/contract_function_simulator/contract_function_simulator.js +10 -7
  14. package/dest/contract_function_simulator/ephemeral_array_service.d.ts +28 -0
  15. package/dest/contract_function_simulator/ephemeral_array_service.d.ts.map +1 -0
  16. package/dest/contract_function_simulator/ephemeral_array_service.js +78 -0
  17. package/dest/contract_function_simulator/noir-structs/event_validation_request.d.ts +3 -4
  18. package/dest/contract_function_simulator/noir-structs/event_validation_request.d.ts.map +1 -1
  19. package/dest/contract_function_simulator/noir-structs/event_validation_request.js +3 -6
  20. package/dest/contract_function_simulator/noir-structs/log_retrieval_request.d.ts +1 -1
  21. package/dest/contract_function_simulator/noir-structs/log_retrieval_request.js +1 -1
  22. package/dest/contract_function_simulator/noir-structs/log_retrieval_response.d.ts +1 -1
  23. package/dest/contract_function_simulator/noir-structs/log_retrieval_response.js +1 -1
  24. package/dest/contract_function_simulator/noir-structs/note_validation_request.d.ts +3 -4
  25. package/dest/contract_function_simulator/noir-structs/note_validation_request.d.ts.map +1 -1
  26. package/dest/contract_function_simulator/noir-structs/note_validation_request.js +3 -6
  27. package/dest/contract_function_simulator/oracle/interfaces.d.ts +31 -20
  28. package/dest/contract_function_simulator/oracle/interfaces.d.ts.map +1 -1
  29. package/dest/contract_function_simulator/oracle/legacy_oracle_mappings.d.ts +1 -1
  30. package/dest/contract_function_simulator/oracle/legacy_oracle_mappings.d.ts.map +1 -1
  31. package/dest/contract_function_simulator/oracle/legacy_oracle_mappings.js +28 -23
  32. package/dest/contract_function_simulator/oracle/oracle.d.ts +50 -20
  33. package/dest/contract_function_simulator/oracle/oracle.d.ts.map +1 -1
  34. package/dest/contract_function_simulator/oracle/oracle.js +157 -41
  35. package/dest/contract_function_simulator/oracle/private_execution.js +1 -1
  36. package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts +16 -15
  37. package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts.map +1 -1
  38. package/dest/contract_function_simulator/oracle/private_execution_oracle.js +36 -21
  39. package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts +58 -42
  40. package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts.map +1 -1
  41. package/dest/contract_function_simulator/oracle/utility_execution_oracle.js +205 -96
  42. package/dest/contract_function_simulator/pick_notes.d.ts +1 -1
  43. package/dest/contract_function_simulator/pick_notes.d.ts.map +1 -1
  44. package/dest/contract_function_simulator/pick_notes.js +20 -3
  45. package/dest/contract_function_simulator/proxied_contract_data_source.d.ts +1 -1
  46. package/dest/contract_function_simulator/proxied_contract_data_source.d.ts.map +1 -1
  47. package/dest/contract_function_simulator/proxied_contract_data_source.js +3 -0
  48. package/dest/contract_logging.d.ts +9 -4
  49. package/dest/contract_logging.d.ts.map +1 -1
  50. package/dest/contract_logging.js +21 -6
  51. package/dest/contract_sync/contract_sync_service.d.ts +3 -4
  52. package/dest/contract_sync/contract_sync_service.d.ts.map +1 -1
  53. package/dest/contract_sync/contract_sync_service.js +37 -35
  54. package/dest/contract_sync/helpers.d.ts +2 -3
  55. package/dest/contract_sync/helpers.d.ts.map +1 -1
  56. package/dest/contract_sync/helpers.js +7 -2
  57. package/dest/debug/pxe_debug_utils.d.ts +3 -3
  58. package/dest/debug/pxe_debug_utils.d.ts.map +1 -1
  59. package/dest/entrypoints/client/bundle/index.d.ts +1 -2
  60. package/dest/entrypoints/client/bundle/index.d.ts.map +1 -1
  61. package/dest/entrypoints/client/bundle/index.js +0 -1
  62. package/dest/entrypoints/client/bundle/utils.d.ts +2 -2
  63. package/dest/entrypoints/client/bundle/utils.d.ts.map +1 -1
  64. package/dest/entrypoints/client/bundle/utils.js +2 -2
  65. package/dest/entrypoints/client/lazy/index.d.ts +1 -2
  66. package/dest/entrypoints/client/lazy/index.d.ts.map +1 -1
  67. package/dest/entrypoints/client/lazy/index.js +0 -1
  68. package/dest/entrypoints/client/lazy/utils.d.ts +2 -2
  69. package/dest/entrypoints/client/lazy/utils.d.ts.map +1 -1
  70. package/dest/entrypoints/client/lazy/utils.js +2 -2
  71. package/dest/entrypoints/pxe_creation_options.d.ts +3 -1
  72. package/dest/entrypoints/pxe_creation_options.d.ts.map +1 -1
  73. package/dest/entrypoints/pxe_creation_options.js +3 -1
  74. package/dest/entrypoints/server/index.d.ts +2 -3
  75. package/dest/entrypoints/server/index.d.ts.map +1 -1
  76. package/dest/entrypoints/server/index.js +1 -2
  77. package/dest/entrypoints/server/utils.d.ts +2 -2
  78. package/dest/entrypoints/server/utils.d.ts.map +1 -1
  79. package/dest/entrypoints/server/utils.js +2 -2
  80. package/dest/events/event_service.d.ts +3 -2
  81. package/dest/events/event_service.d.ts.map +1 -1
  82. package/dest/events/event_service.js +26 -5
  83. package/dest/events/private_event_filter_validator.d.ts +3 -2
  84. package/dest/events/private_event_filter_validator.d.ts.map +1 -1
  85. package/dest/events/private_event_filter_validator.js +15 -0
  86. package/dest/logs/log_service.d.ts +7 -8
  87. package/dest/logs/log_service.d.ts.map +1 -1
  88. package/dest/logs/log_service.js +27 -37
  89. package/dest/messages/message_context_service.d.ts +3 -3
  90. package/dest/messages/message_context_service.d.ts.map +1 -1
  91. package/dest/messages/message_context_service.js +3 -3
  92. package/dest/notes/note_service.d.ts +4 -5
  93. package/dest/notes/note_service.d.ts.map +1 -1
  94. package/dest/notes/note_service.js +14 -5
  95. package/dest/notes_filter.d.ts +2 -3
  96. package/dest/notes_filter.d.ts.map +1 -1
  97. package/dest/oracle_version.d.ts +4 -3
  98. package/dest/oracle_version.d.ts.map +1 -1
  99. package/dest/oracle_version.js +20 -10
  100. package/dest/private_kernel/private_kernel_execution_prover.d.ts +1 -1
  101. package/dest/private_kernel/private_kernel_execution_prover.d.ts.map +1 -1
  102. package/dest/private_kernel/private_kernel_execution_prover.js +4 -7
  103. package/dest/private_kernel/private_kernel_oracle.d.ts +5 -5
  104. package/dest/private_kernel/private_kernel_oracle.d.ts.map +1 -1
  105. package/dest/private_kernel/private_kernel_oracle.js +12 -15
  106. package/dest/pxe.d.ts +19 -8
  107. package/dest/pxe.d.ts.map +1 -1
  108. package/dest/pxe.js +55 -24
  109. package/dest/storage/anchor_block_store/anchor_block_store.js +1 -1
  110. package/dest/storage/capsule_store/capsule_service.d.ts +21 -0
  111. package/dest/storage/capsule_store/capsule_service.d.ts.map +1 -0
  112. package/dest/storage/capsule_store/capsule_service.js +50 -0
  113. package/dest/storage/capsule_store/capsule_store.d.ts +9 -9
  114. package/dest/storage/capsule_store/capsule_store.d.ts.map +1 -1
  115. package/dest/storage/capsule_store/capsule_store.js +36 -28
  116. package/dest/storage/capsule_store/index.d.ts +2 -1
  117. package/dest/storage/capsule_store/index.d.ts.map +1 -1
  118. package/dest/storage/capsule_store/index.js +1 -0
  119. package/dest/storage/contract_store/contract_store.d.ts +1 -1
  120. package/dest/storage/contract_store/contract_store.d.ts.map +1 -1
  121. package/dest/storage/contract_store/contract_store.js +4 -2
  122. package/dest/storage/metadata.d.ts +1 -1
  123. package/dest/storage/metadata.js +1 -1
  124. package/dest/storage/note_store/note_store.d.ts +1 -1
  125. package/dest/storage/note_store/note_store.d.ts.map +1 -1
  126. package/dest/storage/note_store/note_store.js +2 -2
  127. package/dest/storage/private_event_store/private_event_store.d.ts +1 -1
  128. package/dest/storage/private_event_store/private_event_store.d.ts.map +1 -1
  129. package/dest/storage/private_event_store/private_event_store.js +3 -0
  130. package/dest/storage/private_event_store/stored_private_event.js +1 -1
  131. package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.d.ts +2 -2
  132. package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.d.ts.map +1 -1
  133. package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.js +2 -16
  134. package/package.json +16 -16
  135. package/src/bin/check_oracle_version.ts +4 -4
  136. package/src/block_synchronizer/block_stream_source.ts +52 -0
  137. package/src/block_synchronizer/block_synchronizer.ts +33 -11
  138. package/src/config/index.ts +2 -8
  139. package/src/contract_function_simulator/contract_function_simulator.ts +13 -10
  140. package/src/contract_function_simulator/ephemeral_array_service.ts +110 -0
  141. package/src/contract_function_simulator/noir-structs/event_validation_request.ts +1 -4
  142. package/src/contract_function_simulator/noir-structs/log_retrieval_request.ts +1 -1
  143. package/src/contract_function_simulator/noir-structs/log_retrieval_response.ts +1 -1
  144. package/src/contract_function_simulator/noir-structs/note_validation_request.ts +1 -4
  145. package/src/contract_function_simulator/oracle/interfaces.ts +46 -18
  146. package/src/contract_function_simulator/oracle/legacy_oracle_mappings.ts +20 -51
  147. package/src/contract_function_simulator/oracle/oracle.ts +222 -36
  148. package/src/contract_function_simulator/oracle/private_execution.ts +1 -1
  149. package/src/contract_function_simulator/oracle/private_execution_oracle.ts +49 -23
  150. package/src/contract_function_simulator/oracle/utility_execution_oracle.ts +345 -123
  151. package/src/contract_function_simulator/pick_notes.ts +22 -3
  152. package/src/contract_function_simulator/proxied_contract_data_source.ts +8 -1
  153. package/src/contract_logging.ts +18 -5
  154. package/src/contract_sync/contract_sync_service.ts +64 -69
  155. package/src/contract_sync/helpers.ts +4 -4
  156. package/src/debug/pxe_debug_utils.ts +3 -3
  157. package/src/entrypoints/client/bundle/index.ts +0 -1
  158. package/src/entrypoints/client/bundle/utils.ts +2 -3
  159. package/src/entrypoints/client/lazy/index.ts +0 -1
  160. package/src/entrypoints/client/lazy/utils.ts +2 -3
  161. package/src/entrypoints/pxe_creation_options.ts +7 -0
  162. package/src/entrypoints/server/index.ts +1 -2
  163. package/src/entrypoints/server/utils.ts +2 -3
  164. package/src/events/event_service.ts +30 -5
  165. package/src/events/private_event_filter_validator.ts +21 -1
  166. package/src/logs/log_service.ts +57 -78
  167. package/src/messages/message_context_service.ts +3 -4
  168. package/src/notes/note_service.ts +18 -8
  169. package/src/notes_filter.ts +1 -3
  170. package/src/oracle_version.ts +20 -10
  171. package/src/private_kernel/private_kernel_execution_prover.ts +4 -9
  172. package/src/private_kernel/private_kernel_oracle.ts +14 -14
  173. package/src/pxe.ts +96 -33
  174. package/src/storage/anchor_block_store/anchor_block_store.ts +1 -1
  175. package/src/storage/capsule_store/capsule_service.ts +90 -0
  176. package/src/storage/capsule_store/capsule_store.ts +44 -26
  177. package/src/storage/capsule_store/index.ts +1 -0
  178. package/src/storage/contract_store/contract_store.ts +8 -6
  179. package/src/storage/metadata.ts +1 -1
  180. package/src/storage/note_store/note_store.ts +2 -5
  181. package/src/storage/private_event_store/private_event_store.ts +4 -0
  182. package/src/storage/private_event_store/stored_private_event.ts +1 -1
  183. package/src/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.ts +5 -15
  184. package/dest/access_scopes.d.ts +0 -9
  185. package/dest/access_scopes.d.ts.map +0 -1
  186. package/dest/access_scopes.js +0 -6
  187. package/dest/contract_function_simulator/noir-structs/message_tx_context.d.ts +0 -16
  188. package/dest/contract_function_simulator/noir-structs/message_tx_context.d.ts.map +0 -1
  189. package/dest/contract_function_simulator/noir-structs/message_tx_context.js +0 -57
  190. package/src/access_scopes.ts +0 -9
  191. package/src/contract_function_simulator/noir-structs/message_tx_context.ts +0 -55
package/src/pxe.ts CHANGED
@@ -18,6 +18,7 @@ import {
18
18
  } from '@aztec/stdlib/abi';
19
19
  import type { AuthWitness } from '@aztec/stdlib/auth-witness';
20
20
  import type { AztecAddress } from '@aztec/stdlib/aztec-address';
21
+ import type { L2TipsProvider } from '@aztec/stdlib/block';
21
22
  import {
22
23
  CompleteAddress,
23
24
  type ContractInstanceWithAddress,
@@ -52,7 +53,6 @@ import {
52
53
 
53
54
  import { inspect } from 'util';
54
55
 
55
- import type { AccessScopes } from './access_scopes.js';
56
56
  import { BlockSynchronizer } from './block_synchronizer/index.js';
57
57
  import type { PXEConfig } from './config/index.js';
58
58
  import { BenchmarkedNodeFactory } from './contract_function_simulator/benchmarked_node.js';
@@ -89,6 +89,14 @@ export type PackedPrivateEvent = InTx & {
89
89
  eventSelector: EventSelector;
90
90
  };
91
91
 
92
+ /** Options for PXE.proveTx. */
93
+ export type ProveTxOpts = {
94
+ /** Addresses whose private state and keys are accessible during private execution. */
95
+ scopes: AztecAddress[];
96
+ /** Sender address used to derive discovery tags for private messages (notes, events, logs) this tx emits. */
97
+ senderForTags?: AztecAddress;
98
+ };
99
+
92
100
  /** Options for PXE.profileTx. */
93
101
  export type ProfileTxOpts = {
94
102
  /** The profiling mode to use. */
@@ -96,7 +104,9 @@ export type ProfileTxOpts = {
96
104
  /** If true, proof generation is skipped during profiling. Defaults to true. */
97
105
  skipProofGeneration?: boolean;
98
106
  /** Addresses whose private state and keys are accessible during private execution. */
99
- scopes: AccessScopes;
107
+ scopes: AztecAddress[];
108
+ /** Sender address used to derive discovery tags for private messages (notes, events, logs) this tx emits. */
109
+ senderForTags?: AztecAddress;
100
110
  };
101
111
 
102
112
  /** Options for PXE.simulateTx. */
@@ -112,7 +122,9 @@ export type SimulateTxOpts = {
112
122
  /** State overrides for the simulation, such as contract instances and artifacts. Requires skipKernels: true */
113
123
  overrides?: SimulationOverrides;
114
124
  /** Addresses whose private state and keys are accessible during private execution */
115
- scopes: AccessScopes;
125
+ scopes: AztecAddress[];
126
+ /** Sender address used to derive discovery tags for private messages (notes, events, logs) this tx emits. */
127
+ senderForTags?: AztecAddress;
116
128
  };
117
129
 
118
130
  /** Options for PXE.executeUtility. */
@@ -120,7 +132,7 @@ export type ExecuteUtilityOpts = {
120
132
  /** The authentication witnesses required for the function call. */
121
133
  authwits?: AuthWitness[];
122
134
  /** The accounts whose notes we can access in this call */
123
- scopes: AccessScopes;
135
+ scopes: AztecAddress[];
124
136
  };
125
137
 
126
138
  /** Args for PXE.create. */
@@ -162,6 +174,7 @@ export class PXE {
162
174
  private privateEventStore: PrivateEventStore,
163
175
  private contractSyncService: ContractSyncService,
164
176
  private messageContextService: MessageContextService,
177
+ private l2TipsStore: L2TipsProvider,
165
178
  private simulator: CircuitSimulator,
166
179
  private proverEnabled: boolean,
167
180
  private proofCreator: PrivateKernelProver,
@@ -261,6 +274,7 @@ export class PXE {
261
274
  privateEventStore,
262
275
  contractSyncService,
263
276
  messageContextService,
277
+ tipsStore,
264
278
  simulator,
265
279
  proverEnabled,
266
280
  proofCreator,
@@ -295,6 +309,7 @@ export class PXE {
295
309
  keyStore: this.keyStore,
296
310
  addressStore: this.addressStore,
297
311
  aztecNode: BenchmarkedNodeFactory.create(this.node),
312
+ l2TipsStore: this.l2TipsStore,
298
313
  senderTaggingStore: this.senderTaggingStore,
299
314
  recipientTaggingStore: this.recipientTaggingStore,
300
315
  senderAddressBookStore: this.senderAddressBookStore,
@@ -365,17 +380,24 @@ export class PXE {
365
380
 
366
381
  // Executes the entrypoint private function, as well as all nested private
367
382
  // functions that might arise.
368
- async #executePrivate(
369
- contractFunctionSimulator: ContractFunctionSimulator,
370
- txRequest: TxExecutionRequest,
371
- scopes: AccessScopes,
372
- jobId: string,
373
- ): Promise<PrivateExecutionResult> {
383
+ async #executePrivate({
384
+ contractFunctionSimulator,
385
+ txRequest,
386
+ anchorBlockHeader,
387
+ scopes,
388
+ jobId,
389
+ senderForTags,
390
+ }: {
391
+ contractFunctionSimulator: ContractFunctionSimulator;
392
+ txRequest: TxExecutionRequest;
393
+ anchorBlockHeader: BlockHeader;
394
+ scopes: AztecAddress[];
395
+ jobId: string;
396
+ senderForTags?: AztecAddress;
397
+ }): Promise<PrivateExecutionResult> {
374
398
  const { origin: contractAddress, functionSelector } = txRequest;
375
399
 
376
400
  try {
377
- const anchorBlockHeader = await this.anchorBlockStore.getBlockHeader();
378
-
379
401
  await this.contractSyncService.ensureContractSynced(
380
402
  contractAddress,
381
403
  functionSelector,
@@ -392,6 +414,7 @@ export class PXE {
392
414
  anchorBlockHeader,
393
415
  scopes,
394
416
  jobId,
417
+ senderForTags,
395
418
  });
396
419
  this.log.debug(`Private simulation completed for ${contractAddress.toString()}:${functionSelector}`);
397
420
  return result;
@@ -417,7 +440,7 @@ export class PXE {
417
440
  contractFunctionSimulator: ContractFunctionSimulator,
418
441
  call: FunctionCall,
419
442
  authWitnesses: AuthWitness[] | undefined,
420
- scopes: AccessScopes,
443
+ scopes: AztecAddress[],
421
444
  jobId: string,
422
445
  ) {
423
446
  try {
@@ -480,11 +503,10 @@ export class PXE {
480
503
  txExecutionRequest: TxExecutionRequest,
481
504
  proofCreator: PrivateKernelProver,
482
505
  privateExecutionResult: PrivateExecutionResult,
506
+ anchorBlockHeader: BlockHeader,
483
507
  config: PrivateKernelExecutionProverConfig,
484
508
  ): Promise<PrivateKernelExecutionProofOutput<PrivateKernelTailCircuitPublicInputs>> {
485
- const anchorBlockHeader = await this.anchorBlockStore.getBlockHeader();
486
- const anchorBlockHash = await anchorBlockHeader.hash();
487
- const kernelOracle = new PrivateKernelOracle(this.contractStore, this.keyStore, this.node, anchorBlockHash);
509
+ const kernelOracle = new PrivateKernelOracle(this.contractStore, this.keyStore, this.node, anchorBlockHeader);
488
510
  const kernelTraceProver = new PrivateKernelExecutionProver(
489
511
  kernelOracle,
490
512
  proofCreator,
@@ -502,7 +524,9 @@ export class PXE {
502
524
  * @returns The synced block header
503
525
  */
504
526
  public getSyncedBlockHeader(): Promise<BlockHeader> {
505
- return this.anchorBlockStore.getBlockHeader();
527
+ return this.#putInJobQueue(() => {
528
+ return this.anchorBlockStore.getBlockHeader();
529
+ });
506
530
  }
507
531
 
508
532
  /**
@@ -559,6 +583,12 @@ export class PXE {
559
583
  * TODO: It's strange that we return the address here and I (benesjan) think we should drop the return value.
560
584
  */
561
585
  public async registerSender(sender: AztecAddress): Promise<AztecAddress> {
586
+ if (!(await sender.isValid())) {
587
+ throw new Error(
588
+ `Address ${sender} is not valid: it does not correspond to a point on the Grumpkin curve. Cannot register it as a sender.`,
589
+ );
590
+ }
591
+
562
592
  const accounts = await this.keyStore.getAccounts();
563
593
  if (accounts.includes(sender)) {
564
594
  this.log.info(`Sender:\n "${sender.toString()}"\n already registered.`);
@@ -570,8 +600,8 @@ export class PXE {
570
600
  if (wasAdded) {
571
601
  this.log.info(`Added sender:\n ${sender.toString()}`);
572
602
  // Wipe the entire sync cache: the new sender's tagged logs could contain notes/events for any contract, so
573
- // all contracts must re-sync to discover them.
574
- this.contractSyncService.wipe();
603
+ // all contracts must re-sync to discover them. Queued to avoid wiping while a job is in flight.
604
+ await this.#putInJobQueue(() => Promise.resolve(this.contractSyncService.wipe()));
575
605
  } else {
576
606
  this.log.info(`Sender:\n "${sender.toString()}"\n already registered.`);
577
607
  }
@@ -731,7 +761,7 @@ export class PXE {
731
761
  * @throws If contract code not found, or public simulation reverts.
732
762
  * Also throws if simulatePublic is true and public simulation reverts.
733
763
  */
734
- public proveTx(txRequest: TxExecutionRequest, scopes: AztecAddress[]): Promise<TxProvingResult> {
764
+ public proveTx(txRequest: TxExecutionRequest, { scopes, senderForTags }: ProveTxOpts): Promise<TxProvingResult> {
735
765
  let privateExecutionResult: PrivateExecutionResult;
736
766
  // We disable proving concurrently mostly out of caution, since it accesses some of our stores. Proving is so
737
767
  // computationally demanding that it'd be rare for someone to try to do it concurrently regardless.
@@ -740,16 +770,24 @@ export class PXE {
740
770
  try {
741
771
  const syncTimer = new Timer();
742
772
  await this.blockStateSynchronizer.sync();
773
+ const anchorBlockHeader = await this.anchorBlockStore.getBlockHeader();
743
774
  const syncTime = syncTimer.ms();
744
775
  const contractFunctionSimulator = this.#getSimulatorForTx();
745
- privateExecutionResult = await this.#executePrivate(contractFunctionSimulator, txRequest, scopes, jobId);
776
+ privateExecutionResult = await this.#executePrivate({
777
+ contractFunctionSimulator,
778
+ txRequest,
779
+ anchorBlockHeader,
780
+ scopes,
781
+ jobId,
782
+ senderForTags,
783
+ });
746
784
 
747
785
  const {
748
786
  publicInputs,
749
787
  chonkProof,
750
788
  executionSteps,
751
789
  timings: { proving } = {},
752
- } = await this.#prove(txRequest, this.proofCreator, privateExecutionResult, {
790
+ } = await this.#prove(txRequest, this.proofCreator, privateExecutionResult, anchorBlockHeader, {
753
791
  simulate: false,
754
792
  skipFeeEnforcement: false,
755
793
  profileMode: 'none',
@@ -812,7 +850,7 @@ export class PXE {
812
850
  */
813
851
  public profileTx(
814
852
  txRequest: TxExecutionRequest,
815
- { profileMode, skipProofGeneration = true, scopes }: ProfileTxOpts,
853
+ { profileMode, skipProofGeneration = true, scopes, senderForTags }: ProfileTxOpts,
816
854
  ): Promise<TxProfileResult> {
817
855
  // We disable concurrent profiles for consistency with simulateTx.
818
856
  return this.#putInJobQueue(async jobId => {
@@ -832,15 +870,24 @@ export class PXE {
832
870
  );
833
871
  const syncTimer = new Timer();
834
872
  await this.blockStateSynchronizer.sync();
873
+ const anchorBlockHeader = await this.anchorBlockStore.getBlockHeader();
835
874
  const syncTime = syncTimer.ms();
836
875
 
837
876
  const contractFunctionSimulator = this.#getSimulatorForTx();
838
- const privateExecutionResult = await this.#executePrivate(contractFunctionSimulator, txRequest, scopes, jobId);
877
+ const privateExecutionResult = await this.#executePrivate({
878
+ contractFunctionSimulator,
879
+ txRequest,
880
+ anchorBlockHeader,
881
+ scopes,
882
+ jobId,
883
+ senderForTags,
884
+ });
839
885
 
840
886
  const { executionSteps, timings: { proving } = {} } = await this.#prove(
841
887
  txRequest,
842
888
  this.proofCreator,
843
889
  privateExecutionResult,
890
+ anchorBlockHeader,
844
891
  {
845
892
  simulate: skipProofGeneration,
846
893
  skipFeeEnforcement: false,
@@ -908,6 +955,7 @@ export class PXE {
908
955
  skipKernels = true,
909
956
  overrides,
910
957
  scopes,
958
+ senderForTags,
911
959
  }: SimulateTxOpts,
912
960
  ): Promise<TxSimulationResult> {
913
961
  // We disable concurrent simulations since those might execute oracles which read and write to the PXE stores (e.g.
@@ -930,6 +978,7 @@ export class PXE {
930
978
  );
931
979
  const syncTimer = new Timer();
932
980
  await this.blockStateSynchronizer.sync();
981
+ const anchorBlockHeader = await this.anchorBlockStore.getBlockHeader();
933
982
  const syncTime = syncTimer.ms();
934
983
 
935
984
  const overriddenContracts = overrides?.contracts ? new Set(Object.keys(overrides.contracts)) : undefined;
@@ -949,7 +998,14 @@ export class PXE {
949
998
  }
950
999
 
951
1000
  // Execution of private functions only; no proving, and no kernel logic.
952
- const privateExecutionResult = await this.#executePrivate(contractFunctionSimulator, txRequest, scopes, jobId);
1001
+ const privateExecutionResult = await this.#executePrivate({
1002
+ contractFunctionSimulator,
1003
+ txRequest,
1004
+ anchorBlockHeader,
1005
+ scopes,
1006
+ jobId,
1007
+ senderForTags,
1008
+ });
953
1009
 
954
1010
  let publicInputs: PrivateKernelTailCircuitPublicInputs | undefined;
955
1011
  let executionSteps: PrivateExecutionStep[] = [];
@@ -962,11 +1018,17 @@ export class PXE {
962
1018
  ));
963
1019
  } else {
964
1020
  // Kernel logic, plus proving of all private functions and kernels.
965
- ({ publicInputs, executionSteps } = await this.#prove(txRequest, this.proofCreator, privateExecutionResult, {
966
- simulate: true,
967
- skipFeeEnforcement,
968
- profileMode: 'none',
969
- }));
1021
+ ({ publicInputs, executionSteps } = await this.#prove(
1022
+ txRequest,
1023
+ this.proofCreator,
1024
+ privateExecutionResult,
1025
+ anchorBlockHeader,
1026
+ {
1027
+ simulate: true,
1028
+ skipFeeEnforcement,
1029
+ profileMode: 'none',
1030
+ },
1031
+ ));
970
1032
  }
971
1033
 
972
1034
  const privateSimulationResult = new PrivateSimulationResult(privateExecutionResult, publicInputs);
@@ -1040,7 +1102,7 @@ export class PXE {
1040
1102
  inspect(txRequest),
1041
1103
  `simulatePublic=${simulatePublic}`,
1042
1104
  `skipTxValidation=${skipTxValidation}`,
1043
- `scopes=${scopes === 'ALL_SCOPES' ? scopes : scopes.map(s => s.toString()).join(', ')}`,
1105
+ `scopes=${scopes.map(s => s.toString()).join(', ')}`,
1044
1106
  );
1045
1107
  }
1046
1108
  });
@@ -1052,7 +1114,7 @@ export class PXE {
1052
1114
  */
1053
1115
  public executeUtility(
1054
1116
  call: FunctionCall,
1055
- { authwits, scopes }: ExecuteUtilityOpts = { scopes: 'ALL_SCOPES' },
1117
+ { authwits, scopes }: ExecuteUtilityOpts = { scopes: [] },
1056
1118
  ): Promise<UtilityExecutionResult> {
1057
1119
  // We disable concurrent executions since those might execute oracles which read and write to the PXE stores (e.g.
1058
1120
  // to the capsules), and we need to prevent concurrent runs from interfering with one another (e.g. attempting to
@@ -1110,7 +1172,7 @@ export class PXE {
1110
1172
  throw this.#contextualizeError(
1111
1173
  err,
1112
1174
  `executeUtility ${to}:${name}(${stringifiedArgs})`,
1113
- `scopes=${scopes === 'ALL_SCOPES' ? scopes : scopes.map(s => s.toString()).join(', ')}`,
1175
+ `scopes=${scopes.map(s => s.toString()).join(', ')}`,
1114
1176
  );
1115
1177
  }
1116
1178
  });
@@ -1169,6 +1231,7 @@ export class PXE {
1169
1231
  */
1170
1232
  public async stop(): Promise<void> {
1171
1233
  await this.jobQueue.end();
1234
+ await this.blockStateSynchronizer.stop();
1172
1235
  await this.db.close();
1173
1236
  }
1174
1237
  }
@@ -23,7 +23,7 @@ export class AnchorBlockStore {
23
23
  }
24
24
 
25
25
  async getBlockHeader(): Promise<BlockHeader> {
26
- const headerBuffer = await this.#synchronizedHeader.getAsync();
26
+ const headerBuffer = await this.#store.transactionAsync(() => this.#synchronizedHeader.getAsync());
27
27
  if (!headerBuffer) {
28
28
  throw new Error(`Trying to get block header with a not-yet-synchronized PXE - this should never happen`);
29
29
  }
@@ -0,0 +1,90 @@
1
+ import type { Fr } from '@aztec/foundation/curves/bn254';
2
+ import { AztecAddress } from '@aztec/stdlib/aztec-address';
3
+ import type { Capsule } from '@aztec/stdlib/tx';
4
+
5
+ import type { CapsuleStore } from './capsule_store.js';
6
+
7
+ /**
8
+ * Wraps a CapsuleStore with scope-based access control. Each operation asserts that the requested scope is in the
9
+ * allowed scopes list before delegating to the underlying store.
10
+ */
11
+ export class CapsuleService {
12
+ constructor(
13
+ private readonly capsuleStore: CapsuleStore,
14
+ private readonly allowedScopes: AztecAddress[],
15
+ ) {}
16
+
17
+ setCapsule(contractAddress: AztecAddress, slot: Fr, capsule: Fr[], jobId: string, scope: AztecAddress) {
18
+ assertAllowedScope(scope, this.allowedScopes);
19
+ this.capsuleStore.setCapsule(contractAddress, slot, capsule, jobId, scope);
20
+ }
21
+
22
+ async getCapsule(
23
+ contractAddress: AztecAddress,
24
+ slot: Fr,
25
+ jobId: string,
26
+ scope: AztecAddress,
27
+ transientCapsules?: Capsule[],
28
+ ): Promise<Fr[] | null> {
29
+ assertAllowedScope(scope, this.allowedScopes);
30
+
31
+ // TODO(#12425): On the following line, the pertinent capsule gets overshadowed by the transient one. Tackle this.
32
+ const maybeTransientCapsule = transientCapsules?.find(
33
+ c =>
34
+ c.contractAddress.equals(contractAddress) &&
35
+ c.storageSlot.equals(slot) &&
36
+ (c.scope ?? AztecAddress.ZERO).equals(scope),
37
+ )?.data;
38
+
39
+ return maybeTransientCapsule ?? (await this.capsuleStore.getCapsule(contractAddress, slot, jobId, scope));
40
+ }
41
+
42
+ deleteCapsule(contractAddress: AztecAddress, slot: Fr, jobId: string, scope: AztecAddress) {
43
+ assertAllowedScope(scope, this.allowedScopes);
44
+ this.capsuleStore.deleteCapsule(contractAddress, slot, jobId, scope);
45
+ }
46
+
47
+ copyCapsule(
48
+ contractAddress: AztecAddress,
49
+ srcSlot: Fr,
50
+ dstSlot: Fr,
51
+ numEntries: number,
52
+ jobId: string,
53
+ scope: AztecAddress,
54
+ ): Promise<void> {
55
+ assertAllowedScope(scope, this.allowedScopes);
56
+ return this.capsuleStore.copyCapsule(contractAddress, srcSlot, dstSlot, numEntries, jobId, scope);
57
+ }
58
+
59
+ appendToCapsuleArray(
60
+ contractAddress: AztecAddress,
61
+ baseSlot: Fr,
62
+ content: Fr[][],
63
+ jobId: string,
64
+ scope: AztecAddress,
65
+ ): Promise<void> {
66
+ assertAllowedScope(scope, this.allowedScopes);
67
+ return this.capsuleStore.appendToCapsuleArray(contractAddress, baseSlot, content, jobId, scope);
68
+ }
69
+
70
+ readCapsuleArray(contractAddress: AztecAddress, baseSlot: Fr, jobId: string, scope: AztecAddress): Promise<Fr[][]> {
71
+ assertAllowedScope(scope, this.allowedScopes);
72
+ return this.capsuleStore.readCapsuleArray(contractAddress, baseSlot, jobId, scope);
73
+ }
74
+
75
+ setCapsuleArray(contractAddress: AztecAddress, baseSlot: Fr, content: Fr[][], jobId: string, scope: AztecAddress) {
76
+ assertAllowedScope(scope, this.allowedScopes);
77
+ return this.capsuleStore.setCapsuleArray(contractAddress, baseSlot, content, jobId, scope);
78
+ }
79
+ }
80
+
81
+ function assertAllowedScope(scope: AztecAddress, allowedScopes: AztecAddress[]) {
82
+ if (scope.equals(AztecAddress.ZERO)) {
83
+ return;
84
+ }
85
+ if (!allowedScopes.some((allowed: AztecAddress) => allowed.equals(scope))) {
86
+ throw new Error(
87
+ `Scope ${scope.toString()} is not in the allowed scopes list: [${allowedScopes.map((s: AztecAddress) => s.toString()).join(', ')}]. See https://docs.aztec.network/errors/10`,
88
+ );
89
+ }
90
+ }
@@ -1,7 +1,7 @@
1
1
  import { Fr } from '@aztec/foundation/curves/bn254';
2
2
  import { type Logger, createLogger } from '@aztec/foundation/log';
3
3
  import type { AztecAsyncKVStore, AztecAsyncMap } from '@aztec/kv-store';
4
- import type { AztecAddress } from '@aztec/stdlib/aztec-address';
4
+ import { AztecAddress } from '@aztec/stdlib/aztec-address';
5
5
 
6
6
  import type { StagedStore } from '../../job_coordinator/job_coordinator.js';
7
7
 
@@ -10,11 +10,12 @@ export class CapsuleStore implements StagedStore {
10
10
 
11
11
  #store: AztecAsyncKVStore;
12
12
 
13
- // Arbitrary data stored by contracts. Key is computed as `${contractAddress}:${key}`
13
+ // Arbitrary data stored by contracts. Key is computed as `${contractAddress}:${scope}:${key}`, using the zero
14
+ // address for the global scope.
14
15
  #capsules: AztecAsyncMap<string, Buffer>;
15
16
 
16
- // jobId => `${contractAddress}:${key}` => capsule data
17
- // when `#stagedCapsules.get('some-job-id').get('${some-contract-address:some-key') === null`,
17
+ // jobId => `${contractAddress}:${scope}:${key}` => capsule data
18
+ // when `#stagedCapsules.get('some-job-id').get('${some-contract-address}:${some-scope}:${some-key}') === null`,
18
19
  // it signals that the capsule was deleted during the job, so it needs to be deleted on commit
19
20
  #stagedCapsules: Map<string, Map<string, Buffer | null>>;
20
21
 
@@ -134,8 +135,8 @@ export class CapsuleStore implements StagedStore {
134
135
  * to public contract storage in that it's indexed by the contract address and storage slot but instead of the global
135
136
  * network state it's backed by local PXE db.
136
137
  */
137
- storeCapsule(contractAddress: AztecAddress, slot: Fr, capsule: Fr[], jobId: string) {
138
- const dbSlotKey = dbSlotToKey(contractAddress, slot);
138
+ setCapsule(contractAddress: AztecAddress, slot: Fr, capsule: Fr[], jobId: string, scope: AztecAddress) {
139
+ const dbSlotKey = dbSlotToKey(contractAddress, slot, scope);
139
140
 
140
141
  // A store overrides any pre-existing data on the slot
141
142
  this.#setOnStage(jobId, dbSlotKey, Buffer.concat(capsule.map(value => value.toBuffer())));
@@ -147,8 +148,18 @@ export class CapsuleStore implements StagedStore {
147
148
  * @param slot - The slot in the database to read.
148
149
  * @returns The stored data or `null` if no data is stored under the slot.
149
150
  */
150
- async loadCapsule(contractAddress: AztecAddress, slot: Fr, jobId: string): Promise<Fr[] | null> {
151
- const dataBuffer = await this.#getFromStage(jobId, dbSlotToKey(contractAddress, slot));
151
+ getCapsule(contractAddress: AztecAddress, slot: Fr, jobId: string, scope: AztecAddress): Promise<Fr[] | null> {
152
+ return this.#store.transactionAsync(() => this.#getCapsuleInternal(contractAddress, slot, jobId, scope));
153
+ }
154
+
155
+ /** Same as getCapsule but without its own transaction, for use inside an existing transactionAsync. */
156
+ async #getCapsuleInternal(
157
+ contractAddress: AztecAddress,
158
+ slot: Fr,
159
+ jobId: string,
160
+ scope: AztecAddress,
161
+ ): Promise<Fr[] | null> {
162
+ const dataBuffer = await this.#getFromStage(jobId, dbSlotToKey(contractAddress, slot, scope));
152
163
  if (!dataBuffer) {
153
164
  this.logger.trace(`Data not found for contract ${contractAddress.toString()} and slot ${slot.toString()}`);
154
165
  return null;
@@ -165,9 +176,9 @@ export class CapsuleStore implements StagedStore {
165
176
  * @param contractAddress - The contract address under which the data is scoped.
166
177
  * @param slot - The slot in the database to delete.
167
178
  */
168
- deleteCapsule(contractAddress: AztecAddress, slot: Fr, jobId: string) {
179
+ deleteCapsule(contractAddress: AztecAddress, slot: Fr, jobId: string, scope: AztecAddress) {
169
180
  // 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));
181
+ this.#deleteOnStage(jobId, dbSlotToKey(contractAddress, slot, scope));
171
182
  }
172
183
 
173
184
  /**
@@ -187,6 +198,7 @@ export class CapsuleStore implements StagedStore {
187
198
  dstSlot: Fr,
188
199
  numEntries: number,
189
200
  jobId: string,
201
+ scope: AztecAddress,
190
202
  ): Promise<void> {
191
203
  // This transactional context gives us "copy atomicity":
192
204
  // there shouldn't be concurrent writes to what's being copied here.
@@ -203,8 +215,8 @@ export class CapsuleStore implements StagedStore {
203
215
  }
204
216
 
205
217
  for (const i of indexes) {
206
- const currentSrcSlot = dbSlotToKey(contractAddress, srcSlot.add(new Fr(i)));
207
- const currentDstSlot = dbSlotToKey(contractAddress, dstSlot.add(new Fr(i)));
218
+ const currentSrcSlot = dbSlotToKey(contractAddress, srcSlot.add(new Fr(i)), scope);
219
+ const currentDstSlot = dbSlotToKey(contractAddress, dstSlot.add(new Fr(i)), scope);
208
220
 
209
221
  const toCopy = await this.#getFromStage(jobId, currentSrcSlot);
210
222
  if (!toCopy) {
@@ -224,7 +236,13 @@ export class CapsuleStore implements StagedStore {
224
236
  * @param baseSlot - The slot where the array length is stored
225
237
  * @param content - Array of capsule data to append
226
238
  */
227
- appendToCapsuleArray(contractAddress: AztecAddress, baseSlot: Fr, content: Fr[][], jobId: string): Promise<void> {
239
+ appendToCapsuleArray(
240
+ contractAddress: AztecAddress,
241
+ baseSlot: Fr,
242
+ content: Fr[][],
243
+ jobId: string,
244
+ scope: AztecAddress,
245
+ ): Promise<void> {
228
246
  // We wrap this in a transaction to serialize concurrent calls from Promise.all.
229
247
  // Without this, concurrent appends to the same array could race: both read length=0,
230
248
  // both write at the same slots, one overwrites the other.
@@ -232,22 +250,22 @@ export class CapsuleStore implements StagedStore {
232
250
  // and not using a transaction here would heavily impact performance.
233
251
  return this.#store.transactionAsync(async () => {
234
252
  // Load current length, defaulting to 0 if not found
235
- const lengthData = await this.loadCapsule(contractAddress, baseSlot, jobId);
253
+ const lengthData = await this.#getCapsuleInternal(contractAddress, baseSlot, jobId, scope);
236
254
  const currentLength = lengthData ? lengthData[0].toNumber() : 0;
237
255
 
238
256
  // Store each capsule at consecutive slots after baseSlot + 1 + currentLength
239
257
  for (let i = 0; i < content.length; i++) {
240
258
  const nextSlot = arraySlot(baseSlot, currentLength + i);
241
- this.storeCapsule(contractAddress, nextSlot, content[i], jobId);
259
+ this.setCapsule(contractAddress, nextSlot, content[i], jobId, scope);
242
260
  }
243
261
 
244
262
  // Update length to include all new capsules
245
263
  const newLength = currentLength + content.length;
246
- this.storeCapsule(contractAddress, baseSlot, [new Fr(newLength)], jobId);
264
+ this.setCapsule(contractAddress, baseSlot, [new Fr(newLength)], jobId, scope);
247
265
  });
248
266
  }
249
267
 
250
- readCapsuleArray(contractAddress: AztecAddress, baseSlot: Fr, jobId: string): Promise<Fr[][]> {
268
+ readCapsuleArray(contractAddress: AztecAddress, baseSlot: Fr, jobId: string, scope: AztecAddress): Promise<Fr[][]> {
251
269
  // I'm leaving this transactional context here though because I'm assuming this
252
270
  // gives us "read array atomicity": there shouldn't be concurrent writes to what's being copied
253
271
  // here.
@@ -255,14 +273,14 @@ export class CapsuleStore implements StagedStore {
255
273
  // of jobs: different calls running concurrently on the same contract may cause trouble.
256
274
  return this.#store.transactionAsync(async () => {
257
275
  // Load length, defaulting to 0 if not found
258
- const maybeLength = await this.loadCapsule(contractAddress, baseSlot, jobId);
276
+ const maybeLength = await this.#getCapsuleInternal(contractAddress, baseSlot, jobId, scope);
259
277
  const length = maybeLength ? maybeLength[0].toBigInt() : 0n;
260
278
 
261
279
  const values: Fr[][] = [];
262
280
 
263
281
  // Read each capsule at consecutive slots after baseSlot
264
282
  for (let i = 0; i < length; i++) {
265
- const currentValue = await this.loadCapsule(contractAddress, arraySlot(baseSlot, i), jobId);
283
+ const currentValue = await this.#getCapsuleInternal(contractAddress, arraySlot(baseSlot, i), jobId, scope);
266
284
  if (currentValue == undefined) {
267
285
  throw new Error(
268
286
  `Expected non-empty value at capsule array in base slot ${baseSlot} at index ${i} for contract ${contractAddress}`,
@@ -276,7 +294,7 @@ export class CapsuleStore implements StagedStore {
276
294
  });
277
295
  }
278
296
 
279
- setCapsuleArray(contractAddress: AztecAddress, baseSlot: Fr, content: Fr[][], jobId: string) {
297
+ setCapsuleArray(contractAddress: AztecAddress, baseSlot: Fr, content: Fr[][], jobId: string, scope: AztecAddress) {
280
298
  // This transactional context in theory isn't so critical now because we aren't
281
299
  // writing to DB so if there's exceptions midway and it blows up, no visible impact
282
300
  // to persistent storage will happen.
@@ -287,27 +305,27 @@ export class CapsuleStore implements StagedStore {
287
305
  // of jobs: different calls running concurrently on the same contract may cause trouble.
288
306
  return this.#store.transactionAsync(async () => {
289
307
  // Load current length, defaulting to 0 if not found
290
- const maybeLength = await this.loadCapsule(contractAddress, baseSlot, jobId);
308
+ const maybeLength = await this.#getCapsuleInternal(contractAddress, baseSlot, jobId, scope);
291
309
  const originalLength = maybeLength ? maybeLength[0].toNumber() : 0;
292
310
 
293
311
  // Set the new length
294
- this.storeCapsule(contractAddress, baseSlot, [new Fr(content.length)], jobId);
312
+ this.setCapsule(contractAddress, baseSlot, [new Fr(content.length)], jobId, scope);
295
313
 
296
314
  // Store the new content, possibly overwriting existing values
297
315
  for (let i = 0; i < content.length; i++) {
298
- this.storeCapsule(contractAddress, arraySlot(baseSlot, i), content[i], jobId);
316
+ this.setCapsule(contractAddress, arraySlot(baseSlot, i), content[i], jobId, scope);
299
317
  }
300
318
 
301
319
  // Clear any stragglers
302
320
  for (let i = content.length; i < originalLength; i++) {
303
- this.deleteCapsule(contractAddress, arraySlot(baseSlot, i), jobId);
321
+ this.deleteCapsule(contractAddress, arraySlot(baseSlot, i), jobId, scope);
304
322
  }
305
323
  });
306
324
  }
307
325
  }
308
326
 
309
- function dbSlotToKey(contractAddress: AztecAddress, slot: Fr): string {
310
- return `${contractAddress.toString()}:${slot.toString()}`;
327
+ function dbSlotToKey(contractAddress: AztecAddress, slot: Fr, scope: AztecAddress): string {
328
+ return [contractAddress.toString(), scope.toString(), slot.toString()].join(':');
311
329
  }
312
330
 
313
331
  function arraySlot(baseSlot: Fr, index: number) {
@@ -1 +1,2 @@
1
+ export { CapsuleService } from './capsule_service.js';
1
2
  export { CapsuleStore } from './capsule_store.js';
@@ -168,12 +168,14 @@ export class ContractStore {
168
168
  }
169
169
 
170
170
  async addContractInstance(contract: ContractInstanceWithAddress): Promise<void> {
171
- this.#contractClassIdMap.set(contract.address.toString(), contract.currentContractClassId);
171
+ await this.#store.transactionAsync(async () => {
172
+ await this.#contractInstances.set(
173
+ contract.address.toString(),
174
+ new SerializableContractInstance(contract).toBuffer(),
175
+ );
176
+ });
172
177
 
173
- await this.#contractInstances.set(
174
- contract.address.toString(),
175
- new SerializableContractInstance(contract).toBuffer(),
176
- );
178
+ this.#contractClassIdMap.set(contract.address.toString(), contract.currentContractClassId);
177
179
  }
178
180
 
179
181
  // Private getters
@@ -246,7 +248,7 @@ export class ContractStore {
246
248
  contractClassId: Fr,
247
249
  ): Promise<(ContractClassWithId & ContractClassIdPreimage) | undefined> {
248
250
  const key = contractClassId.toString();
249
- const buf = await this.#contractClassData.getAsync(key);
251
+ const buf = await this.#store.transactionAsync(() => this.#contractClassData.getAsync(key));
250
252
  if (!buf) {
251
253
  return undefined;
252
254
  }
@@ -1 +1 @@
1
- export const PXE_DATA_SCHEMA_VERSION = 4;
1
+ export const PXE_DATA_SCHEMA_VERSION = 5;