@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,12 +1,21 @@
1
- import type { ARCHIVE_HEIGHT, NOTE_HASH_TREE_HEIGHT } from '@aztec/constants';
1
+ import { ARCHIVE_HEIGHT, type NOTE_HASH_TREE_HEIGHT } from '@aztec/constants';
2
2
  import type { BlockNumber } from '@aztec/foundation/branded-types';
3
+ import { uniqueBy } from '@aztec/foundation/collection';
3
4
  import { Aes128 } from '@aztec/foundation/crypto/aes128';
4
5
  import { Fr } from '@aztec/foundation/curves/bn254';
5
- import { Point } from '@aztec/foundation/curves/grumpkin';
6
+ import type { Point } from '@aztec/foundation/curves/grumpkin';
6
7
  import { LogLevels, type Logger, createLogger } from '@aztec/foundation/log';
7
- import type { MembershipWitness } from '@aztec/foundation/trees';
8
+ import { MembershipWitness } from '@aztec/foundation/trees';
8
9
  import type { KeyStore } from '@aztec/key-store';
9
- import { isProtocolContract } from '@aztec/protocol-contracts';
10
+ import {
11
+ type CircuitSimulator,
12
+ ExecutionError,
13
+ extractCallStack,
14
+ resolveAssertionMessageFromError,
15
+ toACVMWitness,
16
+ witnessMapToFields,
17
+ } from '@aztec/simulator/client';
18
+ import { type FunctionCall, FunctionSelector } from '@aztec/stdlib/abi';
10
19
  import type { AuthWitness } from '@aztec/stdlib/auth-witness';
11
20
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
12
21
  import { BlockHash, type L2TipsProvider } from '@aztec/stdlib/block';
@@ -14,16 +23,30 @@ import type { CompleteAddress, ContractInstance, PartialAddress } from '@aztec/s
14
23
  import { siloNullifier } from '@aztec/stdlib/hash';
15
24
  import type { AztecNode } from '@aztec/stdlib/interfaces/server';
16
25
  import type { KeyValidationRequest } from '@aztec/stdlib/kernel';
17
- import { type PublicKeys, computeAddressSecret } from '@aztec/stdlib/keys';
18
- import { MessageContext, deriveAppSiloedSharedSecret } from '@aztec/stdlib/logs';
26
+ import { PublicKeys, computeAddressSecret, hashPublicKey } from '@aztec/stdlib/keys';
27
+ import {
28
+ AppTaggingSecret,
29
+ MessageContext,
30
+ type PendingTaggedLog,
31
+ deriveAppSiloedSharedSecret,
32
+ } from '@aztec/stdlib/logs';
19
33
  import { getNonNullifiedL1ToL2MessageWitness } from '@aztec/stdlib/messaging';
20
34
  import type { NoteStatus } from '@aztec/stdlib/note';
21
35
  import { MerkleTreeId, type NullifierMembershipWitness, PublicDataWitness } from '@aztec/stdlib/trees';
22
- import type { BlockHeader, Capsule, OffchainEffect } from '@aztec/stdlib/tx';
36
+ import {
37
+ type BlockHeader,
38
+ type Capsule,
39
+ type IndexedTxEffect,
40
+ type OffchainEffect,
41
+ TxEffect,
42
+ type TxHash,
43
+ } from '@aztec/stdlib/tx';
23
44
 
24
45
  import { createContractLogger, logContractMessage, stripAztecnrLogPrefix } from '../../contract_logging.js';
25
46
  import type { ContractSyncService } from '../../contract_sync/contract_sync_service.js';
26
47
  import { EventService } from '../../events/event_service.js';
48
+ import type { UtilityCallAuthorizationRequest } from '../../hooks/authorize_utility_call.js';
49
+ import type { ExecutionHooks } from '../../hooks/index.js';
27
50
  import { LogService } from '../../logs/log_service.js';
28
51
  import { MessageContextService } from '../../messages/message_context_service.js';
29
52
  import { NoteService } from '../../notes/note_service.js';
@@ -36,14 +59,20 @@ import type { PrivateEventStore } from '../../storage/private_event_store/privat
36
59
  import type { RecipientTaggingStore } from '../../storage/tagging_store/recipient_tagging_store.js';
37
60
  import type { SenderAddressBookStore } from '../../storage/tagging_store/sender_address_book_store.js';
38
61
  import { EphemeralArrayService } from '../ephemeral_array_service.js';
39
- import { EventValidationRequest } from '../noir-structs/event_validation_request.js';
40
- import { LogRetrievalRequest } from '../noir-structs/log_retrieval_request.js';
41
- import { LogRetrievalResponse } from '../noir-structs/log_retrieval_response.js';
42
- import { NoteValidationRequest } from '../noir-structs/note_validation_request.js';
62
+ import { BoundedVec } from '../noir-structs/bounded_vec.js';
63
+ import { EphemeralArray } from '../noir-structs/ephemeral_array.js';
64
+ import type { EventValidationRequest } from '../noir-structs/event_validation_request.js';
65
+ import type { LogRetrievalRequest } from '../noir-structs/log_retrieval_request.js';
66
+ import type { LogRetrievalResponse } from '../noir-structs/log_retrieval_response.js';
67
+ import type { NoteData } from '../noir-structs/note_data.js';
68
+ import type { NoteValidationRequest } from '../noir-structs/note_validation_request.js';
69
+ import { Option } from '../noir-structs/option.js';
70
+ import type { ProvidedSecret } from '../noir-structs/provided_secret.js';
43
71
  import { UtilityContext } from '../noir-structs/utility_context.js';
44
72
  import { pickNotes } from '../pick_notes.js';
45
- import type { IMiscOracle, IUtilityExecutionOracle, NoteData } from './interfaces.js';
73
+ import type { IMiscOracle, IUtilityExecutionOracle } from './interfaces.js';
46
74
  import { MessageLoadOracleInputs } from './message_load_oracle_inputs.js';
75
+ import { Oracle } from './oracle.js';
47
76
 
48
77
  /** Args for UtilityExecutionOracle constructor. */
49
78
  export type UtilityExecutionOracleArgs = {
@@ -67,6 +96,10 @@ export type UtilityExecutionOracleArgs = {
67
96
  jobId: string;
68
97
  log?: ReturnType<typeof createLogger>;
69
98
  scopes: AztecAddress[];
99
+ simulator: CircuitSimulator;
100
+ hooks?: ExecutionHooks;
101
+ /** Needed to trigger contract synchronization before nested cross-contract calls. */
102
+ utilityExecutor: (call: FunctionCall, scopes: AztecAddress[]) => Promise<void>;
70
103
  };
71
104
 
72
105
  /**
@@ -103,6 +136,9 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
103
136
  protected readonly jobId: string;
104
137
  protected logger: ReturnType<typeof createLogger>;
105
138
  protected readonly scopes: AztecAddress[];
139
+ protected readonly simulator: CircuitSimulator;
140
+ protected readonly hooks: ExecutionHooks | undefined;
141
+ protected readonly utilityExecutor: (call: FunctionCall, scopes: AztecAddress[]) => Promise<void>;
106
142
 
107
143
  constructor(args: UtilityExecutionOracleArgs) {
108
144
  this.contractAddress = args.contractAddress;
@@ -124,29 +160,12 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
124
160
  this.jobId = args.jobId;
125
161
  this.logger = args.log ?? createLogger('simulator:client_view_context');
126
162
  this.scopes = args.scopes;
163
+ this.simulator = args.simulator;
164
+ this.hooks = args.hooks;
165
+ this.utilityExecutor = args.utilityExecutor;
127
166
  }
128
167
 
129
168
  public assertCompatibleOracleVersion(major: number, minor: number): void {
130
- // TODO(F-416): Remove this hack on v5 when protocol contracts are redeployed.
131
- // Protocol contracts/canonical contracts shipped with committed bytecode that cannot be changed. Assert they use
132
- // the expected pinned version or the current one. We want to allow for both the pinned and the current versions
133
- // because we want this code to work with both the pinned and unpinned version since some branches do not have the
134
- // pinned contracts (like e.g. next)
135
- const LEGACY_ORACLE_VERSION = 12;
136
- if (isProtocolContract(this.contractAddress)) {
137
- if (major !== LEGACY_ORACLE_VERSION && major !== ORACLE_VERSION_MAJOR) {
138
- const hint =
139
- major > ORACLE_VERSION_MAJOR
140
- ? 'The contract was compiled with a newer version of Aztec.nr than your private environment supports. Upgrade your private environment to a compatible version.'
141
- : 'The contract was compiled with an older version of Aztec.nr than your private environment supports. Recompile the contract with a compatible version of Aztec.nr.';
142
- throw new Error(
143
- `Incompatible private environment version: ${hint} See https://docs.aztec.network/errors/8 (expected oracle major version ${LEGACY_ORACLE_VERSION} or ${ORACLE_VERSION_MAJOR}, got ${major})`,
144
- );
145
- }
146
- this.contractOracleVersion = { major, minor };
147
- return;
148
- }
149
-
150
169
  if (major !== ORACLE_VERSION_MAJOR) {
151
170
  const hint =
152
171
  major > ORACLE_VERSION_MAJOR
@@ -157,7 +176,6 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
157
176
  );
158
177
  }
159
178
 
160
- // Major matches - store both major and minor for later diagnostics (e.g. when an oracle is not found)
161
179
  this.contractOracleVersion = { major, minor };
162
180
  }
163
181
 
@@ -201,13 +219,17 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
201
219
  * @param noteHash - The note hash to find in the note hash tree.
202
220
  * @returns The membership witness containing the leaf index and sibling path
203
221
  */
204
- public getNoteHashMembershipWitness(
222
+ public async getNoteHashMembershipWitness(
205
223
  blockHash: BlockHash,
206
224
  noteHash: Fr,
207
- ): Promise<MembershipWitness<typeof NOTE_HASH_TREE_HEIGHT> | undefined> {
208
- return this.#queryWithBlockHashNotAfterAnchor(blockHash, () =>
225
+ ): Promise<MembershipWitness<typeof NOTE_HASH_TREE_HEIGHT>> {
226
+ const witness = await this.#queryWithBlockHashNotAfterAnchor(blockHash, () =>
209
227
  this.aztecNode.getNoteHashMembershipWitness(blockHash, noteHash),
210
228
  );
229
+ if (!witness) {
230
+ throw new Error(`Note hash ${noteHash} not found in the note hash tree at block ${blockHash.toString()}.`);
231
+ }
232
+ return witness;
211
233
  }
212
234
 
213
235
  /**
@@ -221,16 +243,17 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
221
243
  * @param blockHash - The block hash to find in the archive tree.
222
244
  * @returns The membership witness containing the leaf index and sibling path
223
245
  */
224
- public getBlockHashMembershipWitness(
246
+ public async getBlockHashMembershipWitness(
225
247
  referenceBlockHash: BlockHash,
226
248
  blockHash: BlockHash,
227
- ): Promise<MembershipWitness<typeof ARCHIVE_HEIGHT> | undefined> {
249
+ ): Promise<Option<MembershipWitness<typeof ARCHIVE_HEIGHT>>> {
228
250
  // Note that we validate that the reference block hash is at or before the anchor block - we don't test the block
229
251
  // hash at all. If the block hash did not exist by the reference block hash, then the node will not return the
230
252
  // membership witness as there is none.
231
- return this.#queryWithBlockHashNotAfterAnchor(referenceBlockHash, () =>
253
+ const witness = await this.#queryWithBlockHashNotAfterAnchor(referenceBlockHash, () =>
232
254
  this.aztecNode.getBlockHashMembershipWitness(referenceBlockHash, blockHash),
233
255
  );
256
+ return witness ? Option.some(witness) : Option.none(MembershipWitness.empty(ARCHIVE_HEIGHT));
234
257
  }
235
258
 
236
259
  /**
@@ -239,13 +262,14 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
239
262
  * @param nullifier - Nullifier we try to find witness for.
240
263
  * @returns The nullifier membership witness (if found).
241
264
  */
242
- public getNullifierMembershipWitness(
243
- blockHash: BlockHash,
244
- nullifier: Fr,
245
- ): Promise<NullifierMembershipWitness | undefined> {
246
- return this.#queryWithBlockHashNotAfterAnchor(blockHash, () =>
265
+ public async getNullifierMembershipWitness(blockHash: BlockHash, nullifier: Fr): Promise<NullifierMembershipWitness> {
266
+ const witness = await this.#queryWithBlockHashNotAfterAnchor(blockHash, () =>
247
267
  this.aztecNode.getNullifierMembershipWitness(blockHash, nullifier),
248
268
  );
269
+ if (!witness) {
270
+ throw new Error(`Nullifier membership witness not found at block ${blockHash.toString()}.`);
271
+ }
272
+ return witness;
249
273
  }
250
274
 
251
275
  /**
@@ -257,13 +281,19 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
257
281
  * list structure" of leaves and proving that a lower nullifier is pointing to a bigger next value than the nullifier
258
282
  * we are trying to prove non-inclusion for.
259
283
  */
260
- public getLowNullifierMembershipWitness(
284
+ public async getLowNullifierMembershipWitness(
261
285
  blockHash: BlockHash,
262
286
  nullifier: Fr,
263
- ): Promise<NullifierMembershipWitness | undefined> {
264
- return this.#queryWithBlockHashNotAfterAnchor(blockHash, () =>
287
+ ): Promise<NullifierMembershipWitness> {
288
+ const witness = await this.#queryWithBlockHashNotAfterAnchor(blockHash, () =>
265
289
  this.aztecNode.getLowNullifierMembershipWitness(blockHash, nullifier),
266
290
  );
291
+ if (!witness) {
292
+ throw new Error(
293
+ `Low nullifier witness not found for nullifier ${nullifier} at block hash ${blockHash.toString()}.`,
294
+ );
295
+ }
296
+ return witness;
267
297
  }
268
298
 
269
299
  /**
@@ -272,10 +302,14 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
272
302
  * @param leafSlot - The slot of the public data tree to get the witness for.
273
303
  * @returns - The witness
274
304
  */
275
- public getPublicDataWitness(blockHash: BlockHash, leafSlot: Fr): Promise<PublicDataWitness | undefined> {
276
- return this.#queryWithBlockHashNotAfterAnchor(blockHash, () =>
305
+ public async getPublicDataWitness(blockHash: BlockHash, leafSlot: Fr): Promise<PublicDataWitness> {
306
+ const witness = await this.#queryWithBlockHashNotAfterAnchor(blockHash, () =>
277
307
  this.aztecNode.getPublicDataWitness(blockHash, leafSlot),
278
308
  );
309
+ if (!witness) {
310
+ throw new Error(`Public data witness not found for slot ${leafSlot} at block hash ${blockHash.toString()}.`);
311
+ }
312
+ return witness;
279
313
  }
280
314
 
281
315
  /**
@@ -283,14 +317,22 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
283
317
  * @param blockNumber - The number of a block of which to get the block header.
284
318
  * @returns Block extracted from a block with block number `blockNumber`.
285
319
  */
286
- public async getBlockHeader(blockNumber: BlockNumber): Promise<BlockHeader | undefined> {
320
+ public async getBlockHeader(blockNumber: BlockNumber): Promise<BlockHeader> {
287
321
  const anchorBlockNumber = this.anchorBlockHeader.getBlockNumber();
288
322
  if (blockNumber > anchorBlockNumber) {
289
323
  throw new Error(`Block number ${blockNumber} is higher than current block ${anchorBlockNumber}`);
290
324
  }
291
325
 
326
+ // Most contracts query state at the "current" block, which is the anchor. Skip the RPC when we can.
327
+ if (blockNumber === anchorBlockNumber) {
328
+ return this.anchorBlockHeader;
329
+ }
330
+
292
331
  const block = await this.aztecNode.getBlock(blockNumber);
293
- return block?.header;
332
+ if (!block?.header) {
333
+ throw new Error(`Block header not found for block ${blockNumber}.`);
334
+ }
335
+ return block.header;
294
336
  }
295
337
 
296
338
  /**
@@ -300,12 +342,12 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
300
342
  */
301
343
  public async getPublicKeysAndPartialAddress(
302
344
  account: AztecAddress,
303
- ): Promise<{ publicKeys: PublicKeys; partialAddress: PartialAddress } | undefined> {
345
+ ): Promise<Option<{ publicKeys: PublicKeys; partialAddress: PartialAddress }>> {
304
346
  const completeAddress = await this.addressStore.getCompleteAddress(account);
305
347
  if (!completeAddress) {
306
- return undefined;
348
+ return Option.none({ publicKeys: PublicKeys.default(), partialAddress: Fr.ZERO });
307
349
  }
308
- return { publicKeys: completeAddress.publicKeys, partialAddress: completeAddress.partialAddress };
350
+ return Option.some({ publicKeys: completeAddress.publicKeys, partialAddress: completeAddress.partialAddress });
309
351
  }
310
352
 
311
353
  protected async getCompleteAddressOrFail(account: AztecAddress): Promise<CompleteAddress> {
@@ -337,8 +379,12 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
337
379
  * @param messageHash - Hash of the message to authenticate.
338
380
  * @returns Authentication witness for the requested message hash, or undefined if not found.
339
381
  */
340
- public getAuthWitness(messageHash: Fr): Promise<Fr[] | undefined> {
341
- return Promise.resolve(this.authWitnesses.find(w => w.requestHash.equals(messageHash))?.witness);
382
+ public getAuthWitness(messageHash: Fr): Promise<Fr[]> {
383
+ const witness = this.authWitnesses.find(w => w.requestHash.equals(messageHash))?.witness;
384
+ if (!witness) {
385
+ throw new Error(`Unknown auth witness for message hash ${messageHash}`);
386
+ }
387
+ return Promise.resolve(witness);
342
388
  }
343
389
 
344
390
  /**
@@ -364,7 +410,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
364
410
  * @returns Array of note data.
365
411
  */
366
412
  public async getNotes(
367
- owner: AztecAddress | undefined,
413
+ owner: Option<AztecAddress>,
368
414
  storageSlot: Fr,
369
415
  numSelects: number,
370
416
  selectByIndexes: number[],
@@ -379,11 +425,13 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
379
425
  limit: number,
380
426
  offset: number,
381
427
  status: NoteStatus,
382
- ): Promise<NoteData[]> {
428
+ maxNotes: number,
429
+ packedHintedNoteLength: number,
430
+ ): Promise<BoundedVec<NoteData>> {
383
431
  const noteService = new NoteService(this.noteStore, this.aztecNode, this.anchorBlockHeader, this.jobId);
384
432
 
385
- const dbNotes = await noteService.getNotes(this.contractAddress, owner, storageSlot, status, this.scopes);
386
- return pickNotes<NoteData>(dbNotes, {
433
+ const dbNotes = await noteService.getNotes(this.contractAddress, owner.value, storageSlot, status, this.scopes);
434
+ const picked = pickNotes<NoteData>(dbNotes, {
387
435
  selects: selectByIndexes.slice(0, numSelects).map((index, i) => ({
388
436
  selector: { index, offset: selectByOffsets[i], length: selectByLengths[i] },
389
437
  value: selectValues[i],
@@ -396,6 +444,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
396
444
  limit,
397
445
  offset,
398
446
  });
447
+ return BoundedVec.from({ data: picked, maxLength: maxNotes, elementSize: packedHintedNoteLength });
399
448
  }
400
449
 
401
450
  /**
@@ -498,7 +547,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
498
547
  return this.aztecnrLogger;
499
548
  }
500
549
 
501
- public async log(level: number, message: string, fields: Fr[]): Promise<void> {
550
+ public async log(level: number, message: string, _fieldsSize: number, fields: Fr[]): Promise<void> {
502
551
  if (!LogLevels[level]) {
503
552
  throw new Error(`Invalid log level: ${level}`);
504
553
  }
@@ -509,24 +558,18 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
509
558
  logContractMessage(logger, LogLevels[level], strippedMessage, fields);
510
559
  }
511
560
 
512
- // Deprecated, only kept for backwards compatibility until Alpha v5 rolls out.
513
- public async getPendingTaggedLogs(pendingTaggedLogArrayBaseSlot: Fr, scope: AztecAddress) {
514
- const logService = this.#createLogService();
515
- const logs = await logService.fetchTaggedLogs(this.contractAddress, scope);
516
- await this.capsuleService.appendToCapsuleArray(
517
- this.contractAddress,
518
- pendingTaggedLogArrayBaseSlot,
519
- logs.map(log => log.toFields()),
520
- this.jobId,
521
- scope,
522
- );
523
- }
561
+ /** Fetches pending tagged logs into a freshly allocated ephemeral array and returns it. */
562
+ public async getPendingTaggedLogs(
563
+ scope: AztecAddress,
564
+ providedSecrets: EphemeralArray<ProvidedSecret>,
565
+ ): Promise<EphemeralArray<PendingTaggedLog>> {
566
+ const secrets = providedSecrets
567
+ .readAll(this.ephemeralArrayService)
568
+ .map(ps => new AppTaggingSecret(ps.secret, this.contractAddress, ps.mode));
524
569
 
525
- /** Fetches pending tagged logs into a freshly allocated ephemeral array and returns its base slot. */
526
- public async getPendingTaggedLogsV2(scope: AztecAddress): Promise<Fr> {
527
570
  const logService = this.#createLogService();
528
- const logs = await logService.fetchTaggedLogs(this.contractAddress, scope);
529
- return this.ephemeralArrayService.newArray(logs.map(log => log.toFields()));
571
+ const logs = await logService.fetchTaggedLogs(this.contractAddress, scope, secrets);
572
+ return EphemeralArray.fromValues(this.ephemeralArrayService, logs);
530
573
  }
531
574
 
532
575
  #createLogService(): LogService {
@@ -543,246 +586,85 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
543
586
  );
544
587
  }
545
588
 
546
- /**
547
- * Legacy: validates note/event requests stored in capsule arrays.
548
- *
549
- * Deprecated, only kept for backwards compatibility until Alpha v5 rolls out.
550
- */
551
589
  public async validateAndStoreEnqueuedNotesAndEvents(
552
- contractAddress: AztecAddress,
553
- noteValidationRequestsArrayBaseSlot: Fr,
554
- eventValidationRequestsArrayBaseSlot: Fr,
555
- maxNotePackedLen: number,
556
- maxEventSerializedLen: number,
590
+ noteValidationRequests: EphemeralArray<NoteValidationRequest>,
591
+ eventValidationRequests: EphemeralArray<EventValidationRequest>,
557
592
  scope: AztecAddress,
558
593
  ) {
559
- // TODO(#10727): allow other contracts to store notes
560
- if (!this.contractAddress.equals(contractAddress)) {
561
- throw new Error(`Got a note validation request from ${contractAddress}, expected ${this.contractAddress}`);
562
- }
563
-
564
- const noteValidationRequests = (
565
- await this.capsuleService.readCapsuleArray(
566
- contractAddress,
567
- noteValidationRequestsArrayBaseSlot,
568
- this.jobId,
569
- scope,
570
- )
571
- ).map(fields => NoteValidationRequest.fromFields(fields, maxNotePackedLen));
572
-
573
- const eventValidationRequests = (
574
- await this.capsuleService.readCapsuleArray(
575
- contractAddress,
576
- eventValidationRequestsArrayBaseSlot,
577
- this.jobId,
578
- scope,
579
- )
580
- ).map(fields => EventValidationRequest.fromFields(fields, maxEventSerializedLen));
581
-
582
- await this.#processValidationRequests(noteValidationRequests, eventValidationRequests, scope);
583
-
584
- await this.capsuleService.setCapsuleArray(
585
- contractAddress,
586
- noteValidationRequestsArrayBaseSlot,
587
- [],
588
- this.jobId,
589
- scope,
590
- );
591
- await this.capsuleService.setCapsuleArray(
592
- contractAddress,
593
- eventValidationRequestsArrayBaseSlot,
594
- [],
595
- this.jobId,
594
+ await this.#processValidationRequests(
595
+ noteValidationRequests.readAll(this.ephemeralArrayService),
596
+ eventValidationRequests.readAll(this.ephemeralArrayService),
596
597
  scope,
597
598
  );
598
599
  }
599
600
 
600
- public async validateAndStoreEnqueuedNotesAndEventsV2(
601
- noteValidationRequestsArrayBaseSlot: Fr,
602
- eventValidationRequestsArrayBaseSlot: Fr,
603
- maxNotePackedLen: number,
604
- maxEventSerializedLen: number,
605
- scope: AztecAddress,
606
- ) {
607
- const noteValidationRequests = this.ephemeralArrayService
608
- .readArrayAt(noteValidationRequestsArrayBaseSlot)
609
- .map(fields => NoteValidationRequest.fromFields(fields, maxNotePackedLen));
610
-
611
- const eventValidationRequests = this.ephemeralArrayService
612
- .readArrayAt(eventValidationRequestsArrayBaseSlot)
613
- .map(fields => EventValidationRequest.fromFields(fields, maxEventSerializedLen));
614
-
615
- await this.#processValidationRequests(noteValidationRequests, eventValidationRequests, scope);
616
- }
617
-
618
- /**
619
- * Dispatches note and event validation requests to the service layer.
620
- *
621
- * This function is an auxiliary to support legacy (capsule backed) and new (ephemeral array backed) versions of the
622
- * `validateAndStoreEnqueuedNotesAndEvents` oracle.
623
- */
624
601
  async #processValidationRequests(
625
602
  noteValidationRequests: NoteValidationRequest[],
626
603
  eventValidationRequests: EventValidationRequest[],
627
604
  scope: AztecAddress,
628
605
  ) {
629
- const noteService = new NoteService(this.noteStore, this.aztecNode, this.anchorBlockHeader, this.jobId);
630
- const noteStorePromises = noteValidationRequests.map(request =>
631
- noteService.validateAndStoreNote(
632
- request.contractAddress,
633
- request.owner,
634
- request.storageSlot,
635
- request.randomness,
636
- request.noteNonce,
637
- request.content,
638
- request.noteHash,
639
- request.nullifier,
640
- request.txHash,
641
- scope,
642
- ),
643
- );
606
+ const txEffects = await this.#fetchTxEffects([
607
+ ...noteValidationRequests.map(r => r.txHash),
608
+ ...eventValidationRequests.map(r => r.txHash),
609
+ ]);
644
610
 
611
+ const noteService = new NoteService(this.noteStore, this.aztecNode, this.anchorBlockHeader, this.jobId);
645
612
  const eventService = new EventService(this.anchorBlockHeader, this.aztecNode, this.privateEventStore, this.jobId);
646
- const eventStorePromises = eventValidationRequests.map(request =>
647
- eventService.validateAndStoreEvent(
648
- request.contractAddress,
649
- request.eventTypeId,
650
- request.randomness,
651
- request.serializedEvent,
652
- request.eventCommitment,
653
- request.txHash,
654
- scope,
655
- ),
656
- );
657
613
 
658
- await Promise.all([...noteStorePromises, ...eventStorePromises]);
614
+ await Promise.all([
615
+ noteService.validateAndStoreNotes(noteValidationRequests, scope, txEffects),
616
+ eventService.validateAndStoreEvents(eventValidationRequests, scope, txEffects),
617
+ ]);
659
618
  }
660
619
 
661
620
  public async getLogsByTag(
662
- contractAddress: AztecAddress,
663
- logRetrievalRequestsArrayBaseSlot: Fr,
664
- logRetrievalResponsesArrayBaseSlot: Fr,
665
- scope: AztecAddress,
666
- ) {
667
- // TODO(#10727): allow other contracts to process partial notes
668
- if (!this.contractAddress.equals(contractAddress)) {
669
- throw new Error(`Got a note validation request from ${contractAddress}, expected ${this.contractAddress}`);
670
- }
671
-
672
- // We read all log retrieval requests and process them all concurrently. This makes the process much faster as we
673
- // don't need to wait for the network round-trip.
674
- const logRetrievalRequests = (
675
- await this.capsuleService.readCapsuleArray(contractAddress, logRetrievalRequestsArrayBaseSlot, this.jobId, scope)
676
- ).map(LogRetrievalRequest.fromFields);
677
-
621
+ requests: EphemeralArray<LogRetrievalRequest>,
622
+ ): Promise<EphemeralArray<EphemeralArray<LogRetrievalResponse>>> {
623
+ const logRetrievalRequests = requests.readAll(this.ephemeralArrayService);
678
624
  const logService = this.#createLogService();
679
- const maybeLogRetrievalResponses = await logService.fetchLogsByTag(contractAddress, logRetrievalRequests);
680
625
 
681
- // Requests are cleared once we're done.
682
- await this.capsuleService.setCapsuleArray(
683
- contractAddress,
684
- logRetrievalRequestsArrayBaseSlot,
685
- [],
686
- this.jobId,
687
- scope,
688
- );
626
+ const logRetrievalResponses = await logService.fetchLogsByTag(this.contractAddress, logRetrievalRequests);
689
627
 
690
- // The responses are stored as Option<LogRetrievalResponse> in a second CapsuleArray.
691
- await this.capsuleService.setCapsuleArray(
692
- contractAddress,
693
- logRetrievalResponsesArrayBaseSlot,
694
- maybeLogRetrievalResponses.map(LogRetrievalResponse.toSerializedOption),
695
- this.jobId,
696
- scope,
628
+ // Create an inner ephemeral array for each request's matching logs, then wrap all slots in an outer array.
629
+ const innerArrays = logRetrievalResponses.map(responses =>
630
+ EphemeralArray.fromValues(this.ephemeralArrayService, responses),
697
631
  );
698
- }
699
632
 
700
- public async getLogsByTagV2(requestArrayBaseSlot: Fr): Promise<Fr> {
701
- const logRetrievalRequests = this.ephemeralArrayService
702
- .readArrayAt(requestArrayBaseSlot)
703
- .map(LogRetrievalRequest.fromFields);
704
- const logService = this.#createLogService();
705
-
706
- const maybeLogRetrievalResponses = await logService.fetchLogsByTag(this.contractAddress, logRetrievalRequests);
707
-
708
- return this.ephemeralArrayService.newArray(maybeLogRetrievalResponses.map(LogRetrievalResponse.toSerializedOption));
633
+ return EphemeralArray.fromValues(this.ephemeralArrayService, innerArrays);
709
634
  }
710
635
 
711
- // Deprecated, only kept for backwards compatibility until Alpha v5 rolls out.
636
+ /** Reads tx hash requests from an ephemeral array, resolves their contexts, and returns the response array. */
712
637
  public async getMessageContextsByTxHash(
713
- contractAddress: AztecAddress,
714
- messageContextRequestsArrayBaseSlot: Fr,
715
- messageContextResponsesArrayBaseSlot: Fr,
716
- scope: AztecAddress,
717
- ) {
718
- try {
719
- if (!this.contractAddress.equals(contractAddress)) {
720
- throw new Error(`Got a message context request from ${contractAddress}, expected ${this.contractAddress}`);
721
- }
722
-
723
- // TODO(@mverzilli): this is a prime example of where using an ephemeral array would make much more sense, we don't
724
- // need scopes here, we just need a bit of shared memory to cross boundaries between Noir and TS.
725
- // At the same time, we don't want to allow any global scope access other than where backwards compatibility
726
- // forces us to. Hence we need the scope here to be artificial.
727
- const requestCapsules = await this.capsuleService.readCapsuleArray(
728
- contractAddress,
729
- messageContextRequestsArrayBaseSlot,
730
- this.jobId,
731
- scope,
732
- );
733
-
734
- const txHashes = requestCapsules.map((fields, i) => {
735
- if (fields.length !== 1) {
736
- throw new Error(
737
- `Malformed message context request at index ${i}: expected 1 field (tx hash), got ${fields.length}`,
738
- );
739
- }
740
- return fields[0];
741
- });
742
-
743
- const maybeMessageContexts = await this.messageContextService.getMessageContextsByTxHash(
744
- txHashes,
745
- this.anchorBlockHeader.getBlockNumber(),
746
- );
747
-
748
- // Leave response in response capsule array.
749
- await this.capsuleService.setCapsuleArray(
750
- contractAddress,
751
- messageContextResponsesArrayBaseSlot,
752
- maybeMessageContexts.map(MessageContext.toSerializedOption),
753
- this.jobId,
754
- scope,
755
- );
756
- } finally {
757
- await this.capsuleService.setCapsuleArray(
758
- contractAddress,
759
- messageContextRequestsArrayBaseSlot,
760
- [],
761
- this.jobId,
762
- scope,
763
- );
764
- }
765
- }
766
-
767
- /** Reads tx hash requests from an ephemeral array, resolves their contexts, and returns the response slot. */
768
- public async getMessageContextsByTxHashV2(requestArrayBaseSlot: Fr): Promise<Fr> {
769
- const requestFields = this.ephemeralArrayService.readArrayAt(requestArrayBaseSlot);
770
-
771
- const txHashes = requestFields.map((fields, i) => {
772
- if (fields.length !== 1) {
773
- throw new Error(
774
- `Malformed message context request at index ${i}: expected 1 field (tx hash), got ${fields.length}`,
775
- );
776
- }
777
- return fields[0];
778
- });
638
+ requests: EphemeralArray<Fr>,
639
+ ): Promise<EphemeralArray<Option<MessageContext>>> {
640
+ const txHashes = requests.readAll(this.ephemeralArrayService);
779
641
 
780
642
  const maybeMessageContexts = await this.messageContextService.getMessageContextsByTxHash(
781
643
  txHashes,
782
644
  this.anchorBlockHeader.getBlockNumber(),
783
645
  );
784
646
 
785
- return this.ephemeralArrayService.newArray(maybeMessageContexts.map(MessageContext.toSerializedOption));
647
+ const options = maybeMessageContexts.map(mc =>
648
+ mc ? Option.some(mc) : Option.none<MessageContext>(MessageContext.empty()),
649
+ );
650
+ return EphemeralArray.fromValues(this.ephemeralArrayService, options);
651
+ }
652
+
653
+ /**
654
+ * Fetches the effects of a transaction by its hash. Returns null if the tx is not found or is beyond the anchor
655
+ * block.
656
+ */
657
+ public async getTxEffect(txHash: TxHash): Promise<Option<TxEffect>> {
658
+ if (txHash.hash.isZero()) {
659
+ throw new Error('Invalid tx hash passed into aztec_utl_getTxEffect oracle handler');
660
+ }
661
+
662
+ const receipt = await this.aztecNode.getTxReceipt(txHash, { includeTxEffect: true });
663
+ if (!receipt.isMined() || !receipt.txEffect || receipt.blockNumber > this.anchorBlockHeader.getBlockNumber()) {
664
+ return Option.none(TxEffect.empty());
665
+ }
666
+
667
+ return Option.some(receipt.txEffect);
786
668
  }
787
669
 
788
670
  public setCapsule(contractAddress: AztecAddress, slot: Fr, capsule: Fr[], scope: AztecAddress): void {
@@ -793,12 +675,18 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
793
675
  this.capsuleService.setCapsule(contractAddress, slot, capsule, this.jobId, scope);
794
676
  }
795
677
 
796
- public getCapsule(contractAddress: AztecAddress, slot: Fr, scope: AztecAddress): Promise<Fr[] | null> {
678
+ public async getCapsule(
679
+ contractAddress: AztecAddress,
680
+ slot: Fr,
681
+ tSize: number,
682
+ scope: AztecAddress,
683
+ ): Promise<Option<Fr[]>> {
797
684
  if (!contractAddress.equals(this.contractAddress)) {
798
685
  // TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
799
686
  throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
800
687
  }
801
- return this.capsuleService.getCapsule(contractAddress, slot, this.jobId, scope, this.capsules);
688
+ const values = await this.capsuleService.getCapsule(contractAddress, slot, this.jobId, scope, this.capsules);
689
+ return values ? Option.some(values) : Option.none(new Array(tSize).fill(Fr.ZERO));
802
690
  }
803
691
 
804
692
  public deleteCapsule(contractAddress: AztecAddress, slot: Fr, scope: AztecAddress): void {
@@ -827,38 +715,57 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
827
715
  * Clears cached sync state for a contract for a set of scopes, forcing re-sync on the next query so that newly
828
716
  * stored notes or events are discovered.
829
717
  */
830
- public setContractSyncCacheInvalid(contractAddress: AztecAddress, scopes: AztecAddress[]): void {
718
+ public setContractSyncCacheInvalid(contractAddress: AztecAddress, scopes: BoundedVec<AztecAddress>): void {
831
719
  if (!contractAddress.equals(this.contractAddress)) {
832
720
  throw new Error(`Contract ${this.contractAddress} cannot invalidate sync cache of ${contractAddress}`);
833
721
  }
834
- this.contractSyncService.invalidateContractForScopes(contractAddress, scopes);
722
+ this.contractSyncService.invalidateContractForScopes(contractAddress, scopes.data);
835
723
  }
836
724
 
837
725
  // TODO(#11849): consider replacing this oracle with a pure Noir implementation of aes decryption.
838
- public decryptAes128(ciphertext: Buffer, iv: Buffer, symKey: Buffer): Promise<Buffer> {
839
- const aes128 = new Aes128();
840
- return aes128.decryptBufferCBC(ciphertext, iv, symKey);
726
+ public async decryptAes128(
727
+ ciphertext: BoundedVec<number>,
728
+ iv: Buffer,
729
+ symKey: Buffer,
730
+ ): Promise<Option<BoundedVec<number>>> {
731
+ const capacity = ciphertext.maxLength;
732
+ try {
733
+ const aes128 = new Aes128();
734
+ const plaintext = await aes128.decryptBufferCBC(Buffer.from(ciphertext.data), iv, symKey);
735
+ return Option.some(BoundedVec.from<number>({ data: [...plaintext], maxLength: capacity }));
736
+ } catch {
737
+ return Option.none(BoundedVec.empty<number>({ maxLength: capacity }));
738
+ }
841
739
  }
842
740
 
843
741
  /**
844
- * Retrieves the app-siloed shared secret for a given address and ephemeral public key.
845
- * @param address - The address to get the secret for.
846
- * @param ephPk - The ephemeral public key to get the secret for.
742
+ * Retrieves app-siloed shared secrets for multiple ephemeral public keys stored in an ephemeral array.
743
+ * @param address - The recipient address.
744
+ * @param ephPks - Ephemeral array containing the serialized Points.
847
745
  * @param contractAddress - The contract address for app-siloing (validated against execution context).
848
- * @returns The app-siloed shared secret as a Field.
746
+ * @returns A new ephemeral array containing the computed shared secrets.
849
747
  */
850
- public async getSharedSecret(address: AztecAddress, ephPk: Point, contractAddress: AztecAddress): Promise<Fr> {
748
+ public async getSharedSecrets(
749
+ address: AztecAddress,
750
+ ephPks: EphemeralArray<Point>,
751
+ contractAddress: AztecAddress,
752
+ ): Promise<EphemeralArray<Fr>> {
851
753
  if (!contractAddress.equals(this.contractAddress)) {
852
754
  throw new Error(
853
- `getSharedSecret called with contract address ${contractAddress}, expected ${this.contractAddress}`,
755
+ `getSharedSecrets called with contract address ${contractAddress}, expected ${this.contractAddress}`,
854
756
  );
855
757
  }
856
758
  const recipientCompleteAddress = await this.getCompleteAddressOrFail(address);
857
- const ivskM = await this.keyStore.getMasterSecretKey(
858
- recipientCompleteAddress.publicKeys.masterIncomingViewingPublicKey,
859
- );
759
+ const ivpkMHash = await hashPublicKey(recipientCompleteAddress.publicKeys.ivpkM);
760
+ const ivskM = await this.keyStore.getMasterSecretKey(ivpkMHash);
860
761
  const addressSecret = await computeAddressSecret(await recipientCompleteAddress.getPreaddress(), ivskM);
861
- return deriveAppSiloedSharedSecret(addressSecret, ephPk, this.contractAddress);
762
+
763
+ const ephPkPoints = ephPks.readAll(this.ephemeralArrayService);
764
+ const secrets = await Promise.all(
765
+ ephPkPoints.map(ephPk => deriveAppSiloedSharedSecret(addressSecret, ephPk, this.contractAddress)),
766
+ );
767
+
768
+ return EphemeralArray.fromValues(this.ephemeralArrayService, secrets);
862
769
  }
863
770
 
864
771
  public pushEphemeral(slot: Fr, elements: Fr[]): number {
@@ -894,28 +801,167 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
894
801
  return Promise.resolve();
895
802
  }
896
803
 
804
+ /** Executes another utility function from within this one and returns its serialized return values. */
805
+ public async callUtilityFunction(
806
+ targetContractAddress: AztecAddress,
807
+ functionSelector: FunctionSelector,
808
+ args: Fr[],
809
+ ): Promise<Fr[]> {
810
+ const targetArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(
811
+ targetContractAddress,
812
+ functionSelector,
813
+ );
814
+
815
+ if (!targetContractAddress.equals(this.contractAddress)) {
816
+ const [callerInstance, targetInstance] = await Promise.all([
817
+ this.getContractInstance(this.contractAddress),
818
+ this.getContractInstance(targetContractAddress),
819
+ ]);
820
+ const request: UtilityCallAuthorizationRequest = {
821
+ caller: this.contractAddress,
822
+ callerClassId: callerInstance.currentContractClassId,
823
+ target: targetContractAddress,
824
+ targetClassId: targetInstance.currentContractClassId,
825
+ functionSelector,
826
+ functionName: targetArtifact.name,
827
+ args,
828
+ callerContext: this.callerContext,
829
+ };
830
+
831
+ const response = this.hooks
832
+ ? await this.hooks.authorizeUtilityCall(request)
833
+ : { authorized: false, reason: 'No execution hooks configured' };
834
+
835
+ if (!response.authorized) {
836
+ const reason = response.reason ? `: ${response.reason}` : '';
837
+ throw new Error(
838
+ `Cross-contract utility call denied${reason}. ${this.contractAddress} attempted to call ` +
839
+ `${targetContractAddress}:${functionSelector} (${targetArtifact.name}). ` +
840
+ `See https://docs.aztec.network/errors/11`,
841
+ );
842
+ }
843
+
844
+ await this.contractSyncService.ensureContractSynced(
845
+ targetContractAddress,
846
+ functionSelector,
847
+ this.utilityExecutor,
848
+ this.anchorBlockHeader,
849
+ this.jobId,
850
+ this.scopes,
851
+ );
852
+ }
853
+
854
+ this.logger.debug(
855
+ `Calling nested utility function ${targetContractAddress}:${functionSelector} from ${this.contractAddress}`,
856
+ );
857
+
858
+ const nestedOracle = new UtilityExecutionOracle({
859
+ contractAddress: targetContractAddress,
860
+ authWitnesses: this.authWitnesses,
861
+ capsules: this.capsules,
862
+ anchorBlockHeader: this.anchorBlockHeader,
863
+ contractStore: this.contractStore,
864
+ noteStore: this.noteStore,
865
+ keyStore: this.keyStore,
866
+ addressStore: this.addressStore,
867
+ aztecNode: this.aztecNode,
868
+ recipientTaggingStore: this.recipientTaggingStore,
869
+ senderAddressBookStore: this.senderAddressBookStore,
870
+ capsuleService: this.capsuleService,
871
+ privateEventStore: this.privateEventStore,
872
+ messageContextService: this.messageContextService,
873
+ contractSyncService: this.contractSyncService,
874
+ l2TipsStore: this.l2TipsStore,
875
+ jobId: this.jobId,
876
+ scopes: this.scopes,
877
+ simulator: this.simulator,
878
+ hooks: this.hooks,
879
+ utilityExecutor: this.utilityExecutor,
880
+ log: this.logger,
881
+ });
882
+
883
+ const initialWitness = toACVMWitness(0, args);
884
+ const acvmCallback = new Oracle(nestedOracle);
885
+ const acirExecutionResult = await this.simulator
886
+ .executeUserCircuit(initialWitness, targetArtifact, acvmCallback.toACIRCallback())
887
+ .catch((err: Error) => {
888
+ err.message = resolveAssertionMessageFromError(err, targetArtifact);
889
+ throw new ExecutionError(
890
+ err.message,
891
+ { contractAddress: targetContractAddress, functionSelector },
892
+ extractCallStack(err, targetArtifact.debug),
893
+ { cause: err },
894
+ );
895
+ });
896
+
897
+ return witnessMapToFields(acirExecutionResult.returnWitness);
898
+ }
899
+
897
900
  /** Returns offchain effects collected during execution. */
898
901
  public getOffchainEffects(): OffchainEffect[] {
899
902
  return this.offchainEffects;
900
903
  }
901
904
 
905
+ /**
906
+ * Fetches tx effects for the given hashes in parallel, deduplicating repeated hashes so each tx is only requested
907
+ * once. Returns a map keyed by `TxHash.toString()`; hashes for which the node has no tx effect are omitted.
908
+ */
909
+ async #fetchTxEffects(txHashes: TxHash[]): Promise<Map<string, IndexedTxEffect>> {
910
+ const uniqueTxHashes = uniqueBy(txHashes, h => h.toString());
911
+ const fetched = await Promise.all(
912
+ uniqueTxHashes.map(h => this.aztecNode.getTxReceipt(h, { includeTxEffect: true })),
913
+ );
914
+ return new Map(
915
+ uniqueTxHashes
916
+ .map((h, i): [string, IndexedTxEffect | undefined] => {
917
+ const receipt = fetched[i];
918
+ if (!receipt.isMined() || !receipt.txEffect) {
919
+ return [h.toString(), undefined];
920
+ }
921
+ return [
922
+ h.toString(),
923
+ {
924
+ data: receipt.txEffect,
925
+ l2BlockNumber: receipt.blockNumber,
926
+ l2BlockHash: receipt.blockHash,
927
+ txIndexInBlock: receipt.txIndexInBlock,
928
+ slotNumber: receipt.slotNumber,
929
+ },
930
+ ];
931
+ })
932
+ .filter((entry): entry is [string, IndexedTxEffect] => entry[1] !== undefined),
933
+ );
934
+ }
935
+
902
936
  /** Runs a query concurrently with a validation that the block hash is not ahead of the anchor block. */
903
937
  async #queryWithBlockHashNotAfterAnchor<T>(blockHash: BlockHash, query: () => Promise<T>): Promise<T> {
938
+ // Most contracts query state at the "current" block, which is the anchor. Skip the validation when we can.
939
+ const anchorHash = await this.anchorBlockHeader.hash();
940
+ if (blockHash.equals(anchorHash)) {
941
+ return query();
942
+ }
943
+
904
944
  const [response] = await Promise.all([
905
945
  query(),
906
946
  (async () => {
907
- const header = await this.aztecNode.getBlockHeader(blockHash);
947
+ const block = await this.aztecNode.getBlock(blockHash);
948
+ const header = block?.header;
908
949
  if (!header) {
909
950
  throw new Error(`Could not find block header for block hash ${blockHash}`);
910
951
  }
911
952
 
912
953
  if (header.getBlockNumber() > this.anchorBlockHeader.getBlockNumber()) {
913
954
  throw new Error(
914
- `Made a node query with a reference block hash ${blockHash} with block number ${header.getBlockNumber()}, which is ahead of the anchor block number ${this.anchorBlockHeader.getBlockNumber()} (from anchor block hash ${await this.anchorBlockHeader.hash()}).`,
955
+ `Made a node query with a reference block hash ${blockHash} with block number ${header.getBlockNumber()}, which is ahead of the anchor block number ${this.anchorBlockHeader.getBlockNumber()} (from anchor block hash ${anchorHash}).`,
915
956
  );
916
957
  }
917
958
  })(),
918
959
  ]);
919
960
  return response;
920
961
  }
962
+
963
+ /** The execution context of the current call. */
964
+ protected get callerContext(): 'private' | 'private view' | 'utility' {
965
+ return 'utility';
966
+ }
921
967
  }