@aztec/pxe 0.0.1-commit.d431d1c → 0.0.1-commit.d939eb5aa

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 (269) hide show
  1. package/dest/bin/check_oracle_version.js +5 -5
  2. package/dest/block_synchronizer/block_synchronizer.d.ts +9 -5
  3. package/dest/block_synchronizer/block_synchronizer.d.ts.map +1 -1
  4. package/dest/block_synchronizer/block_synchronizer.js +68 -16
  5. package/dest/config/index.d.ts +4 -2
  6. package/dest/config/index.d.ts.map +1 -1
  7. package/dest/config/index.js +12 -2
  8. package/dest/config/package_info.js +1 -1
  9. package/dest/contract_function_simulator/contract_function_simulator.d.ts +63 -31
  10. package/dest/contract_function_simulator/contract_function_simulator.d.ts.map +1 -1
  11. package/dest/contract_function_simulator/contract_function_simulator.js +206 -78
  12. package/dest/contract_function_simulator/ephemeral_array_service.d.ts +28 -0
  13. package/dest/contract_function_simulator/ephemeral_array_service.d.ts.map +1 -0
  14. package/dest/contract_function_simulator/ephemeral_array_service.js +78 -0
  15. package/dest/contract_function_simulator/execution_tagging_index_cache.d.ts +7 -7
  16. package/dest/contract_function_simulator/execution_tagging_index_cache.d.ts.map +1 -1
  17. package/dest/contract_function_simulator/execution_tagging_index_cache.js +19 -11
  18. package/dest/contract_function_simulator/index.d.ts +2 -1
  19. package/dest/contract_function_simulator/index.d.ts.map +1 -1
  20. package/dest/contract_function_simulator/index.js +1 -0
  21. package/dest/contract_function_simulator/noir-structs/event_validation_request.d.ts +5 -7
  22. package/dest/contract_function_simulator/noir-structs/event_validation_request.d.ts.map +1 -1
  23. package/dest/contract_function_simulator/noir-structs/event_validation_request.js +9 -11
  24. package/dest/contract_function_simulator/noir-structs/log_retrieval_request.d.ts +1 -1
  25. package/dest/contract_function_simulator/noir-structs/log_retrieval_request.js +1 -1
  26. package/dest/contract_function_simulator/noir-structs/log_retrieval_response.d.ts +2 -2
  27. package/dest/contract_function_simulator/noir-structs/log_retrieval_response.d.ts.map +1 -1
  28. package/dest/contract_function_simulator/noir-structs/log_retrieval_response.js +2 -4
  29. package/dest/contract_function_simulator/noir-structs/note_validation_request.d.ts +5 -8
  30. package/dest/contract_function_simulator/noir-structs/note_validation_request.d.ts.map +1 -1
  31. package/dest/contract_function_simulator/noir-structs/note_validation_request.js +7 -12
  32. package/dest/contract_function_simulator/oracle/interfaces.d.ts +65 -46
  33. package/dest/contract_function_simulator/oracle/interfaces.d.ts.map +1 -1
  34. package/dest/contract_function_simulator/oracle/legacy_oracle_mappings.d.ts +9 -0
  35. package/dest/contract_function_simulator/oracle/legacy_oracle_mappings.d.ts.map +1 -0
  36. package/dest/contract_function_simulator/oracle/legacy_oracle_mappings.js +47 -0
  37. package/dest/contract_function_simulator/oracle/oracle.d.ts +75 -42
  38. package/dest/contract_function_simulator/oracle/oracle.d.ts.map +1 -1
  39. package/dest/contract_function_simulator/oracle/oracle.js +319 -112
  40. package/dest/contract_function_simulator/oracle/private_execution.d.ts +2 -22
  41. package/dest/contract_function_simulator/oracle/private_execution.d.ts.map +1 -1
  42. package/dest/contract_function_simulator/oracle/private_execution.js +5 -40
  43. package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts +59 -77
  44. package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts.map +1 -1
  45. package/dest/contract_function_simulator/oracle/private_execution_oracle.js +120 -86
  46. package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts +134 -67
  47. package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts.map +1 -1
  48. package/dest/contract_function_simulator/oracle/utility_execution_oracle.js +337 -151
  49. package/dest/contract_function_simulator/pick_notes.d.ts +1 -1
  50. package/dest/contract_function_simulator/pick_notes.d.ts.map +1 -1
  51. package/dest/contract_function_simulator/pick_notes.js +9 -2
  52. package/dest/contract_function_simulator/proxied_contract_data_source.d.ts +1 -1
  53. package/dest/contract_function_simulator/proxied_contract_data_source.d.ts.map +1 -1
  54. package/dest/contract_function_simulator/proxied_contract_data_source.js +3 -0
  55. package/dest/contract_logging.d.ts +27 -0
  56. package/dest/contract_logging.d.ts.map +1 -0
  57. package/dest/contract_logging.js +38 -0
  58. package/dest/contract_sync/contract_sync_service.d.ts +44 -0
  59. package/dest/contract_sync/contract_sync_service.d.ts.map +1 -0
  60. package/dest/contract_sync/contract_sync_service.js +116 -0
  61. package/dest/contract_sync/helpers.d.ts +28 -0
  62. package/dest/contract_sync/helpers.d.ts.map +1 -0
  63. package/dest/contract_sync/helpers.js +60 -0
  64. package/dest/debug/pxe_debug_utils.d.ts +24 -10
  65. package/dest/debug/pxe_debug_utils.d.ts.map +1 -1
  66. package/dest/debug/pxe_debug_utils.js +28 -17
  67. package/dest/entrypoints/client/bundle/index.d.ts +3 -1
  68. package/dest/entrypoints/client/bundle/index.d.ts.map +1 -1
  69. package/dest/entrypoints/client/bundle/index.js +2 -0
  70. package/dest/entrypoints/client/bundle/utils.d.ts +2 -2
  71. package/dest/entrypoints/client/bundle/utils.d.ts.map +1 -1
  72. package/dest/entrypoints/client/bundle/utils.js +23 -9
  73. package/dest/entrypoints/client/lazy/index.d.ts +3 -1
  74. package/dest/entrypoints/client/lazy/index.d.ts.map +1 -1
  75. package/dest/entrypoints/client/lazy/index.js +2 -0
  76. package/dest/entrypoints/client/lazy/utils.d.ts +3 -3
  77. package/dest/entrypoints/client/lazy/utils.d.ts.map +1 -1
  78. package/dest/entrypoints/client/lazy/utils.js +24 -10
  79. package/dest/entrypoints/pxe_creation_options.d.ts +5 -2
  80. package/dest/entrypoints/pxe_creation_options.d.ts.map +1 -1
  81. package/dest/entrypoints/pxe_creation_options.js +3 -1
  82. package/dest/entrypoints/server/index.d.ts +4 -2
  83. package/dest/entrypoints/server/index.d.ts.map +1 -1
  84. package/dest/entrypoints/server/index.js +3 -1
  85. package/dest/entrypoints/server/utils.d.ts +2 -2
  86. package/dest/entrypoints/server/utils.d.ts.map +1 -1
  87. package/dest/entrypoints/server/utils.js +30 -11
  88. package/dest/events/event_service.d.ts +6 -6
  89. package/dest/events/event_service.d.ts.map +1 -1
  90. package/dest/events/event_service.js +21 -10
  91. package/dest/events/private_event_filter_validator.d.ts +3 -2
  92. package/dest/events/private_event_filter_validator.d.ts.map +1 -1
  93. package/dest/events/private_event_filter_validator.js +15 -0
  94. package/dest/job_coordinator/job_coordinator.d.ts +3 -2
  95. package/dest/job_coordinator/job_coordinator.d.ts.map +1 -1
  96. package/dest/job_coordinator/job_coordinator.js +3 -2
  97. package/dest/logs/log_service.d.ts +10 -9
  98. package/dest/logs/log_service.d.ts.map +1 -1
  99. package/dest/logs/log_service.js +50 -64
  100. package/dest/messages/message_context_service.d.ts +17 -0
  101. package/dest/messages/message_context_service.d.ts.map +1 -0
  102. package/dest/messages/message_context_service.js +36 -0
  103. package/dest/notes/note_service.d.ts +8 -8
  104. package/dest/notes/note_service.d.ts.map +1 -1
  105. package/dest/notes/note_service.js +29 -19
  106. package/dest/notes_filter.d.ts +24 -0
  107. package/dest/notes_filter.d.ts.map +1 -0
  108. package/dest/notes_filter.js +4 -0
  109. package/dest/oracle_version.d.ts +4 -3
  110. package/dest/oracle_version.d.ts.map +1 -1
  111. package/dest/oracle_version.js +20 -9
  112. package/dest/private_kernel/hints/compute_tx_expiration_timestamp.d.ts +4 -0
  113. package/dest/private_kernel/hints/compute_tx_expiration_timestamp.d.ts.map +1 -0
  114. package/dest/private_kernel/hints/{compute_tx_include_by_timestamp.js → compute_tx_expiration_timestamp.js} +12 -12
  115. package/dest/private_kernel/hints/index.d.ts +1 -1
  116. package/dest/private_kernel/hints/index.js +1 -1
  117. package/dest/private_kernel/hints/private_kernel_reset_private_inputs_builder.d.ts +4 -3
  118. package/dest/private_kernel/hints/private_kernel_reset_private_inputs_builder.d.ts.map +1 -1
  119. package/dest/private_kernel/hints/private_kernel_reset_private_inputs_builder.js +129 -68
  120. package/dest/private_kernel/hints/test_utils.d.ts +122 -0
  121. package/dest/private_kernel/hints/test_utils.d.ts.map +1 -0
  122. package/dest/private_kernel/hints/test_utils.js +203 -0
  123. package/dest/private_kernel/private_kernel_execution_prover.d.ts +3 -2
  124. package/dest/private_kernel/private_kernel_execution_prover.d.ts.map +1 -1
  125. package/dest/private_kernel/private_kernel_execution_prover.js +20 -15
  126. package/dest/private_kernel/private_kernel_oracle.d.ts +8 -4
  127. package/dest/private_kernel/private_kernel_oracle.d.ts.map +1 -1
  128. package/dest/private_kernel/private_kernel_oracle.js +7 -3
  129. package/dest/pxe.d.ts +74 -24
  130. package/dest/pxe.d.ts.map +1 -1
  131. package/dest/pxe.js +142 -80
  132. package/dest/storage/address_store/address_store.d.ts +1 -1
  133. package/dest/storage/address_store/address_store.d.ts.map +1 -1
  134. package/dest/storage/address_store/address_store.js +12 -11
  135. package/dest/storage/anchor_block_store/anchor_block_store.d.ts +9 -1
  136. package/dest/storage/anchor_block_store/anchor_block_store.d.ts.map +1 -1
  137. package/dest/storage/anchor_block_store/anchor_block_store.js +8 -1
  138. package/dest/storage/capsule_store/capsule_service.d.ts +21 -0
  139. package/dest/storage/capsule_store/capsule_service.d.ts.map +1 -0
  140. package/dest/storage/capsule_store/capsule_service.js +50 -0
  141. package/dest/storage/capsule_store/capsule_store.d.ts +9 -9
  142. package/dest/storage/capsule_store/capsule_store.d.ts.map +1 -1
  143. package/dest/storage/capsule_store/capsule_store.js +39 -36
  144. package/dest/storage/capsule_store/index.d.ts +2 -1
  145. package/dest/storage/capsule_store/index.d.ts.map +1 -1
  146. package/dest/storage/capsule_store/index.js +1 -0
  147. package/dest/storage/contract_store/contract_store.d.ts +42 -16
  148. package/dest/storage/contract_store/contract_store.d.ts.map +1 -1
  149. package/dest/storage/contract_store/contract_store.js +157 -84
  150. package/dest/storage/metadata.d.ts +1 -1
  151. package/dest/storage/metadata.js +1 -1
  152. package/dest/storage/note_store/note_store.d.ts +47 -49
  153. package/dest/storage/note_store/note_store.d.ts.map +1 -1
  154. package/dest/storage/note_store/note_store.js +278 -252
  155. package/dest/storage/note_store/stored_note.d.ts +16 -0
  156. package/dest/storage/note_store/stored_note.d.ts.map +1 -0
  157. package/dest/storage/note_store/stored_note.js +43 -0
  158. package/dest/storage/private_event_store/private_event_store.d.ts +17 -4
  159. package/dest/storage/private_event_store/private_event_store.d.ts.map +1 -1
  160. package/dest/storage/private_event_store/private_event_store.js +198 -147
  161. package/dest/storage/private_event_store/stored_private_event.d.ts +23 -0
  162. package/dest/storage/private_event_store/stored_private_event.d.ts.map +1 -0
  163. package/dest/storage/private_event_store/stored_private_event.js +56 -0
  164. package/dest/storage/tagging_store/recipient_tagging_store.d.ts +6 -6
  165. package/dest/storage/tagging_store/recipient_tagging_store.d.ts.map +1 -1
  166. package/dest/storage/tagging_store/recipient_tagging_store.js +31 -19
  167. package/dest/storage/tagging_store/sender_address_book_store.d.ts +1 -1
  168. package/dest/storage/tagging_store/sender_address_book_store.d.ts.map +1 -1
  169. package/dest/storage/tagging_store/sender_address_book_store.js +20 -14
  170. package/dest/storage/tagging_store/sender_tagging_store.d.ts +29 -28
  171. package/dest/storage/tagging_store/sender_tagging_store.d.ts.map +1 -1
  172. package/dest/storage/tagging_store/sender_tagging_store.js +233 -137
  173. package/dest/tagging/get_all_logs_by_tags.d.ts +24 -0
  174. package/dest/tagging/get_all_logs_by_tags.d.ts.map +1 -0
  175. package/dest/tagging/get_all_logs_by_tags.js +60 -0
  176. package/dest/tagging/index.d.ts +4 -3
  177. package/dest/tagging/index.d.ts.map +1 -1
  178. package/dest/tagging/index.js +2 -1
  179. package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.d.ts +5 -5
  180. package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.d.ts.map +1 -1
  181. package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.js +7 -21
  182. package/dest/tagging/recipient_sync/utils/find_highest_indexes.js +2 -2
  183. package/dest/tagging/recipient_sync/utils/load_logs_for_range.d.ts +7 -7
  184. package/dest/tagging/recipient_sync/utils/load_logs_for_range.d.ts.map +1 -1
  185. package/dest/tagging/recipient_sync/utils/load_logs_for_range.js +16 -12
  186. package/dest/tagging/sender_sync/sync_sender_tagging_indexes.d.ts +5 -8
  187. package/dest/tagging/sender_sync/sync_sender_tagging_indexes.d.ts.map +1 -1
  188. package/dest/tagging/sender_sync/sync_sender_tagging_indexes.js +13 -7
  189. package/dest/tagging/sender_sync/utils/get_status_change_of_pending.d.ts +4 -3
  190. package/dest/tagging/sender_sync/utils/get_status_change_of_pending.d.ts.map +1 -1
  191. package/dest/tagging/sender_sync/utils/get_status_change_of_pending.js +23 -16
  192. package/dest/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.d.ts +6 -7
  193. package/dest/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.d.ts.map +1 -1
  194. package/dest/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.js +42 -27
  195. package/package.json +25 -16
  196. package/src/bin/check_oracle_version.ts +5 -4
  197. package/src/block_synchronizer/block_synchronizer.ts +82 -33
  198. package/src/config/index.ts +9 -1
  199. package/src/config/package_info.ts +1 -1
  200. package/src/contract_function_simulator/contract_function_simulator.ts +366 -142
  201. package/src/contract_function_simulator/ephemeral_array_service.ts +110 -0
  202. package/src/contract_function_simulator/execution_tagging_index_cache.ts +19 -14
  203. package/src/contract_function_simulator/index.ts +1 -0
  204. package/src/contract_function_simulator/noir-structs/event_validation_request.ts +10 -10
  205. package/src/contract_function_simulator/noir-structs/log_retrieval_request.ts +1 -1
  206. package/src/contract_function_simulator/noir-structs/log_retrieval_response.ts +2 -5
  207. package/src/contract_function_simulator/noir-structs/note_validation_request.ts +5 -11
  208. package/src/contract_function_simulator/oracle/interfaces.ts +95 -58
  209. package/src/contract_function_simulator/oracle/legacy_oracle_mappings.ts +104 -0
  210. package/src/contract_function_simulator/oracle/oracle.ts +404 -150
  211. package/src/contract_function_simulator/oracle/private_execution.ts +5 -64
  212. package/src/contract_function_simulator/oracle/private_execution_oracle.ts +160 -182
  213. package/src/contract_function_simulator/oracle/utility_execution_oracle.ts +564 -182
  214. package/src/contract_function_simulator/pick_notes.ts +9 -2
  215. package/src/contract_function_simulator/proxied_contract_data_source.ts +8 -1
  216. package/src/contract_logging.ts +52 -0
  217. package/src/contract_sync/contract_sync_service.ts +176 -0
  218. package/src/contract_sync/helpers.ts +98 -0
  219. package/src/debug/pxe_debug_utils.ts +63 -18
  220. package/src/entrypoints/client/bundle/index.ts +2 -0
  221. package/src/entrypoints/client/bundle/utils.ts +18 -18
  222. package/src/entrypoints/client/lazy/index.ts +2 -0
  223. package/src/entrypoints/client/lazy/utils.ts +19 -18
  224. package/src/entrypoints/pxe_creation_options.ts +9 -1
  225. package/src/entrypoints/server/index.ts +3 -1
  226. package/src/entrypoints/server/utils.ts +24 -29
  227. package/src/events/event_service.ts +22 -11
  228. package/src/events/private_event_filter_validator.ts +21 -1
  229. package/src/job_coordinator/job_coordinator.ts +4 -3
  230. package/src/logs/log_service.ts +93 -105
  231. package/src/messages/message_context_service.ts +44 -0
  232. package/src/notes/note_service.ts +38 -26
  233. package/src/notes_filter.ts +24 -0
  234. package/src/oracle_version.ts +20 -9
  235. package/src/private_kernel/hints/{compute_tx_include_by_timestamp.ts → compute_tx_expiration_timestamp.ts} +13 -13
  236. package/src/private_kernel/hints/index.ts +1 -1
  237. package/src/private_kernel/hints/private_kernel_reset_private_inputs_builder.ts +164 -117
  238. package/src/private_kernel/hints/test_utils.ts +325 -0
  239. package/src/private_kernel/private_kernel_execution_prover.ts +24 -19
  240. package/src/private_kernel/private_kernel_oracle.ts +9 -9
  241. package/src/pxe.ts +272 -126
  242. package/src/storage/address_store/address_store.ts +15 -15
  243. package/src/storage/anchor_block_store/anchor_block_store.ts +8 -0
  244. package/src/storage/capsule_store/capsule_service.ts +90 -0
  245. package/src/storage/capsule_store/capsule_store.ts +42 -34
  246. package/src/storage/capsule_store/index.ts +1 -0
  247. package/src/storage/contract_store/contract_store.ts +186 -96
  248. package/src/storage/metadata.ts +1 -1
  249. package/src/storage/note_store/note_store.ts +318 -318
  250. package/src/storage/note_store/stored_note.ts +48 -0
  251. package/src/storage/private_event_store/private_event_store.ts +250 -190
  252. package/src/storage/private_event_store/stored_private_event.ts +73 -0
  253. package/src/storage/tagging_store/recipient_tagging_store.ts +38 -24
  254. package/src/storage/tagging_store/sender_address_book_store.ts +20 -14
  255. package/src/storage/tagging_store/sender_tagging_store.ts +287 -156
  256. package/src/tagging/get_all_logs_by_tags.ts +92 -0
  257. package/src/tagging/index.ts +3 -2
  258. package/src/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.ts +19 -24
  259. package/src/tagging/recipient_sync/utils/find_highest_indexes.ts +2 -2
  260. package/src/tagging/recipient_sync/utils/load_logs_for_range.ts +17 -16
  261. package/src/tagging/sender_sync/sync_sender_tagging_indexes.ts +25 -10
  262. package/src/tagging/sender_sync/utils/get_status_change_of_pending.ts +29 -26
  263. package/src/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.ts +39 -29
  264. package/dest/private_kernel/hints/compute_tx_include_by_timestamp.d.ts +0 -4
  265. package/dest/private_kernel/hints/compute_tx_include_by_timestamp.d.ts.map +0 -1
  266. package/dest/tree_membership/tree_membership_service.d.ts +0 -50
  267. package/dest/tree_membership/tree_membership_service.d.ts.map +0 -1
  268. package/dest/tree_membership/tree_membership_service.js +0 -75
  269. package/src/tree_membership/tree_membership_service.ts +0 -97
@@ -1,35 +1,41 @@
1
+ import type { ARCHIVE_HEIGHT, NOTE_HASH_TREE_HEIGHT } from '@aztec/constants';
1
2
  import type { BlockNumber } from '@aztec/foundation/branded-types';
2
3
  import { Aes128 } from '@aztec/foundation/crypto/aes128';
3
4
  import { Fr } from '@aztec/foundation/curves/bn254';
4
5
  import { Point } from '@aztec/foundation/curves/grumpkin';
5
- import { LogLevels, applyStringFormatting, createLogger } from '@aztec/foundation/log';
6
+ import { LogLevels, type Logger, createLogger } from '@aztec/foundation/log';
7
+ import type { MembershipWitness } from '@aztec/foundation/trees';
6
8
  import type { KeyStore } from '@aztec/key-store';
9
+ import { isProtocolContract } from '@aztec/protocol-contracts';
7
10
  import type { AuthWitness } from '@aztec/stdlib/auth-witness';
8
11
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
9
- import { L2BlockHash } from '@aztec/stdlib/block';
10
- import type { CompleteAddress, ContractInstance } from '@aztec/stdlib/contract';
12
+ import { BlockHash, type L2TipsProvider } from '@aztec/stdlib/block';
13
+ import type { CompleteAddress, ContractInstance, PartialAddress } from '@aztec/stdlib/contract';
11
14
  import { siloNullifier } from '@aztec/stdlib/hash';
12
15
  import type { AztecNode } from '@aztec/stdlib/interfaces/server';
13
16
  import type { KeyValidationRequest } from '@aztec/stdlib/kernel';
14
- import { computeAddressSecret } from '@aztec/stdlib/keys';
15
- import { deriveEcdhSharedSecret } from '@aztec/stdlib/logs';
17
+ import { type PublicKeys, computeAddressSecret } from '@aztec/stdlib/keys';
18
+ import { MessageContext, deriveAppSiloedSharedSecret } from '@aztec/stdlib/logs';
19
+ import { getNonNullifiedL1ToL2MessageWitness } from '@aztec/stdlib/messaging';
16
20
  import type { NoteStatus } from '@aztec/stdlib/note';
17
21
  import { MerkleTreeId, type NullifierMembershipWitness, PublicDataWitness } from '@aztec/stdlib/trees';
18
- import type { BlockHeader, Capsule } from '@aztec/stdlib/tx';
22
+ import type { BlockHeader, Capsule, OffchainEffect } from '@aztec/stdlib/tx';
19
23
 
24
+ import { createContractLogger, logContractMessage, stripAztecnrLogPrefix } from '../../contract_logging.js';
25
+ import type { ContractSyncService } from '../../contract_sync/contract_sync_service.js';
20
26
  import { EventService } from '../../events/event_service.js';
21
27
  import { LogService } from '../../logs/log_service.js';
28
+ import { MessageContextService } from '../../messages/message_context_service.js';
22
29
  import { NoteService } from '../../notes/note_service.js';
23
- import { ORACLE_VERSION } from '../../oracle_version.js';
30
+ import { ORACLE_VERSION_MAJOR } from '../../oracle_version.js';
24
31
  import type { AddressStore } from '../../storage/address_store/address_store.js';
25
- import type { AnchorBlockStore } from '../../storage/anchor_block_store/anchor_block_store.js';
26
- import type { CapsuleStore } from '../../storage/capsule_store/capsule_store.js';
32
+ import type { CapsuleService } from '../../storage/capsule_store/capsule_service.js';
27
33
  import type { ContractStore } from '../../storage/contract_store/contract_store.js';
28
34
  import type { NoteStore } from '../../storage/note_store/note_store.js';
29
35
  import type { PrivateEventStore } from '../../storage/private_event_store/private_event_store.js';
30
36
  import type { RecipientTaggingStore } from '../../storage/tagging_store/recipient_tagging_store.js';
31
37
  import type { SenderAddressBookStore } from '../../storage/tagging_store/sender_address_book_store.js';
32
- import { TreeMembershipService } from '../../tree_membership/tree_membership_service.js';
38
+ import { EphemeralArrayService } from '../ephemeral_array_service.js';
33
39
  import { EventValidationRequest } from '../noir-structs/event_validation_request.js';
34
40
  import { LogRetrievalRequest } from '../noir-structs/log_retrieval_request.js';
35
41
  import { LogRetrievalResponse } from '../noir-structs/log_retrieval_response.js';
@@ -39,6 +45,30 @@ import { pickNotes } from '../pick_notes.js';
39
45
  import type { IMiscOracle, IUtilityExecutionOracle, NoteData } from './interfaces.js';
40
46
  import { MessageLoadOracleInputs } from './message_load_oracle_inputs.js';
41
47
 
48
+ /** Args for UtilityExecutionOracle constructor. */
49
+ export type UtilityExecutionOracleArgs = {
50
+ contractAddress: AztecAddress;
51
+ /** List of transient auth witnesses to be used during this simulation */
52
+ authWitnesses: AuthWitness[];
53
+ capsules: Capsule[]; // TODO(#12425): Rename to transientCapsules
54
+ anchorBlockHeader: BlockHeader;
55
+ contractStore: ContractStore;
56
+ noteStore: NoteStore;
57
+ keyStore: KeyStore;
58
+ addressStore: AddressStore;
59
+ aztecNode: AztecNode;
60
+ recipientTaggingStore: RecipientTaggingStore;
61
+ senderAddressBookStore: SenderAddressBookStore;
62
+ capsuleService: CapsuleService;
63
+ privateEventStore: PrivateEventStore;
64
+ messageContextService: MessageContextService;
65
+ contractSyncService: ContractSyncService;
66
+ l2TipsStore: L2TipsProvider;
67
+ jobId: string;
68
+ log?: ReturnType<typeof createLogger>;
69
+ scopes: AztecAddress[];
70
+ };
71
+
42
72
  /**
43
73
  * The oracle for an execution of utility contract functions.
44
74
  */
@@ -46,40 +76,101 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
46
76
  isMisc = true as const;
47
77
  isUtility = true as const;
48
78
 
49
- private aztecNrDebugLog = createLogger('aztec-nr:debug_log');
50
-
51
- constructor(
52
- protected readonly contractAddress: AztecAddress,
53
- /** List of transient auth witnesses to be used during this simulation */
54
- protected readonly authWitnesses: AuthWitness[],
55
- protected readonly capsules: Capsule[], // TODO(#12425): Rename to transientCapsules
56
- protected readonly anchorBlockHeader: BlockHeader,
57
- protected readonly contractStore: ContractStore,
58
- protected readonly noteStore: NoteStore,
59
- protected readonly keyStore: KeyStore,
60
- protected readonly addressStore: AddressStore,
61
- protected readonly aztecNode: AztecNode,
62
- protected readonly anchorBlockStore: AnchorBlockStore,
63
- protected readonly recipientTaggingStore: RecipientTaggingStore,
64
- protected readonly senderAddressBookStore: SenderAddressBookStore,
65
- protected readonly capsuleStore: CapsuleStore,
66
- protected readonly privateEventStore: PrivateEventStore,
67
- protected readonly jobId: string,
68
- protected log = createLogger('simulator:client_view_context'),
69
- protected readonly scopes?: AztecAddress[],
70
- ) {}
71
-
72
- public utilityAssertCompatibleOracleVersion(version: number): void {
73
- if (version !== ORACLE_VERSION) {
74
- throw new Error(`Incompatible oracle version. Expected version ${ORACLE_VERSION}, got ${version}.`);
79
+ private contractLogger: Logger | undefined;
80
+ private aztecnrLogger: Logger | undefined;
81
+ private offchainEffects: OffchainEffect[] = [];
82
+ private readonly ephemeralArrayService = new EphemeralArrayService();
83
+
84
+ // We store oracle version to be able to show a nice error message when an oracle handler is missing.
85
+ private contractOracleVersion: { major: number; minor: number } | undefined;
86
+
87
+ protected readonly contractAddress: AztecAddress;
88
+ protected readonly authWitnesses: AuthWitness[];
89
+ protected readonly capsules: Capsule[];
90
+ protected readonly anchorBlockHeader: BlockHeader;
91
+ protected readonly contractStore: ContractStore;
92
+ protected readonly noteStore: NoteStore;
93
+ protected readonly keyStore: KeyStore;
94
+ protected readonly addressStore: AddressStore;
95
+ protected readonly aztecNode: AztecNode;
96
+ protected readonly recipientTaggingStore: RecipientTaggingStore;
97
+ protected readonly senderAddressBookStore: SenderAddressBookStore;
98
+ protected readonly capsuleService: CapsuleService;
99
+ protected readonly privateEventStore: PrivateEventStore;
100
+ protected readonly messageContextService: MessageContextService;
101
+ protected readonly contractSyncService: ContractSyncService;
102
+ protected readonly l2TipsStore: L2TipsProvider;
103
+ protected readonly jobId: string;
104
+ protected logger: ReturnType<typeof createLogger>;
105
+ protected readonly scopes: AztecAddress[];
106
+
107
+ constructor(args: UtilityExecutionOracleArgs) {
108
+ this.contractAddress = args.contractAddress;
109
+ this.authWitnesses = args.authWitnesses;
110
+ this.capsules = args.capsules;
111
+ this.anchorBlockHeader = args.anchorBlockHeader;
112
+ this.contractStore = args.contractStore;
113
+ this.noteStore = args.noteStore;
114
+ this.keyStore = args.keyStore;
115
+ this.addressStore = args.addressStore;
116
+ this.aztecNode = args.aztecNode;
117
+ this.recipientTaggingStore = args.recipientTaggingStore;
118
+ this.senderAddressBookStore = args.senderAddressBookStore;
119
+ this.capsuleService = args.capsuleService;
120
+ this.privateEventStore = args.privateEventStore;
121
+ this.messageContextService = args.messageContextService;
122
+ this.contractSyncService = args.contractSyncService;
123
+ this.l2TipsStore = args.l2TipsStore;
124
+ this.jobId = args.jobId;
125
+ this.logger = args.log ?? createLogger('simulator:client_view_context');
126
+ this.scopes = args.scopes;
127
+ }
128
+
129
+ 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
+ if (major !== ORACLE_VERSION_MAJOR) {
151
+ const hint =
152
+ major > ORACLE_VERSION_MAJOR
153
+ ? 'The contract was compiled with a newer version of Aztec.nr than your private environment supports. Upgrade your private environment to a compatible version.'
154
+ : '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.';
155
+ throw new Error(
156
+ `Incompatible private environment version: ${hint} See https://docs.aztec.network/errors/8 (expected oracle major version ${ORACLE_VERSION_MAJOR}, got ${major})`,
157
+ );
75
158
  }
159
+
160
+ // Major matches - store both major and minor for later diagnostics (e.g. when an oracle is not found)
161
+ this.contractOracleVersion = { major, minor };
162
+ }
163
+
164
+ // Prefixed with "nonOracleFunction" as it is not used as an oracle handler.
165
+ public nonOracleFunctionGetContractOracleVersion(): { major: number; minor: number } | undefined {
166
+ return this.contractOracleVersion;
76
167
  }
77
168
 
78
- public utilityGetRandomField(): Fr {
169
+ public getRandomField(): Fr {
79
170
  return Fr.random();
80
171
  }
81
172
 
82
- public utilityGetUtilityContext(): UtilityContext {
173
+ public getUtilityContext(): UtilityContext {
83
174
  return new UtilityContext(this.anchorBlockHeader, this.contractAddress);
84
175
  }
85
176
 
@@ -88,21 +179,58 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
88
179
  * @param pkMHash - The master public key hash.
89
180
  * @returns A Promise that resolves to nullifier keys.
90
181
  * @throws If the keys are not registered in the key store.
182
+ * @throws If scopes are defined and the account is not in the scopes.
91
183
  */
92
- public utilityGetKeyValidationRequest(pkMHash: Fr): Promise<KeyValidationRequest> {
184
+ public async getKeyValidationRequest(pkMHash: Fr): Promise<KeyValidationRequest> {
185
+ let hasAccess = false;
186
+ for (let i = 0; i < this.scopes.length && !hasAccess; i++) {
187
+ if (await this.keyStore.accountHasKey(this.scopes[i], pkMHash)) {
188
+ hasAccess = true;
189
+ }
190
+ }
191
+ if (!hasAccess) {
192
+ throw new Error(`Key validation request denied: no scoped account has a key with hash ${pkMHash.toString()}.`);
193
+ }
93
194
  return this.keyStore.getKeyValidationRequest(pkMHash, this.contractAddress);
94
195
  }
95
196
 
96
197
  /**
97
- * Fetches the index and sibling path of a leaf at a given block from a given tree.
98
- * @param blockHash - The block hash at which to get the membership witness.
99
- * @param treeId - Id of the tree to get the sibling path from.
100
- * @param leafValue - The leaf value
101
- * @returns The index and sibling path concatenated [index, sibling_path]
198
+ * Fetches the index and sibling path of a leaf at a given block from the note hash tree.
199
+ * @param blockHash - The hash of a block that contains the note hash tree root in which to find the
200
+ * membership witness.
201
+ * @param noteHash - The note hash to find in the note hash tree.
202
+ * @returns The membership witness containing the leaf index and sibling path
102
203
  */
103
- public utilityGetMembershipWitness(blockHash: L2BlockHash, treeId: MerkleTreeId, leafValue: Fr): Promise<Fr[]> {
104
- const treeMembershipService = new TreeMembershipService(this.aztecNode);
105
- return treeMembershipService.getMembershipWitness(blockHash, treeId, leafValue);
204
+ public getNoteHashMembershipWitness(
205
+ blockHash: BlockHash,
206
+ noteHash: Fr,
207
+ ): Promise<MembershipWitness<typeof NOTE_HASH_TREE_HEIGHT> | undefined> {
208
+ return this.#queryWithBlockHashNotAfterAnchor(blockHash, () =>
209
+ this.aztecNode.getNoteHashMembershipWitness(blockHash, noteHash),
210
+ );
211
+ }
212
+
213
+ /**
214
+ * Fetches the index and sibling path of a block hash in the archive tree.
215
+ *
216
+ * Block hashes are the leaves of the archive tree. Each time a new block is added to the chain,
217
+ * its block hash is appended as a new leaf to the archive tree.
218
+ *
219
+ * @param referenceBlockHash - The hash of a block that contains the archive tree root in which to find the membership
220
+ * witness.
221
+ * @param blockHash - The block hash to find in the archive tree.
222
+ * @returns The membership witness containing the leaf index and sibling path
223
+ */
224
+ public getBlockHashMembershipWitness(
225
+ referenceBlockHash: BlockHash,
226
+ blockHash: BlockHash,
227
+ ): Promise<MembershipWitness<typeof ARCHIVE_HEIGHT> | undefined> {
228
+ // Note that we validate that the reference block hash is at or before the anchor block - we don't test the block
229
+ // hash at all. If the block hash did not exist by the reference block hash, then the node will not return the
230
+ // membership witness as there is none.
231
+ return this.#queryWithBlockHashNotAfterAnchor(referenceBlockHash, () =>
232
+ this.aztecNode.getBlockHashMembershipWitness(referenceBlockHash, blockHash),
233
+ );
106
234
  }
107
235
 
108
236
  /**
@@ -111,11 +239,13 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
111
239
  * @param nullifier - Nullifier we try to find witness for.
112
240
  * @returns The nullifier membership witness (if found).
113
241
  */
114
- public async utilityGetNullifierMembershipWitness(
115
- blockHash: L2BlockHash,
242
+ public getNullifierMembershipWitness(
243
+ blockHash: BlockHash,
116
244
  nullifier: Fr,
117
245
  ): Promise<NullifierMembershipWitness | undefined> {
118
- return await this.aztecNode.getNullifierMembershipWitness(blockHash, nullifier);
246
+ return this.#queryWithBlockHashNotAfterAnchor(blockHash, () =>
247
+ this.aztecNode.getNullifierMembershipWitness(blockHash, nullifier),
248
+ );
119
249
  }
120
250
 
121
251
  /**
@@ -127,12 +257,13 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
127
257
  * list structure" of leaves and proving that a lower nullifier is pointing to a bigger next value than the nullifier
128
258
  * we are trying to prove non-inclusion for.
129
259
  */
130
- public async utilityGetLowNullifierMembershipWitness(
131
- blockHash: L2BlockHash,
260
+ public getLowNullifierMembershipWitness(
261
+ blockHash: BlockHash,
132
262
  nullifier: Fr,
133
263
  ): Promise<NullifierMembershipWitness | undefined> {
134
- const treeMembershipService = new TreeMembershipService(this.aztecNode);
135
- return await treeMembershipService.getLowNullifierMembershipWitness(blockHash, nullifier);
264
+ return this.#queryWithBlockHashNotAfterAnchor(blockHash, () =>
265
+ this.aztecNode.getLowNullifierMembershipWitness(blockHash, nullifier),
266
+ );
136
267
  }
137
268
 
138
269
  /**
@@ -141,12 +272,10 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
141
272
  * @param leafSlot - The slot of the public data tree to get the witness for.
142
273
  * @returns - The witness
143
274
  */
144
- public async utilityGetPublicDataWitness(
145
- blockHash: L2BlockHash,
146
- leafSlot: Fr,
147
- ): Promise<PublicDataWitness | undefined> {
148
- const treeMembershipService = new TreeMembershipService(this.aztecNode);
149
- return await treeMembershipService.getPublicDataWitness(blockHash, leafSlot);
275
+ public getPublicDataWitness(blockHash: BlockHash, leafSlot: Fr): Promise<PublicDataWitness | undefined> {
276
+ return this.#queryWithBlockHashNotAfterAnchor(blockHash, () =>
277
+ this.aztecNode.getPublicDataWitness(blockHash, leafSlot),
278
+ );
150
279
  }
151
280
 
152
281
  /**
@@ -154,8 +283,8 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
154
283
  * @param blockNumber - The number of a block of which to get the block header.
155
284
  * @returns Block extracted from a block with block number `blockNumber`.
156
285
  */
157
- public async utilityGetBlockHeader(blockNumber: BlockNumber): Promise<BlockHeader | undefined> {
158
- const anchorBlockNumber = (await this.anchorBlockStore.getBlockHeader()).getBlockNumber();
286
+ public async getBlockHeader(blockNumber: BlockNumber): Promise<BlockHeader | undefined> {
287
+ const anchorBlockNumber = this.anchorBlockHeader.getBlockNumber();
159
288
  if (blockNumber > anchorBlockNumber) {
160
289
  throw new Error(`Block number ${blockNumber} is higher than current block ${anchorBlockNumber}`);
161
290
  }
@@ -165,16 +294,21 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
165
294
  }
166
295
 
167
296
  /**
168
- * Retrieve the complete address associated to a given address.
297
+ * Retrieve the public keys and partial address associated to a given address.
169
298
  * @param account - The account address.
170
- * @returns A complete address associated with the input address.
171
- * @throws An error if the account is not registered in the database.
299
+ * @returns The public keys and partial address, or `undefined` if the account is not registered.
172
300
  */
173
- public utilityGetPublicKeysAndPartialAddress(account: AztecAddress): Promise<CompleteAddress> {
174
- return this.getCompleteAddress(account);
301
+ public async getPublicKeysAndPartialAddress(
302
+ account: AztecAddress,
303
+ ): Promise<{ publicKeys: PublicKeys; partialAddress: PartialAddress } | undefined> {
304
+ const completeAddress = await this.addressStore.getCompleteAddress(account);
305
+ if (!completeAddress) {
306
+ return undefined;
307
+ }
308
+ return { publicKeys: completeAddress.publicKeys, partialAddress: completeAddress.partialAddress };
175
309
  }
176
310
 
177
- protected async getCompleteAddress(account: AztecAddress): Promise<CompleteAddress> {
311
+ protected async getCompleteAddressOrFail(account: AztecAddress): Promise<CompleteAddress> {
178
312
  const completeAddress = await this.addressStore.getCompleteAddress(account);
179
313
  if (!completeAddress) {
180
314
  throw new Error(
@@ -190,11 +324,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
190
324
  * @param address - Address.
191
325
  * @returns A contract instance.
192
326
  */
193
- public utilityGetContractInstance(address: AztecAddress): Promise<ContractInstance> {
194
- return this.getContractInstance(address);
195
- }
196
-
197
- protected async getContractInstance(address: AztecAddress): Promise<ContractInstance> {
327
+ public async getContractInstance(address: AztecAddress): Promise<ContractInstance> {
198
328
  const instance = await this.contractStore.getContractInstance(address);
199
329
  if (!instance) {
200
330
  throw new Error(`No contract instance found for address ${address.toString()}`);
@@ -208,7 +338,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
208
338
  * @param messageHash - Hash of the message to authenticate.
209
339
  * @returns Authentication witness for the requested message hash.
210
340
  */
211
- public utilityGetAuthWitness(messageHash: Fr): Promise<Fr[] | undefined> {
341
+ public getAuthWitness(messageHash: Fr): Promise<Fr[] | undefined> {
212
342
  return Promise.resolve(this.authWitnesses.find(w => w.requestHash.equals(messageHash))?.witness);
213
343
  }
214
344
 
@@ -234,7 +364,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
234
364
  * @param status - The status of notes to fetch.
235
365
  * @returns Array of note data.
236
366
  */
237
- public async utilityGetNotes(
367
+ public async getNotes(
238
368
  owner: AztecAddress | undefined,
239
369
  storageSlot: Fr,
240
370
  numSelects: number,
@@ -251,7 +381,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
251
381
  offset: number,
252
382
  status: NoteStatus,
253
383
  ): Promise<NoteData[]> {
254
- const noteService = new NoteService(this.noteStore, this.aztecNode, this.anchorBlockStore);
384
+ const noteService = new NoteService(this.noteStore, this.aztecNode, this.anchorBlockHeader, this.jobId);
255
385
 
256
386
  const dbNotes = await noteService.getNotes(this.contractAddress, owner, storageSlot, status, this.scopes);
257
387
  return pickNotes<NoteData>(dbNotes, {
@@ -274,30 +404,34 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
274
404
  * @param innerNullifier - The inner nullifier.
275
405
  * @returns A boolean indicating whether the nullifier exists in the tree or not.
276
406
  */
277
- public async utilityCheckNullifierExists(innerNullifier: Fr) {
278
- const nullifier = await siloNullifier(this.contractAddress, innerNullifier!);
279
- const treeMembershipService = new TreeMembershipService(this.aztecNode);
280
- const index = await treeMembershipService.getNullifierIndex(nullifier);
281
- return index !== undefined;
407
+ public async doesNullifierExist(innerNullifier: Fr) {
408
+ const [nullifier, anchorBlockHash] = await Promise.all([
409
+ siloNullifier(this.contractAddress, innerNullifier!),
410
+ this.anchorBlockHeader.hash(),
411
+ ]);
412
+ const [leafIndex] = await this.aztecNode.findLeavesIndexes(anchorBlockHash, MerkleTreeId.NULLIFIER_TREE, [
413
+ nullifier,
414
+ ]);
415
+ return leafIndex?.data !== undefined;
282
416
  }
283
417
 
284
418
  /**
285
- * Fetches a message from the executionStore, given its key.
419
+ * Returns the membership witness of an un-nullified L1 to L2 message.
286
420
  * @param contractAddress - Address of a contract by which the message was emitted.
287
421
  * @param messageHash - Hash of the message.
288
422
  * @param secret - Secret used to compute a nullifier.
289
423
  * @dev Contract address and secret are only used to compute the nullifier to get non-nullified messages
290
424
  * @returns The l1 to l2 membership witness (index of message in the tree and sibling path).
291
425
  */
292
- public async utilityGetL1ToL2MembershipWitness(contractAddress: AztecAddress, messageHash: Fr, secret: Fr) {
293
- const treeMembershipService = new TreeMembershipService(this.aztecNode);
294
- const [messageIndex, siblingPath] = await treeMembershipService.getL1ToL2MembershipWitness(
426
+ public async getL1ToL2MembershipWitness(contractAddress: AztecAddress, messageHash: Fr, secret: Fr) {
427
+ const [messageIndex, siblingPath] = await getNonNullifiedL1ToL2MessageWitness(
428
+ this.aztecNode,
295
429
  contractAddress,
296
430
  messageHash,
297
431
  secret,
432
+ await this.anchorBlockHeader.hash(),
298
433
  );
299
434
 
300
- // Assuming messageIndex is what you intended to use for the index in MessageLoadOracleInputs
301
435
  return new MessageLoadOracleInputs(messageIndex, siblingPath);
302
436
  }
303
437
 
@@ -308,93 +442,194 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
308
442
  * @param startStorageSlot - The starting storage slot.
309
443
  * @param numberOfElements - Number of elements to read from the starting storage slot.
310
444
  */
311
- public async utilityStorageRead(
312
- blockHash: L2BlockHash,
445
+ public getFromPublicStorage(
446
+ blockHash: BlockHash,
313
447
  contractAddress: AztecAddress,
314
448
  startStorageSlot: Fr,
315
449
  numberOfElements: number,
316
450
  ) {
317
- const values = [];
451
+ return this.#queryWithBlockHashNotAfterAnchor(blockHash, async () => {
452
+ const slots = Array(numberOfElements)
453
+ .fill(0)
454
+ .map((_, i) => new Fr(startStorageSlot.value + BigInt(i)));
455
+
456
+ const values = await Promise.all(
457
+ slots.map(storageSlot => this.aztecNode.getPublicStorageAt(blockHash, contractAddress, storageSlot)),
458
+ );
459
+
460
+ this.logger.debug(
461
+ `Oracle storage read: slots=[${slots.map(slot => slot.toString()).join(', ')}] address=${contractAddress.toString()} values=[${values.join(', ')}]`,
462
+ );
463
+
464
+ return values;
465
+ });
466
+ }
318
467
 
319
- // TODO: why do we serialize these requests? This should probably a single call
320
- // Privacy considerations?
321
- for (let i = 0n; i < numberOfElements; i++) {
322
- const storageSlot = new Fr(startStorageSlot.value + i);
323
- const value = await this.aztecNode.getPublicStorageAt(blockHash, contractAddress, storageSlot);
468
+ /**
469
+ * Returns a per-contract logger whose output is prefixed with `contract:<name>(<addrAbbrev>)`.
470
+ */
471
+ async #getContractLogger(): Promise<Logger> {
472
+ if (!this.contractLogger) {
473
+ // Purpose of instanceId is to distinguish logs from different instances of the same component. It makes sense
474
+ // to re-use jobId as instanceId here as executions of different PXE jobs are isolated.
475
+ this.contractLogger = await createContractLogger(
476
+ this.contractAddress,
477
+ addr => this.contractStore.getDebugContractName(addr),
478
+ 'user',
479
+ { instanceId: this.jobId },
480
+ );
481
+ }
482
+ return this.contractLogger;
483
+ }
324
484
 
325
- this.log.debug(
326
- `Oracle storage read: slot=${storageSlot.toString()} address-${contractAddress.toString()} value=${value}`,
485
+ /**
486
+ * Returns a per-contract logger whose output is prefixed with `aztecnr:<name>(<addrAbbrev>)`.
487
+ */
488
+ async #getAztecnrLogger(): Promise<Logger> {
489
+ if (!this.aztecnrLogger) {
490
+ // Purpose of instanceId is to distinguish logs from different instances of the same component. It makes sense
491
+ // to re-use jobId as instanceId here as executions of different PXE jobs are isolated.
492
+ this.aztecnrLogger = await createContractLogger(
493
+ this.contractAddress,
494
+ addr => this.contractStore.getDebugContractName(addr),
495
+ 'aztecnr',
496
+ { instanceId: this.jobId },
327
497
  );
328
- values.push(value);
329
498
  }
330
- return values;
499
+ return this.aztecnrLogger;
331
500
  }
332
501
 
333
- public utilityDebugLog(level: number, message: string, fields: Fr[]): void {
502
+ public async log(level: number, message: string, fields: Fr[]): Promise<void> {
334
503
  if (!LogLevels[level]) {
335
- throw new Error(`Invalid debug log level: ${level}`);
504
+ throw new Error(`Invalid log level: ${level}`);
336
505
  }
337
- const levelName = LogLevels[level];
338
- this.aztecNrDebugLog[levelName](`${applyStringFormatting(message, fields)}`);
506
+
507
+ const { kind, message: strippedMessage } = stripAztecnrLogPrefix(message);
508
+
509
+ const logger = kind == 'aztecnr' ? await this.#getAztecnrLogger() : await this.#getContractLogger();
510
+ logContractMessage(logger, LogLevels[level], strippedMessage, fields);
339
511
  }
340
512
 
341
- public async utilityFetchTaggedLogs(pendingTaggedLogArrayBaseSlot: Fr) {
342
- const logService = new LogService(
513
+ // Deprecated, only kept for backwards compatibility until Alpha v5 rolls out.
514
+ public async getPendingTaggedLogs(pendingTaggedLogArrayBaseSlot: Fr, scope: AztecAddress) {
515
+ const logService = this.#createLogService();
516
+ const logs = await logService.fetchTaggedLogs(this.contractAddress, scope);
517
+ await this.capsuleService.appendToCapsuleArray(
518
+ this.contractAddress,
519
+ pendingTaggedLogArrayBaseSlot,
520
+ logs.map(log => log.toFields()),
521
+ this.jobId,
522
+ scope,
523
+ );
524
+ }
525
+
526
+ /** Fetches pending tagged logs into a freshly allocated ephemeral array and returns its base slot. */
527
+ public async getPendingTaggedLogsV2(scope: AztecAddress): Promise<Fr> {
528
+ const logService = this.#createLogService();
529
+ const logs = await logService.fetchTaggedLogs(this.contractAddress, scope);
530
+ return this.ephemeralArrayService.newArray(logs.map(log => log.toFields()));
531
+ }
532
+
533
+ #createLogService(): LogService {
534
+ return new LogService(
343
535
  this.aztecNode,
344
- this.anchorBlockStore,
536
+ this.anchorBlockHeader,
537
+ this.l2TipsStore,
345
538
  this.keyStore,
346
- this.capsuleStore,
347
539
  this.recipientTaggingStore,
348
540
  this.senderAddressBookStore,
349
541
  this.addressStore,
350
542
  this.jobId,
543
+ this.logger.getBindings(),
351
544
  );
352
-
353
- const noteService = new NoteService(this.noteStore, this.aztecNode, this.anchorBlockStore);
354
-
355
- // It is acceptable to run the following operations in parallel for several reasons:
356
- // 1. syncTaggedLogs does not write to the note store — it only stores the pending tagged logs in a capsule array,
357
- // which is then processed in Noir after this handler returns.
358
- // 2. Even if syncTaggedLogs did write to the note store, it would not cause inconsistent state.
359
- await Promise.all([
360
- logService.syncTaggedLogs(this.contractAddress, pendingTaggedLogArrayBaseSlot, this.scopes),
361
- noteService.syncNoteNullifiers(this.contractAddress),
362
- ]);
363
545
  }
364
546
 
365
547
  /**
366
- * Validates all note and event validation requests enqueued via `enqueue_note_for_validation` and
367
- * `enqueue_event_for_validation`, inserting them into the note database and event store respectively, making them
368
- * queryable via `get_notes` and `getPrivateEvents`.
548
+ * Legacy: validates note/event requests stored in capsule arrays.
369
549
  *
370
- * This automatically clears both validation request queues, so no further work needs to be done by the caller.
371
- * @param contractAddress - The address of the contract that the logs are tagged for.
372
- * @param noteValidationRequestsArrayBaseSlot - The base slot of capsule array containing note validation requests.
373
- * @param eventValidationRequestsArrayBaseSlot - The base slot of capsule array containing event validation requests.
550
+ * Deprecated, only kept for backwards compatibility until Alpha v5 rolls out.
374
551
  */
375
- public async utilityValidateEnqueuedNotesAndEvents(
552
+ public async validateAndStoreEnqueuedNotesAndEvents(
376
553
  contractAddress: AztecAddress,
377
554
  noteValidationRequestsArrayBaseSlot: Fr,
378
555
  eventValidationRequestsArrayBaseSlot: Fr,
556
+ maxNotePackedLen: number,
557
+ maxEventSerializedLen: number,
558
+ scope: AztecAddress,
379
559
  ) {
380
560
  // TODO(#10727): allow other contracts to store notes
381
561
  if (!this.contractAddress.equals(contractAddress)) {
382
562
  throw new Error(`Got a note validation request from ${contractAddress}, expected ${this.contractAddress}`);
383
563
  }
384
564
 
385
- // We read all note and event validation requests and process them all concurrently. This makes the process much
386
- // faster as we don't need to wait for the network round-trip.
387
565
  const noteValidationRequests = (
388
- await this.capsuleStore.readCapsuleArray(contractAddress, noteValidationRequestsArrayBaseSlot, this.jobId)
389
- ).map(NoteValidationRequest.fromFields);
566
+ await this.capsuleService.readCapsuleArray(
567
+ contractAddress,
568
+ noteValidationRequestsArrayBaseSlot,
569
+ this.jobId,
570
+ scope,
571
+ )
572
+ ).map(fields => NoteValidationRequest.fromFields(fields, maxNotePackedLen));
390
573
 
391
574
  const eventValidationRequests = (
392
- await this.capsuleStore.readCapsuleArray(contractAddress, eventValidationRequestsArrayBaseSlot, this.jobId)
393
- ).map(EventValidationRequest.fromFields);
575
+ await this.capsuleService.readCapsuleArray(
576
+ contractAddress,
577
+ eventValidationRequestsArrayBaseSlot,
578
+ this.jobId,
579
+ scope,
580
+ )
581
+ ).map(fields => EventValidationRequest.fromFields(fields, maxEventSerializedLen));
394
582
 
395
- const noteService = new NoteService(this.noteStore, this.aztecNode, this.anchorBlockStore);
583
+ await this.#processValidationRequests(noteValidationRequests, eventValidationRequests, scope);
584
+
585
+ await this.capsuleService.setCapsuleArray(
586
+ contractAddress,
587
+ noteValidationRequestsArrayBaseSlot,
588
+ [],
589
+ this.jobId,
590
+ scope,
591
+ );
592
+ await this.capsuleService.setCapsuleArray(
593
+ contractAddress,
594
+ eventValidationRequestsArrayBaseSlot,
595
+ [],
596
+ this.jobId,
597
+ scope,
598
+ );
599
+ }
600
+
601
+ public async validateAndStoreEnqueuedNotesAndEventsV2(
602
+ noteValidationRequestsArrayBaseSlot: Fr,
603
+ eventValidationRequestsArrayBaseSlot: Fr,
604
+ maxNotePackedLen: number,
605
+ maxEventSerializedLen: number,
606
+ scope: AztecAddress,
607
+ ) {
608
+ const noteValidationRequests = this.ephemeralArrayService
609
+ .readArrayAt(noteValidationRequestsArrayBaseSlot)
610
+ .map(fields => NoteValidationRequest.fromFields(fields, maxNotePackedLen));
611
+
612
+ const eventValidationRequests = this.ephemeralArrayService
613
+ .readArrayAt(eventValidationRequestsArrayBaseSlot)
614
+ .map(fields => EventValidationRequest.fromFields(fields, maxEventSerializedLen));
615
+
616
+ await this.#processValidationRequests(noteValidationRequests, eventValidationRequests, scope);
617
+ }
618
+
619
+ /**
620
+ * Dispatches note and event validation requests to the service layer.
621
+ *
622
+ * This function is an auxiliary to support legacy (capsule backed) and new (ephemeral array backed) versions of the
623
+ * `validateAndStoreEnqueuedNotesAndEvents` oracle.
624
+ */
625
+ async #processValidationRequests(
626
+ noteValidationRequests: NoteValidationRequest[],
627
+ eventValidationRequests: EventValidationRequest[],
628
+ scope: AztecAddress,
629
+ ) {
630
+ const noteService = new NoteService(this.noteStore, this.aztecNode, this.anchorBlockHeader, this.jobId);
396
631
  const noteStorePromises = noteValidationRequests.map(request =>
397
- noteService.storeNote(
632
+ noteService.validateAndStoreNote(
398
633
  request.contractAddress,
399
634
  request.owner,
400
635
  request.storageSlot,
@@ -404,34 +639,31 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
404
639
  request.noteHash,
405
640
  request.nullifier,
406
641
  request.txHash,
407
- request.recipient,
642
+ scope,
408
643
  ),
409
644
  );
410
645
 
411
- const eventService = new EventService(this.anchorBlockStore, this.aztecNode, this.privateEventStore, this.jobId);
646
+ const eventService = new EventService(this.anchorBlockHeader, this.aztecNode, this.privateEventStore, this.jobId);
412
647
  const eventStorePromises = eventValidationRequests.map(request =>
413
- eventService.storeEvent(
648
+ eventService.validateAndStoreEvent(
414
649
  request.contractAddress,
415
650
  request.eventTypeId,
416
651
  request.randomness,
417
652
  request.serializedEvent,
418
653
  request.eventCommitment,
419
654
  request.txHash,
420
- request.recipient,
655
+ scope,
421
656
  ),
422
657
  );
423
658
 
424
659
  await Promise.all([...noteStorePromises, ...eventStorePromises]);
425
-
426
- // Requests are cleared once we're done.
427
- await this.capsuleStore.setCapsuleArray(contractAddress, noteValidationRequestsArrayBaseSlot, [], this.jobId);
428
- await this.capsuleStore.setCapsuleArray(contractAddress, eventValidationRequestsArrayBaseSlot, [], this.jobId);
429
660
  }
430
661
 
431
- public async utilityBulkRetrieveLogs(
662
+ public async getLogsByTag(
432
663
  contractAddress: AztecAddress,
433
664
  logRetrievalRequestsArrayBaseSlot: Fr,
434
665
  logRetrievalResponsesArrayBaseSlot: Fr,
666
+ scope: AztecAddress,
435
667
  ) {
436
668
  // TODO(#10727): allow other contracts to process partial notes
437
669
  if (!this.contractAddress.equals(contractAddress)) {
@@ -441,100 +673,250 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
441
673
  // We read all log retrieval requests and process them all concurrently. This makes the process much faster as we
442
674
  // don't need to wait for the network round-trip.
443
675
  const logRetrievalRequests = (
444
- await this.capsuleStore.readCapsuleArray(contractAddress, logRetrievalRequestsArrayBaseSlot, this.jobId)
676
+ await this.capsuleService.readCapsuleArray(contractAddress, logRetrievalRequestsArrayBaseSlot, this.jobId, scope)
445
677
  ).map(LogRetrievalRequest.fromFields);
446
678
 
447
- const logService = new LogService(
448
- this.aztecNode,
449
- this.anchorBlockStore,
450
- this.keyStore,
451
- this.capsuleStore,
452
- this.recipientTaggingStore,
453
- this.senderAddressBookStore,
454
- this.addressStore,
455
- this.jobId,
456
- );
457
-
458
- const maybeLogRetrievalResponses = await logService.bulkRetrieveLogs(logRetrievalRequests);
679
+ const logService = this.#createLogService();
680
+ const maybeLogRetrievalResponses = await logService.fetchLogsByTag(contractAddress, logRetrievalRequests);
459
681
 
460
682
  // Requests are cleared once we're done.
461
- await this.capsuleStore.setCapsuleArray(contractAddress, logRetrievalRequestsArrayBaseSlot, [], this.jobId);
683
+ await this.capsuleService.setCapsuleArray(
684
+ contractAddress,
685
+ logRetrievalRequestsArrayBaseSlot,
686
+ [],
687
+ this.jobId,
688
+ scope,
689
+ );
462
690
 
463
691
  // The responses are stored as Option<LogRetrievalResponse> in a second CapsuleArray.
464
- await this.capsuleStore.setCapsuleArray(
692
+ await this.capsuleService.setCapsuleArray(
465
693
  contractAddress,
466
694
  logRetrievalResponsesArrayBaseSlot,
467
695
  maybeLogRetrievalResponses.map(LogRetrievalResponse.toSerializedOption),
468
696
  this.jobId,
697
+ scope,
469
698
  );
470
699
  }
471
700
 
472
- public utilityStoreCapsule(contractAddress: AztecAddress, slot: Fr, capsule: Fr[]): Promise<void> {
701
+ public async getLogsByTagV2(requestArrayBaseSlot: Fr): Promise<Fr> {
702
+ const logRetrievalRequests = this.ephemeralArrayService
703
+ .readArrayAt(requestArrayBaseSlot)
704
+ .map(LogRetrievalRequest.fromFields);
705
+ const logService = this.#createLogService();
706
+
707
+ const maybeLogRetrievalResponses = await logService.fetchLogsByTag(this.contractAddress, logRetrievalRequests);
708
+
709
+ return this.ephemeralArrayService.newArray(maybeLogRetrievalResponses.map(LogRetrievalResponse.toSerializedOption));
710
+ }
711
+
712
+ // Deprecated, only kept for backwards compatibility until Alpha v5 rolls out.
713
+ public async getMessageContextsByTxHash(
714
+ contractAddress: AztecAddress,
715
+ messageContextRequestsArrayBaseSlot: Fr,
716
+ messageContextResponsesArrayBaseSlot: Fr,
717
+ scope: AztecAddress,
718
+ ) {
719
+ try {
720
+ if (!this.contractAddress.equals(contractAddress)) {
721
+ throw new Error(`Got a message context request from ${contractAddress}, expected ${this.contractAddress}`);
722
+ }
723
+
724
+ // TODO(@mverzilli): this is a prime example of where using an ephemeral array would make much more sense, we don't
725
+ // need scopes here, we just need a bit of shared memory to cross boundaries between Noir and TS.
726
+ // At the same time, we don't want to allow any global scope access other than where backwards compatibility
727
+ // forces us to. Hence we need the scope here to be artificial.
728
+ const requestCapsules = await this.capsuleService.readCapsuleArray(
729
+ contractAddress,
730
+ messageContextRequestsArrayBaseSlot,
731
+ this.jobId,
732
+ scope,
733
+ );
734
+
735
+ const txHashes = requestCapsules.map((fields, i) => {
736
+ if (fields.length !== 1) {
737
+ throw new Error(
738
+ `Malformed message context request at index ${i}: expected 1 field (tx hash), got ${fields.length}`,
739
+ );
740
+ }
741
+ return fields[0];
742
+ });
743
+
744
+ const maybeMessageContexts = await this.messageContextService.getMessageContextsByTxHash(
745
+ txHashes,
746
+ this.anchorBlockHeader.getBlockNumber(),
747
+ );
748
+
749
+ // Leave response in response capsule array.
750
+ await this.capsuleService.setCapsuleArray(
751
+ contractAddress,
752
+ messageContextResponsesArrayBaseSlot,
753
+ maybeMessageContexts.map(MessageContext.toSerializedOption),
754
+ this.jobId,
755
+ scope,
756
+ );
757
+ } finally {
758
+ await this.capsuleService.setCapsuleArray(
759
+ contractAddress,
760
+ messageContextRequestsArrayBaseSlot,
761
+ [],
762
+ this.jobId,
763
+ scope,
764
+ );
765
+ }
766
+ }
767
+
768
+ /** Reads tx hash requests from an ephemeral array, resolves their contexts, and returns the response slot. */
769
+ public async getMessageContextsByTxHashV2(requestArrayBaseSlot: Fr): Promise<Fr> {
770
+ const requestFields = this.ephemeralArrayService.readArrayAt(requestArrayBaseSlot);
771
+
772
+ const txHashes = requestFields.map((fields, i) => {
773
+ if (fields.length !== 1) {
774
+ throw new Error(
775
+ `Malformed message context request at index ${i}: expected 1 field (tx hash), got ${fields.length}`,
776
+ );
777
+ }
778
+ return fields[0];
779
+ });
780
+
781
+ const maybeMessageContexts = await this.messageContextService.getMessageContextsByTxHash(
782
+ txHashes,
783
+ this.anchorBlockHeader.getBlockNumber(),
784
+ );
785
+
786
+ return this.ephemeralArrayService.newArray(maybeMessageContexts.map(MessageContext.toSerializedOption));
787
+ }
788
+
789
+ public setCapsule(contractAddress: AztecAddress, slot: Fr, capsule: Fr[], scope: AztecAddress): void {
473
790
  if (!contractAddress.equals(this.contractAddress)) {
474
791
  // TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
475
792
  throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
476
793
  }
477
- this.capsuleStore.storeCapsule(this.contractAddress, slot, capsule, this.jobId);
478
- return Promise.resolve();
794
+ this.capsuleService.setCapsule(contractAddress, slot, capsule, this.jobId, scope);
479
795
  }
480
796
 
481
- public async utilityLoadCapsule(contractAddress: AztecAddress, slot: Fr): Promise<Fr[] | null> {
797
+ public getCapsule(contractAddress: AztecAddress, slot: Fr, scope: AztecAddress): Promise<Fr[] | null> {
482
798
  if (!contractAddress.equals(this.contractAddress)) {
483
799
  // TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
484
800
  throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
485
801
  }
486
- return (
487
- // TODO(#12425): On the following line, the pertinent capsule gets overshadowed by the transient one. Tackle this.
488
- this.capsules.find(c => c.contractAddress.equals(contractAddress) && c.storageSlot.equals(slot))?.data ??
489
- (await this.capsuleStore.loadCapsule(this.contractAddress, slot, this.jobId))
490
- );
802
+ return this.capsuleService.getCapsule(contractAddress, slot, this.jobId, scope, this.capsules);
491
803
  }
492
804
 
493
- public utilityDeleteCapsule(contractAddress: AztecAddress, slot: Fr): Promise<void> {
805
+ public deleteCapsule(contractAddress: AztecAddress, slot: Fr, scope: AztecAddress): void {
494
806
  if (!contractAddress.equals(this.contractAddress)) {
495
807
  // TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
496
808
  throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
497
809
  }
498
- this.capsuleStore.deleteCapsule(this.contractAddress, slot, this.jobId);
499
- return Promise.resolve();
810
+ this.capsuleService.deleteCapsule(contractAddress, slot, this.jobId, scope);
500
811
  }
501
812
 
502
- public utilityCopyCapsule(
813
+ public copyCapsule(
503
814
  contractAddress: AztecAddress,
504
815
  srcSlot: Fr,
505
816
  dstSlot: Fr,
506
817
  numEntries: number,
818
+ scope: AztecAddress,
507
819
  ): Promise<void> {
508
820
  if (!contractAddress.equals(this.contractAddress)) {
509
821
  // TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
510
822
  throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
511
823
  }
512
- return this.capsuleStore.copyCapsule(this.contractAddress, srcSlot, dstSlot, numEntries, this.jobId);
824
+ return this.capsuleService.copyCapsule(contractAddress, srcSlot, dstSlot, numEntries, this.jobId, scope);
825
+ }
826
+
827
+ /**
828
+ * Clears cached sync state for a contract for a set of scopes, forcing re-sync on the next query so that newly
829
+ * stored notes or events are discovered.
830
+ */
831
+ public setContractSyncCacheInvalid(contractAddress: AztecAddress, scopes: AztecAddress[]): void {
832
+ if (!contractAddress.equals(this.contractAddress)) {
833
+ throw new Error(`Contract ${this.contractAddress} cannot invalidate sync cache of ${contractAddress}`);
834
+ }
835
+ this.contractSyncService.invalidateContractForScopes(contractAddress, scopes);
513
836
  }
514
837
 
515
838
  // TODO(#11849): consider replacing this oracle with a pure Noir implementation of aes decryption.
516
- public utilityAes128Decrypt(ciphertext: Buffer, iv: Buffer, symKey: Buffer): Promise<Buffer> {
839
+ public decryptAes128(ciphertext: Buffer, iv: Buffer, symKey: Buffer): Promise<Buffer> {
517
840
  const aes128 = new Aes128();
518
841
  return aes128.decryptBufferCBC(ciphertext, iv, symKey);
519
842
  }
520
843
 
521
844
  /**
522
- * Retrieves the shared secret for a given address and ephemeral public key.
845
+ * Retrieves the app-siloed shared secret for a given address and ephemeral public key.
523
846
  * @param address - The address to get the secret for.
524
847
  * @param ephPk - The ephemeral public key to get the secret for.
525
- * @returns The secret for the given address.
848
+ * @param contractAddress - The contract address for app-siloing (validated against execution context).
849
+ * @returns The app-siloed shared secret as a Field.
526
850
  */
527
- public utilityGetSharedSecret(address: AztecAddress, ephPk: Point): Promise<Point> {
528
- return this.getSharedSecret(address, ephPk);
529
- }
530
-
531
- protected async getSharedSecret(address: AztecAddress, ephPk: Point): Promise<Point> {
532
- // TODO(#12656): return an app-siloed secret
533
- const recipientCompleteAddress = await this.getCompleteAddress(address);
851
+ public async getSharedSecret(address: AztecAddress, ephPk: Point, contractAddress: AztecAddress): Promise<Fr> {
852
+ if (!contractAddress.equals(this.contractAddress)) {
853
+ throw new Error(
854
+ `getSharedSecret called with contract address ${contractAddress}, expected ${this.contractAddress}`,
855
+ );
856
+ }
857
+ const recipientCompleteAddress = await this.getCompleteAddressOrFail(address);
534
858
  const ivskM = await this.keyStore.getMasterSecretKey(
535
859
  recipientCompleteAddress.publicKeys.masterIncomingViewingPublicKey,
536
860
  );
537
861
  const addressSecret = await computeAddressSecret(await recipientCompleteAddress.getPreaddress(), ivskM);
538
- return deriveEcdhSharedSecret(addressSecret, ephPk);
862
+ return deriveAppSiloedSharedSecret(addressSecret, ephPk, this.contractAddress);
863
+ }
864
+
865
+ public pushEphemeral(slot: Fr, elements: Fr[]): number {
866
+ return this.ephemeralArrayService.push(slot, elements);
867
+ }
868
+
869
+ public popEphemeral(slot: Fr): Fr[] {
870
+ return this.ephemeralArrayService.pop(slot);
871
+ }
872
+
873
+ public getEphemeral(slot: Fr, index: number): Fr[] {
874
+ return this.ephemeralArrayService.get(slot, index);
875
+ }
876
+
877
+ public setEphemeral(slot: Fr, index: number, elements: Fr[]): void {
878
+ this.ephemeralArrayService.set(slot, index, elements);
879
+ }
880
+
881
+ public getEphemeralLen(slot: Fr): number {
882
+ return this.ephemeralArrayService.len(slot);
883
+ }
884
+
885
+ public removeEphemeral(slot: Fr, index: number): void {
886
+ this.ephemeralArrayService.remove(slot, index);
887
+ }
888
+
889
+ public clearEphemeral(slot: Fr): void {
890
+ this.ephemeralArrayService.clear(slot);
891
+ }
892
+
893
+ public emitOffchainEffect(data: Fr[]): Promise<void> {
894
+ this.offchainEffects.push({ data, contractAddress: this.contractAddress });
895
+ return Promise.resolve();
896
+ }
897
+
898
+ /** Returns offchain effects collected during execution. */
899
+ public getOffchainEffects(): OffchainEffect[] {
900
+ return this.offchainEffects;
901
+ }
902
+
903
+ /** Runs a query concurrently with a validation that the block hash is not ahead of the anchor block. */
904
+ async #queryWithBlockHashNotAfterAnchor<T>(blockHash: BlockHash, query: () => Promise<T>): Promise<T> {
905
+ const [response] = await Promise.all([
906
+ query(),
907
+ (async () => {
908
+ const header = await this.aztecNode.getBlockHeader(blockHash);
909
+ if (!header) {
910
+ throw new Error(`Could not find block header for block hash ${blockHash}`);
911
+ }
912
+
913
+ if (header.getBlockNumber() > this.anchorBlockHeader.getBlockNumber()) {
914
+ throw new Error(
915
+ `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()}).`,
916
+ );
917
+ }
918
+ })(),
919
+ ]);
920
+ return response;
539
921
  }
540
922
  }