@aztec/pxe 0.0.1-commit.2448fdb → 0.0.1-commit.2606882

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 (279) hide show
  1. package/dest/bin/check_oracle_version.js +40 -96
  2. package/dest/bin/index.d.ts +2 -0
  3. package/dest/bin/index.d.ts.map +1 -0
  4. package/dest/bin/index.js +1 -0
  5. package/dest/bin/oracle_version_helpers.d.ts +26 -0
  6. package/dest/bin/oracle_version_helpers.d.ts.map +1 -0
  7. package/dest/bin/oracle_version_helpers.js +93 -0
  8. package/dest/block_synchronizer/block_stream_source.d.ts +10 -0
  9. package/dest/block_synchronizer/block_stream_source.d.ts.map +1 -0
  10. package/dest/block_synchronizer/block_stream_source.js +62 -0
  11. package/dest/block_synchronizer/block_synchronizer.d.ts +5 -3
  12. package/dest/block_synchronizer/block_synchronizer.d.ts.map +1 -1
  13. package/dest/block_synchronizer/block_synchronizer.js +21 -11
  14. package/dest/config/index.d.ts +8 -2
  15. package/dest/config/index.d.ts.map +1 -1
  16. package/dest/config/index.js +13 -15
  17. package/dest/config/package_info.js +1 -1
  18. package/dest/contract_function_simulator/contract_function_simulator.d.ts +4 -1
  19. package/dest/contract_function_simulator/contract_function_simulator.d.ts.map +1 -1
  20. package/dest/contract_function_simulator/contract_function_simulator.js +20 -12
  21. package/dest/contract_function_simulator/execution_note_cache.d.ts +2 -2
  22. package/dest/contract_function_simulator/execution_note_cache.d.ts.map +1 -1
  23. package/dest/contract_function_simulator/execution_tagging_index_cache.d.ts +5 -9
  24. package/dest/contract_function_simulator/execution_tagging_index_cache.d.ts.map +1 -1
  25. package/dest/contract_function_simulator/execution_tagging_index_cache.js +3 -7
  26. package/dest/contract_function_simulator/index.d.ts +13 -2
  27. package/dest/contract_function_simulator/index.d.ts.map +1 -1
  28. package/dest/contract_function_simulator/index.js +10 -0
  29. package/dest/contract_function_simulator/noir-structs/bounded_vec.d.ts +48 -0
  30. package/dest/contract_function_simulator/noir-structs/bounded_vec.d.ts.map +1 -0
  31. package/dest/contract_function_simulator/noir-structs/bounded_vec.js +45 -0
  32. package/dest/contract_function_simulator/noir-structs/ephemeral_array.d.ts +37 -0
  33. package/dest/contract_function_simulator/noir-structs/ephemeral_array.d.ts.map +1 -0
  34. package/dest/contract_function_simulator/noir-structs/ephemeral_array.js +59 -0
  35. package/dest/contract_function_simulator/noir-structs/event_validation_request.d.ts +3 -2
  36. package/dest/contract_function_simulator/noir-structs/event_validation_request.d.ts.map +1 -1
  37. package/dest/contract_function_simulator/noir-structs/event_validation_request.js +3 -2
  38. package/dest/contract_function_simulator/noir-structs/log_retrieval_request.d.ts +12 -2
  39. package/dest/contract_function_simulator/noir-structs/log_retrieval_request.d.ts.map +1 -1
  40. package/dest/contract_function_simulator/noir-structs/log_retrieval_request.js +34 -3
  41. package/dest/contract_function_simulator/noir-structs/note_data.d.ts +27 -0
  42. package/dest/contract_function_simulator/noir-structs/note_data.d.ts.map +1 -0
  43. package/dest/contract_function_simulator/noir-structs/note_data.js +3 -0
  44. package/dest/contract_function_simulator/noir-structs/note_validation_request.d.ts +3 -2
  45. package/dest/contract_function_simulator/noir-structs/note_validation_request.d.ts.map +1 -1
  46. package/dest/contract_function_simulator/noir-structs/note_validation_request.js +3 -2
  47. package/dest/contract_function_simulator/noir-structs/option.d.ts +61 -0
  48. package/dest/contract_function_simulator/noir-structs/option.d.ts.map +1 -0
  49. package/dest/contract_function_simulator/noir-structs/option.js +62 -0
  50. package/dest/contract_function_simulator/noir-structs/provided_secret.d.ts +11 -0
  51. package/dest/contract_function_simulator/noir-structs/provided_secret.d.ts.map +1 -0
  52. package/dest/contract_function_simulator/noir-structs/provided_secret.js +24 -0
  53. package/dest/contract_function_simulator/oracle/interfaces.d.ts +16 -114
  54. package/dest/contract_function_simulator/oracle/interfaces.d.ts.map +1 -1
  55. package/dest/contract_function_simulator/oracle/interfaces.js +2 -2
  56. package/dest/contract_function_simulator/oracle/note_packing_utils.d.ts +2 -2
  57. package/dest/contract_function_simulator/oracle/note_packing_utils.d.ts.map +1 -1
  58. package/dest/contract_function_simulator/oracle/note_packing_utils.js +2 -2
  59. package/dest/contract_function_simulator/oracle/oracle.d.ts +55 -57
  60. package/dest/contract_function_simulator/oracle/oracle.d.ts.map +1 -1
  61. package/dest/contract_function_simulator/oracle/oracle.js +343 -344
  62. package/dest/contract_function_simulator/oracle/oracle_registry.d.ts +127 -0
  63. package/dest/contract_function_simulator/oracle/oracle_registry.d.ts.map +1 -0
  64. package/dest/contract_function_simulator/oracle/oracle_registry.js +786 -0
  65. package/dest/contract_function_simulator/oracle/oracle_type_mappings.d.ts +139 -0
  66. package/dest/contract_function_simulator/oracle/oracle_type_mappings.d.ts.map +1 -0
  67. package/dest/contract_function_simulator/oracle/oracle_type_mappings.js +560 -0
  68. package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts +27 -29
  69. package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts.map +1 -1
  70. package/dest/contract_function_simulator/oracle/private_execution_oracle.js +55 -47
  71. package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts +59 -39
  72. package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts.map +1 -1
  73. package/dest/contract_function_simulator/oracle/utility_execution_oracle.js +244 -149
  74. package/dest/contract_function_simulator/proxied_contract_data_source.d.ts +1 -1
  75. package/dest/contract_function_simulator/proxied_contract_data_source.d.ts.map +1 -1
  76. package/dest/contract_function_simulator/proxied_contract_data_source.js +35 -67
  77. package/dest/contract_sync/contract_sync_service.d.ts +4 -6
  78. package/dest/contract_sync/contract_sync_service.d.ts.map +1 -1
  79. package/dest/contract_sync/contract_sync_service.js +43 -24
  80. package/dest/contract_sync/helpers.d.ts +2 -3
  81. package/dest/contract_sync/helpers.d.ts.map +1 -1
  82. package/dest/contract_sync/helpers.js +12 -19
  83. package/dest/debug/pxe_debug_utils.d.ts +1 -6
  84. package/dest/debug/pxe_debug_utils.d.ts.map +1 -1
  85. package/dest/debug/pxe_debug_utils.js +0 -6
  86. package/dest/entrypoints/client/bundle/utils.d.ts +1 -1
  87. package/dest/entrypoints/client/bundle/utils.d.ts.map +1 -1
  88. package/dest/entrypoints/client/bundle/utils.js +11 -3
  89. package/dest/entrypoints/client/lazy/utils.d.ts +1 -1
  90. package/dest/entrypoints/client/lazy/utils.d.ts.map +1 -1
  91. package/dest/entrypoints/client/lazy/utils.js +11 -3
  92. package/dest/entrypoints/pxe_creation_options.d.ts +7 -1
  93. package/dest/entrypoints/pxe_creation_options.d.ts.map +1 -1
  94. package/dest/entrypoints/server/index.d.ts +2 -1
  95. package/dest/entrypoints/server/index.d.ts.map +1 -1
  96. package/dest/entrypoints/server/index.js +1 -0
  97. package/dest/entrypoints/server/utils.d.ts +3 -2
  98. package/dest/entrypoints/server/utils.d.ts.map +1 -1
  99. package/dest/entrypoints/server/utils.js +11 -3
  100. package/dest/events/event_service.d.ts +13 -5
  101. package/dest/events/event_service.d.ts.map +1 -1
  102. package/dest/events/event_service.js +30 -9
  103. package/dest/hooks/authorize_utility_call.d.ts +41 -0
  104. package/dest/hooks/authorize_utility_call.d.ts.map +1 -0
  105. package/dest/hooks/authorize_utility_call.js +4 -0
  106. package/dest/hooks/execution_hooks.d.ts +42 -0
  107. package/dest/hooks/execution_hooks.d.ts.map +1 -0
  108. package/dest/hooks/execution_hooks.js +9 -0
  109. package/dest/hooks/index.d.ts +4 -0
  110. package/dest/hooks/index.d.ts.map +1 -0
  111. package/dest/hooks/index.js +1 -0
  112. package/dest/logs/log_service.d.ts +6 -5
  113. package/dest/logs/log_service.d.ts.map +1 -1
  114. package/dest/logs/log_service.js +112 -48
  115. package/dest/messages/message_context_service.d.ts +1 -1
  116. package/dest/messages/message_context_service.d.ts.map +1 -1
  117. package/dest/messages/message_context_service.js +28 -9
  118. package/dest/notes/note_service.d.ts +25 -3
  119. package/dest/notes/note_service.d.ts.map +1 -1
  120. package/dest/notes/note_service.js +80 -65
  121. package/dest/oracle_version.d.ts +3 -3
  122. package/dest/oracle_version.js +4 -4
  123. package/dest/private_kernel/batch_planner.d.ts +47 -0
  124. package/dest/private_kernel/batch_planner.d.ts.map +1 -0
  125. package/dest/private_kernel/batch_planner.js +104 -0
  126. package/dest/private_kernel/hints/private_kernel_reset_private_inputs_builder.js +1 -1
  127. package/dest/private_kernel/hints/test_utils.d.ts +1 -1
  128. package/dest/private_kernel/hints/test_utils.d.ts.map +1 -1
  129. package/dest/private_kernel/hints/test_utils.js +2 -3
  130. package/dest/private_kernel/private_kernel_execution_prover.d.ts +6 -2
  131. package/dest/private_kernel/private_kernel_execution_prover.d.ts.map +1 -1
  132. package/dest/private_kernel/private_kernel_execution_prover.js +148 -52
  133. package/dest/private_kernel/private_kernel_oracle.d.ts +6 -6
  134. package/dest/private_kernel/private_kernel_oracle.d.ts.map +1 -1
  135. package/dest/private_kernel/private_kernel_oracle.js +12 -7
  136. package/dest/pxe.d.ts +54 -7
  137. package/dest/pxe.d.ts.map +1 -1
  138. package/dest/pxe.js +126 -84
  139. package/dest/storage/backwards_compatibility_tests/kv_store_snapshot.d.ts +42 -0
  140. package/dest/storage/backwards_compatibility_tests/kv_store_snapshot.d.ts.map +1 -0
  141. package/dest/storage/backwards_compatibility_tests/kv_store_snapshot.js +93 -0
  142. package/dest/storage/backwards_compatibility_tests/schema_tests.d.ts +15 -0
  143. package/dest/storage/backwards_compatibility_tests/schema_tests.d.ts.map +1 -0
  144. package/dest/storage/backwards_compatibility_tests/schema_tests.js +591 -0
  145. package/dest/storage/backwards_compatibility_tests/store_spy.d.ts +19 -0
  146. package/dest/storage/backwards_compatibility_tests/store_spy.d.ts.map +1 -0
  147. package/dest/storage/backwards_compatibility_tests/store_spy.js +63 -0
  148. package/dest/storage/contract_store/contract_store.d.ts +1 -1
  149. package/dest/storage/contract_store/contract_store.d.ts.map +1 -1
  150. package/dest/storage/contract_store/contract_store.js +5 -24
  151. package/dest/storage/metadata.d.ts +1 -1
  152. package/dest/storage/metadata.js +1 -1
  153. package/dest/storage/open_pxe_stores.d.ts +33 -0
  154. package/dest/storage/open_pxe_stores.d.ts.map +1 -0
  155. package/dest/storage/open_pxe_stores.js +27 -0
  156. package/dest/storage/private_event_store/stored_private_event.js +1 -1
  157. package/dest/storage/tagging_store/recipient_tagging_store.d.ts +6 -6
  158. package/dest/storage/tagging_store/recipient_tagging_store.d.ts.map +1 -1
  159. package/dest/storage/tagging_store/sender_tagging_store.d.ts +5 -5
  160. package/dest/storage/tagging_store/sender_tagging_store.d.ts.map +1 -1
  161. package/dest/storage/tagging_store/sender_tagging_store.js +3 -3
  162. package/dest/tagging/get_all_logs_by_tags.d.ts +34 -10
  163. package/dest/tagging/get_all_logs_by_tags.d.ts.map +1 -1
  164. package/dest/tagging/get_all_logs_by_tags.js +36 -37
  165. package/dest/tagging/index.d.ts +5 -4
  166. package/dest/tagging/index.d.ts.map +1 -1
  167. package/dest/tagging/index.js +4 -3
  168. package/dest/tagging/persist_sender_tagging_index_ranges.d.ts +29 -0
  169. package/dest/tagging/persist_sender_tagging_index_ranges.d.ts.map +1 -0
  170. package/dest/tagging/persist_sender_tagging_index_ranges.js +42 -0
  171. package/dest/tagging/recipient_sync/sync_tagged_private_logs.d.ts +56 -0
  172. package/dest/tagging/recipient_sync/sync_tagged_private_logs.d.ts.map +1 -0
  173. package/dest/tagging/recipient_sync/sync_tagged_private_logs.js +163 -0
  174. package/dest/tagging/recipient_sync/utils/find_highest_indexes.d.ts +3 -3
  175. package/dest/tagging/recipient_sync/utils/find_highest_indexes.d.ts.map +1 -1
  176. package/dest/tagging/reconcile_tagging_index_ranges.d.ts +36 -0
  177. package/dest/tagging/reconcile_tagging_index_ranges.d.ts.map +1 -0
  178. package/dest/tagging/reconcile_tagging_index_ranges.js +74 -0
  179. package/dest/tagging/sender_sync/sync_sender_tagging_indexes.d.ts +4 -5
  180. package/dest/tagging/sender_sync/sync_sender_tagging_indexes.d.ts.map +1 -1
  181. package/dest/tagging/sender_sync/sync_sender_tagging_indexes.js +26 -14
  182. package/dest/tagging/sender_sync/utils/get_status_change_of_pending.d.ts +11 -6
  183. package/dest/tagging/sender_sync/utils/get_status_change_of_pending.d.ts.map +1 -1
  184. package/dest/tagging/sender_sync/utils/get_status_change_of_pending.js +21 -0
  185. package/dest/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.d.ts +4 -4
  186. package/dest/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.d.ts.map +1 -1
  187. package/dest/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.js +2 -2
  188. package/package.json +20 -17
  189. package/src/bin/check_oracle_version.ts +46 -119
  190. package/src/bin/index.ts +1 -0
  191. package/src/bin/oracle_version_helpers.ts +121 -0
  192. package/src/block_synchronizer/block_stream_source.ts +81 -0
  193. package/src/block_synchronizer/block_synchronizer.ts +22 -12
  194. package/src/config/index.ts +15 -9
  195. package/src/config/package_info.ts +1 -1
  196. package/src/contract_function_simulator/contract_function_simulator.ts +34 -11
  197. package/src/contract_function_simulator/execution_note_cache.ts +1 -1
  198. package/src/contract_function_simulator/execution_tagging_index_cache.ts +5 -9
  199. package/src/contract_function_simulator/index.ts +50 -1
  200. package/src/contract_function_simulator/noir-structs/bounded_vec.ts +55 -0
  201. package/src/contract_function_simulator/noir-structs/ephemeral_array.ts +66 -0
  202. package/src/contract_function_simulator/noir-structs/event_validation_request.ts +3 -2
  203. package/src/contract_function_simulator/noir-structs/log_retrieval_request.ts +35 -2
  204. package/src/contract_function_simulator/noir-structs/note_data.ts +27 -0
  205. package/src/contract_function_simulator/noir-structs/note_validation_request.ts +3 -2
  206. package/src/contract_function_simulator/noir-structs/option.ts +69 -0
  207. package/src/contract_function_simulator/noir-structs/provided_secret.ts +27 -0
  208. package/src/contract_function_simulator/oracle/interfaces.ts +12 -204
  209. package/src/contract_function_simulator/oracle/note_packing_utils.ts +3 -3
  210. package/src/contract_function_simulator/oracle/oracle.ts +406 -556
  211. package/src/contract_function_simulator/oracle/oracle_registry.ts +585 -0
  212. package/src/contract_function_simulator/oracle/oracle_type_mappings.ts +553 -0
  213. package/src/contract_function_simulator/oracle/private_execution_oracle.ts +74 -67
  214. package/src/contract_function_simulator/oracle/utility_execution_oracle.ts +350 -304
  215. package/src/contract_function_simulator/proxied_contract_data_source.ts +40 -70
  216. package/src/contract_sync/contract_sync_service.ts +56 -43
  217. package/src/contract_sync/helpers.ts +11 -23
  218. package/src/debug/pxe_debug_utils.ts +0 -8
  219. package/src/entrypoints/client/bundle/utils.ts +8 -2
  220. package/src/entrypoints/client/lazy/utils.ts +8 -2
  221. package/src/entrypoints/pxe_creation_options.ts +7 -0
  222. package/src/entrypoints/server/index.ts +1 -0
  223. package/src/entrypoints/server/utils.ts +13 -3
  224. package/src/events/event_service.ts +54 -19
  225. package/src/hooks/authorize_utility_call.ts +44 -0
  226. package/src/hooks/execution_hooks.ts +48 -0
  227. package/src/hooks/index.ts +7 -0
  228. package/src/logs/log_service.ts +137 -92
  229. package/src/messages/message_context_service.ts +42 -24
  230. package/src/notes/note_service.ts +115 -91
  231. package/src/oracle_version.ts +4 -4
  232. package/src/private_kernel/batch_planner.ts +169 -0
  233. package/src/private_kernel/hints/private_kernel_reset_private_inputs_builder.ts +1 -1
  234. package/src/private_kernel/hints/test_utils.ts +2 -9
  235. package/src/private_kernel/private_kernel_execution_prover.ts +236 -73
  236. package/src/private_kernel/private_kernel_oracle.ts +21 -11
  237. package/src/pxe.ts +208 -85
  238. package/src/storage/backwards_compatibility_tests/__snapshots__/AddressStore.json +22 -0
  239. package/src/storage/backwards_compatibility_tests/__snapshots__/AnchorBlockStore.json +3 -0
  240. package/src/storage/backwards_compatibility_tests/__snapshots__/CapsuleStore.json +16 -0
  241. package/src/storage/backwards_compatibility_tests/__snapshots__/ContractStore.json +28 -0
  242. package/src/storage/backwards_compatibility_tests/__snapshots__/KeyStore.json +52 -0
  243. package/src/storage/backwards_compatibility_tests/__snapshots__/L2TipsKVStore.json +46 -0
  244. package/src/storage/backwards_compatibility_tests/__snapshots__/NoteStore.json +36 -0
  245. package/src/storage/backwards_compatibility_tests/__snapshots__/PrivateEventStore.json +44 -0
  246. package/src/storage/backwards_compatibility_tests/__snapshots__/RecipientTaggingStore.json +18 -0
  247. package/src/storage/backwards_compatibility_tests/__snapshots__/SenderAddressBookStore.json +16 -0
  248. package/src/storage/backwards_compatibility_tests/__snapshots__/SenderTaggingStore.json +22 -0
  249. package/src/storage/backwards_compatibility_tests/__snapshots__/opened_stores.json +97 -0
  250. package/src/storage/backwards_compatibility_tests/kv_store_snapshot.ts +122 -0
  251. package/src/storage/backwards_compatibility_tests/schema_tests.ts +712 -0
  252. package/src/storage/backwards_compatibility_tests/store_spy.ts +73 -0
  253. package/src/storage/contract_store/contract_store.ts +6 -29
  254. package/src/storage/metadata.ts +1 -1
  255. package/src/storage/open_pxe_stores.ts +49 -0
  256. package/src/storage/private_event_store/stored_private_event.ts +1 -1
  257. package/src/storage/tagging_store/recipient_tagging_store.ts +5 -9
  258. package/src/storage/tagging_store/sender_tagging_store.ts +6 -6
  259. package/src/tagging/get_all_logs_by_tags.ts +78 -50
  260. package/src/tagging/index.ts +4 -3
  261. package/src/tagging/persist_sender_tagging_index_ranges.ts +57 -0
  262. package/src/tagging/recipient_sync/sync_tagged_private_logs.ts +240 -0
  263. package/src/tagging/recipient_sync/utils/find_highest_indexes.ts +2 -2
  264. package/src/tagging/reconcile_tagging_index_ranges.ts +102 -0
  265. package/src/tagging/sender_sync/sync_sender_tagging_indexes.ts +41 -19
  266. package/src/tagging/sender_sync/utils/get_status_change_of_pending.ts +23 -8
  267. package/src/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.ts +4 -5
  268. package/dest/contract_function_simulator/oracle/legacy_oracle_mappings.d.ts +0 -9
  269. package/dest/contract_function_simulator/oracle/legacy_oracle_mappings.d.ts.map +0 -1
  270. package/dest/contract_function_simulator/oracle/legacy_oracle_mappings.js +0 -47
  271. package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.d.ts +0 -14
  272. package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.d.ts.map +0 -1
  273. package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.js +0 -85
  274. package/dest/tagging/recipient_sync/utils/load_logs_for_range.d.ts +0 -14
  275. package/dest/tagging/recipient_sync/utils/load_logs_for_range.d.ts.map +0 -1
  276. package/dest/tagging/recipient_sync/utils/load_logs_for_range.js +0 -33
  277. package/src/contract_function_simulator/oracle/legacy_oracle_mappings.ts +0 -104
  278. package/src/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.ts +0 -130
  279. package/src/tagging/recipient_sync/utils/load_logs_for_range.ts +0 -44
@@ -1,13 +1,20 @@
1
- import { FunctionSelector } from '@aztec/stdlib/abi';
2
- import { AztecAddress } from '@aztec/stdlib/aztec-address';
1
+ import { type FunctionSelector, findFunctionArtifactBySelector } from '@aztec/stdlib/abi';
2
+ import type { AztecAddress } from '@aztec/stdlib/aztec-address';
3
3
  import type { ContractOverrides } from '@aztec/stdlib/tx';
4
4
 
5
5
  import type { ContractStore } from '../storage/contract_store/contract_store.js';
6
6
 
7
7
  /*
8
- * Proxy generator for a ContractStore that allows overriding contract instances and artifacts, so
9
- * the contract function simulator can execute different bytecode on certain addresses. An example use case
10
- * would be overriding your own account contract so that valid signatures don't have to be provided while simulating.
8
+ * Proxy generator for a ContractStore that allows overriding contract instances at given addresses,
9
+ * so the contract function simulator can execute different bytecode on certain addresses. An example
10
+ * use case would be overriding your own account contract so that valid signatures don't have to be
11
+ * provided while simulating.
12
+ *
13
+ * Function artifact lookups for an overridden address are routed via the override-instance's
14
+ * `currentContractClassId` rather than the underlying ContractStore's address→class mapping —
15
+ * `ContractStore.getFunctionArtifact` calls `this.getContractInstance` internally, which the proxy
16
+ * cannot intercept (the binding sees the raw target, not the proxy). The target class must be
17
+ * registered ahead of time via `pxe.registerContractClass(...)`.
11
18
  */
12
19
  export class ProxiedContractStoreFactory {
13
20
  static create(contractStore: ContractStore, overrides?: ContractOverrides) {
@@ -17,73 +24,36 @@ export class ProxiedContractStoreFactory {
17
24
 
18
25
  return new Proxy(contractStore, {
19
26
  get(target, prop: keyof ContractStore) {
20
- switch (prop) {
21
- case 'getContractInstance': {
22
- return async (address: AztecAddress) => {
23
- if (overrides[address.toString()]) {
24
- const { instance } = overrides[address.toString()]!;
25
- instance.address = address;
26
- const realInstance = await target.getContractInstance(address);
27
- if (!realInstance) {
28
- throw new Error(`Contract instance not found for address: ${address}`);
29
- }
30
- instance.currentContractClassId = realInstance.currentContractClassId;
31
- instance.originalContractClassId = realInstance.originalContractClassId;
32
- instance.initializationHash = realInstance.initializationHash;
33
- return instance;
34
- } else {
35
- return target.getContractInstance(address);
36
- }
37
- };
38
- }
39
- case 'getFunctionArtifact': {
40
- return async (contractAddress: AztecAddress, selector: FunctionSelector) => {
41
- if (overrides[contractAddress.toString()]) {
42
- const { artifact } = overrides[contractAddress.toString()]!;
43
- const functions = artifact.functions;
44
- for (let i = 0; i < functions.length; i++) {
45
- const fn = functions[i];
46
- const fnSelector = await FunctionSelector.fromNameAndParameters(fn.name, fn.parameters);
47
- if (fnSelector.equals(selector)) {
48
- return fn;
49
- }
50
- }
51
- throw new Error(
52
- `Function with selector ${selector} not found in stub artifact for overridden contract at ${contractAddress}. The stub does not implement this function.`,
53
- );
54
- } else {
55
- return target.getFunctionArtifact(contractAddress, selector);
56
- }
57
- };
58
- }
59
- case 'getFunctionArtifactWithDebugMetadata': {
60
- return async (contractAddress: AztecAddress, selector: FunctionSelector) => {
61
- if (overrides[contractAddress.toString()]) {
62
- const { artifact } = overrides[contractAddress.toString()]!;
63
- const functions = artifact.functions;
64
- for (let i = 0; i < functions.length; i++) {
65
- const fn = functions[i];
66
- const fnSelector = await FunctionSelector.fromNameAndParameters(fn.name, fn.parameters);
67
- if (fnSelector.equals(selector)) {
68
- return fn;
69
- }
70
- }
71
- throw new Error(
72
- `Function with selector ${selector} not found in stub artifact for overridden contract at ${contractAddress}. The stub does not implement this function.`,
73
- );
74
- } else {
75
- return target.getFunctionArtifactWithDebugMetadata(contractAddress, selector);
76
- }
77
- };
78
- }
79
- default: {
80
- const value = Reflect.get(target, prop);
81
- if (typeof value === 'function') {
82
- return value.bind(target);
27
+ if (prop === 'getContractInstance') {
28
+ return (address: AztecAddress) => {
29
+ const override = overrides[address.toString()];
30
+ return override ? Promise.resolve(override.instance) : target.getContractInstance(address);
31
+ };
32
+ }
33
+ if (prop === 'getFunctionArtifact' || prop === 'getFunctionArtifactWithDebugMetadata') {
34
+ return async (contractAddress: AztecAddress, selector: FunctionSelector) => {
35
+ const override = overrides[contractAddress.toString()];
36
+ if (!override) {
37
+ return (target[prop] as Function).call(target, contractAddress, selector);
38
+ }
39
+ const artifact = await target.getContractArtifact(override.instance.currentContractClassId);
40
+ if (!artifact) {
41
+ throw new Error(
42
+ `No artifact registered for override class ${override.instance.currentContractClassId} ` +
43
+ `at ${contractAddress}. Register it via pxe.registerContractClass(...) before simulating.`,
44
+ );
45
+ }
46
+ const fn = await findFunctionArtifactBySelector(artifact, selector);
47
+ if (!fn) {
48
+ throw new Error(
49
+ `Function with selector ${selector} not found in stub artifact for overridden contract at ${contractAddress}.`,
50
+ );
83
51
  }
84
- return value;
85
- }
52
+ return { ...fn, contractName: artifact.name };
53
+ };
86
54
  }
55
+ const value = Reflect.get(target, prop);
56
+ return typeof value === 'function' ? value.bind(target) : value;
87
57
  },
88
58
  }) satisfies ContractStore;
89
59
  }
@@ -1,14 +1,16 @@
1
1
  import type { Logger } from '@aztec/foundation/log';
2
2
  import { Semaphore } from '@aztec/foundation/queue';
3
+ import { isProtocolContract } from '@aztec/protocol-contracts';
3
4
  import type { FunctionCall, FunctionSelector } from '@aztec/stdlib/abi';
4
5
  import type { AztecAddress } from '@aztec/stdlib/aztec-address';
5
6
  import type { AztecNode } from '@aztec/stdlib/interfaces/client';
6
7
  import type { BlockHeader } from '@aztec/stdlib/tx';
7
8
 
8
9
  import type { StagedStore } from '../job_coordinator/job_coordinator.js';
10
+ import { NoteService } from '../notes/note_service.js';
9
11
  import type { ContractStore } from '../storage/contract_store/contract_store.js';
10
12
  import type { NoteStore } from '../storage/note_store/note_store.js';
11
- import { syncState, verifyCurrentClassId } from './helpers.js';
13
+ import { syncScope, verifyCurrentClassId } from './helpers.js';
12
14
 
13
15
  /** Maximum number of scope syncs running concurrently across the PXE. */
14
16
  const MAX_CONCURRENT_SCOPE_SYNCS = 5;
@@ -27,8 +29,9 @@ export class ContractSyncService implements StagedStore {
27
29
  // The value is a promise that resolves when the contract is synced.
28
30
  private syncedContracts: Map<string, Promise<void>> = new Map();
29
31
 
30
- // Per-job excluded contract addresses - these contracts should not be synced.
31
- private excludedFromSync: Map<string, Set<string>> = new Map();
32
+ // Tracks class ID verification per contract. Keyed by contract address only (no scope), since
33
+ // class ID verification is scope-independent. Cleared on wipe/discard.
34
+ private classIdVerificationCache: Map<string, Promise<void>> = new Map();
32
35
 
33
36
  // Bounds the number of scope syncs running concurrently. Scopes beyond this limit queue here. Sized to trade off
34
37
  // parallelism on non-ACIR work (node RPC, note store reads) against memory pressure from concurrent circuit
@@ -42,11 +45,6 @@ export class ContractSyncService implements StagedStore {
42
45
  private log: Logger,
43
46
  ) {}
44
47
 
45
- /** Sets contracts that should be skipped during sync for a specific job. */
46
- setExcludedFromSync(jobId: string, addresses: Set<string>): void {
47
- this.excludedFromSync.set(jobId, addresses);
48
- }
49
-
50
48
  /**
51
49
  * Ensures a contract's private state is synchronized and that the PXE holds the current class artifact.
52
50
  * Uses a cache to avoid redundant sync operations - the cache is wiped when the anchor block changes.
@@ -64,26 +62,8 @@ export class ContractSyncService implements StagedStore {
64
62
  jobId: string,
65
63
  scopes: AztecAddress[],
66
64
  ): Promise<void> {
67
- if (this.#shouldSkipSync(jobId, contractAddress)) {
68
- return;
69
- }
70
-
71
- this.#startSyncIfNeeded(
72
- contractAddress,
73
- scopes,
74
- () => verifyCurrentClassId(contractAddress, this.aztecNode, this.contractStore, anchorBlockHeader),
75
- scope =>
76
- syncState(
77
- contractAddress,
78
- this.contractStore,
79
- functionToInvokeAfterSync,
80
- utilityExecutor,
81
- this.noteStore,
82
- this.aztecNode,
83
- anchorBlockHeader,
84
- jobId,
85
- scope,
86
- ),
65
+ this.#startSyncIfNeeded(contractAddress, scopes, anchorBlockHeader, jobId, scope =>
66
+ syncScope(contractAddress, this.contractStore, functionToInvokeAfterSync, utilityExecutor, scope),
87
67
  );
88
68
 
89
69
  await this.#awaitSync(contractAddress, scopes);
@@ -101,35 +81,32 @@ export class ContractSyncService implements StagedStore {
101
81
  wipe(): void {
102
82
  this.log.debug(`Wiping contract sync cache (${this.syncedContracts.size} entries)`);
103
83
  this.syncedContracts.clear();
84
+ this.classIdVerificationCache.clear();
104
85
  }
105
86
 
106
- commit(jobId: string): Promise<void> {
107
- // Clear excluded contracts for this job
108
- this.excludedFromSync.delete(jobId);
87
+ commit(_jobId: string): Promise<void> {
109
88
  return Promise.resolve();
110
89
  }
111
90
 
112
- discardStaged(jobId: string): Promise<void> {
91
+ discardStaged(_jobId: string): Promise<void> {
113
92
  // We clear the synced contracts cache here because, when the job is discarded, any associated database writes from
114
93
  // the sync are also undone.
115
94
  this.syncedContracts.clear();
116
- this.excludedFromSync.delete(jobId);
95
+ this.classIdVerificationCache.clear();
117
96
  return Promise.resolve();
118
97
  }
119
- /** Returns true if sync should be skipped for this contract */
120
- #shouldSkipSync(jobId: string, contractAddress: AztecAddress): boolean {
121
- return !!this.excludedFromSync.get(jobId)?.has(contractAddress.toString());
122
- }
123
98
 
124
99
  /**
125
- * If there are unsynced scopes, starts one sync per scope (bounded by #syncSlot) and stores each promise in the
126
- * cache with per-scope error cleanup. The verifyFn runs once for the whole fan-out and is awaited by every new
127
- * scope's promise, matching the pre-parallelization invariant that a cache-miss batch re-verifies the class id.
100
+ * For each unsynced scope, creates a promise that waits on:
101
+ * 1. Class ID verification (cached per contract, scope-independent).
102
+ * 2. Note nullifier sync (shared, batched across all unsynced scopes).
103
+ * 3. Per-scope sync (individual, semaphore-bounded).
128
104
  */
129
105
  #startSyncIfNeeded(
130
106
  contractAddress: AztecAddress,
131
107
  scopes: AztecAddress[],
132
- verifyFn: () => Promise<void>,
108
+ anchorBlockHeader: BlockHeader,
109
+ jobId: string,
133
110
  syncScopeFn: (scope: AztecAddress) => Promise<void>,
134
111
  ): void {
135
112
  const scopesToSync = scopes.filter(scope => !this.syncedContracts.has(toKey(contractAddress, scope)));
@@ -138,11 +115,13 @@ export class ContractSyncService implements StagedStore {
138
115
  }
139
116
 
140
117
  this.log.debug(`Syncing contract ${contractAddress} for ${scopesToSync.length} scope(s)`);
141
- const verifyPromise = verifyFn();
118
+
119
+ const verifyPromise = this.#verifyClassId(contractAddress, anchorBlockHeader);
120
+ const syncNullifiersPromise = this.#syncNoteNullifiers(contractAddress, anchorBlockHeader, jobId, scopesToSync);
142
121
 
143
122
  for (const scope of scopesToSync) {
144
123
  const key = toKey(contractAddress, scope);
145
- const promise = Promise.all([verifyPromise, this.#runBounded(() => syncScopeFn(scope))])
124
+ const promise = Promise.all([verifyPromise, syncNullifiersPromise, this.#runBounded(() => syncScopeFn(scope))])
146
125
  .then(() => {})
147
126
  .catch(err => {
148
127
  this.syncedContracts.delete(key);
@@ -152,6 +131,40 @@ export class ContractSyncService implements StagedStore {
152
131
  }
153
132
  }
154
133
 
134
+ /** Verifies the local class ID matches the on-chain value (cached, evicts on failure so retries re-verify). */
135
+ #verifyClassId(contractAddress: AztecAddress, anchorBlockHeader: BlockHeader): Promise<void> {
136
+ const contractKey = contractAddress.toString();
137
+ const cached = this.classIdVerificationCache.get(contractKey);
138
+ if (cached) {
139
+ return cached;
140
+ }
141
+ const promise = verifyCurrentClassId(contractAddress, this.aztecNode, this.contractStore, anchorBlockHeader).catch(
142
+ err => {
143
+ this.classIdVerificationCache.delete(contractKey);
144
+ throw err;
145
+ },
146
+ );
147
+ this.classIdVerificationCache.set(contractKey, promise);
148
+ return promise;
149
+ }
150
+
151
+ /** Syncs note nullifiers across all unsynced scopes in a single batched call. */
152
+ async #syncNoteNullifiers(
153
+ contractAddress: AztecAddress,
154
+ anchorBlockHeader: BlockHeader,
155
+ jobId: string,
156
+ scopes: AztecAddress[],
157
+ ): Promise<void> {
158
+ // Protocol contracts don't have private state to sync
159
+ if (isProtocolContract(contractAddress)) {
160
+ return;
161
+ }
162
+ // This runs in parallel with per-scope sync (which also writes to the note store). That's safe because
163
+ // the note store handles concurrent operations.
164
+ const noteService = new NoteService(this.noteStore, this.aztecNode, anchorBlockHeader, jobId);
165
+ await noteService.syncNoteNullifiers(contractAddress, scopes);
166
+ }
167
+
155
168
  /** Runs fn while holding a slot in #syncSlot, bounding total concurrent scope syncs. */
156
169
  async #runBounded<T>(fn: () => Promise<T>): Promise<T> {
157
170
  await this.#syncSlot.acquire();
@@ -6,9 +6,7 @@ import { DelayedPublicMutableValues, DelayedPublicMutableValuesWithHash } from '
6
6
  import type { AztecNode } from '@aztec/stdlib/interfaces/client';
7
7
  import type { BlockHeader } from '@aztec/stdlib/tx';
8
8
 
9
- import { NoteService } from '../notes/note_service.js';
10
9
  import type { ContractStore } from '../storage/contract_store/contract_store.js';
11
- import type { NoteStore } from '../storage/note_store/note_store.js';
12
10
 
13
11
  /**
14
12
  * Read the current class id of a contract from the execution data provider or AztecNode. If not found, class id
@@ -38,36 +36,26 @@ export async function readCurrentClassId(
38
36
  return currentClassId;
39
37
  }
40
38
 
41
- export async function syncState(
39
+ export async function syncScope(
42
40
  contractAddress: AztecAddress,
43
41
  contractStore: ContractStore,
44
42
  functionToInvokeAfterSync: FunctionSelector | null,
45
43
  utilityExecutor: (privateSyncCall: FunctionCall, scopes: AztecAddress[]) => Promise<any>,
46
- noteStore: NoteStore,
47
- aztecNode: AztecNode,
48
- anchorBlockHeader: BlockHeader,
49
- jobId: string,
50
44
  scope: AztecAddress,
51
45
  ) {
52
46
  // Protocol contracts don't have private state to sync
53
- if (!isProtocolContract(contractAddress)) {
54
- const syncStateFunctionCall = await contractStore.getFunctionCall('sync_state', [scope], contractAddress);
55
- if (functionToInvokeAfterSync && functionToInvokeAfterSync.equals(syncStateFunctionCall.selector)) {
56
- throw new Error(
57
- 'Forbidden `sync_state` invocation. `sync_state` can only be invoked by PXE, manual execution can lead to inconsistencies.',
58
- );
59
- }
60
-
61
- const noteService = new NoteService(noteStore, aztecNode, anchorBlockHeader, jobId);
62
- const scopes: AztecAddress[] = [scope];
47
+ if (isProtocolContract(contractAddress)) {
48
+ return;
49
+ }
63
50
 
64
- // Both sync_state and syncNoteNullifiers interact with the note store, but running them in parallel is safe
65
- // because note store is designed to handle concurrent operations.
66
- await Promise.all([
67
- utilityExecutor(syncStateFunctionCall, scopes),
68
- noteService.syncNoteNullifiers(contractAddress, scopes),
69
- ]);
51
+ const syncStateFunctionCall = await contractStore.getFunctionCall('sync_state', [scope], contractAddress);
52
+ if (functionToInvokeAfterSync && functionToInvokeAfterSync.equals(syncStateFunctionCall.selector)) {
53
+ throw new Error(
54
+ 'Forbidden `sync_state` invocation. `sync_state` can only be invoked by PXE, manual execution can lead to inconsistencies.',
55
+ );
70
56
  }
57
+
58
+ await utilityExecutor(syncStateFunctionCall, [scope]);
71
59
  }
72
60
 
73
61
  /**
@@ -82,12 +82,4 @@ export class PXEDebugUtils {
82
82
  return this.noteStore.getNotes(filter, jobId);
83
83
  });
84
84
  }
85
-
86
- /**
87
- * Triggers a sync of the PXE with the node.
88
- * Blocks until the sync is complete.
89
- */
90
- public sync(): Promise<void> {
91
- return this.#putJobInQueue(() => this.blockStateSynchronizer.sync());
92
- }
93
85
  }
@@ -3,6 +3,7 @@ import { createLogger } from '@aztec/foundation/log';
3
3
  import { createStore } from '@aztec/kv-store/indexeddb';
4
4
  import { BundledProtocolContractsProvider } from '@aztec/protocol-contracts/providers/bundle';
5
5
  import { WASMSimulator } from '@aztec/simulator/client';
6
+ import { getStandardMultiCallEntrypoint } from '@aztec/standard-contracts/multi-call-entrypoint';
6
7
  import type { AztecNode } from '@aztec/stdlib/interfaces/client';
7
8
 
8
9
  import type { PXEConfig } from '../../../config/index.js';
@@ -28,10 +29,10 @@ export async function createPXE(
28
29
  const actor = options.loggerActorLabel;
29
30
  const loggers = options.loggers ?? {};
30
31
 
31
- const l1Contracts = await aztecNode.getL1ContractAddresses();
32
+ const l1ContractAddresses = await aztecNode.getL1ContractAddresses();
32
33
  const configWithContracts = {
33
34
  ...config,
34
- l1Contracts,
35
+ ...l1ContractAddresses,
35
36
  } as PXEConfig;
36
37
 
37
38
  const storeLogger = loggers.store ?? createLogger('pxe:data:idb', { actor });
@@ -49,6 +50,9 @@ export async function createPXE(
49
50
  prover = new BBBundlePrivateKernelProver(simulator, { ...options.proverOrOptions, logger: proverLogger });
50
51
  }
51
52
  const protocolContractsProvider = new BundledProtocolContractsProvider();
53
+ const preloadedContractsProvider = options.preloadedContractsProvider ?? {
54
+ getPreloadedContracts: async () => [await getStandardMultiCallEntrypoint()],
55
+ };
52
56
 
53
57
  const pxeLogger = loggers.pxe ?? createLogger('pxe:service', { actor });
54
58
  const pxe = await PXE.create({
@@ -57,8 +61,10 @@ export async function createPXE(
57
61
  proofCreator: prover,
58
62
  simulator,
59
63
  protocolContractsProvider,
64
+ preloadedContractsProvider,
60
65
  config,
61
66
  loggerOrSuffix: pxeLogger,
67
+ hooks: options.hooks,
62
68
  });
63
69
  return pxe;
64
70
  }
@@ -3,6 +3,7 @@ import { createLogger } from '@aztec/foundation/log';
3
3
  import { createStore } from '@aztec/kv-store/indexeddb';
4
4
  import { LazyProtocolContractsProvider } from '@aztec/protocol-contracts/providers/lazy';
5
5
  import { WASMSimulator } from '@aztec/simulator/client';
6
+ import { getStandardMultiCallEntrypoint } from '@aztec/standard-contracts/multi-call-entrypoint/lazy';
6
7
  import type { AztecNode } from '@aztec/stdlib/interfaces/client';
7
8
 
8
9
  import type { PXEConfig } from '../../../config/index.js';
@@ -26,10 +27,10 @@ export async function createPXE(
26
27
  ) {
27
28
  const actor = options.loggerActorLabel;
28
29
 
29
- const l1Contracts = await aztecNode.getL1ContractAddresses();
30
+ const l1ContractAddresses = await aztecNode.getL1ContractAddresses();
30
31
  const configWithContracts = {
31
32
  ...config,
32
- l1Contracts,
33
+ ...l1ContractAddresses,
33
34
  } as PXEConfig;
34
35
 
35
36
  const loggers = options.loggers ?? {};
@@ -49,6 +50,9 @@ export async function createPXE(
49
50
  prover = new BBLazyPrivateKernelProver(simulator, { ...options.proverOrOptions, logger: proverLogger });
50
51
  }
51
52
  const protocolContractsProvider = new LazyProtocolContractsProvider();
53
+ const preloadedContractsProvider = options.preloadedContractsProvider ?? {
54
+ getPreloadedContracts: async () => [await getStandardMultiCallEntrypoint()],
55
+ };
52
56
 
53
57
  const pxeLogger = loggers.pxe ?? createLogger('pxe:service', { actor });
54
58
  const pxe = await PXE.create({
@@ -57,8 +61,10 @@ export async function createPXE(
57
61
  proofCreator: prover,
58
62
  simulator,
59
63
  protocolContractsProvider,
64
+ preloadedContractsProvider,
60
65
  config,
61
66
  loggerOrSuffix: pxeLogger,
67
+ hooks: options.hooks,
62
68
  });
63
69
  return pxe;
64
70
  }
@@ -4,6 +4,9 @@ import type { AztecAsyncKVStore } from '@aztec/kv-store';
4
4
  import type { CircuitSimulator } from '@aztec/simulator/client';
5
5
  import type { PrivateKernelProver } from '@aztec/stdlib/interfaces/client';
6
6
 
7
+ import type { ExecutionHooks } from '../hooks/index.js';
8
+ import type { PreloadedContractsProvider } from '../pxe.js';
9
+
7
10
  export type PXECreationOptions = {
8
11
  loggers?: { store?: Logger; pxe?: Logger; prover?: Logger };
9
12
  /** Actor label to include in log output (e.g., 'pxe-0', 'pxe-test'). */
@@ -11,6 +14,10 @@ export type PXECreationOptions = {
11
14
  proverOrOptions?: PrivateKernelProver | BBPrivateKernelProverOptions;
12
15
  store?: AztecAsyncKVStore;
13
16
  simulator?: CircuitSimulator;
17
+ /** Optional hooks to observe and influence contract execution. */
18
+ hooks?: ExecutionHooks;
19
+ /** Contracts to preload; used directly in place of the PXE's default (the standard multi-call entrypoint). */
20
+ preloadedContractsProvider?: PreloadedContractsProvider;
14
21
  };
15
22
 
16
23
  /** Checks if the given value implements the PrivateKernelProver interface via duck-typing. */
@@ -1,5 +1,6 @@
1
1
  export * from '../../notes_filter.js';
2
2
  export * from '../../pxe.js';
3
+ export * from '../../hooks/index.js';
3
4
  export * from '../../config/index.js';
4
5
  export * from '../../error_enriching.js';
5
6
  export * from '../../storage/index.js';
@@ -1,9 +1,11 @@
1
1
  import { BBBundlePrivateKernelProver } from '@aztec/bb-prover/client/bundle';
2
+ import type { L1ContractAddresses } from '@aztec/ethereum/l1-contract-addresses';
2
3
  import { createLogger } from '@aztec/foundation/log';
3
4
  import { createStore } from '@aztec/kv-store/lmdb-v2';
4
5
  import { BundledProtocolContractsProvider } from '@aztec/protocol-contracts/providers/bundle';
5
6
  import { MemoryCircuitRecorder, SimulatorRecorderWrapper, WASMSimulator } from '@aztec/simulator/client';
6
7
  import { FileCircuitRecorder } from '@aztec/simulator/testing';
8
+ import { getStandardMultiCallEntrypoint } from '@aztec/standard-contracts/multi-call-entrypoint';
7
9
  import type { AztecNode } from '@aztec/stdlib/interfaces/client';
8
10
 
9
11
  import type { PXEConfig } from '../../config/index.js';
@@ -11,7 +13,10 @@ import { PXE } from '../../pxe.js';
11
13
  import { PXE_DATA_SCHEMA_VERSION } from '../../storage/index.js';
12
14
  import { type PXECreationOptions, isPrivateKernelProver } from '../pxe_creation_options.js';
13
15
 
14
- type PXEConfigWithoutDefaults = Omit<PXEConfig, 'l1Contracts' | 'l1ChainId' | 'l2BlockBatchSize' | 'rollupVersion'>;
16
+ type PXEConfigWithoutDefaults = Omit<
17
+ PXEConfig,
18
+ 'l1ChainId' | 'l2BlockBatchSize' | 'rollupVersion' | keyof L1ContractAddresses
19
+ >;
15
20
 
16
21
  export async function createPXE(
17
22
  aztecNode: AztecNode,
@@ -27,10 +32,10 @@ export async function createPXE(
27
32
  const simulator = new SimulatorRecorderWrapper(new WASMSimulator(simulatorLogger), recorder);
28
33
  const loggers = options.loggers ?? {};
29
34
 
30
- const { l1ChainId, l1ContractAddresses: l1Contracts, rollupVersion } = await aztecNode.getNodeInfo();
35
+ const { l1ChainId, l1ContractAddresses, rollupVersion } = await aztecNode.getNodeInfo();
31
36
  const configWithContracts: PXEConfig = {
32
37
  ...config,
33
- l1Contracts,
38
+ ...l1ContractAddresses,
34
39
  l1ChainId,
35
40
  rollupVersion,
36
41
  l2BlockBatchSize: 50,
@@ -55,6 +60,9 @@ export async function createPXE(
55
60
  }
56
61
 
57
62
  const protocolContractsProvider = new BundledProtocolContractsProvider();
63
+ const preloadedContractsProvider = options.preloadedContractsProvider ?? {
64
+ getPreloadedContracts: async () => [await getStandardMultiCallEntrypoint()],
65
+ };
58
66
 
59
67
  const pxeLogger = loggers.pxe ?? createLogger('pxe:service', { actor });
60
68
  const pxe = await PXE.create({
@@ -63,8 +71,10 @@ export async function createPXE(
63
71
  proofCreator: prover,
64
72
  simulator,
65
73
  protocolContractsProvider,
74
+ preloadedContractsProvider,
66
75
  config: configWithContracts,
67
76
  loggerOrSuffix: pxeLogger,
77
+ hooks: options.hooks,
68
78
  });
69
79
  return pxe;
70
80
  }
@@ -1,11 +1,10 @@
1
- import type { Fr } from '@aztec/foundation/curves/bn254';
2
1
  import { createLogger } from '@aztec/foundation/log';
3
- import type { EventSelector } from '@aztec/stdlib/abi';
4
2
  import type { AztecAddress } from '@aztec/stdlib/aztec-address';
5
- import { siloNullifier } from '@aztec/stdlib/hash';
3
+ import { computePrivateEventCommitment, siloNullifier } from '@aztec/stdlib/hash';
6
4
  import type { AztecNode } from '@aztec/stdlib/interfaces/server';
7
- import type { BlockHeader, TxHash } from '@aztec/stdlib/tx';
5
+ import type { BlockHeader, IndexedTxEffect } from '@aztec/stdlib/tx';
8
6
 
7
+ import type { EventValidationRequest } from '../contract_function_simulator/noir-structs/event_validation_request.js';
9
8
  import { PrivateEventStore } from '../storage/private_event_store/private_event_store.js';
10
9
 
11
10
  export class EventService {
@@ -17,30 +16,66 @@ export class EventService {
17
16
  private readonly log = createLogger('pxe:event_service'),
18
17
  ) {}
19
18
 
20
- public async validateAndStoreEvent(
21
- contractAddress: AztecAddress,
22
- selector: EventSelector,
23
- randomness: Fr,
24
- content: Fr[],
25
- eventCommitment: Fr,
26
- txHash: TxHash,
19
+ /**
20
+ * Validates and stores a batch of private events against pre-fetched tx effects.
21
+ *
22
+ * @param requests - The events to validate and store.
23
+ * @param scope - The scope under which the events are being stored.
24
+ * @param txEffects - Pre-fetched tx effects keyed by `TxHash.toString()`. Must contain entries for every request's
25
+ * txHash; missing entries are treated as a node bug and cause an error.
26
+ */
27
+ public async validateAndStoreEvents(
28
+ requests: EventValidationRequest[],
27
29
  scope: AztecAddress,
30
+ txEffects: Map<string, IndexedTxEffect>,
28
31
  ): Promise<void> {
32
+ if (requests.length === 0) {
33
+ return;
34
+ }
35
+
36
+ const anchorBlockNumber = this.anchorBlockHeader.getBlockNumber();
37
+
38
+ await Promise.all(requests.map(req => this.#validateAndStoreEvent(req, scope, txEffects, anchorBlockNumber)));
39
+ }
40
+
41
+ async #validateAndStoreEvent(
42
+ request: EventValidationRequest,
43
+ scope: AztecAddress,
44
+ txEffects: Map<string, IndexedTxEffect>,
45
+ anchorBlockNumber: number,
46
+ ): Promise<void> {
47
+ const {
48
+ contractAddress,
49
+ eventTypeId: selector,
50
+ randomness,
51
+ serializedEvent: content,
52
+ eventCommitment,
53
+ txHash,
54
+ } = request;
55
+
56
+ // Defense-in-depth: the built-in private-event path derives this commitment from content before enqueueing, but
57
+ // unconstrained PXE-side code (e.g. a custom message handler) can reach this oracle with arbitrary
58
+ // (content, commitment) pairs. Without this check it could bind arbitrary content to a legitimate tx nullifier,
59
+ // causing PXE to surface fabricated event data.
60
+ const recomputedCommitment = await computePrivateEventCommitment(randomness, selector.toField(), content);
61
+ if (!recomputedCommitment.equals(eventCommitment)) {
62
+ this.log.warn(
63
+ `Skipping event whose content does not hash to the provided commitment. contract=${contractAddress}, selector=${selector}, eventCommitment=${eventCommitment}, txHash=${txHash}, recomputedCommitment=${recomputedCommitment}`,
64
+ );
65
+ return;
66
+ }
67
+
29
68
  // While using 'latest' block number would be fine for private events since they cannot be accessed from Aztec.nr
30
69
  // (and thus we're less concerned about being ahead of the synced block), we use the synced block number to
31
70
  // maintain consistent behavior in the PXE. Additionally, events should never be ahead of the synced block here
32
71
  // since `fetchTaggedLogs` only processes logs up to the synced block.
33
- const [siloedEventCommitment, txEffect] = await Promise.all([
34
- siloNullifier(contractAddress, eventCommitment),
35
- this.aztecNode.getTxEffect(txHash),
36
- ]);
37
-
38
- const anchorBlockNumber = this.anchorBlockHeader.getBlockNumber();
72
+ const siloedEventCommitment = await siloNullifier(contractAddress, eventCommitment);
39
73
 
74
+ const txEffect = txEffects.get(txHash.toString());
40
75
  if (!txEffect) {
41
76
  // We error out instead of just logging a warning and skipping the event because this would indicate a bug. This
42
- // is because the node has already served info about this tx either when obtaining the log (TxScopedL2Log contain
43
- // tx info) or when getting metadata for the offchain message (before the message got passed to `process_log`).
77
+ // is because the node has already served info about this tx either when obtaining the log (LogResult carries
78
+ // the tx info) or when getting metadata for the offchain message (before the message got passed to `process_log`).
44
79
  throw new Error(`Could not find tx effect for tx hash ${txHash} when processing an event.`);
45
80
  }
46
81