@aztec/pxe 3.0.0-canary.a9708bd → 3.0.0-devnet.20251212

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 (264) hide show
  1. package/README.md +5 -5
  2. package/dest/bin/check_oracle_version.d.ts +1 -1
  3. package/dest/bin/check_oracle_version.js +110 -10
  4. package/dest/config/index.d.ts +9 -17
  5. package/dest/config/index.d.ts.map +1 -1
  6. package/dest/config/index.js +10 -16
  7. package/dest/config/package_info.d.ts +1 -1
  8. package/dest/config/package_info.js +1 -1
  9. package/dest/contract_function_simulator/contract_function_simulator.d.ts +6 -6
  10. package/dest/contract_function_simulator/contract_function_simulator.d.ts.map +1 -1
  11. package/dest/contract_function_simulator/contract_function_simulator.js +97 -42
  12. package/dest/contract_function_simulator/execution_data_provider.d.ts +40 -57
  13. package/dest/contract_function_simulator/execution_data_provider.d.ts.map +1 -1
  14. package/dest/contract_function_simulator/execution_note_cache.d.ts +11 -9
  15. package/dest/contract_function_simulator/execution_note_cache.d.ts.map +1 -1
  16. package/dest/contract_function_simulator/execution_note_cache.js +28 -17
  17. package/dest/contract_function_simulator/execution_tagging_index_cache.d.ts +16 -0
  18. package/dest/contract_function_simulator/execution_tagging_index_cache.d.ts.map +1 -0
  19. package/dest/contract_function_simulator/execution_tagging_index_cache.js +26 -0
  20. package/dest/contract_function_simulator/hashed_values_cache.d.ts +2 -2
  21. package/dest/contract_function_simulator/hashed_values_cache.d.ts.map +1 -1
  22. package/dest/contract_function_simulator/index.d.ts +4 -2
  23. package/dest/contract_function_simulator/index.d.ts.map +1 -1
  24. package/dest/contract_function_simulator/index.js +2 -1
  25. package/dest/contract_function_simulator/noir-structs/event_validation_request.d.ts +2 -2
  26. package/dest/contract_function_simulator/noir-structs/event_validation_request.d.ts.map +1 -1
  27. package/dest/contract_function_simulator/noir-structs/log_retrieval_request.d.ts +2 -2
  28. package/dest/contract_function_simulator/noir-structs/log_retrieval_request.d.ts.map +1 -1
  29. package/dest/contract_function_simulator/noir-structs/log_retrieval_response.d.ts +3 -3
  30. package/dest/contract_function_simulator/noir-structs/log_retrieval_response.d.ts.map +1 -1
  31. package/dest/contract_function_simulator/noir-structs/log_retrieval_response.js +8 -4
  32. package/dest/contract_function_simulator/noir-structs/note_validation_request.d.ts +6 -3
  33. package/dest/contract_function_simulator/noir-structs/note_validation_request.d.ts.map +1 -1
  34. package/dest/contract_function_simulator/noir-structs/note_validation_request.js +12 -3
  35. package/dest/contract_function_simulator/noir-structs/utility_context.d.ts +22 -0
  36. package/dest/contract_function_simulator/noir-structs/utility_context.d.ts.map +1 -0
  37. package/dest/contract_function_simulator/noir-structs/utility_context.js +33 -0
  38. package/dest/contract_function_simulator/oracle/index.d.ts +2 -2
  39. package/dest/contract_function_simulator/oracle/index.d.ts.map +1 -1
  40. package/dest/contract_function_simulator/oracle/index.js +1 -1
  41. package/dest/contract_function_simulator/oracle/interfaces.d.ts +104 -0
  42. package/dest/contract_function_simulator/oracle/interfaces.d.ts.map +1 -0
  43. package/dest/contract_function_simulator/oracle/interfaces.js +4 -0
  44. package/dest/contract_function_simulator/oracle/message_load_oracle_inputs.d.ts +2 -4
  45. package/dest/contract_function_simulator/oracle/message_load_oracle_inputs.d.ts.map +1 -1
  46. package/dest/contract_function_simulator/oracle/message_load_oracle_inputs.js +1 -1
  47. package/dest/contract_function_simulator/oracle/note_packing_utils.d.ts +10 -4
  48. package/dest/contract_function_simulator/oracle/note_packing_utils.d.ts.map +1 -1
  49. package/dest/contract_function_simulator/oracle/note_packing_utils.js +10 -5
  50. package/dest/contract_function_simulator/oracle/oracle.d.ts +17 -15
  51. package/dest/contract_function_simulator/oracle/oracle.d.ts.map +1 -1
  52. package/dest/contract_function_simulator/oracle/oracle.js +101 -81
  53. package/dest/contract_function_simulator/oracle/private_execution.d.ts +6 -5
  54. package/dest/contract_function_simulator/oracle/private_execution.d.ts.map +1 -1
  55. package/dest/contract_function_simulator/oracle/private_execution.js +7 -16
  56. package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts +34 -22
  57. package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts.map +1 -1
  58. package/dest/contract_function_simulator/oracle/private_execution_oracle.js +89 -25
  59. package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts +23 -33
  60. package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts.map +1 -1
  61. package/dest/contract_function_simulator/oracle/utility_execution_oracle.js +38 -42
  62. package/dest/contract_function_simulator/pick_notes.d.ts +2 -2
  63. package/dest/contract_function_simulator/pick_notes.d.ts.map +1 -1
  64. package/dest/contract_function_simulator/pick_notes.js +1 -1
  65. package/dest/contract_function_simulator/proxied_contract_data_source.d.ts +1 -1
  66. package/dest/contract_function_simulator/proxied_contract_data_source.d.ts.map +1 -1
  67. package/dest/contract_function_simulator/proxied_node.d.ts +1 -1
  68. package/dest/contract_function_simulator/proxied_node.d.ts.map +1 -1
  69. package/dest/contract_function_simulator/pxe_oracle_interface.d.ts +34 -68
  70. package/dest/contract_function_simulator/pxe_oracle_interface.d.ts.map +1 -1
  71. package/dest/contract_function_simulator/pxe_oracle_interface.js +220 -208
  72. package/dest/entrypoints/client/bundle/index.d.ts +4 -2
  73. package/dest/entrypoints/client/bundle/index.d.ts.map +1 -1
  74. package/dest/entrypoints/client/bundle/index.js +2 -1
  75. package/dest/entrypoints/client/bundle/utils.d.ts +9 -9
  76. package/dest/entrypoints/client/bundle/utils.d.ts.map +1 -1
  77. package/dest/entrypoints/client/bundle/utils.js +12 -12
  78. package/dest/entrypoints/client/lazy/index.d.ts +4 -2
  79. package/dest/entrypoints/client/lazy/index.d.ts.map +1 -1
  80. package/dest/entrypoints/client/lazy/index.js +2 -1
  81. package/dest/entrypoints/client/lazy/utils.d.ts +8 -8
  82. package/dest/entrypoints/client/lazy/utils.d.ts.map +1 -1
  83. package/dest/entrypoints/client/lazy/utils.js +11 -11
  84. package/dest/entrypoints/pxe_creation_options.d.ts +3 -1
  85. package/dest/entrypoints/pxe_creation_options.d.ts.map +1 -1
  86. package/dest/entrypoints/server/index.d.ts +4 -2
  87. package/dest/entrypoints/server/index.d.ts.map +1 -1
  88. package/dest/entrypoints/server/index.js +2 -1
  89. package/dest/entrypoints/server/utils.d.ts +5 -24
  90. package/dest/entrypoints/server/utils.d.ts.map +1 -1
  91. package/dest/entrypoints/server/utils.js +9 -41
  92. package/dest/error_enriching.d.ts +11 -0
  93. package/dest/error_enriching.d.ts.map +1 -0
  94. package/dest/{pxe_service/error_enriching.js → error_enriching.js} +3 -0
  95. package/dest/events/index.d.ts +2 -0
  96. package/dest/events/index.d.ts.map +1 -0
  97. package/dest/events/index.js +1 -0
  98. package/dest/events/private_event_filter_validator.d.ts +8 -0
  99. package/dest/events/private_event_filter_validator.d.ts.map +1 -0
  100. package/dest/events/private_event_filter_validator.js +39 -0
  101. package/dest/oracle_version.d.ts +3 -3
  102. package/dest/oracle_version.js +2 -2
  103. package/dest/private_kernel/hints/build_private_kernel_reset_private_inputs.d.ts +3 -3
  104. package/dest/private_kernel/hints/build_private_kernel_reset_private_inputs.d.ts.map +1 -1
  105. package/dest/private_kernel/hints/build_private_kernel_reset_private_inputs.js +7 -7
  106. package/dest/private_kernel/hints/compute_tx_include_by_timestamp.d.ts +1 -1
  107. package/dest/private_kernel/hints/compute_tx_include_by_timestamp.js +6 -6
  108. package/dest/private_kernel/hints/index.d.ts +1 -1
  109. package/dest/private_kernel/index.d.ts +1 -1
  110. package/dest/private_kernel/private_kernel_execution_prover.d.ts +9 -2
  111. package/dest/private_kernel/private_kernel_execution_prover.d.ts.map +1 -1
  112. package/dest/private_kernel/private_kernel_execution_prover.js +38 -32
  113. package/dest/private_kernel/private_kernel_oracle.d.ts +3 -2
  114. package/dest/private_kernel/private_kernel_oracle.d.ts.map +1 -1
  115. package/dest/private_kernel/private_kernel_oracle_impl.d.ts +8 -7
  116. package/dest/private_kernel/private_kernel_oracle_impl.d.ts.map +1 -1
  117. package/dest/pxe.d.ts +240 -0
  118. package/dest/pxe.d.ts.map +1 -0
  119. package/dest/{pxe_service/pxe_service.js → pxe.js} +227 -241
  120. package/dest/storage/address_data_provider/address_data_provider.d.ts +2 -4
  121. package/dest/storage/address_data_provider/address_data_provider.d.ts.map +1 -1
  122. package/dest/storage/address_data_provider/address_data_provider.js +0 -3
  123. package/dest/storage/address_data_provider/index.d.ts +1 -1
  124. package/dest/storage/capsule_data_provider/capsule_data_provider.d.ts +3 -5
  125. package/dest/storage/capsule_data_provider/capsule_data_provider.d.ts.map +1 -1
  126. package/dest/storage/capsule_data_provider/capsule_data_provider.js +1 -5
  127. package/dest/storage/capsule_data_provider/index.d.ts +1 -1
  128. package/dest/storage/contract_data_provider/contract_data_provider.d.ts +6 -17
  129. package/dest/storage/contract_data_provider/contract_data_provider.d.ts.map +1 -1
  130. package/dest/storage/contract_data_provider/contract_data_provider.js +0 -15
  131. package/dest/storage/contract_data_provider/index.d.ts +1 -1
  132. package/dest/storage/contract_data_provider/private_functions_tree.d.ts +1 -1
  133. package/dest/storage/contract_data_provider/private_functions_tree.d.ts.map +1 -1
  134. package/dest/storage/contract_data_provider/private_functions_tree.js +1 -1
  135. package/dest/storage/index.d.ts +1 -2
  136. package/dest/storage/index.d.ts.map +1 -1
  137. package/dest/storage/index.js +0 -1
  138. package/dest/storage/metadata.d.ts +1 -1
  139. package/dest/storage/note_data_provider/index.d.ts +2 -2
  140. package/dest/storage/note_data_provider/index.d.ts.map +1 -1
  141. package/dest/storage/note_data_provider/index.js +1 -1
  142. package/dest/storage/note_data_provider/note_data_provider.d.ts +75 -11
  143. package/dest/storage/note_data_provider/note_data_provider.d.ts.map +1 -1
  144. package/dest/storage/note_data_provider/note_data_provider.js +143 -81
  145. package/dest/storage/private_event_data_provider/private_event_data_provider.d.ts +31 -17
  146. package/dest/storage/private_event_data_provider/private_event_data_provider.d.ts.map +1 -1
  147. package/dest/storage/private_event_data_provider/private_event_data_provider.js +47 -28
  148. package/dest/storage/sync_data_provider/index.d.ts +1 -1
  149. package/dest/storage/sync_data_provider/sync_data_provider.d.ts +4 -5
  150. package/dest/storage/sync_data_provider/sync_data_provider.d.ts.map +1 -1
  151. package/dest/storage/sync_data_provider/sync_data_provider.js +0 -3
  152. package/dest/storage/tagging_data_provider/index.d.ts +1 -1
  153. package/dest/storage/tagging_data_provider/tagging_data_provider.d.ts +29 -7
  154. package/dest/storage/tagging_data_provider/tagging_data_provider.d.ts.map +1 -1
  155. package/dest/storage/tagging_data_provider/tagging_data_provider.js +46 -39
  156. package/dest/synchronizer/index.d.ts +1 -1
  157. package/dest/synchronizer/synchronizer.d.ts +3 -2
  158. package/dest/synchronizer/synchronizer.d.ts.map +1 -1
  159. package/dest/synchronizer/synchronizer.js +4 -4
  160. package/dest/tagging/constants.d.ts +2 -0
  161. package/dest/tagging/constants.d.ts.map +1 -0
  162. package/dest/tagging/constants.js +2 -0
  163. package/dest/tagging/index.d.ts +7 -0
  164. package/dest/tagging/index.d.ts.map +1 -0
  165. package/dest/tagging/index.js +5 -0
  166. package/dest/tagging/siloed_tag.d.ts +14 -0
  167. package/dest/tagging/siloed_tag.d.ts.map +1 -0
  168. package/dest/tagging/siloed_tag.js +20 -0
  169. package/dest/tagging/tag.d.ts +12 -0
  170. package/dest/tagging/tag.d.ts.map +1 -0
  171. package/dest/tagging/tag.js +17 -0
  172. package/dest/tagging/utils.d.ts +18 -0
  173. package/dest/tagging/utils.d.ts.map +1 -0
  174. package/dest/tagging/utils.js +24 -0
  175. package/package.json +22 -24
  176. package/src/bin/check_oracle_version.ts +134 -10
  177. package/src/config/index.ts +18 -32
  178. package/src/config/package_info.ts +1 -1
  179. package/src/contract_function_simulator/contract_function_simulator.ts +151 -62
  180. package/src/contract_function_simulator/execution_data_provider.ts +47 -65
  181. package/src/contract_function_simulator/execution_note_cache.ts +33 -17
  182. package/src/contract_function_simulator/execution_tagging_index_cache.ts +32 -0
  183. package/src/contract_function_simulator/hashed_values_cache.ts +1 -1
  184. package/src/contract_function_simulator/index.ts +3 -1
  185. package/src/contract_function_simulator/noir-structs/event_validation_request.ts +1 -1
  186. package/src/contract_function_simulator/noir-structs/log_retrieval_request.ts +1 -1
  187. package/src/contract_function_simulator/noir-structs/log_retrieval_response.ts +10 -5
  188. package/src/contract_function_simulator/noir-structs/note_validation_request.ts +14 -2
  189. package/src/contract_function_simulator/noir-structs/utility_context.ts +42 -0
  190. package/src/contract_function_simulator/oracle/index.ts +1 -1
  191. package/src/contract_function_simulator/oracle/interfaces.ts +176 -0
  192. package/src/contract_function_simulator/oracle/message_load_oracle_inputs.ts +1 -1
  193. package/src/contract_function_simulator/oracle/note_packing_utils.ts +21 -5
  194. package/src/contract_function_simulator/oracle/oracle.ts +135 -80
  195. package/src/contract_function_simulator/oracle/private_execution.ts +10 -17
  196. package/src/contract_function_simulator/oracle/private_execution_oracle.ts +123 -49
  197. package/src/contract_function_simulator/oracle/utility_execution_oracle.ts +68 -80
  198. package/src/contract_function_simulator/pick_notes.ts +1 -1
  199. package/src/contract_function_simulator/pxe_oracle_interface.ts +291 -271
  200. package/src/entrypoints/client/bundle/index.ts +3 -1
  201. package/src/entrypoints/client/bundle/utils.ts +15 -23
  202. package/src/entrypoints/client/lazy/index.ts +3 -1
  203. package/src/entrypoints/client/lazy/utils.ts +14 -22
  204. package/src/entrypoints/pxe_creation_options.ts +2 -0
  205. package/src/entrypoints/server/index.ts +3 -1
  206. package/src/entrypoints/server/utils.ts +12 -56
  207. package/src/{pxe_service/error_enriching.ts → error_enriching.ts} +5 -1
  208. package/src/events/index.ts +1 -0
  209. package/src/events/private_event_filter_validator.ts +47 -0
  210. package/src/oracle_version.ts +2 -2
  211. package/src/private_kernel/hints/build_private_kernel_reset_private_inputs.ts +5 -9
  212. package/src/private_kernel/hints/compute_tx_include_by_timestamp.ts +6 -6
  213. package/src/private_kernel/private_kernel_execution_prover.ts +51 -43
  214. package/src/private_kernel/private_kernel_oracle.ts +2 -1
  215. package/src/private_kernel/private_kernel_oracle_impl.ts +4 -3
  216. package/src/{pxe_service/pxe_service.ts → pxe.ts} +256 -308
  217. package/src/storage/address_data_provider/address_data_provider.ts +1 -7
  218. package/src/storage/capsule_data_provider/capsule_data_provider.ts +2 -12
  219. package/src/storage/contract_data_provider/contract_data_provider.ts +4 -27
  220. package/src/storage/contract_data_provider/private_functions_tree.ts +1 -1
  221. package/src/storage/index.ts +0 -1
  222. package/src/storage/note_data_provider/index.ts +1 -1
  223. package/src/storage/note_data_provider/note_data_provider.ts +171 -109
  224. package/src/storage/private_event_data_provider/private_event_data_provider.ts +69 -41
  225. package/src/storage/sync_data_provider/sync_data_provider.ts +3 -8
  226. package/src/storage/tagging_data_provider/tagging_data_provider.ts +52 -55
  227. package/src/synchronizer/synchronizer.ts +4 -4
  228. package/src/tagging/constants.ts +2 -0
  229. package/src/tagging/index.ts +6 -0
  230. package/src/tagging/siloed_tag.ts +22 -0
  231. package/src/tagging/tag.ts +16 -0
  232. package/src/tagging/utils.ts +31 -0
  233. package/dest/bin/index.d.ts +0 -3
  234. package/dest/bin/index.d.ts.map +0 -1
  235. package/dest/bin/index.js +0 -48
  236. package/dest/contract_function_simulator/oracle/typed_oracle.d.ts +0 -87
  237. package/dest/contract_function_simulator/oracle/typed_oracle.d.ts.map +0 -1
  238. package/dest/contract_function_simulator/oracle/typed_oracle.js +0 -146
  239. package/dest/contract_function_simulator/tagging_utils.d.ts +0 -17
  240. package/dest/contract_function_simulator/tagging_utils.d.ts.map +0 -1
  241. package/dest/contract_function_simulator/tagging_utils.js +0 -23
  242. package/dest/pxe_service/error_enriching.d.ts +0 -11
  243. package/dest/pxe_service/error_enriching.d.ts.map +0 -1
  244. package/dest/pxe_service/index.d.ts +0 -3
  245. package/dest/pxe_service/index.d.ts.map +0 -1
  246. package/dest/pxe_service/index.js +0 -2
  247. package/dest/pxe_service/pxe_service.d.ts +0 -100
  248. package/dest/pxe_service/pxe_service.d.ts.map +0 -1
  249. package/dest/storage/data_provider.d.ts +0 -4
  250. package/dest/storage/data_provider.d.ts.map +0 -1
  251. package/dest/storage/data_provider.js +0 -1
  252. package/dest/storage/note_data_provider/note_dao.d.ts +0 -100
  253. package/dest/storage/note_data_provider/note_dao.d.ts.map +0 -1
  254. package/dest/storage/note_data_provider/note_dao.js +0 -102
  255. package/dest/test/pxe_test_suite.d.ts +0 -3
  256. package/dest/test/pxe_test_suite.d.ts.map +0 -1
  257. package/dest/test/pxe_test_suite.js +0 -97
  258. package/src/bin/index.ts +0 -62
  259. package/src/contract_function_simulator/oracle/typed_oracle.ts +0 -289
  260. package/src/contract_function_simulator/tagging_utils.ts +0 -32
  261. package/src/pxe_service/index.ts +0 -2
  262. package/src/storage/data_provider.ts +0 -3
  263. package/src/storage/note_data_provider/note_dao.ts +0 -154
  264. package/src/test/pxe_test_suite.ts +0 -113
@@ -1,23 +1,18 @@
1
1
  import type { L1_TO_L2_MSG_TREE_HEIGHT } from '@aztec/constants';
2
2
  import { timesParallel } from '@aztec/foundation/collection';
3
- import { Fr, Point } from '@aztec/foundation/fields';
3
+ import { Fr } from '@aztec/foundation/curves/bn254';
4
+ import { Point } from '@aztec/foundation/curves/grumpkin';
4
5
  import { createLogger } from '@aztec/foundation/log';
5
6
  import type { KeyStore } from '@aztec/key-store';
6
- import {
7
- EventSelector,
8
- type FunctionArtifactWithContractName,
9
- FunctionSelector,
10
- getFunctionArtifact,
11
- } from '@aztec/stdlib/abi';
7
+ import { EventSelector, type FunctionArtifactWithContractName, FunctionSelector } from '@aztec/stdlib/abi';
12
8
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
13
- import type { InBlock, L2Block, L2BlockNumber } from '@aztec/stdlib/block';
9
+ import type { BlockParameter, DataInBlock, L2Block } from '@aztec/stdlib/block';
14
10
  import type { CompleteAddress, ContractInstance } from '@aztec/stdlib/contract';
15
11
  import { computeUniqueNoteHash, siloNoteHash, siloNullifier, siloPrivateLog } from '@aztec/stdlib/hash';
16
12
  import { type AztecNode, MAX_RPC_LEN } from '@aztec/stdlib/interfaces/client';
17
13
  import type { KeyValidationRequest } from '@aztec/stdlib/kernel';
18
- import { computeAddressSecret, computeAppTaggingSecret } from '@aztec/stdlib/keys';
14
+ import { computeAddressSecret } from '@aztec/stdlib/keys';
19
15
  import {
20
- IndexedTaggingSecret,
21
16
  PendingTaggedLog,
22
17
  PrivateLogWithTxData,
23
18
  PublicLog,
@@ -27,10 +22,10 @@ import {
27
22
  } from '@aztec/stdlib/logs';
28
23
  import { getNonNullifiedL1ToL2MessageWitness } from '@aztec/stdlib/messaging';
29
24
  import { Note, type NoteStatus } from '@aztec/stdlib/note';
25
+ import { NoteDao } from '@aztec/stdlib/note';
30
26
  import { MerkleTreeId, type NullifierMembershipWitness, PublicDataWitness } from '@aztec/stdlib/trees';
31
27
  import type { BlockHeader } from '@aztec/stdlib/tx';
32
28
  import { TxHash } from '@aztec/stdlib/tx';
33
- import type { UInt64 } from '@aztec/stdlib/types';
34
29
 
35
30
  import type { ExecutionDataProvider, ExecutionStats } from '../contract_function_simulator/execution_data_provider.js';
36
31
  import { MessageLoadOracleInputs } from '../contract_function_simulator/oracle/message_load_oracle_inputs.js';
@@ -38,17 +33,23 @@ import { ORACLE_VERSION } from '../oracle_version.js';
38
33
  import type { AddressDataProvider } from '../storage/address_data_provider/address_data_provider.js';
39
34
  import type { CapsuleDataProvider } from '../storage/capsule_data_provider/capsule_data_provider.js';
40
35
  import type { ContractDataProvider } from '../storage/contract_data_provider/contract_data_provider.js';
41
- import { NoteDao } from '../storage/note_data_provider/note_dao.js';
42
36
  import type { NoteDataProvider } from '../storage/note_data_provider/note_data_provider.js';
43
37
  import type { PrivateEventDataProvider } from '../storage/private_event_data_provider/private_event_data_provider.js';
44
38
  import type { SyncDataProvider } from '../storage/sync_data_provider/sync_data_provider.js';
45
39
  import type { TaggingDataProvider } from '../storage/tagging_data_provider/tagging_data_provider.js';
40
+ import {
41
+ DirectionalAppTaggingSecret,
42
+ SiloedTag,
43
+ Tag,
44
+ WINDOW_HALF_SIZE,
45
+ getInitialIndexesMap,
46
+ getPreTagsForTheWindow,
47
+ } from '../tagging/index.js';
46
48
  import { EventValidationRequest } from './noir-structs/event_validation_request.js';
47
49
  import { LogRetrievalRequest } from './noir-structs/log_retrieval_request.js';
48
50
  import { LogRetrievalResponse } from './noir-structs/log_retrieval_response.js';
49
51
  import { NoteValidationRequest } from './noir-structs/note_validation_request.js';
50
52
  import type { ProxiedNode } from './proxied_node.js';
51
- import { WINDOW_HALF_SIZE, getIndexedTaggingSecretsForTheWindow, getInitialIndexesMap } from './tagging_utils.js';
52
53
 
53
54
  /**
54
55
  * A data layer that provides and stores information needed for simulating/proving a transaction.
@@ -76,7 +77,7 @@ export class PXEOracleInterface implements ExecutionDataProvider {
76
77
  if (!completeAddress) {
77
78
  throw new Error(
78
79
  `No public key registered for address ${account}.
79
- Register it by calling pxe.addAccount(...).\nSee docs for context: https://docs.aztec.network/developers/reference/debugging/aztecnr-errors#simulation-error-no-public-key-registered-for-address-0x0-register-it-by-calling-pxeregisterrecipient-or-pxeregisteraccount`,
80
+ Register it by calling pxe.addAccount(...).\nSee docs for context: https://docs.aztec.network/developers/resources/debugging/aztecnr-errors#simulation-error-no-public-key-registered-for-address-0x0-register-it-by-calling-pxeregisterrecipient-or-pxeregisteraccount`,
80
81
  );
81
82
  }
82
83
  return completeAddress;
@@ -90,23 +91,34 @@ export class PXEOracleInterface implements ExecutionDataProvider {
90
91
  return instance;
91
92
  }
92
93
 
93
- async getNotes(contractAddress: AztecAddress, storageSlot: Fr, status: NoteStatus, scopes?: AztecAddress[]) {
94
+ async getNotes(
95
+ contractAddress: AztecAddress,
96
+ owner: AztecAddress | undefined,
97
+ storageSlot: Fr,
98
+ status: NoteStatus,
99
+ scopes?: AztecAddress[],
100
+ ) {
94
101
  const noteDaos = await this.noteDataProvider.getNotes({
95
102
  contractAddress,
103
+ owner,
96
104
  storageSlot,
97
105
  status,
98
106
  scopes,
99
107
  });
100
- return noteDaos.map(({ contractAddress, storageSlot, noteNonce, note, noteHash, siloedNullifier, index }) => ({
101
- contractAddress,
102
- storageSlot,
103
- noteNonce,
104
- note,
105
- noteHash,
106
- siloedNullifier,
107
- // PXE can use this index to get full MembershipWitness
108
- index,
109
- }));
108
+ return noteDaos.map(
109
+ ({ contractAddress, owner, storageSlot, randomness, noteNonce, note, noteHash, siloedNullifier, index }) => ({
110
+ contractAddress,
111
+ owner,
112
+ storageSlot,
113
+ randomness,
114
+ noteNonce,
115
+ note,
116
+ noteHash,
117
+ siloedNullifier,
118
+ // PXE can use this index to get full MembershipWitness
119
+ index,
120
+ }),
121
+ );
110
122
  }
111
123
 
112
124
  async getFunctionArtifact(
@@ -124,18 +136,6 @@ export class PXEOracleInterface implements ExecutionDataProvider {
124
136
  };
125
137
  }
126
138
 
127
- async getFunctionArtifactByName(
128
- contractAddress: AztecAddress,
129
- functionName: string,
130
- ): Promise<FunctionArtifactWithContractName | undefined> {
131
- const instance = await this.contractDataProvider.getContractInstance(contractAddress);
132
- if (!instance) {
133
- return;
134
- }
135
- const artifact = await this.contractDataProvider.getContractArtifact(instance.currentContractClassId);
136
- return artifact && getFunctionArtifact(artifact, functionName);
137
- }
138
-
139
139
  /**
140
140
  * Fetches a message from the db, given its key.
141
141
  * @param contractAddress - Address of a contract by which the message was emitted.
@@ -164,12 +164,12 @@ export class PXEOracleInterface implements ExecutionDataProvider {
164
164
  return await this.#findLeafIndex('latest', MerkleTreeId.NULLIFIER_TREE, nullifier);
165
165
  }
166
166
 
167
- async #findLeafIndex(blockNumber: L2BlockNumber, treeId: MerkleTreeId, leafValue: Fr): Promise<bigint | undefined> {
167
+ async #findLeafIndex(blockNumber: BlockParameter, treeId: MerkleTreeId, leafValue: Fr): Promise<bigint | undefined> {
168
168
  const [leafIndex] = await this.aztecNode.findLeavesIndexes(blockNumber, treeId, [leafValue]);
169
169
  return leafIndex?.data;
170
170
  }
171
171
 
172
- public async getMembershipWitness(blockNumber: number, treeId: MerkleTreeId, leafValue: Fr): Promise<Fr[]> {
172
+ public async getMembershipWitness(blockNumber: BlockParameter, treeId: MerkleTreeId, leafValue: Fr): Promise<Fr[]> {
173
173
  const witness = await this.#tryGetMembershipWitness(blockNumber, treeId, leafValue);
174
174
  if (!witness) {
175
175
  throw new Error(`Leaf value ${leafValue} not found in tree ${MerkleTreeId[treeId]} at block ${blockNumber}`);
@@ -177,7 +177,11 @@ export class PXEOracleInterface implements ExecutionDataProvider {
177
177
  return witness;
178
178
  }
179
179
 
180
- async #tryGetMembershipWitness(blockNumber: number, treeId: MerkleTreeId, value: Fr): Promise<Fr[] | undefined> {
180
+ async #tryGetMembershipWitness(
181
+ blockNumber: BlockParameter,
182
+ treeId: MerkleTreeId,
183
+ value: Fr,
184
+ ): Promise<Fr[] | undefined> {
181
185
  switch (treeId) {
182
186
  case MerkleTreeId.NULLIFIER_TREE:
183
187
  return (await this.aztecNode.getNullifierMembershipWitness(blockNumber, value))?.withoutPreimage().toFields();
@@ -193,43 +197,53 @@ export class PXEOracleInterface implements ExecutionDataProvider {
193
197
  }
194
198
 
195
199
  public async getNullifierMembershipWitnessAtLatestBlock(nullifier: Fr) {
196
- return this.getNullifierMembershipWitness(await this.getBlockNumber(), nullifier);
200
+ const blockNumber = (await this.getAnchorBlockHeader()).globalVariables.blockNumber;
201
+ return this.getNullifierMembershipWitness(blockNumber, nullifier);
197
202
  }
198
203
 
199
204
  public getNullifierMembershipWitness(
200
- blockNumber: number,
205
+ blockNumber: BlockParameter,
201
206
  nullifier: Fr,
202
207
  ): Promise<NullifierMembershipWitness | undefined> {
203
208
  return this.aztecNode.getNullifierMembershipWitness(blockNumber, nullifier);
204
209
  }
205
210
 
206
- public getLowNullifierMembershipWitness(
207
- blockNumber: number,
211
+ public async getLowNullifierMembershipWitness(
212
+ blockNumber: BlockParameter,
208
213
  nullifier: Fr,
209
214
  ): Promise<NullifierMembershipWitness | undefined> {
215
+ const header = await this.getAnchorBlockHeader();
216
+ if (blockNumber !== 'latest' && blockNumber > header.globalVariables.blockNumber) {
217
+ throw new Error(`Block number ${blockNumber} is higher than current block ${header.globalVariables.blockNumber}`);
218
+ }
210
219
  return this.aztecNode.getLowNullifierMembershipWitness(blockNumber, nullifier);
211
220
  }
212
221
 
213
- public async getBlock(blockNumber: number): Promise<L2Block | undefined> {
222
+ public async getBlock(blockNumber: BlockParameter): Promise<L2Block | undefined> {
223
+ const header = await this.getAnchorBlockHeader();
224
+ if (blockNumber !== 'latest' && blockNumber > header.globalVariables.blockNumber) {
225
+ throw new Error(`Block number ${blockNumber} is higher than current block ${header.globalVariables.blockNumber}`);
226
+ }
214
227
  return await this.aztecNode.getBlock(blockNumber);
215
228
  }
216
229
 
217
- public async getPublicDataWitness(blockNumber: number, leafSlot: Fr): Promise<PublicDataWitness | undefined> {
230
+ public async getPublicDataWitness(blockNumber: BlockParameter, leafSlot: Fr): Promise<PublicDataWitness | undefined> {
231
+ const header = await this.getAnchorBlockHeader();
232
+ if (blockNumber !== 'latest' && blockNumber > header.globalVariables.blockNumber) {
233
+ throw new Error(`Block number ${blockNumber} is higher than current block ${header.globalVariables.blockNumber}`);
234
+ }
218
235
  return await this.aztecNode.getPublicDataWitness(blockNumber, leafSlot);
219
236
  }
220
237
 
221
- public async getPublicStorageAt(blockNumber: number, contract: AztecAddress, slot: Fr): Promise<Fr> {
238
+ public async getPublicStorageAt(blockNumber: BlockParameter, contract: AztecAddress, slot: Fr): Promise<Fr> {
239
+ const header = await this.getAnchorBlockHeader();
240
+ if (blockNumber !== 'latest' && blockNumber > header.globalVariables.blockNumber) {
241
+ throw new Error(`Block number ${blockNumber} is higher than current block ${header.globalVariables.blockNumber}`);
242
+ }
222
243
  return await this.aztecNode.getPublicStorageAt(blockNumber, contract, slot);
223
244
  }
224
245
 
225
- /**
226
- * Retrieve the latest block header synchronized by the PXE.
227
- * @dev This structure is fed into the circuits simulator and is used to prove against certain historical roots.
228
- * @returns The BlockHeader object.
229
- * TODO: I think this naming is bad as it's not the latest block header synched by the node, but the latest block
230
- * header synchronized by the PXE. Would rename this to something like getSynchronizedBlockHeader().
231
- */
232
- getBlockHeader(): Promise<BlockHeader> {
246
+ getAnchorBlockHeader(): Promise<BlockHeader> {
233
247
  return this.syncDataProvider.getBlockHeader();
234
248
  }
235
249
 
@@ -239,42 +253,6 @@ export class PXEOracleInterface implements ExecutionDataProvider {
239
253
  }
240
254
  }
241
255
 
242
- /**
243
- * Fetches the latest block number synchronized by the node.
244
- * @returns The block number.
245
- */
246
- public async getBlockNumber(): Promise<number> {
247
- return await this.aztecNode.getBlockNumber();
248
- }
249
-
250
- /**
251
- * Fetches the timestamp of the latest block synchronized by the node.
252
- * @returns The timestamp.
253
- */
254
- public async getTimestamp(): Promise<UInt64> {
255
- const latestBlockHeader = await this.aztecNode.getBlockHeader();
256
- if (!latestBlockHeader) {
257
- throw new Error('Latest block header not found when getting timestamp');
258
- }
259
- return latestBlockHeader.globalVariables.timestamp;
260
- }
261
-
262
- /**
263
- * Fetches the current chain id.
264
- * @returns The chain id.
265
- */
266
- public async getChainId(): Promise<number> {
267
- return await this.aztecNode.getChainId();
268
- }
269
-
270
- /**
271
- * Fetches the current version.
272
- * @returns The version.
273
- */
274
- public async getVersion(): Promise<number> {
275
- return await this.aztecNode.getVersion();
276
- }
277
-
278
256
  public getDebugFunctionName(contractAddress: AztecAddress, selector: FunctionSelector): Promise<string> {
279
257
  return this.contractDataProvider.getDebugFunctionName(contractAddress, selector);
280
258
  }
@@ -289,74 +267,43 @@ export class PXEOracleInterface implements ExecutionDataProvider {
289
267
  return this.taggingDataProvider.getSenderAddresses();
290
268
  }
291
269
 
292
- /**
293
- * Returns the tagging secret for a given sender and recipient pair. For this to work, the ivsk_m of the sender must be known.
294
- * Includes the next index to be used used for tagging with this secret.
295
- * @param contractAddress - The contract address to silo the secret for
296
- * @param sender - The address sending the note
297
- * @param recipient - The address receiving the note
298
- * @returns An indexed tagging secret that can be used to tag notes.
299
- */
300
- public async getIndexedTaggingSecretAsSender(
301
- contractAddress: AztecAddress,
302
- sender: AztecAddress,
303
- recipient: AztecAddress,
304
- ): Promise<IndexedTaggingSecret> {
305
- await this.syncTaggedLogsAsSender(contractAddress, sender, recipient);
306
-
307
- const appTaggingSecret = await this.#calculateAppTaggingSecret(contractAddress, sender, recipient);
308
- const [index] = await this.taggingDataProvider.getTaggingSecretsIndexesAsSender([appTaggingSecret], sender);
309
-
310
- return new IndexedTaggingSecret(appTaggingSecret, index);
270
+ public getLastUsedIndexAsSender(secret: DirectionalAppTaggingSecret): Promise<number | undefined> {
271
+ return this.taggingDataProvider.getLastUsedIndexesAsSender(secret);
311
272
  }
312
273
 
313
- /**
314
- * Increments the tagging secret for a given sender and recipient pair. For this to work, the ivsk_m of the sender must be known.
315
- * @param contractAddress - The contract address to silo the secret for
316
- * @param sender - The address sending the note
317
- * @param recipient - The address receiving the note
318
- */
319
- public async incrementAppTaggingSecretIndexAsSender(
274
+ public async calculateDirectionalAppTaggingSecret(
320
275
  contractAddress: AztecAddress,
321
276
  sender: AztecAddress,
322
277
  recipient: AztecAddress,
323
- ): Promise<void> {
324
- const secret = await this.#calculateAppTaggingSecret(contractAddress, sender, recipient);
325
- const contractName = await this.contractDataProvider.getDebugContractName(contractAddress);
326
- this.log.debug(`Incrementing app tagging secret at ${contractName}(${contractAddress})`, {
327
- secret,
328
- sender,
278
+ ) {
279
+ const senderCompleteAddress = await this.getCompleteAddress(sender);
280
+ const senderIvsk = await this.keyStore.getMasterIncomingViewingSecretKey(sender);
281
+ return DirectionalAppTaggingSecret.compute(
282
+ senderCompleteAddress,
283
+ senderIvsk,
329
284
  recipient,
330
- contractName,
331
285
  contractAddress,
332
- });
333
-
334
- const [index] = await this.taggingDataProvider.getTaggingSecretsIndexesAsSender([secret], sender);
335
- await this.taggingDataProvider.setTaggingSecretsIndexesAsSender(
336
- [new IndexedTaggingSecret(secret, index + 1)],
337
- sender,
286
+ recipient,
338
287
  );
339
288
  }
340
289
 
341
- async #calculateAppTaggingSecret(contractAddress: AztecAddress, sender: AztecAddress, recipient: AztecAddress) {
342
- const senderCompleteAddress = await this.getCompleteAddress(sender);
343
- const senderIvsk = await this.keyStore.getMasterIncomingViewingSecretKey(sender);
344
- return computeAppTaggingSecret(senderCompleteAddress, senderIvsk, recipient, contractAddress);
345
- }
346
-
347
290
  /**
348
- * Returns the indexed tagging secrets for a given recipient and all the senders in the address book
291
+ * Returns the last used tagging indexes along with the directional app tagging secrets for a given recipient and all
292
+ * the senders in the address book.
349
293
  * This method should be exposed as an oracle call to allow aztec.nr to perform the orchestration
350
294
  * of the syncTaggedLogs and processTaggedLogs methods. However, it is not possible to do so at the moment,
351
295
  * so we're keeping it private for now.
352
296
  * @param contractAddress - The contract address to silo the secret for
353
297
  * @param recipient - The address receiving the notes
354
- * @returns A list of indexed tagging secrets
298
+ * @returns A list of directional app tagging secrets along with the last used tagging indexes. If the corresponding
299
+ * secret was never used, the index is undefined.
300
+ * TODO(benesjan): The naming here is broken as the function name does not reflect the return type. Fix when associating
301
+ * indexes with tx hash.
355
302
  */
356
- async #getIndexedTaggingSecretsForSenders(
303
+ async #getLastUsedTaggingIndexesForSenders(
357
304
  contractAddress: AztecAddress,
358
305
  recipient: AztecAddress,
359
- ): Promise<IndexedTaggingSecret[]> {
306
+ ): Promise<{ secret: DirectionalAppTaggingSecret; index: number | undefined }[]> {
360
307
  const recipientCompleteAddress = await this.getCompleteAddress(recipient);
361
308
  const recipientIvsk = await this.keyStore.getMasterIncomingViewingSecretKey(recipient);
362
309
 
@@ -366,29 +313,36 @@ export class PXEOracleInterface implements ExecutionDataProvider {
366
313
  ...(await this.taggingDataProvider.getSenderAddresses()),
367
314
  ...(await this.keyStore.getAccounts()),
368
315
  ].filter((address, index, self) => index === self.findIndex(otherAddress => otherAddress.equals(address)));
369
- const appTaggingSecrets = await Promise.all(
370
- senders.map(contact =>
371
- computeAppTaggingSecret(recipientCompleteAddress, recipientIvsk, contact, contractAddress),
372
- ),
316
+ const secrets = await Promise.all(
317
+ senders.map(contact => {
318
+ return DirectionalAppTaggingSecret.compute(
319
+ recipientCompleteAddress,
320
+ recipientIvsk,
321
+ contact,
322
+ contractAddress,
323
+ recipient,
324
+ );
325
+ }),
373
326
  );
374
- const indexes = await this.taggingDataProvider.getTaggingSecretsIndexesAsRecipient(appTaggingSecrets, recipient);
375
- return appTaggingSecrets.map((secret, i) => new IndexedTaggingSecret(secret, indexes[i]));
327
+ const indexes = await this.taggingDataProvider.getLastUsedIndexesAsRecipient(secrets);
328
+ if (indexes.length !== secrets.length) {
329
+ throw new Error('Indexes and directional app tagging secrets have different lengths');
330
+ }
331
+
332
+ return secrets.map((secret, i) => ({
333
+ secret,
334
+ index: indexes[i],
335
+ }));
376
336
  }
377
337
 
378
- /**
379
- * Updates the local index of the shared tagging secret of a sender / recipient pair
380
- * if a log with a larger index is found from the node.
381
- * @param contractAddress - The address of the contract that the logs are tagged for
382
- * @param sender - The address of the sender, we must know the sender's ivsk_m.
383
- * @param recipient - The address of the recipient.
384
- */
385
338
  public async syncTaggedLogsAsSender(
339
+ secret: DirectionalAppTaggingSecret,
386
340
  contractAddress: AztecAddress,
387
- sender: AztecAddress,
388
- recipient: AztecAddress,
389
341
  ): Promise<void> {
390
- const appTaggingSecret = await this.#calculateAppTaggingSecret(contractAddress, sender, recipient);
391
- const [oldIndex] = await this.taggingDataProvider.getTaggingSecretsIndexesAsSender([appTaggingSecret], sender);
342
+ const lastUsedIndex = await this.taggingDataProvider.getLastUsedIndexesAsSender(secret);
343
+ // If lastUsedIndex is undefined, we've never used this secret, so start from 0
344
+ // Otherwise, start from one past the last used index
345
+ const startIndex = lastUsedIndex === undefined ? 0 : lastUsedIndex + 1;
392
346
 
393
347
  // This algorithm works such that:
394
348
  // 1. If we find minimum consecutive empty logs in a window of logs we set the index to the index of the last log
@@ -398,48 +352,51 @@ export class PXEOracleInterface implements ExecutionDataProvider {
398
352
  const MIN_CONSECUTIVE_EMPTY_LOGS = 10;
399
353
  const WINDOW_SIZE = MIN_CONSECUTIVE_EMPTY_LOGS * 2;
400
354
 
401
- let [numConsecutiveEmptyLogs, currentIndex] = [0, oldIndex];
355
+ let [numConsecutiveEmptyLogs, currentIndex] = [0, startIndex];
356
+ let lastFoundLogIndex: number | undefined = undefined;
402
357
  do {
403
358
  // We compute the tags for the current window of indexes
404
- const currentTags = await timesParallel(WINDOW_SIZE, i => {
405
- const indexedAppTaggingSecret = new IndexedTaggingSecret(appTaggingSecret, currentIndex + i);
406
- return indexedAppTaggingSecret.computeSiloedTag(recipient, contractAddress);
359
+ const currentTags = await timesParallel(WINDOW_SIZE, async i => {
360
+ return SiloedTag.compute(await Tag.compute({ secret, index: currentIndex + i }), contractAddress);
407
361
  });
408
362
 
409
363
  // We fetch the logs for the tags
410
- const possibleLogs = await this.#getPrivateLogsByTags(currentTags);
364
+ // TODO: The following conversion is unfortunate and we should most likely just type the #getPrivateLogsByTags
365
+ // to accept SiloedTag[] instead of Fr[]. That would result in a large change so I didn't do it yet.
366
+ const tagsAsFr = currentTags.map(tag => tag.value);
367
+ const possibleLogs = await this.#getPrivateLogsByTags(tagsAsFr);
411
368
 
412
369
  // We find the index of the last log in the window that is not empty
413
- const indexOfLastLog = possibleLogs.findLastIndex(possibleLog => possibleLog.length !== 0);
370
+ const indexOfLastLogWithinArray = possibleLogs.findLastIndex(possibleLog => possibleLog.length !== 0);
414
371
 
415
- if (indexOfLastLog === -1) {
372
+ if (indexOfLastLogWithinArray === -1) {
416
373
  // We haven't found any logs in the current window so we stop looking
417
374
  break;
418
375
  }
419
376
 
420
- // We move the current index to that of the last log we found
421
- currentIndex += indexOfLastLog + 1;
377
+ // We've found logs so we update the last found log index
378
+ lastFoundLogIndex = (lastFoundLogIndex ?? 0) + indexOfLastLogWithinArray;
379
+ // We move the current index to that of the log right after the last found log
380
+ currentIndex = lastFoundLogIndex + 1;
422
381
 
423
382
  // We compute the number of consecutive empty logs we found and repeat the process if we haven't found enough.
424
- numConsecutiveEmptyLogs = WINDOW_SIZE - indexOfLastLog - 1;
383
+ numConsecutiveEmptyLogs = WINDOW_SIZE - indexOfLastLogWithinArray - 1;
425
384
  } while (numConsecutiveEmptyLogs < MIN_CONSECUTIVE_EMPTY_LOGS);
426
385
 
427
386
  const contractName = await this.contractDataProvider.getDebugContractName(contractAddress);
428
- if (currentIndex !== oldIndex) {
429
- await this.taggingDataProvider.setTaggingSecretsIndexesAsSender(
430
- [new IndexedTaggingSecret(appTaggingSecret, currentIndex)],
431
- sender,
432
- );
387
+ if (lastFoundLogIndex !== undefined) {
388
+ // Last found index is defined meaning we have actually found logs so we update the last used index
389
+ await this.taggingDataProvider.setLastUsedIndexesAsSender([{ secret, index: lastFoundLogIndex }]);
433
390
 
434
- this.log.debug(`Syncing logs for sender ${sender} at contract ${contractName}(${contractAddress})`, {
435
- sender,
436
- secret: appTaggingSecret,
391
+ this.log.debug(`Syncing logs for secret ${secret.toString()} at contract ${contractName}(${contractAddress})`, {
437
392
  index: currentIndex,
438
393
  contractName,
439
394
  contractAddress,
440
395
  });
441
396
  } else {
442
- this.log.debug(`No new logs found for sender ${sender} at contract ${contractName}(${contractAddress})`);
397
+ this.log.debug(
398
+ `No new logs found for secret ${secret.toString()} at contract ${contractName}(${contractAddress})`,
399
+ );
443
400
  }
444
401
  }
445
402
 
@@ -471,7 +428,7 @@ export class PXEOracleInterface implements ExecutionDataProvider {
471
428
  const contractName = await this.contractDataProvider.getDebugContractName(contractAddress);
472
429
  for (const recipient of recipients) {
473
430
  // Get all the secrets for the recipient and sender pairs (#9365)
474
- const secrets = await this.#getIndexedTaggingSecretsForSenders(contractAddress, recipient);
431
+ const indexedSecrets = await this.#getLastUsedTaggingIndexesForSenders(contractAddress, recipient);
475
432
 
476
433
  // We fetch logs for a window of indexes in a range:
477
434
  // <latest_log_index - WINDOW_HALF_SIZE, latest_log_index + WINDOW_HALF_SIZE>.
@@ -481,24 +438,35 @@ export class PXEOracleInterface implements ExecutionDataProvider {
481
438
  // for logs the first time we don't receive any logs for a tag, we might never receive anything from that sender again.
482
439
  // Also there's a possibility that we have advanced our index, but the sender has reused it, so we might have missed
483
440
  // some logs. For these reasons, we have to look both back and ahead of the stored index.
484
- let secretsAndWindows = secrets.map(secret => {
485
- return {
486
- appTaggingSecret: secret.appTaggingSecret,
487
- leftMostIndex: Math.max(0, secret.index - WINDOW_HALF_SIZE),
488
- rightMostIndex: secret.index + WINDOW_HALF_SIZE,
489
- };
441
+ let secretsAndWindows = indexedSecrets.map(indexedSecret => {
442
+ if (indexedSecret.index === undefined) {
443
+ return {
444
+ secret: indexedSecret.secret,
445
+ leftMostIndex: 0,
446
+ rightMostIndex: WINDOW_HALF_SIZE,
447
+ };
448
+ } else {
449
+ return {
450
+ secret: indexedSecret.secret,
451
+ leftMostIndex: Math.max(0, indexedSecret.index - WINDOW_HALF_SIZE),
452
+ rightMostIndex: indexedSecret.index + WINDOW_HALF_SIZE,
453
+ };
454
+ }
490
455
  });
491
456
 
492
457
  // As we iterate we store the largest index we have seen for a given secret to later on store it in the db.
493
458
  const newLargestIndexMapToStore: { [k: string]: number } = {};
494
459
 
495
- // The initial/unmodified indexes of the secrets stored in a key-value map where key is the app tagging secret.
496
- const initialIndexesMap = getInitialIndexesMap(secrets);
460
+ // The initial/unmodified indexes of the secrets stored in a key-value map where key is the directional app
461
+ // tagging secret.
462
+ const initialIndexesMap = getInitialIndexesMap(indexedSecrets);
497
463
 
498
464
  while (secretsAndWindows.length > 0) {
499
- const secretsForTheWholeWindow = getIndexedTaggingSecretsForTheWindow(secretsAndWindows);
465
+ const preTagsForTheWholeWindow = getPreTagsForTheWindow(secretsAndWindows);
500
466
  const tagsForTheWholeWindow = await Promise.all(
501
- secretsForTheWholeWindow.map(secret => secret.computeSiloedTag(recipient, contractAddress)),
467
+ preTagsForTheWholeWindow.map(async preTag => {
468
+ return SiloedTag.compute(await Tag.compute(preTag), contractAddress);
469
+ }),
502
470
  );
503
471
 
504
472
  // We store the new largest indexes we find in the iteration in the following map to later on construct
@@ -506,7 +474,10 @@ export class PXEOracleInterface implements ExecutionDataProvider {
506
474
  const newLargestIndexMapForIteration: { [k: string]: number } = {};
507
475
 
508
476
  // Fetch the private logs for the tags and iterate over them
509
- const logsByTags = await this.#getPrivateLogsByTags(tagsForTheWholeWindow);
477
+ // TODO: The following conversion is unfortunate and we should most likely just type the #getPrivateLogsByTags
478
+ // to accept SiloedTag[] instead of Fr[]. That would result in a large change so I didn't do it yet.
479
+ const tagsForTheWholeWindowAsFr = tagsForTheWholeWindow.map(tag => tag.value);
480
+ const logsByTags = await this.#getPrivateLogsByTags(tagsForTheWholeWindowAsFr);
510
481
  this.log.debug(`Found ${logsByTags.filter(logs => logs.length > 0).length} logs as recipient ${recipient}`, {
511
482
  recipient,
512
483
  contractName,
@@ -516,7 +487,7 @@ export class PXEOracleInterface implements ExecutionDataProvider {
516
487
  for (let logIndex = 0; logIndex < logsByTags.length; logIndex++) {
517
488
  const logsByTag = logsByTags[logIndex];
518
489
  if (logsByTag.length > 0) {
519
- // We filter out the logs that are newer than the historical block number of the tx currently being constructed
490
+ // We filter out the logs that are newer than the anchor block number of the tx currently being constructed
520
491
  const filteredLogsByBlockNumber = logsByTag.filter(l => l.blockNumber <= maxBlockNumber);
521
492
 
522
493
  // We store the logs in capsules (to later be obtained in Noir)
@@ -527,25 +498,25 @@ export class PXEOracleInterface implements ExecutionDataProvider {
527
498
  filteredLogsByBlockNumber,
528
499
  );
529
500
 
530
- // We retrieve the indexed tagging secret corresponding to the log as I need that to evaluate whether
501
+ // We retrieve the pre tag corresponding to the log as I need that to evaluate whether
531
502
  // a new largest index have been found.
532
- const secretCorrespondingToLog = secretsForTheWholeWindow[logIndex];
533
- const initialIndex = initialIndexesMap[secretCorrespondingToLog.appTaggingSecret.toString()];
503
+ const preTagCorrespondingToLog = preTagsForTheWholeWindow[logIndex];
504
+ const initialIndex = initialIndexesMap[preTagCorrespondingToLog.secret.toString()];
534
505
 
535
506
  if (
536
- secretCorrespondingToLog.index >= initialIndex &&
537
- (newLargestIndexMapForIteration[secretCorrespondingToLog.appTaggingSecret.toString()] === undefined ||
538
- secretCorrespondingToLog.index >=
539
- newLargestIndexMapForIteration[secretCorrespondingToLog.appTaggingSecret.toString()])
507
+ preTagCorrespondingToLog.index >= initialIndex &&
508
+ (newLargestIndexMapForIteration[preTagCorrespondingToLog.secret.toString()] === undefined ||
509
+ preTagCorrespondingToLog.index >=
510
+ newLargestIndexMapForIteration[preTagCorrespondingToLog.secret.toString()])
540
511
  ) {
541
512
  // We have found a new largest index so we store it for later processing (storing it in the db + fetching
542
513
  // the difference of the window sets of current and the next iteration)
543
- newLargestIndexMapForIteration[secretCorrespondingToLog.appTaggingSecret.toString()] =
544
- secretCorrespondingToLog.index + 1;
514
+ newLargestIndexMapForIteration[preTagCorrespondingToLog.secret.toString()] =
515
+ preTagCorrespondingToLog.index + 1;
545
516
 
546
517
  this.log.debug(
547
518
  `Incrementing index to ${
548
- secretCorrespondingToLog.index + 1
519
+ preTagCorrespondingToLog.index + 1
549
520
  } at contract ${contractName}(${contractAddress})`,
550
521
  );
551
522
  }
@@ -556,21 +527,23 @@ export class PXEOracleInterface implements ExecutionDataProvider {
556
527
  // for. Note that it's very unlikely that a new log from the current window would appear between the iterations
557
528
  // so we fetch the logs only for the difference of the window sets.
558
529
  const newSecretsAndWindows = [];
559
- for (const [appTaggingSecret, newIndex] of Object.entries(newLargestIndexMapForIteration)) {
560
- const secret = secrets.find(secret => secret.appTaggingSecret.toString() === appTaggingSecret);
561
- if (secret) {
530
+ for (const [directionalAppTaggingSecret, newIndex] of Object.entries(newLargestIndexMapForIteration)) {
531
+ const maybeIndexedSecret = indexedSecrets.find(
532
+ indexedSecret => indexedSecret.secret.toString() === directionalAppTaggingSecret,
533
+ );
534
+ if (maybeIndexedSecret) {
562
535
  newSecretsAndWindows.push({
563
- appTaggingSecret: secret.appTaggingSecret,
536
+ secret: maybeIndexedSecret.secret,
564
537
  // We set the left most index to the new index to avoid fetching the same logs again
565
538
  leftMostIndex: newIndex,
566
539
  rightMostIndex: newIndex + WINDOW_HALF_SIZE,
567
540
  });
568
541
 
569
542
  // We store the new largest index in the map to later store it in the db.
570
- newLargestIndexMapToStore[appTaggingSecret] = newIndex;
543
+ newLargestIndexMapToStore[directionalAppTaggingSecret] = newIndex;
571
544
  } else {
572
545
  throw new Error(
573
- `Secret not found for appTaggingSecret ${appTaggingSecret}. This is a bug as it should never happen!`,
546
+ `Secret not found for directionalAppTaggingSecret ${directionalAppTaggingSecret}. This is a bug as it should never happen!`,
574
547
  );
575
548
  }
576
549
  }
@@ -579,12 +552,14 @@ export class PXEOracleInterface implements ExecutionDataProvider {
579
552
  secretsAndWindows = newSecretsAndWindows;
580
553
  }
581
554
 
582
- // At this point we have processed all the logs for the recipient so we store the new largest indexes in the db.
583
- await this.taggingDataProvider.setTaggingSecretsIndexesAsRecipient(
584
- Object.entries(newLargestIndexMapToStore).map(
585
- ([appTaggingSecret, index]) => new IndexedTaggingSecret(Fr.fromHexString(appTaggingSecret), index),
586
- ),
587
- recipient,
555
+ // At this point we have processed all the logs for the recipient so we store the last used indexes in the db.
556
+ // newLargestIndexMapToStore contains "next" indexes to look for (one past the last found), so subtract 1 to get
557
+ // last used.
558
+ await this.taggingDataProvider.setLastUsedIndexesAsRecipient(
559
+ Object.entries(newLargestIndexMapToStore).map(([directionalAppTaggingSecret, index]) => ({
560
+ secret: DirectionalAppTaggingSecret.fromString(directionalAppTaggingSecret),
561
+ index: index - 1,
562
+ })),
588
563
  );
589
564
  }
590
565
  }
@@ -637,7 +612,9 @@ export class PXEOracleInterface implements ExecutionDataProvider {
637
612
  const noteDeliveries = noteValidationRequests.map(request =>
638
613
  this.deliverNote(
639
614
  request.contractAddress,
615
+ request.owner,
640
616
  request.storageSlot,
617
+ request.randomness,
641
618
  request.noteNonce,
642
619
  request.content,
643
620
  request.noteHash,
@@ -667,7 +644,9 @@ export class PXEOracleInterface implements ExecutionDataProvider {
667
644
 
668
645
  async deliverNote(
669
646
  contractAddress: AztecAddress,
647
+ owner: AztecAddress,
670
648
  storageSlot: Fr,
649
+ randomness: Fr,
671
650
  noteNonce: Fr,
672
651
  content: Fr[],
673
652
  noteHash: Fr,
@@ -701,6 +680,20 @@ export class PXEOracleInterface implements ExecutionDataProvider {
701
680
  const uniqueNoteHash = await computeUniqueNoteHash(noteNonce, await siloNoteHash(contractAddress, noteHash));
702
681
  const siloedNullifier = await siloNullifier(contractAddress, nullifier);
703
682
 
683
+ const txEffect = await this.aztecNode.getTxEffect(txHash);
684
+ if (!txEffect) {
685
+ throw new Error(`Could not find tx effect for tx hash ${txHash}`);
686
+ }
687
+
688
+ if (txEffect.l2BlockNumber > syncedBlockNumber) {
689
+ throw new Error(`Could not find tx effect for tx hash ${txHash} as of block number ${syncedBlockNumber}`);
690
+ }
691
+
692
+ const noteInTx = txEffect.data.noteHashes.some(nh => nh.equals(uniqueNoteHash));
693
+ if (!noteInTx) {
694
+ throw new Error(`Note hash ${noteHash} (uniqued as ${uniqueNoteHash}) is not present in tx ${txHash}`);
695
+ }
696
+
704
697
  // We store notes by their index in the global note hash tree, which has the convenient side effect of validating
705
698
  // note existence in said tree. We concurrently also check if the note's nullifier exists, performing all node
706
699
  // queries in a single round-trip.
@@ -718,17 +711,19 @@ export class PXEOracleInterface implements ExecutionDataProvider {
718
711
  const noteDao = new NoteDao(
719
712
  new Note(content),
720
713
  contractAddress,
714
+ owner,
721
715
  storageSlot,
716
+ randomness,
722
717
  noteNonce,
723
718
  noteHash,
724
719
  siloedNullifier,
725
720
  txHash,
726
- uniqueNoteHashTreeIndexInBlock?.l2BlockNumber,
727
- uniqueNoteHashTreeIndexInBlock?.l2BlockHash.toString(),
728
- uniqueNoteHashTreeIndexInBlock?.data,
729
- recipient,
721
+ uniqueNoteHashTreeIndexInBlock.l2BlockNumber,
722
+ uniqueNoteHashTreeIndexInBlock.l2BlockHash.toString(),
723
+ uniqueNoteHashTreeIndexInBlock.data,
730
724
  );
731
725
 
726
+ // The note was found by `recipient`, so we use that as the scope when storing the note.
732
727
  await this.noteDataProvider.addNotes([noteDao], recipient);
733
728
  this.log.verbose('Added note', {
734
729
  index: noteDao.index,
@@ -740,7 +735,7 @@ export class PXEOracleInterface implements ExecutionDataProvider {
740
735
 
741
736
  if (nullifierIndex !== undefined) {
742
737
  const { data: _, ...blockHashAndNum } = nullifierIndex;
743
- await this.noteDataProvider.removeNullifiedNotes([{ data: siloedNullifier, ...blockHashAndNum }], recipient);
738
+ await this.noteDataProvider.applyNullifiers([{ data: siloedNullifier, ...blockHashAndNum }]);
744
739
 
745
740
  this.log.verbose(`Removed just-added note`, {
746
741
  contract: contractAddress,
@@ -791,7 +786,7 @@ export class PXEOracleInterface implements ExecutionDataProvider {
791
786
  privateLog.firstNullifierInTx,
792
787
  );
793
788
  } else {
794
- null;
789
+ return null;
795
790
  }
796
791
  }),
797
792
  );
@@ -813,15 +808,32 @@ export class PXEOracleInterface implements ExecutionDataProvider {
813
808
  content: Fr[],
814
809
  eventCommitment: Fr,
815
810
  txHash: TxHash,
816
- recipient: AztecAddress,
811
+ scope: AztecAddress,
817
812
  ): Promise<void> {
818
813
  // While using 'latest' block number would be fine for private events since they cannot be accessed from Aztec.nr
819
814
  // (and thus we're less concerned about being ahead of the synced block), we use the synced block number to
820
815
  // maintain consistent behavior in the PXE. Additionally, events should never be ahead of the synced block here
821
816
  // since `fetchTaggedLogs` only processes logs up to the synced block.
822
- const syncedBlockNumber = await this.syncDataProvider.getBlockNumber();
817
+ const [syncedBlockNumber, siloedEventCommitment, txEffect] = await Promise.all([
818
+ this.syncDataProvider.getBlockNumber(),
819
+ siloNullifier(contractAddress, eventCommitment),
820
+ this.aztecNode.getTxEffect(txHash),
821
+ ]);
822
+
823
+ if (!txEffect) {
824
+ throw new Error(`Could not find tx effect for tx hash ${txHash}`);
825
+ }
823
826
 
824
- const siloedEventCommitment = await siloNullifier(contractAddress, eventCommitment);
827
+ if (txEffect.l2BlockNumber > syncedBlockNumber) {
828
+ throw new Error(`Could not find tx effect for tx hash ${txHash} as of block number ${syncedBlockNumber}`);
829
+ }
830
+
831
+ const eventInTx = txEffect.data.nullifiers.some(n => n.equals(siloedEventCommitment));
832
+ if (!eventInTx) {
833
+ throw new Error(
834
+ `Event commitment ${eventCommitment} (siloed as ${siloedEventCommitment}) is not present in tx ${txHash}`,
835
+ );
836
+ }
825
837
 
826
838
  const [nullifierIndex] = await this.aztecNode.findLeavesIndexes(syncedBlockNumber, MerkleTreeId.NULLIFIER_TREE, [
827
839
  siloedEventCommitment,
@@ -834,13 +846,16 @@ export class PXEOracleInterface implements ExecutionDataProvider {
834
846
  }
835
847
 
836
848
  return this.privateEventDataProvider.storePrivateEventLog(
837
- contractAddress,
838
- recipient,
839
849
  selector,
840
850
  content,
841
- txHash,
842
851
  Number(nullifierIndex.data), // Index of the event commitment in the nullifier tree
843
- nullifierIndex.l2BlockNumber, // Block in which the event was emitted
852
+ {
853
+ contractAddress,
854
+ scope,
855
+ txHash,
856
+ l2BlockNumber: nullifierIndex.l2BlockNumber, // Block number in which the event was emitted
857
+ l2BlockHash: nullifierIndex.l2BlockHash, // Block hash in which the event was emitted
858
+ },
844
859
  );
845
860
  }
846
861
 
@@ -912,60 +927,65 @@ export class PXEOracleInterface implements ExecutionDataProvider {
912
927
  );
913
928
  }
914
929
 
915
- public async removeNullifiedNotes(contractAddress: AztecAddress) {
930
+ /**
931
+ * Looks for nullifiers of active contract notes and marks them as nullified if a nullifier is found.
932
+ *
933
+ * Fetches notes from the NoteDataProvider and checks which nullifiers are present in the
934
+ * onchain nullifier Merkle tree - up to the latest locally synced block. We use the
935
+ * locally synced block instead of querying the chain's 'latest' block to ensure correctness:
936
+ * notes are only marked nullified once their corresponding nullifier has been included in a
937
+ * block up to which the PXE has synced.
938
+ * This allows recent nullifications to be processed even if the node is not an archive node.
939
+ *
940
+ * @param contractAddress - The contract whose notes should be checked and nullified.
941
+ */
942
+ public async syncNoteNullifiers(contractAddress: AztecAddress) {
916
943
  this.log.verbose('Searching for nullifiers of known notes', { contract: contractAddress });
917
944
 
918
- // We avoid making node queries at 'latest' since we mark notes as nullified only if the corresponding nullifier
919
- // has been included in a block up to which PXE has synced. Note that while this technically results in historical
920
- // queries, we perform it at the latest locally synced block number which *should* be recent enough to be
921
- // available, even for non-archive nodes.
922
945
  const syncedBlockNumber = await this.syncDataProvider.getBlockNumber();
923
946
 
924
- for (const recipient of await this.keyStore.getAccounts()) {
925
- const currentNotesForRecipient = await this.noteDataProvider.getNotes({ contractAddress, recipient });
947
+ const contractNotes = await this.noteDataProvider.getNotes({ contractAddress });
926
948
 
927
- if (currentNotesForRecipient.length === 0) {
928
- // Save a call to the node if there are no notes for the recipient
929
- continue;
930
- }
949
+ if (contractNotes.length === 0) {
950
+ return;
951
+ }
931
952
 
932
- const nullifiersToCheck = currentNotesForRecipient.map(note => note.siloedNullifier);
933
- const nullifierBatches = nullifiersToCheck.reduce(
934
- (acc, nullifier) => {
935
- if (acc[acc.length - 1].length < MAX_RPC_LEN) {
936
- acc[acc.length - 1].push(nullifier);
937
- } else {
938
- acc.push([nullifier]);
939
- }
940
- return acc;
941
- },
942
- [[]] as Fr[][],
943
- );
944
- const nullifierIndexes = (
945
- await Promise.all(
946
- nullifierBatches.map(batch =>
947
- this.aztecNode.findLeavesIndexes(syncedBlockNumber, MerkleTreeId.NULLIFIER_TREE, batch),
948
- ),
949
- )
950
- ).flat();
951
-
952
- const foundNullifiers = nullifiersToCheck
953
- .map((nullifier, i) => {
954
- if (nullifierIndexes[i] !== undefined) {
955
- return { ...nullifierIndexes[i], ...{ data: nullifier } } as InBlock<Fr>;
956
- }
957
- })
958
- .filter(nullifier => nullifier !== undefined) as InBlock<Fr>[];
959
-
960
- const nullifiedNotes = await this.noteDataProvider.removeNullifiedNotes(foundNullifiers, recipient);
961
- nullifiedNotes.forEach(noteDao => {
962
- this.log.verbose(`Removed note for contract ${noteDao.contractAddress} at slot ${noteDao.storageSlot}`, {
963
- contract: noteDao.contractAddress,
964
- slot: noteDao.storageSlot,
965
- nullifier: noteDao.siloedNullifier.toString(),
966
- });
953
+ const nullifiersToCheck = contractNotes.map(note => note.siloedNullifier);
954
+ const nullifierBatches = nullifiersToCheck.reduce(
955
+ (acc, nullifier) => {
956
+ if (acc[acc.length - 1].length < MAX_RPC_LEN) {
957
+ acc[acc.length - 1].push(nullifier);
958
+ } else {
959
+ acc.push([nullifier]);
960
+ }
961
+ return acc;
962
+ },
963
+ [[]] as Fr[][],
964
+ );
965
+ const nullifierIndexes = (
966
+ await Promise.all(
967
+ nullifierBatches.map(batch =>
968
+ this.aztecNode.findLeavesIndexes(syncedBlockNumber, MerkleTreeId.NULLIFIER_TREE, batch),
969
+ ),
970
+ )
971
+ ).flat();
972
+
973
+ const foundNullifiers = nullifiersToCheck
974
+ .map((nullifier, i) => {
975
+ if (nullifierIndexes[i] !== undefined) {
976
+ return { ...nullifierIndexes[i], ...{ data: nullifier } } as DataInBlock<Fr>;
977
+ }
978
+ })
979
+ .filter(nullifier => nullifier !== undefined) as DataInBlock<Fr>[];
980
+
981
+ const nullifiedNotes = await this.noteDataProvider.applyNullifiers(foundNullifiers);
982
+ nullifiedNotes.forEach(noteDao => {
983
+ this.log.verbose(`Removed note for contract ${noteDao.contractAddress} at slot ${noteDao.storageSlot}`, {
984
+ contract: noteDao.contractAddress,
985
+ slot: noteDao.storageSlot,
986
+ nullifier: noteDao.siloedNullifier.toString(),
967
987
  });
968
- }
988
+ });
969
989
  }
970
990
 
971
991
  storeCapsule(contractAddress: AztecAddress, slot: Fr, capsule: Fr[]): Promise<void> {