@aztec/pxe 0.0.1-commit.0c875d939 → 0.0.1-commit.0dc957cde

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 (245) hide show
  1. package/dest/bin/check_oracle_version.js +4 -4
  2. package/dest/block_synchronizer/block_synchronizer.d.ts +6 -2
  3. package/dest/block_synchronizer/block_synchronizer.d.ts.map +1 -1
  4. package/dest/block_synchronizer/block_synchronizer.js +19 -1
  5. package/dest/config/index.d.ts +2 -2
  6. package/dest/config/index.d.ts.map +1 -1
  7. package/dest/config/index.js +8 -15
  8. package/dest/config/package_info.js +1 -1
  9. package/dest/contract_function_simulator/contract_function_simulator.d.ts +13 -5
  10. package/dest/contract_function_simulator/contract_function_simulator.d.ts.map +1 -1
  11. package/dest/contract_function_simulator/contract_function_simulator.js +44 -19
  12. package/dest/contract_function_simulator/ephemeral_array_service.d.ts +28 -0
  13. package/dest/contract_function_simulator/ephemeral_array_service.d.ts.map +1 -0
  14. package/dest/contract_function_simulator/ephemeral_array_service.js +78 -0
  15. package/dest/contract_function_simulator/execution_tagging_index_cache.d.ts +7 -7
  16. package/dest/contract_function_simulator/execution_tagging_index_cache.d.ts.map +1 -1
  17. package/dest/contract_function_simulator/execution_tagging_index_cache.js +19 -11
  18. package/dest/contract_function_simulator/index.d.ts +2 -1
  19. package/dest/contract_function_simulator/index.d.ts.map +1 -1
  20. package/dest/contract_function_simulator/index.js +1 -0
  21. package/dest/contract_function_simulator/noir-structs/event_validation_request.d.ts +4 -6
  22. package/dest/contract_function_simulator/noir-structs/event_validation_request.d.ts.map +1 -1
  23. package/dest/contract_function_simulator/noir-structs/event_validation_request.js +8 -10
  24. package/dest/contract_function_simulator/noir-structs/log_retrieval_request.d.ts +1 -1
  25. package/dest/contract_function_simulator/noir-structs/log_retrieval_request.js +1 -1
  26. package/dest/contract_function_simulator/noir-structs/log_retrieval_response.d.ts +2 -2
  27. package/dest/contract_function_simulator/noir-structs/log_retrieval_response.d.ts.map +1 -1
  28. package/dest/contract_function_simulator/noir-structs/log_retrieval_response.js +2 -4
  29. package/dest/contract_function_simulator/noir-structs/note_validation_request.d.ts +4 -7
  30. package/dest/contract_function_simulator/noir-structs/note_validation_request.d.ts.map +1 -1
  31. package/dest/contract_function_simulator/noir-structs/note_validation_request.js +6 -11
  32. package/dest/contract_function_simulator/oracle/interfaces.d.ts +61 -45
  33. package/dest/contract_function_simulator/oracle/interfaces.d.ts.map +1 -1
  34. package/dest/contract_function_simulator/oracle/legacy_oracle_mappings.d.ts +9 -0
  35. package/dest/contract_function_simulator/oracle/legacy_oracle_mappings.d.ts.map +1 -0
  36. package/dest/contract_function_simulator/oracle/legacy_oracle_mappings.js +47 -0
  37. package/dest/contract_function_simulator/oracle/oracle.d.ts +75 -44
  38. package/dest/contract_function_simulator/oracle/oracle.d.ts.map +1 -1
  39. package/dest/contract_function_simulator/oracle/oracle.js +281 -96
  40. package/dest/contract_function_simulator/oracle/private_execution.js +5 -3
  41. package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts +25 -50
  42. package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts.map +1 -1
  43. package/dest/contract_function_simulator/oracle/private_execution_oracle.js +59 -84
  44. package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts +94 -60
  45. package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts.map +1 -1
  46. package/dest/contract_function_simulator/oracle/utility_execution_oracle.js +277 -114
  47. package/dest/contract_function_simulator/pick_notes.d.ts +1 -1
  48. package/dest/contract_function_simulator/pick_notes.d.ts.map +1 -1
  49. package/dest/contract_function_simulator/pick_notes.js +20 -3
  50. package/dest/contract_function_simulator/proxied_contract_data_source.d.ts +1 -1
  51. package/dest/contract_function_simulator/proxied_contract_data_source.d.ts.map +1 -1
  52. package/dest/contract_function_simulator/proxied_contract_data_source.js +3 -0
  53. package/dest/contract_logging.d.ts +27 -0
  54. package/dest/contract_logging.d.ts.map +1 -0
  55. package/dest/contract_logging.js +38 -0
  56. package/dest/contract_sync/contract_sync_service.d.ts +6 -5
  57. package/dest/contract_sync/contract_sync_service.d.ts.map +1 -1
  58. package/dest/contract_sync/contract_sync_service.js +62 -43
  59. package/dest/contract_sync/helpers.d.ts +2 -3
  60. package/dest/contract_sync/helpers.d.ts.map +1 -1
  61. package/dest/contract_sync/helpers.js +7 -2
  62. package/dest/debug/pxe_debug_utils.d.ts +3 -3
  63. package/dest/debug/pxe_debug_utils.d.ts.map +1 -1
  64. package/dest/debug/pxe_debug_utils.js +4 -4
  65. package/dest/entrypoints/client/bundle/index.d.ts +2 -2
  66. package/dest/entrypoints/client/bundle/index.d.ts.map +1 -1
  67. package/dest/entrypoints/client/bundle/index.js +1 -1
  68. package/dest/entrypoints/client/bundle/utils.d.ts +2 -2
  69. package/dest/entrypoints/client/bundle/utils.d.ts.map +1 -1
  70. package/dest/entrypoints/client/bundle/utils.js +2 -2
  71. package/dest/entrypoints/client/lazy/index.d.ts +2 -2
  72. package/dest/entrypoints/client/lazy/index.d.ts.map +1 -1
  73. package/dest/entrypoints/client/lazy/index.js +1 -1
  74. package/dest/entrypoints/client/lazy/utils.d.ts +2 -2
  75. package/dest/entrypoints/client/lazy/utils.d.ts.map +1 -1
  76. package/dest/entrypoints/client/lazy/utils.js +2 -2
  77. package/dest/entrypoints/pxe_creation_options.d.ts +3 -1
  78. package/dest/entrypoints/pxe_creation_options.d.ts.map +1 -1
  79. package/dest/entrypoints/pxe_creation_options.js +3 -1
  80. package/dest/entrypoints/server/index.d.ts +2 -3
  81. package/dest/entrypoints/server/index.d.ts.map +1 -1
  82. package/dest/entrypoints/server/index.js +1 -2
  83. package/dest/entrypoints/server/utils.d.ts +2 -2
  84. package/dest/entrypoints/server/utils.d.ts.map +1 -1
  85. package/dest/entrypoints/server/utils.js +2 -2
  86. package/dest/events/event_service.d.ts +3 -2
  87. package/dest/events/event_service.d.ts.map +1 -1
  88. package/dest/events/event_service.js +26 -5
  89. package/dest/events/private_event_filter_validator.d.ts +3 -2
  90. package/dest/events/private_event_filter_validator.d.ts.map +1 -1
  91. package/dest/events/private_event_filter_validator.js +15 -0
  92. package/dest/logs/log_service.d.ts +7 -8
  93. package/dest/logs/log_service.d.ts.map +1 -1
  94. package/dest/logs/log_service.js +29 -39
  95. package/dest/messages/message_context_service.d.ts +17 -0
  96. package/dest/messages/message_context_service.d.ts.map +1 -0
  97. package/dest/messages/message_context_service.js +36 -0
  98. package/dest/notes/note_service.d.ts +4 -5
  99. package/dest/notes/note_service.d.ts.map +1 -1
  100. package/dest/notes/note_service.js +14 -5
  101. package/dest/notes_filter.d.ts +2 -3
  102. package/dest/notes_filter.d.ts.map +1 -1
  103. package/dest/oracle_version.d.ts +4 -3
  104. package/dest/oracle_version.d.ts.map +1 -1
  105. package/dest/oracle_version.js +20 -10
  106. package/dest/private_kernel/hints/compute_tx_expiration_timestamp.d.ts +4 -0
  107. package/dest/private_kernel/hints/compute_tx_expiration_timestamp.d.ts.map +1 -0
  108. package/dest/private_kernel/hints/{compute_tx_include_by_timestamp.js → compute_tx_expiration_timestamp.js} +12 -12
  109. package/dest/private_kernel/hints/index.d.ts +1 -1
  110. package/dest/private_kernel/hints/index.js +1 -1
  111. package/dest/private_kernel/hints/private_kernel_reset_private_inputs_builder.d.ts +4 -3
  112. package/dest/private_kernel/hints/private_kernel_reset_private_inputs_builder.d.ts.map +1 -1
  113. package/dest/private_kernel/hints/private_kernel_reset_private_inputs_builder.js +129 -68
  114. package/dest/private_kernel/hints/test_utils.d.ts +122 -0
  115. package/dest/private_kernel/hints/test_utils.d.ts.map +1 -0
  116. package/dest/private_kernel/hints/test_utils.js +203 -0
  117. package/dest/private_kernel/private_kernel_execution_prover.d.ts +1 -1
  118. package/dest/private_kernel/private_kernel_execution_prover.d.ts.map +1 -1
  119. package/dest/private_kernel/private_kernel_execution_prover.js +18 -13
  120. package/dest/private_kernel/private_kernel_oracle.d.ts +10 -6
  121. package/dest/private_kernel/private_kernel_oracle.d.ts.map +1 -1
  122. package/dest/private_kernel/private_kernel_oracle.js +19 -18
  123. package/dest/pxe.d.ts +17 -13
  124. package/dest/pxe.d.ts.map +1 -1
  125. package/dest/pxe.js +91 -60
  126. package/dest/storage/anchor_block_store/anchor_block_store.js +1 -1
  127. package/dest/storage/capsule_store/capsule_service.d.ts +21 -0
  128. package/dest/storage/capsule_store/capsule_service.d.ts.map +1 -0
  129. package/dest/storage/capsule_store/capsule_service.js +50 -0
  130. package/dest/storage/capsule_store/capsule_store.d.ts +9 -9
  131. package/dest/storage/capsule_store/capsule_store.d.ts.map +1 -1
  132. package/dest/storage/capsule_store/capsule_store.js +36 -28
  133. package/dest/storage/capsule_store/index.d.ts +2 -1
  134. package/dest/storage/capsule_store/index.d.ts.map +1 -1
  135. package/dest/storage/capsule_store/index.js +1 -0
  136. package/dest/storage/contract_store/contract_store.d.ts +42 -15
  137. package/dest/storage/contract_store/contract_store.d.ts.map +1 -1
  138. package/dest/storage/contract_store/contract_store.js +143 -65
  139. package/dest/storage/metadata.d.ts +1 -1
  140. package/dest/storage/metadata.js +1 -1
  141. package/dest/storage/note_store/note_store.d.ts +1 -1
  142. package/dest/storage/note_store/note_store.d.ts.map +1 -1
  143. package/dest/storage/note_store/note_store.js +2 -2
  144. package/dest/storage/private_event_store/private_event_store.d.ts +1 -1
  145. package/dest/storage/private_event_store/private_event_store.d.ts.map +1 -1
  146. package/dest/storage/private_event_store/private_event_store.js +3 -0
  147. package/dest/storage/private_event_store/stored_private_event.js +1 -1
  148. package/dest/storage/tagging_store/recipient_tagging_store.d.ts +6 -6
  149. package/dest/storage/tagging_store/recipient_tagging_store.d.ts.map +1 -1
  150. package/dest/storage/tagging_store/sender_tagging_store.d.ts +29 -28
  151. package/dest/storage/tagging_store/sender_tagging_store.d.ts.map +1 -1
  152. package/dest/storage/tagging_store/sender_tagging_store.js +141 -115
  153. package/dest/tagging/get_all_logs_by_tags.d.ts +1 -1
  154. package/dest/tagging/get_all_logs_by_tags.d.ts.map +1 -1
  155. package/dest/tagging/get_all_logs_by_tags.js +17 -3
  156. package/dest/tagging/index.d.ts +3 -3
  157. package/dest/tagging/index.d.ts.map +1 -1
  158. package/dest/tagging/index.js +1 -1
  159. package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.d.ts +4 -5
  160. package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.d.ts.map +1 -1
  161. package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.js +8 -22
  162. package/dest/tagging/recipient_sync/utils/find_highest_indexes.js +2 -2
  163. package/dest/tagging/recipient_sync/utils/load_logs_for_range.d.ts +6 -7
  164. package/dest/tagging/recipient_sync/utils/load_logs_for_range.d.ts.map +1 -1
  165. package/dest/tagging/recipient_sync/utils/load_logs_for_range.js +12 -11
  166. package/dest/tagging/sender_sync/sync_sender_tagging_indexes.d.ts +4 -8
  167. package/dest/tagging/sender_sync/sync_sender_tagging_indexes.d.ts.map +1 -1
  168. package/dest/tagging/sender_sync/sync_sender_tagging_indexes.js +13 -7
  169. package/dest/tagging/sender_sync/utils/get_status_change_of_pending.d.ts +4 -3
  170. package/dest/tagging/sender_sync/utils/get_status_change_of_pending.d.ts.map +1 -1
  171. package/dest/tagging/sender_sync/utils/get_status_change_of_pending.js +20 -10
  172. package/dest/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.d.ts +5 -7
  173. package/dest/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.d.ts.map +1 -1
  174. package/dest/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.js +36 -24
  175. package/package.json +16 -16
  176. package/src/bin/check_oracle_version.ts +4 -4
  177. package/src/block_synchronizer/block_synchronizer.ts +22 -2
  178. package/src/config/index.ts +3 -9
  179. package/src/config/package_info.ts +1 -1
  180. package/src/contract_function_simulator/contract_function_simulator.ts +66 -33
  181. package/src/contract_function_simulator/ephemeral_array_service.ts +110 -0
  182. package/src/contract_function_simulator/execution_tagging_index_cache.ts +19 -14
  183. package/src/contract_function_simulator/index.ts +1 -0
  184. package/src/contract_function_simulator/noir-structs/event_validation_request.ts +9 -9
  185. package/src/contract_function_simulator/noir-structs/log_retrieval_request.ts +1 -1
  186. package/src/contract_function_simulator/noir-structs/log_retrieval_response.ts +2 -5
  187. package/src/contract_function_simulator/noir-structs/note_validation_request.ts +4 -10
  188. package/src/contract_function_simulator/oracle/interfaces.ts +82 -54
  189. package/src/contract_function_simulator/oracle/legacy_oracle_mappings.ts +104 -0
  190. package/src/contract_function_simulator/oracle/oracle.ts +363 -139
  191. package/src/contract_function_simulator/oracle/private_execution.ts +4 -4
  192. package/src/contract_function_simulator/oracle/private_execution_oracle.ts +72 -104
  193. package/src/contract_function_simulator/oracle/utility_execution_oracle.ts +457 -152
  194. package/src/contract_function_simulator/pick_notes.ts +22 -3
  195. package/src/contract_function_simulator/proxied_contract_data_source.ts +8 -1
  196. package/src/contract_logging.ts +52 -0
  197. package/src/contract_sync/contract_sync_service.ts +99 -75
  198. package/src/contract_sync/helpers.ts +4 -4
  199. package/src/debug/pxe_debug_utils.ts +7 -7
  200. package/src/entrypoints/client/bundle/index.ts +1 -1
  201. package/src/entrypoints/client/bundle/utils.ts +2 -3
  202. package/src/entrypoints/client/lazy/index.ts +1 -1
  203. package/src/entrypoints/client/lazy/utils.ts +2 -3
  204. package/src/entrypoints/pxe_creation_options.ts +7 -0
  205. package/src/entrypoints/server/index.ts +1 -2
  206. package/src/entrypoints/server/utils.ts +2 -3
  207. package/src/events/event_service.ts +30 -5
  208. package/src/events/private_event_filter_validator.ts +21 -1
  209. package/src/logs/log_service.ts +59 -75
  210. package/src/messages/message_context_service.ts +44 -0
  211. package/src/notes/note_service.ts +18 -8
  212. package/src/notes_filter.ts +1 -3
  213. package/src/oracle_version.ts +20 -10
  214. package/src/private_kernel/hints/{compute_tx_include_by_timestamp.ts → compute_tx_expiration_timestamp.ts} +13 -13
  215. package/src/private_kernel/hints/index.ts +1 -1
  216. package/src/private_kernel/hints/private_kernel_reset_private_inputs_builder.ts +164 -117
  217. package/src/private_kernel/hints/test_utils.ts +325 -0
  218. package/src/private_kernel/private_kernel_execution_prover.ts +18 -16
  219. package/src/private_kernel/private_kernel_oracle.ts +21 -21
  220. package/src/pxe.ts +152 -74
  221. package/src/storage/anchor_block_store/anchor_block_store.ts +1 -1
  222. package/src/storage/capsule_store/capsule_service.ts +90 -0
  223. package/src/storage/capsule_store/capsule_store.ts +44 -26
  224. package/src/storage/capsule_store/index.ts +1 -0
  225. package/src/storage/contract_store/contract_store.ts +177 -76
  226. package/src/storage/metadata.ts +1 -1
  227. package/src/storage/note_store/note_store.ts +2 -5
  228. package/src/storage/private_event_store/private_event_store.ts +4 -0
  229. package/src/storage/private_event_store/stored_private_event.ts +1 -1
  230. package/src/storage/tagging_store/recipient_tagging_store.ts +9 -5
  231. package/src/storage/tagging_store/sender_tagging_store.ts +185 -138
  232. package/src/tagging/get_all_logs_by_tags.ts +28 -4
  233. package/src/tagging/index.ts +2 -2
  234. package/src/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.ts +12 -25
  235. package/src/tagging/recipient_sync/utils/find_highest_indexes.ts +2 -2
  236. package/src/tagging/recipient_sync/utils/load_logs_for_range.ts +10 -15
  237. package/src/tagging/sender_sync/sync_sender_tagging_indexes.ts +23 -10
  238. package/src/tagging/sender_sync/utils/get_status_change_of_pending.ts +26 -11
  239. package/src/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.ts +27 -26
  240. package/dest/access_scopes.d.ts +0 -9
  241. package/dest/access_scopes.d.ts.map +0 -1
  242. package/dest/access_scopes.js +0 -6
  243. package/dest/private_kernel/hints/compute_tx_include_by_timestamp.d.ts +0 -4
  244. package/dest/private_kernel/hints/compute_tx_include_by_timestamp.d.ts.map +0 -1
  245. package/src/access_scopes.ts +0 -9
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,
@@ -47,12 +48,11 @@ import {
47
48
  TxProfileResult,
48
49
  TxProvingResult,
49
50
  TxSimulationResult,
50
- UtilitySimulationResult,
51
+ UtilityExecutionResult,
51
52
  } from '@aztec/stdlib/tx';
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';
@@ -61,12 +61,14 @@ import {
61
61
  generateSimulatedProvingResult,
62
62
  } from './contract_function_simulator/contract_function_simulator.js';
63
63
  import { ProxiedContractStoreFactory } from './contract_function_simulator/proxied_contract_data_source.js';
64
+ import { displayDebugLogs } from './contract_logging.js';
64
65
  import { ContractSyncService } from './contract_sync/contract_sync_service.js';
65
66
  import { readCurrentClassId } from './contract_sync/helpers.js';
66
67
  import { PXEDebugUtils } from './debug/pxe_debug_utils.js';
67
68
  import { enrichPublicSimulationError, enrichSimulationError } from './error_enriching.js';
68
69
  import { PrivateEventFilterValidator } from './events/private_event_filter_validator.js';
69
70
  import { JobCoordinator } from './job_coordinator/job_coordinator.js';
71
+ import { MessageContextService } from './messages/message_context_service.js';
70
72
  import {
71
73
  PrivateKernelExecutionProver,
72
74
  type PrivateKernelExecutionProverConfig,
@@ -94,7 +96,7 @@ export type ProfileTxOpts = {
94
96
  /** If true, proof generation is skipped during profiling. Defaults to true. */
95
97
  skipProofGeneration?: boolean;
96
98
  /** Addresses whose private state and keys are accessible during private execution. */
97
- scopes: AccessScopes;
99
+ scopes: AztecAddress[];
98
100
  };
99
101
 
100
102
  /** Options for PXE.simulateTx. */
@@ -105,18 +107,20 @@ export type SimulateTxOpts = {
105
107
  skipTxValidation?: boolean;
106
108
  /** If false, fees are enforced. */
107
109
  skipFeeEnforcement?: boolean;
108
- /** State overrides for the simulation, such as contract instances and artifacts. */
110
+ /** If true, kernel logic is emulated in TS for simulation */
111
+ skipKernels?: boolean;
112
+ /** State overrides for the simulation, such as contract instances and artifacts. Requires skipKernels: true */
109
113
  overrides?: SimulationOverrides;
110
114
  /** Addresses whose private state and keys are accessible during private execution */
111
- scopes: AccessScopes;
115
+ scopes: AztecAddress[];
112
116
  };
113
117
 
114
- /** Options for PXE.simulateUtility. */
115
- export type SimulateUtilityOpts = {
118
+ /** Options for PXE.executeUtility. */
119
+ export type ExecuteUtilityOpts = {
116
120
  /** The authentication witnesses required for the function call. */
117
121
  authwits?: AuthWitness[];
118
122
  /** The accounts whose notes we can access in this call */
119
- scopes: AccessScopes;
123
+ scopes: AztecAddress[];
120
124
  };
121
125
 
122
126
  /** Args for PXE.create. */
@@ -144,6 +148,7 @@ export type PXECreateArgs = {
144
148
  export class PXE {
145
149
  private constructor(
146
150
  private node: AztecNode,
151
+ private db: AztecAsyncKVStore,
147
152
  private blockStateSynchronizer: BlockSynchronizer,
148
153
  private keyStore: KeyStore,
149
154
  private contractStore: ContractStore,
@@ -156,6 +161,8 @@ export class PXE {
156
161
  private addressStore: AddressStore,
157
162
  private privateEventStore: PrivateEventStore,
158
163
  private contractSyncService: ContractSyncService,
164
+ private messageContextService: MessageContextService,
165
+ private l2TipsStore: L2TipsProvider,
159
166
  private simulator: CircuitSimulator,
160
167
  private proverEnabled: boolean,
161
168
  private proofCreator: PrivateKernelProver,
@@ -211,6 +218,8 @@ export class PXE {
211
218
  noteStore,
212
219
  createLogger('pxe:contract_sync', bindings),
213
220
  );
221
+ const messageContextService = new MessageContextService(node);
222
+
214
223
  const synchronizer = new BlockSynchronizer(
215
224
  node,
216
225
  store,
@@ -239,6 +248,7 @@ export class PXE {
239
248
 
240
249
  const pxe = new PXE(
241
250
  node,
251
+ store,
242
252
  synchronizer,
243
253
  keyStore,
244
254
  contractStore,
@@ -251,6 +261,8 @@ export class PXE {
251
261
  addressStore,
252
262
  privateEventStore,
253
263
  contractSyncService,
264
+ messageContextService,
265
+ tipsStore,
254
266
  simulator,
255
267
  proverEnabled,
256
268
  proofCreator,
@@ -264,7 +276,7 @@ export class PXE {
264
276
  debugUtils.setPXEHelpers(
265
277
  pxe.#putInJobQueue.bind(pxe),
266
278
  pxe.#getSimulatorForTx.bind(pxe),
267
- pxe.#simulateUtility.bind(pxe),
279
+ pxe.#executeUtility.bind(pxe),
268
280
  );
269
281
 
270
282
  pxe.jobQueue.start();
@@ -285,6 +297,7 @@ export class PXE {
285
297
  keyStore: this.keyStore,
286
298
  addressStore: this.addressStore,
287
299
  aztecNode: BenchmarkedNodeFactory.create(this.node),
300
+ l2TipsStore: this.l2TipsStore,
288
301
  senderTaggingStore: this.senderTaggingStore,
289
302
  recipientTaggingStore: this.recipientTaggingStore,
290
303
  senderAddressBookStore: this.senderAddressBookStore,
@@ -292,6 +305,7 @@ export class PXE {
292
305
  privateEventStore: this.privateEventStore,
293
306
  simulator: this.simulator,
294
307
  contractSyncService: this.contractSyncService,
308
+ messageContextService: this.messageContextService,
295
309
  });
296
310
  }
297
311
 
@@ -344,9 +358,8 @@ export class PXE {
344
358
  async #registerProtocolContracts() {
345
359
  const registered: Record<string, string> = {};
346
360
  for (const name of protocolContractNames) {
347
- const { address, contractClass, instance, artifact } =
348
- await this.protocolContractsProvider.getProtocolContractArtifact(name);
349
- await this.contractStore.addContractArtifact(contractClass.id, artifact);
361
+ const { address, instance, artifact } = await this.protocolContractsProvider.getProtocolContractArtifact(name);
362
+ await this.contractStore.addContractArtifact(artifact);
350
363
  await this.contractStore.addContractInstance(instance);
351
364
  registered[name] = address.toString();
352
365
  }
@@ -358,19 +371,18 @@ export class PXE {
358
371
  async #executePrivate(
359
372
  contractFunctionSimulator: ContractFunctionSimulator,
360
373
  txRequest: TxExecutionRequest,
361
- scopes: AccessScopes,
374
+ anchorBlockHeader: BlockHeader,
375
+ scopes: AztecAddress[],
362
376
  jobId: string,
363
377
  ): Promise<PrivateExecutionResult> {
364
378
  const { origin: contractAddress, functionSelector } = txRequest;
365
379
 
366
380
  try {
367
- const anchorBlockHeader = await this.anchorBlockStore.getBlockHeader();
368
-
369
381
  await this.contractSyncService.ensureContractSynced(
370
382
  contractAddress,
371
383
  functionSelector,
372
384
  (privateSyncCall, execScopes) =>
373
- this.#simulateUtility(contractFunctionSimulator, privateSyncCall, [], execScopes, jobId),
385
+ this.#executeUtility(contractFunctionSimulator, privateSyncCall, [], execScopes, jobId),
374
386
  anchorBlockHeader,
375
387
  jobId,
376
388
  scopes,
@@ -394,25 +406,32 @@ export class PXE {
394
406
  }
395
407
 
396
408
  /**
397
- * Simulate a utility function call on the given contract.
409
+ * Execute a utility function call on the given contract.
398
410
  * @param contractFunctionSimulator - The simulator to use for the function call.
399
411
  * @param call - The function call to execute.
400
412
  * @param authWitnesses - Authentication witnesses required for the function call.
401
413
  * @param scopes - Optional array of account addresses whose notes can be accessed in this call. Defaults to all
402
414
  * accounts if not specified.
403
415
  * @param jobId - The job ID for staged writes.
404
- * @returns The simulation result containing the outputs of the utility function.
416
+ * @returns The execution result containing the outputs of the utility function.
405
417
  */
406
- async #simulateUtility(
418
+ async #executeUtility(
407
419
  contractFunctionSimulator: ContractFunctionSimulator,
408
420
  call: FunctionCall,
409
421
  authWitnesses: AuthWitness[] | undefined,
410
- scopes: AccessScopes,
422
+ scopes: AztecAddress[],
411
423
  jobId: string,
412
424
  ) {
413
425
  try {
414
426
  const anchorBlockHeader = await this.anchorBlockStore.getBlockHeader();
415
- return contractFunctionSimulator.runUtility(call, authWitnesses ?? [], anchorBlockHeader, scopes, jobId);
427
+ const { result, offchainEffects } = await contractFunctionSimulator.runUtility(
428
+ call,
429
+ authWitnesses ?? [],
430
+ anchorBlockHeader,
431
+ scopes,
432
+ jobId,
433
+ );
434
+ return { result, offchainEffects };
416
435
  } catch (err) {
417
436
  if (err instanceof SimulationError) {
418
437
  await enrichSimulationError(err, this.contractStore, this.log);
@@ -463,11 +482,10 @@ export class PXE {
463
482
  txExecutionRequest: TxExecutionRequest,
464
483
  proofCreator: PrivateKernelProver,
465
484
  privateExecutionResult: PrivateExecutionResult,
485
+ anchorBlockHeader: BlockHeader,
466
486
  config: PrivateKernelExecutionProverConfig,
467
487
  ): Promise<PrivateKernelExecutionProofOutput<PrivateKernelTailCircuitPublicInputs>> {
468
- const anchorBlockHeader = await this.anchorBlockStore.getBlockHeader();
469
- const anchorBlockHash = await anchorBlockHeader.hash();
470
- const kernelOracle = new PrivateKernelOracle(this.contractStore, this.keyStore, this.node, anchorBlockHash);
488
+ const kernelOracle = new PrivateKernelOracle(this.contractStore, this.keyStore, this.node, anchorBlockHeader);
471
489
  const kernelTraceProver = new PrivateKernelExecutionProver(
472
490
  kernelOracle,
473
491
  proofCreator,
@@ -485,7 +503,9 @@ export class PXE {
485
503
  * @returns The synced block header
486
504
  */
487
505
  public getSyncedBlockHeader(): Promise<BlockHeader> {
488
- return this.anchorBlockStore.getBlockHeader();
506
+ return this.#putInJobQueue(() => {
507
+ return this.anchorBlockStore.getBlockHeader();
508
+ });
489
509
  }
490
510
 
491
511
  /**
@@ -542,6 +562,12 @@ export class PXE {
542
562
  * TODO: It's strange that we return the address here and I (benesjan) think we should drop the return value.
543
563
  */
544
564
  public async registerSender(sender: AztecAddress): Promise<AztecAddress> {
565
+ if (!(await sender.isValid())) {
566
+ throw new Error(
567
+ `Address ${sender} is not valid: it does not correspond to a point on the Grumpkin curve. Cannot register it as a sender.`,
568
+ );
569
+ }
570
+
545
571
  const accounts = await this.keyStore.getAccounts();
546
572
  if (accounts.includes(sender)) {
547
573
  this.log.info(`Sender:\n "${sender.toString()}"\n already registered.`);
@@ -552,6 +578,9 @@ export class PXE {
552
578
 
553
579
  if (wasAdded) {
554
580
  this.log.info(`Added sender:\n ${sender.toString()}`);
581
+ // Wipe the entire sync cache: the new sender's tagged logs could contain notes/events for any contract, so
582
+ // all contracts must re-sync to discover them. Queued to avoid wiping while a job is in flight.
583
+ await this.#putInJobQueue(() => Promise.resolve(this.contractSyncService.wipe()));
555
584
  } else {
556
585
  this.log.info(`Sender:\n "${sender.toString()}"\n already registered.`);
557
586
  }
@@ -601,8 +630,7 @@ export class PXE {
601
630
  * @param artifact - The build artifact for the contract class.
602
631
  */
603
632
  public async registerContractClass(artifact: ContractArtifact): Promise<void> {
604
- const { id: contractClassId } = await getContractClassFromArtifact(artifact);
605
- await this.contractStore.addContractArtifact(contractClassId, artifact);
633
+ const contractClassId = await this.contractStore.addContractArtifact(artifact);
606
634
  this.log.info(`Added contract class ${artifact.name} with id ${contractClassId}`);
607
635
  }
608
636
 
@@ -621,17 +649,17 @@ export class PXE {
621
649
  if (artifact) {
622
650
  // If the user provides an artifact, validate it against the expected class id and register it
623
651
  const contractClass = await getContractClassFromArtifact(artifact);
624
- const contractClassId = contractClass.id;
625
- if (!contractClassId.equals(instance.currentContractClassId)) {
652
+ if (!contractClass.id.equals(instance.currentContractClassId)) {
626
653
  throw new Error(
627
- `Artifact does not match expected class id (computed ${contractClassId} but instance refers to ${instance.currentContractClassId})`,
654
+ `Artifact does not match expected class id (computed ${contractClass.id} but instance refers to ${instance.currentContractClassId})`,
628
655
  );
629
656
  }
630
657
  const computedAddress = await computeContractAddressFromInstance(instance);
631
658
  if (!computedAddress.equals(instance.address)) {
632
659
  throw new Error('Added a contract in which the address does not match the contract instance.');
633
660
  }
634
- await this.contractStore.addContractArtifact(contractClass.id, artifact);
661
+
662
+ await this.contractStore.addContractArtifact(artifact, contractClass);
635
663
 
636
664
  const publicFunctionSignatures = artifact.functions
637
665
  .filter(fn => fn.functionType === FunctionType.PUBLIC)
@@ -680,15 +708,16 @@ export class PXE {
680
708
  throw new Error('Could not update contract to a class different from the current one.');
681
709
  }
682
710
 
683
- await this.contractStore.addContractArtifact(contractClass.id, artifact);
684
-
685
711
  const publicFunctionSignatures = artifact.functions
686
712
  .filter(fn => fn.functionType === FunctionType.PUBLIC)
687
713
  .map(fn => decodeFunctionSignature(fn.name, fn.parameters));
688
714
  await this.node.registerContractFunctionSignatures(publicFunctionSignatures);
689
715
 
690
716
  currentInstance.currentContractClassId = contractClass.id;
691
- await this.contractStore.addContractInstance(currentInstance);
717
+ await Promise.all([
718
+ this.contractStore.addContractArtifact(artifact, contractClass),
719
+ this.contractStore.addContractInstance(currentInstance),
720
+ ]);
692
721
  this.log.info(`Updated contract ${artifact.name} at ${contractAddress.toString()} to class ${contractClass.id}`);
693
722
  });
694
723
  }
@@ -720,16 +749,23 @@ export class PXE {
720
749
  try {
721
750
  const syncTimer = new Timer();
722
751
  await this.blockStateSynchronizer.sync();
752
+ const anchorBlockHeader = await this.anchorBlockStore.getBlockHeader();
723
753
  const syncTime = syncTimer.ms();
724
754
  const contractFunctionSimulator = this.#getSimulatorForTx();
725
- privateExecutionResult = await this.#executePrivate(contractFunctionSimulator, txRequest, scopes, jobId);
755
+ privateExecutionResult = await this.#executePrivate(
756
+ contractFunctionSimulator,
757
+ txRequest,
758
+ anchorBlockHeader,
759
+ scopes,
760
+ jobId,
761
+ );
726
762
 
727
763
  const {
728
764
  publicInputs,
729
765
  chonkProof,
730
766
  executionSteps,
731
767
  timings: { proving } = {},
732
- } = await this.#prove(txRequest, this.proofCreator, privateExecutionResult, {
768
+ } = await this.#prove(txRequest, this.proofCreator, privateExecutionResult, anchorBlockHeader, {
733
769
  simulate: false,
734
770
  skipFeeEnforcement: false,
735
771
  profileMode: 'none',
@@ -764,17 +800,17 @@ export class PXE {
764
800
  // transaction before this one is included in a block from this PXE, and that transaction contains a log with
765
801
  // a tag derived from the same secret, we would reuse the tag and the transactions would be linked. Hence
766
802
  // storing the tags here prevents linkage of txs sent from the same PXE.
767
- const preTagsUsedInTheTx = privateExecutionResult.entrypoint.preTags;
768
- if (preTagsUsedInTheTx.length > 0) {
803
+ const taggingIndexRangesUsedInTheTx = privateExecutionResult.entrypoint.taggingIndexRanges;
804
+ if (taggingIndexRangesUsedInTheTx.length > 0) {
769
805
  // TODO(benesjan): The following is an expensive operation. Figure out a way to avoid it.
770
806
  const txHash = (await txProvingResult.toTx()).txHash;
771
807
 
772
- await this.senderTaggingStore.storePendingIndexes(preTagsUsedInTheTx, txHash, jobId);
773
- this.log.debug(`Stored used pre-tags as sender for the tx`, {
774
- preTagsUsedInTheTx,
808
+ await this.senderTaggingStore.storePendingIndexes(taggingIndexRangesUsedInTheTx, txHash, jobId);
809
+ this.log.debug(`Stored used tagging index ranges as sender for the tx`, {
810
+ taggingIndexRangesUsedInTheTx,
775
811
  });
776
812
  } else {
777
- this.log.debug(`No pre-tags used in the tx`);
813
+ this.log.debug(`No tagging index ranges used in the tx`);
778
814
  }
779
815
 
780
816
  return txProvingResult;
@@ -812,15 +848,23 @@ export class PXE {
812
848
  );
813
849
  const syncTimer = new Timer();
814
850
  await this.blockStateSynchronizer.sync();
851
+ const anchorBlockHeader = await this.anchorBlockStore.getBlockHeader();
815
852
  const syncTime = syncTimer.ms();
816
853
 
817
854
  const contractFunctionSimulator = this.#getSimulatorForTx();
818
- const privateExecutionResult = await this.#executePrivate(contractFunctionSimulator, txRequest, scopes, jobId);
855
+ const privateExecutionResult = await this.#executePrivate(
856
+ contractFunctionSimulator,
857
+ txRequest,
858
+ anchorBlockHeader,
859
+ scopes,
860
+ jobId,
861
+ );
819
862
 
820
863
  const { executionSteps, timings: { proving } = {} } = await this.#prove(
821
864
  txRequest,
822
865
  this.proofCreator,
823
866
  privateExecutionResult,
867
+ anchorBlockHeader,
824
868
  {
825
869
  simulate: skipProofGeneration,
826
870
  skipFeeEnforcement: false,
@@ -881,7 +925,14 @@ export class PXE {
881
925
  */
882
926
  public simulateTx(
883
927
  txRequest: TxExecutionRequest,
884
- { simulatePublic, skipTxValidation = false, skipFeeEnforcement = false, overrides, scopes }: SimulateTxOpts,
928
+ {
929
+ simulatePublic,
930
+ skipTxValidation = false,
931
+ skipFeeEnforcement = false,
932
+ skipKernels = true,
933
+ overrides,
934
+ scopes,
935
+ }: SimulateTxOpts,
885
936
  ): Promise<TxSimulationResult> {
886
937
  // We disable concurrent simulations since those might execute oracles which read and write to the PXE stores (e.g.
887
938
  // to the capsules), and we need to prevent concurrent runs from interfering with one another (e.g. attempting to
@@ -903,23 +954,33 @@ export class PXE {
903
954
  );
904
955
  const syncTimer = new Timer();
905
956
  await this.blockStateSynchronizer.sync();
957
+ const anchorBlockHeader = await this.anchorBlockStore.getBlockHeader();
906
958
  const syncTime = syncTimer.ms();
907
959
 
908
- const contractFunctionSimulator = this.#getSimulatorForTx(overrides);
909
- // Temporary: in case there are overrides, we have to skip the kernels or validations
910
- // will fail. Consider handing control to the user/wallet on whether they want to run them
911
- // or not.
912
960
  const overriddenContracts = overrides?.contracts ? new Set(Object.keys(overrides.contracts)) : undefined;
913
961
  const hasOverriddenContracts = overriddenContracts !== undefined && overriddenContracts.size > 0;
914
- const skipKernels = hasOverriddenContracts;
915
962
 
916
- // Set overridden contracts on the sync service so it knows to skip syncing them
963
+ if (hasOverriddenContracts && !skipKernels) {
964
+ throw new Error(
965
+ 'Simulating with overridden contracts is not compatible with kernel execution. Please set skipKernels to true when simulating with overridden contracts.',
966
+ );
967
+ }
968
+ const contractFunctionSimulator = this.#getSimulatorForTx(overrides);
969
+
917
970
  if (hasOverriddenContracts) {
918
- this.contractSyncService.setOverriddenContracts(jobId, overriddenContracts);
971
+ // Overridden contracts don't have a sync function, so calling sync on them would fail.
972
+ // We exclude them so the sync service skips them entirely.
973
+ this.contractSyncService.setExcludedFromSync(jobId, overriddenContracts);
919
974
  }
920
975
 
921
976
  // Execution of private functions only; no proving, and no kernel logic.
922
- const privateExecutionResult = await this.#executePrivate(contractFunctionSimulator, txRequest, scopes, jobId);
977
+ const privateExecutionResult = await this.#executePrivate(
978
+ contractFunctionSimulator,
979
+ txRequest,
980
+ anchorBlockHeader,
981
+ scopes,
982
+ jobId,
983
+ );
923
984
 
924
985
  let publicInputs: PrivateKernelTailCircuitPublicInputs | undefined;
925
986
  let executionSteps: PrivateExecutionStep[] = [];
@@ -932,11 +993,17 @@ export class PXE {
932
993
  ));
933
994
  } else {
934
995
  // Kernel logic, plus proving of all private functions and kernels.
935
- ({ publicInputs, executionSteps } = await this.#prove(txRequest, this.proofCreator, privateExecutionResult, {
936
- simulate: true,
937
- skipFeeEnforcement,
938
- profileMode: 'none',
939
- }));
996
+ ({ publicInputs, executionSteps } = await this.#prove(
997
+ txRequest,
998
+ this.proofCreator,
999
+ privateExecutionResult,
1000
+ anchorBlockHeader,
1001
+ {
1002
+ simulate: true,
1003
+ skipFeeEnforcement,
1004
+ profileMode: 'none',
1005
+ },
1006
+ ));
940
1007
  }
941
1008
 
942
1009
  const privateSimulationResult = new PrivateSimulationResult(privateExecutionResult, publicInputs);
@@ -947,6 +1014,9 @@ export class PXE {
947
1014
  const publicSimulationTimer = new Timer();
948
1015
  publicOutput = await this.#simulatePublicCalls(simulatedTx, skipFeeEnforcement);
949
1016
  publicSimulationTime = publicSimulationTimer.ms();
1017
+ if (publicOutput?.debugLogs?.length) {
1018
+ await displayDebugLogs(publicOutput.debugLogs, addr => this.contractStore.getDebugContractName(addr));
1019
+ }
950
1020
  }
951
1021
 
952
1022
  let validationTime: number | undefined;
@@ -955,7 +1025,8 @@ export class PXE {
955
1025
  const validationResult = await this.node.isValidTx(simulatedTx, { isSimulation: true, skipFeeEnforcement });
956
1026
  validationTime = validationTimer.ms();
957
1027
  if (validationResult.result === 'invalid') {
958
- throw new Error('The simulated transaction is unable to be added to state and is invalid.');
1028
+ const reason = validationResult.reason.length > 0 ? ` Reason: ${validationResult.reason.join(', ')}` : '';
1029
+ throw new Error(`The simulated transaction is unable to be added to state and is invalid.${reason}`);
959
1030
  }
960
1031
  }
961
1032
 
@@ -1006,23 +1077,23 @@ export class PXE {
1006
1077
  inspect(txRequest),
1007
1078
  `simulatePublic=${simulatePublic}`,
1008
1079
  `skipTxValidation=${skipTxValidation}`,
1009
- `scopes=${scopes === 'ALL_SCOPES' ? scopes : scopes.map(s => s.toString()).join(', ')}`,
1080
+ `scopes=${scopes.map(s => s.toString()).join(', ')}`,
1010
1081
  );
1011
1082
  }
1012
1083
  });
1013
1084
  }
1014
1085
 
1015
1086
  /**
1016
- * Simulates the execution of a contract utility function.
1087
+ * Executes a contract utility function.
1017
1088
  * @param call - The function call containing the function details, arguments, and target contract address.
1018
1089
  */
1019
- public simulateUtility(
1090
+ public executeUtility(
1020
1091
  call: FunctionCall,
1021
- { authwits, scopes }: SimulateUtilityOpts = { scopes: 'ALL_SCOPES' },
1022
- ): Promise<UtilitySimulationResult> {
1023
- // We disable concurrent simulations since those might execute oracles which read and write to the PXE stores (e.g.
1092
+ { authwits, scopes }: ExecuteUtilityOpts = { scopes: [] },
1093
+ ): Promise<UtilityExecutionResult> {
1094
+ // We disable concurrent executions since those might execute oracles which read and write to the PXE stores (e.g.
1024
1095
  // to the capsules), and we need to prevent concurrent runs from interfering with one another (e.g. attempting to
1025
- // delete the same read value, or reading values that another simulation is currently modifying).
1096
+ // delete the same read value, or reading values that another execution is currently modifying).
1026
1097
  return this.#putInJobQueue(async jobId => {
1027
1098
  try {
1028
1099
  const totalTimer = new Timer();
@@ -1037,13 +1108,13 @@ export class PXE {
1037
1108
  call.to,
1038
1109
  call.selector,
1039
1110
  (privateSyncCall, execScopes) =>
1040
- this.#simulateUtility(contractFunctionSimulator, privateSyncCall, [], execScopes, jobId),
1111
+ this.#executeUtility(contractFunctionSimulator, privateSyncCall, [], execScopes, jobId),
1041
1112
  anchorBlockHeader,
1042
1113
  jobId,
1043
1114
  scopes,
1044
1115
  );
1045
1116
 
1046
- const executionResult = await this.#simulateUtility(
1117
+ const { result: executionResult, offchainEffects } = await this.#executeUtility(
1047
1118
  contractFunctionSimulator,
1048
1119
  call,
1049
1120
  authwits ?? [],
@@ -1064,14 +1135,19 @@ export class PXE {
1064
1135
  };
1065
1136
 
1066
1137
  const simulationStats = contractFunctionSimulator.getStats();
1067
- return { result: executionResult, stats: { timings, nodeRPCCalls: simulationStats.nodeRPCCalls } };
1138
+ return {
1139
+ result: executionResult,
1140
+ offchainEffects,
1141
+ anchorBlockTimestamp: anchorBlockHeader.globalVariables.timestamp,
1142
+ stats: { timings, nodeRPCCalls: simulationStats.nodeRPCCalls },
1143
+ };
1068
1144
  } catch (err: any) {
1069
1145
  const { to, name, args } = call;
1070
1146
  const stringifiedArgs = args.map(arg => arg.toString()).join(', ');
1071
1147
  throw this.#contextualizeError(
1072
1148
  err,
1073
- `simulateUtility ${to}:${name}(${stringifiedArgs})`,
1074
- `scopes=${scopes === 'ALL_SCOPES' ? scopes : scopes.map(s => s.toString()).join(', ')}`,
1149
+ `executeUtility ${to}:${name}(${stringifiedArgs})`,
1150
+ `scopes=${scopes.map(s => s.toString()).join(', ')}`,
1075
1151
  );
1076
1152
  }
1077
1153
  });
@@ -1108,7 +1184,7 @@ export class PXE {
1108
1184
  filter.contractAddress,
1109
1185
  null,
1110
1186
  async (privateSyncCall, execScopes) =>
1111
- await this.#simulateUtility(contractFunctionSimulator, privateSyncCall, [], execScopes, jobId),
1187
+ await this.#executeUtility(contractFunctionSimulator, privateSyncCall, [], execScopes, jobId),
1112
1188
  anchorBlockHeader,
1113
1189
  jobId,
1114
1190
  filter.scopes,
@@ -1126,9 +1202,11 @@ export class PXE {
1126
1202
  }
1127
1203
 
1128
1204
  /**
1129
- * Stops the PXE's job queue.
1205
+ * Stops the PXE's job queue and closes the backing store.
1130
1206
  */
1131
- public stop(): Promise<void> {
1132
- return this.jobQueue.end();
1207
+ public async stop(): Promise<void> {
1208
+ await this.jobQueue.end();
1209
+ await this.blockStateSynchronizer.stop();
1210
+ await this.db.close();
1133
1211
  }
1134
1212
  }
@@ -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
+ }