@aztec/pxe 0.0.1-commit.fcb71a6 → 0.0.1-commit.fffb133c

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 (218) hide show
  1. package/dest/bin/check_oracle_version.js +1 -1
  2. package/dest/block_synchronizer/block_synchronizer.d.ts +10 -4
  3. package/dest/block_synchronizer/block_synchronizer.d.ts.map +1 -1
  4. package/dest/block_synchronizer/block_synchronizer.js +66 -18
  5. package/dest/config/index.d.ts +3 -1
  6. package/dest/config/index.d.ts.map +1 -1
  7. package/dest/config/index.js +17 -0
  8. package/dest/config/package_info.js +1 -1
  9. package/dest/contract_function_simulator/benchmarked_node.d.ts +9 -0
  10. package/dest/contract_function_simulator/benchmarked_node.d.ts.map +1 -0
  11. package/dest/contract_function_simulator/benchmarked_node.js +77 -0
  12. package/dest/contract_function_simulator/contract_function_simulator.d.ts +8 -9
  13. package/dest/contract_function_simulator/contract_function_simulator.d.ts.map +1 -1
  14. package/dest/contract_function_simulator/contract_function_simulator.js +32 -21
  15. package/dest/contract_function_simulator/execution_note_cache.d.ts +18 -9
  16. package/dest/contract_function_simulator/execution_note_cache.d.ts.map +1 -1
  17. package/dest/contract_function_simulator/execution_note_cache.js +45 -28
  18. package/dest/contract_function_simulator/index.d.ts +2 -2
  19. package/dest/contract_function_simulator/index.d.ts.map +1 -1
  20. package/dest/contract_function_simulator/index.js +1 -1
  21. package/dest/contract_function_simulator/noir-structs/event_validation_request.d.ts +4 -3
  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 +6 -3
  24. package/dest/contract_function_simulator/noir-structs/note_validation_request.d.ts +1 -1
  25. package/dest/contract_function_simulator/noir-structs/note_validation_request.js +1 -1
  26. package/dest/contract_function_simulator/noir-structs/utility_context.d.ts +4 -10
  27. package/dest/contract_function_simulator/noir-structs/utility_context.d.ts.map +1 -1
  28. package/dest/contract_function_simulator/noir-structs/utility_context.js +7 -18
  29. package/dest/contract_function_simulator/oracle/interfaces.d.ts +15 -11
  30. package/dest/contract_function_simulator/oracle/interfaces.d.ts.map +1 -1
  31. package/dest/contract_function_simulator/oracle/message_load_oracle_inputs.d.ts +3 -1
  32. package/dest/contract_function_simulator/oracle/message_load_oracle_inputs.d.ts.map +1 -1
  33. package/dest/contract_function_simulator/oracle/note_packing_utils.d.ts +6 -6
  34. package/dest/contract_function_simulator/oracle/note_packing_utils.d.ts.map +1 -1
  35. package/dest/contract_function_simulator/oracle/note_packing_utils.js +8 -8
  36. package/dest/contract_function_simulator/oracle/oracle.d.ts +10 -8
  37. package/dest/contract_function_simulator/oracle/oracle.d.ts.map +1 -1
  38. package/dest/contract_function_simulator/oracle/oracle.js +43 -32
  39. package/dest/contract_function_simulator/oracle/private_execution.d.ts +2 -26
  40. package/dest/contract_function_simulator/oracle/private_execution.d.ts.map +1 -1
  41. package/dest/contract_function_simulator/oracle/private_execution.js +1 -37
  42. package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts +11 -17
  43. package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts.map +1 -1
  44. package/dest/contract_function_simulator/oracle/private_execution_oracle.js +23 -39
  45. package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts +27 -17
  46. package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts.map +1 -1
  47. package/dest/contract_function_simulator/oracle/utility_execution_oracle.js +72 -72
  48. package/dest/contract_sync/index.d.ts +23 -0
  49. package/dest/contract_sync/index.d.ts.map +1 -0
  50. package/dest/contract_sync/index.js +54 -0
  51. package/dest/debug/pxe_debug_utils.d.ts +1 -1
  52. package/dest/debug/pxe_debug_utils.d.ts.map +1 -1
  53. package/dest/debug/pxe_debug_utils.js +3 -2
  54. package/dest/entrypoints/client/bundle/utils.d.ts +1 -1
  55. package/dest/entrypoints/client/bundle/utils.d.ts.map +1 -1
  56. package/dest/entrypoints/client/bundle/utils.js +10 -1
  57. package/dest/entrypoints/client/lazy/utils.d.ts +1 -1
  58. package/dest/entrypoints/client/lazy/utils.d.ts.map +1 -1
  59. package/dest/entrypoints/client/lazy/utils.js +10 -1
  60. package/dest/entrypoints/pxe_creation_options.d.ts +3 -2
  61. package/dest/entrypoints/pxe_creation_options.d.ts.map +1 -1
  62. package/dest/entrypoints/server/index.d.ts +3 -1
  63. package/dest/entrypoints/server/index.d.ts.map +1 -1
  64. package/dest/entrypoints/server/index.js +2 -0
  65. package/dest/entrypoints/server/utils.d.ts +1 -1
  66. package/dest/entrypoints/server/utils.d.ts.map +1 -1
  67. package/dest/entrypoints/server/utils.js +11 -7
  68. package/dest/events/event_service.d.ts +4 -3
  69. package/dest/events/event_service.d.ts.map +1 -1
  70. package/dest/events/event_service.js +17 -19
  71. package/dest/events/private_event_filter_validator.d.ts +5 -5
  72. package/dest/events/private_event_filter_validator.d.ts.map +1 -1
  73. package/dest/events/private_event_filter_validator.js +5 -6
  74. package/dest/job_coordinator/job_coordinator.d.ts +74 -0
  75. package/dest/job_coordinator/job_coordinator.d.ts.map +1 -0
  76. package/dest/job_coordinator/job_coordinator.js +93 -0
  77. package/dest/logs/log_service.d.ts +3 -2
  78. package/dest/logs/log_service.d.ts.map +1 -1
  79. package/dest/logs/log_service.js +21 -13
  80. package/dest/notes/note_service.d.ts +5 -4
  81. package/dest/notes/note_service.d.ts.map +1 -1
  82. package/dest/notes/note_service.js +30 -34
  83. package/dest/oracle_version.d.ts +3 -3
  84. package/dest/oracle_version.d.ts.map +1 -1
  85. package/dest/oracle_version.js +4 -3
  86. package/dest/private_kernel/hints/index.d.ts +2 -2
  87. package/dest/private_kernel/hints/index.d.ts.map +1 -1
  88. package/dest/private_kernel/hints/index.js +1 -1
  89. package/dest/private_kernel/hints/private_kernel_reset_private_inputs_builder.d.ts +28 -0
  90. package/dest/private_kernel/hints/private_kernel_reset_private_inputs_builder.d.ts.map +1 -0
  91. package/dest/private_kernel/hints/{build_private_kernel_reset_private_inputs.js → private_kernel_reset_private_inputs_builder.js} +13 -7
  92. package/dest/private_kernel/private_kernel_execution_prover.d.ts +1 -1
  93. package/dest/private_kernel/private_kernel_execution_prover.d.ts.map +1 -1
  94. package/dest/private_kernel/private_kernel_execution_prover.js +4 -5
  95. package/dest/private_kernel/private_kernel_oracle.d.ts +24 -28
  96. package/dest/private_kernel/private_kernel_oracle.d.ts.map +1 -1
  97. package/dest/private_kernel/private_kernel_oracle.js +90 -2
  98. package/dest/pxe.d.ts +8 -36
  99. package/dest/pxe.d.ts.map +1 -1
  100. package/dest/pxe.js +70 -93
  101. package/dest/storage/capsule_store/capsule_store.d.ts +24 -9
  102. package/dest/storage/capsule_store/capsule_store.d.ts.map +1 -1
  103. package/dest/storage/capsule_store/capsule_store.js +132 -23
  104. package/dest/storage/contract_store/contract_store.d.ts +1 -2
  105. package/dest/storage/contract_store/contract_store.d.ts.map +1 -1
  106. package/dest/storage/contract_store/contract_store.js +0 -12
  107. package/dest/storage/note_store/note_store.d.ts +45 -56
  108. package/dest/storage/note_store/note_store.d.ts.map +1 -1
  109. package/dest/storage/note_store/note_store.js +244 -263
  110. package/dest/storage/note_store/stored_note.d.ts +16 -0
  111. package/dest/storage/note_store/stored_note.d.ts.map +1 -0
  112. package/dest/storage/note_store/stored_note.js +43 -0
  113. package/dest/storage/private_event_store/private_event_store.d.ts +47 -7
  114. package/dest/storage/private_event_store/private_event_store.d.ts.map +1 -1
  115. package/dest/storage/private_event_store/private_event_store.js +203 -68
  116. package/dest/storage/private_event_store/stored_private_event.d.ts +23 -0
  117. package/dest/storage/private_event_store/stored_private_event.d.ts.map +1 -0
  118. package/dest/storage/private_event_store/stored_private_event.js +56 -0
  119. package/dest/storage/tagging_store/recipient_tagging_store.d.ts +15 -8
  120. package/dest/storage/tagging_store/recipient_tagging_store.d.ts.map +1 -1
  121. package/dest/storage/tagging_store/recipient_tagging_store.js +69 -12
  122. package/dest/storage/tagging_store/sender_tagging_store.d.ts +19 -9
  123. package/dest/storage/tagging_store/sender_tagging_store.d.ts.map +1 -1
  124. package/dest/storage/tagging_store/sender_tagging_store.js +110 -28
  125. package/dest/tagging/constants.d.ts +2 -0
  126. package/dest/tagging/constants.d.ts.map +1 -0
  127. package/dest/tagging/constants.js +10 -0
  128. package/dest/tagging/get_all_logs_by_tags.d.ts +24 -0
  129. package/dest/tagging/get_all_logs_by_tags.d.ts.map +1 -0
  130. package/dest/tagging/get_all_logs_by_tags.js +46 -0
  131. package/dest/tagging/index.d.ts +3 -2
  132. package/dest/tagging/index.d.ts.map +1 -1
  133. package/dest/tagging/index.js +2 -10
  134. package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.d.ts +3 -2
  135. package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.d.ts.map +1 -1
  136. package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.js +8 -8
  137. package/dest/tagging/recipient_sync/utils/load_logs_for_range.d.ts +3 -2
  138. package/dest/tagging/recipient_sync/utils/load_logs_for_range.d.ts.map +1 -1
  139. package/dest/tagging/recipient_sync/utils/load_logs_for_range.js +5 -2
  140. package/dest/tagging/sender_sync/sync_sender_tagging_indexes.d.ts +3 -2
  141. package/dest/tagging/sender_sync/sync_sender_tagging_indexes.d.ts.map +1 -1
  142. package/dest/tagging/sender_sync/sync_sender_tagging_indexes.js +8 -8
  143. package/dest/tagging/sender_sync/utils/get_status_change_of_pending.d.ts +1 -1
  144. package/dest/tagging/sender_sync/utils/get_status_change_of_pending.d.ts.map +1 -1
  145. package/dest/tagging/sender_sync/utils/get_status_change_of_pending.js +5 -8
  146. package/dest/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.d.ts +5 -2
  147. package/dest/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.d.ts.map +1 -1
  148. package/dest/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.js +10 -5
  149. package/package.json +18 -18
  150. package/src/bin/check_oracle_version.ts +1 -0
  151. package/src/block_synchronizer/block_synchronizer.ts +77 -20
  152. package/src/config/index.ts +14 -0
  153. package/src/config/package_info.ts +1 -1
  154. package/src/contract_function_simulator/benchmarked_node.ts +103 -0
  155. package/src/contract_function_simulator/contract_function_simulator.ts +37 -26
  156. package/src/contract_function_simulator/execution_note_cache.ts +44 -25
  157. package/src/contract_function_simulator/index.ts +1 -1
  158. package/src/contract_function_simulator/noir-structs/event_validation_request.ts +5 -1
  159. package/src/contract_function_simulator/noir-structs/note_validation_request.ts +1 -1
  160. package/src/contract_function_simulator/noir-structs/utility_context.ts +6 -25
  161. package/src/contract_function_simulator/oracle/interfaces.ts +20 -10
  162. package/src/contract_function_simulator/oracle/note_packing_utils.ts +10 -10
  163. package/src/contract_function_simulator/oracle/oracle.ts +56 -41
  164. package/src/contract_function_simulator/oracle/private_execution.ts +1 -69
  165. package/src/contract_function_simulator/oracle/private_execution_oracle.ts +39 -44
  166. package/src/contract_function_simulator/oracle/utility_execution_oracle.ts +90 -76
  167. package/src/contract_sync/index.ts +98 -0
  168. package/src/debug/pxe_debug_utils.ts +3 -2
  169. package/src/entrypoints/client/bundle/utils.ts +7 -1
  170. package/src/entrypoints/client/lazy/utils.ts +7 -2
  171. package/src/entrypoints/pxe_creation_options.ts +2 -1
  172. package/src/entrypoints/server/index.ts +2 -0
  173. package/src/entrypoints/server/utils.ts +11 -15
  174. package/src/events/event_service.ts +17 -21
  175. package/src/events/private_event_filter_validator.ts +3 -5
  176. package/src/job_coordinator/job_coordinator.ts +149 -0
  177. package/src/logs/log_service.ts +27 -9
  178. package/src/notes/note_service.ts +37 -40
  179. package/src/oracle_version.ts +4 -3
  180. package/src/private_kernel/hints/index.ts +1 -1
  181. package/src/private_kernel/hints/{build_private_kernel_reset_private_inputs.ts → private_kernel_reset_private_inputs_builder.ts} +33 -22
  182. package/src/private_kernel/private_kernel_execution_prover.ts +3 -5
  183. package/src/private_kernel/private_kernel_oracle.ts +116 -36
  184. package/src/pxe.ts +123 -127
  185. package/src/storage/capsule_store/capsule_store.ts +159 -23
  186. package/src/storage/contract_store/contract_store.ts +0 -20
  187. package/src/storage/note_store/note_store.ts +286 -317
  188. package/src/storage/note_store/stored_note.ts +48 -0
  189. package/src/storage/private_event_store/private_event_store.ts +277 -76
  190. package/src/storage/private_event_store/stored_private_event.ts +73 -0
  191. package/src/storage/tagging_store/recipient_tagging_store.ts +89 -13
  192. package/src/storage/tagging_store/sender_tagging_store.ts +129 -28
  193. package/src/tagging/constants.ts +10 -0
  194. package/src/tagging/get_all_logs_by_tags.ts +68 -0
  195. package/src/tagging/index.ts +2 -11
  196. package/src/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.ts +21 -7
  197. package/src/tagging/recipient_sync/utils/load_logs_for_range.ts +7 -1
  198. package/src/tagging/sender_sync/sync_sender_tagging_indexes.ts +10 -7
  199. package/src/tagging/sender_sync/utils/get_status_change_of_pending.ts +5 -13
  200. package/src/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.ts +16 -4
  201. package/dest/contract_function_simulator/proxied_node.d.ts +0 -9
  202. package/dest/contract_function_simulator/proxied_node.d.ts.map +0 -1
  203. package/dest/contract_function_simulator/proxied_node.js +0 -27
  204. package/dest/private_kernel/hints/build_private_kernel_reset_private_inputs.d.ts +0 -28
  205. package/dest/private_kernel/hints/build_private_kernel_reset_private_inputs.d.ts.map +0 -1
  206. package/dest/private_kernel/private_kernel_oracle_impl.d.ts +0 -46
  207. package/dest/private_kernel/private_kernel_oracle_impl.d.ts.map +0 -1
  208. package/dest/private_kernel/private_kernel_oracle_impl.js +0 -86
  209. package/dest/public_storage/public_storage_service.d.ts +0 -24
  210. package/dest/public_storage/public_storage_service.d.ts.map +0 -1
  211. package/dest/public_storage/public_storage_service.js +0 -26
  212. package/dest/tree_membership/tree_membership_service.d.ts +0 -52
  213. package/dest/tree_membership/tree_membership_service.d.ts.map +0 -1
  214. package/dest/tree_membership/tree_membership_service.js +0 -84
  215. package/src/contract_function_simulator/proxied_node.ts +0 -33
  216. package/src/private_kernel/private_kernel_oracle_impl.ts +0 -133
  217. package/src/public_storage/public_storage_service.ts +0 -33
  218. package/src/tree_membership/tree_membership_service.ts +0 -112
@@ -1,6 +1,8 @@
1
1
  import type { AztecAsyncKVStore, AztecAsyncMap } from '@aztec/kv-store';
2
2
  import type { DirectionalAppTaggingSecret } from '@aztec/stdlib/logs';
3
3
 
4
+ import type { StagedStore } from '../../job_coordinator/job_coordinator.js';
5
+
4
6
  /**
5
7
  * Data provider of tagging data used when syncing the logs as a recipient. The sender counterpart of this class
6
8
  * is called SenderTaggingStore. We have the providers separate for the sender and recipient because
@@ -8,46 +10,120 @@ import type { DirectionalAppTaggingSecret } from '@aztec/stdlib/logs';
8
10
  *
9
11
  * @dev Chain reorgs do not need to be handled here because both the finalized and aged indexes refer to finalized
10
12
  * blocks, which by definition cannot be affected by reorgs.
11
- *
12
- * TODO(benesjan): Relocate to yarn-project/pxe/src/storage/tagging_store
13
13
  */
14
- export class RecipientTaggingStore {
14
+ export class RecipientTaggingStore implements StagedStore {
15
+ storeName: string = 'recipient_tagging';
16
+
15
17
  #store: AztecAsyncKVStore;
16
18
 
17
19
  #highestAgedIndex: AztecAsyncMap<string, number>;
18
20
  #highestFinalizedIndex: AztecAsyncMap<string, number>;
19
21
 
22
+ // jobId => secret => number
23
+ #highestAgedIndexForJob: Map<string, Map<string, number>>;
24
+
25
+ // jobId => secret => number
26
+ #highestFinalizedIndexForJob: Map<string, Map<string, number>>;
27
+
20
28
  constructor(store: AztecAsyncKVStore) {
21
29
  this.#store = store;
22
30
 
23
31
  this.#highestAgedIndex = this.#store.openMap('highest_aged_index');
24
32
  this.#highestFinalizedIndex = this.#store.openMap('highest_finalized_index');
33
+
34
+ this.#highestAgedIndexForJob = new Map();
35
+ this.#highestFinalizedIndexForJob = new Map();
36
+ }
37
+
38
+ #getHighestAgedIndexForJob(jobId: string): Map<string, number> {
39
+ let highestAgedIndexForJob = this.#highestAgedIndexForJob.get(jobId);
40
+ if (!highestAgedIndexForJob) {
41
+ highestAgedIndexForJob = new Map();
42
+ this.#highestAgedIndexForJob.set(jobId, highestAgedIndexForJob);
43
+ }
44
+ return highestAgedIndexForJob;
45
+ }
46
+
47
+ async #readHighestAgedIndex(jobId: string, secret: string): Promise<number | undefined> {
48
+ return this.#getHighestAgedIndexForJob(jobId).get(secret) ?? (await this.#highestAgedIndex.getAsync(secret));
49
+ }
50
+
51
+ #writeHighestAgedIndex(jobId: string, secret: string, index: number) {
52
+ this.#getHighestAgedIndexForJob(jobId).set(secret, index);
53
+ }
54
+
55
+ #getHighestFinalizedIndexForJob(jobId: string): Map<string, number> {
56
+ let jobStagedHighestFinalizedIndex = this.#highestFinalizedIndexForJob.get(jobId);
57
+ if (!jobStagedHighestFinalizedIndex) {
58
+ jobStagedHighestFinalizedIndex = new Map();
59
+ this.#highestFinalizedIndexForJob.set(jobId, jobStagedHighestFinalizedIndex);
60
+ }
61
+ return jobStagedHighestFinalizedIndex;
62
+ }
63
+
64
+ async #readHighestFinalizedIndex(jobId: string, secret: string): Promise<number | undefined> {
65
+ return (
66
+ this.#getHighestFinalizedIndexForJob(jobId).get(secret) ?? (await this.#highestFinalizedIndex.getAsync(secret))
67
+ );
68
+ }
69
+
70
+ #writeHighestFinalizedIndex(jobId: string, secret: string, index: number) {
71
+ this.#getHighestFinalizedIndexForJob(jobId).set(secret, index);
72
+ }
73
+
74
+ /**
75
+ * Writes all job-specific in-memory data to persistent storage.
76
+ *
77
+ * @remark This method must run in a DB transaction context. It's designed to be called from JobCoordinator#commitJob.
78
+ */
79
+ async commit(jobId: string): Promise<void> {
80
+ const highestAgedIndexForJob = this.#highestAgedIndexForJob.get(jobId);
81
+ if (highestAgedIndexForJob) {
82
+ for (const [secret, index] of highestAgedIndexForJob.entries()) {
83
+ await this.#highestAgedIndex.set(secret, index);
84
+ }
85
+ }
86
+
87
+ const highestFinalizedIndexForJob = this.#highestFinalizedIndexForJob.get(jobId);
88
+ if (highestFinalizedIndexForJob) {
89
+ for (const [secret, index] of highestFinalizedIndexForJob.entries()) {
90
+ await this.#highestFinalizedIndex.set(secret, index);
91
+ }
92
+ }
93
+
94
+ return this.discardStaged(jobId);
95
+ }
96
+
97
+ discardStaged(jobId: string): Promise<void> {
98
+ this.#highestAgedIndexForJob.delete(jobId);
99
+ this.#highestFinalizedIndexForJob.delete(jobId);
100
+ return Promise.resolve();
25
101
  }
26
102
 
27
- getHighestAgedIndex(secret: DirectionalAppTaggingSecret): Promise<number | undefined> {
28
- return this.#highestAgedIndex.getAsync(secret.toString());
103
+ getHighestAgedIndex(secret: DirectionalAppTaggingSecret, jobId: string): Promise<number | undefined> {
104
+ return this.#readHighestAgedIndex(jobId, secret.toString());
29
105
  }
30
106
 
31
- async updateHighestAgedIndex(secret: DirectionalAppTaggingSecret, index: number): Promise<void> {
32
- const currentIndex = await this.#highestAgedIndex.getAsync(secret.toString());
107
+ async updateHighestAgedIndex(secret: DirectionalAppTaggingSecret, index: number, jobId: string): Promise<void> {
108
+ const currentIndex = await this.#readHighestAgedIndex(jobId, secret.toString());
33
109
  if (currentIndex !== undefined && index <= currentIndex) {
34
110
  // Log sync should never set a lower highest aged index.
35
111
  throw new Error(`New highest aged index (${index}) must be higher than the current one (${currentIndex})`);
36
112
  }
37
- await this.#highestAgedIndex.set(secret.toString(), index);
113
+ this.#writeHighestAgedIndex(jobId, secret.toString(), index);
38
114
  }
39
115
 
40
- getHighestFinalizedIndex(secret: DirectionalAppTaggingSecret): Promise<number | undefined> {
41
- return this.#highestFinalizedIndex.getAsync(secret.toString());
116
+ getHighestFinalizedIndex(secret: DirectionalAppTaggingSecret, jobId: string): Promise<number | undefined> {
117
+ return this.#readHighestFinalizedIndex(jobId, secret.toString());
42
118
  }
43
119
 
44
- async updateHighestFinalizedIndex(secret: DirectionalAppTaggingSecret, index: number): Promise<void> {
45
- const currentIndex = await this.#highestFinalizedIndex.getAsync(secret.toString());
120
+ async updateHighestFinalizedIndex(secret: DirectionalAppTaggingSecret, index: number, jobId: string): Promise<void> {
121
+ const currentIndex = await this.#readHighestFinalizedIndex(jobId, secret.toString());
46
122
  if (currentIndex !== undefined && index < currentIndex) {
47
123
  // Log sync should never set a lower highest finalized index but it can happen that it would try to set the same
48
124
  // one because we are loading logs from highest aged index + 1 and not from the highest finalized index.
49
125
  throw new Error(`New highest finalized index (${index}) must be higher than the current one (${currentIndex})`);
50
126
  }
51
- await this.#highestFinalizedIndex.set(secret.toString(), index);
127
+ this.#writeHighestFinalizedIndex(jobId, secret.toString(), index);
52
128
  }
53
129
  }
@@ -3,14 +3,17 @@ import type { AztecAsyncKVStore, AztecAsyncMap } from '@aztec/kv-store';
3
3
  import type { DirectionalAppTaggingSecret, PreTag } from '@aztec/stdlib/logs';
4
4
  import { TxHash } from '@aztec/stdlib/tx';
5
5
 
6
- import { UNFINALIZED_TAGGING_INDEXES_WINDOW_LEN } from '../../tagging/index.js';
6
+ import type { StagedStore } from '../../job_coordinator/job_coordinator.js';
7
+ import { UNFINALIZED_TAGGING_INDEXES_WINDOW_LEN } from '../../tagging/constants.js';
7
8
 
8
9
  /**
9
10
  * Data provider of tagging data used when syncing the sender tagging indexes. The recipient counterpart of this class
10
- * is called RecipientTaggingStore. We have the providers separate for the sender and recipient because
11
+ * is called RecipientTaggingStore. We have the data stores separate for sender and recipient because
11
12
  * the algorithms are completely disjoint and there is not data reuse between the two.
12
13
  */
13
- export class SenderTaggingStore {
14
+ export class SenderTaggingStore implements StagedStore {
15
+ readonly storeName = 'sender_tagging';
16
+
14
17
  #store: AztecAsyncKVStore;
15
18
 
16
19
  // Stores the pending indexes for each directional app tagging secret. Pending here means that the tx that contained
@@ -21,18 +24,114 @@ export class SenderTaggingStore {
21
24
  // the smaller ones are irrelevant due to tx atomicity.
22
25
  //
23
26
  // TODO(#17615): This assumes no logs are used in the non-revertible phase.
27
+ //
28
+ // directional app tagging secret => { pending index, txHash }[]
24
29
  #pendingIndexes: AztecAsyncMap<string, { index: number; txHash: string }[]>;
25
30
 
31
+ // jobId => directional app tagging secret => { pending index, txHash }[]
32
+ #pendingIndexesForJob: Map<string, Map<string, { index: number; txHash: string }[]>>;
33
+
26
34
  // Stores the last (highest) finalized index for each directional app tagging secret. We care only about the last
27
35
  // index because unlike the pending indexes, it will never happen that a finalized index would be removed and hence
28
36
  // we don't need to store the history.
37
+ //
38
+ // directional app tagging secret => highest finalized index
29
39
  #lastFinalizedIndexes: AztecAsyncMap<string, number>;
30
40
 
41
+ // jobId => directional app tagging secret => highest finalized index
42
+ #lastFinalizedIndexesForJob: Map<string, Map<string, number>>;
43
+
31
44
  constructor(store: AztecAsyncKVStore) {
32
45
  this.#store = store;
33
46
 
34
47
  this.#pendingIndexes = this.#store.openMap('pending_indexes');
35
48
  this.#lastFinalizedIndexes = this.#store.openMap('last_finalized_indexes');
49
+
50
+ this.#pendingIndexesForJob = new Map();
51
+ this.#lastFinalizedIndexesForJob = new Map();
52
+ }
53
+
54
+ #getPendingIndexesForJob(jobId: string): Map<string, { index: number; txHash: string }[]> {
55
+ let pendingIndexesForJob = this.#pendingIndexesForJob.get(jobId);
56
+ if (!pendingIndexesForJob) {
57
+ pendingIndexesForJob = new Map();
58
+ this.#pendingIndexesForJob.set(jobId, pendingIndexesForJob);
59
+ }
60
+ return pendingIndexesForJob;
61
+ }
62
+
63
+ #getLastFinalizedIndexesForJob(jobId: string): Map<string, number> {
64
+ let jobStagedLastFinalizedIndexes = this.#lastFinalizedIndexesForJob.get(jobId);
65
+ if (!jobStagedLastFinalizedIndexes) {
66
+ jobStagedLastFinalizedIndexes = new Map();
67
+ this.#lastFinalizedIndexesForJob.set(jobId, jobStagedLastFinalizedIndexes);
68
+ }
69
+ return jobStagedLastFinalizedIndexes;
70
+ }
71
+
72
+ async #readPendingIndexes(jobId: string, secret: string): Promise<{ index: number; txHash: string }[]> {
73
+ const jobStagedPendingIndexes = this.#getPendingIndexesForJob(jobId);
74
+ const pendingIndexes = jobStagedPendingIndexes.get(secret);
75
+ // We return the staged version of this if it exists, if not, we read from the DB.
76
+ // If the DB also has nothing, we return an empty array [].
77
+ return pendingIndexes !== undefined ? pendingIndexes : ((await this.#pendingIndexes.getAsync(secret)) ?? []);
78
+ }
79
+
80
+ #writePendingIndexes(jobId: string, secret: string, pendingIndexes: { index: number; txHash: string }[]) {
81
+ this.#getPendingIndexesForJob(jobId).set(secret, pendingIndexes);
82
+ }
83
+
84
+ /**
85
+ * Returns a job view of all the secrets that have a corresponding list of pending indexes either in persistent
86
+ * storage or the current job.
87
+ */
88
+ async #readSecretsWithPendingIndexes(jobId: string): Promise<string[]> {
89
+ const storedSecrets = new Set(await toArray(this.#pendingIndexes.keysAsync()));
90
+ const stagedSecrets = this.#getPendingIndexesForJob(jobId).keys();
91
+ return [...storedSecrets.union(new Set(stagedSecrets))];
92
+ }
93
+
94
+ async #readLastFinalizedIndex(jobId: string, secret: string): Promise<number | undefined> {
95
+ return (
96
+ this.#getLastFinalizedIndexesForJob(jobId).get(secret) ?? (await this.#lastFinalizedIndexes.getAsync(secret))
97
+ );
98
+ }
99
+
100
+ #writeLastFinalizedIndex(jobId: string, secret: string, lastFinalizedIndex: number) {
101
+ this.#getLastFinalizedIndexesForJob(jobId).set(secret, lastFinalizedIndex);
102
+ }
103
+
104
+ /**
105
+ * Writes all job-specific in-memory data to persistent storage.
106
+ *
107
+ * @remark This method must run in a DB transaction context. It's designed to be called from JobCoordinator#commitJob.
108
+ */
109
+ async commit(jobId: string): Promise<void> {
110
+ const pendingIndexesForJob = this.#pendingIndexesForJob.get(jobId);
111
+ if (pendingIndexesForJob) {
112
+ for (const [secret, pendingIndexes] of pendingIndexesForJob.entries()) {
113
+ if (pendingIndexes.length === 0) {
114
+ await this.#pendingIndexes.delete(secret);
115
+ } else {
116
+ await this.#pendingIndexes.set(secret, pendingIndexes);
117
+ }
118
+ }
119
+ }
120
+
121
+ const lastFinalizedIndexesForJob = this.#lastFinalizedIndexesForJob.get(jobId);
122
+ if (lastFinalizedIndexesForJob) {
123
+ for (const [secret, lastFinalizedIndex] of lastFinalizedIndexesForJob.entries()) {
124
+ await this.#lastFinalizedIndexes.set(secret, lastFinalizedIndex);
125
+ }
126
+ }
127
+
128
+ return this.discardStaged(jobId);
129
+ }
130
+
131
+ discardStaged(jobId: string): Promise<void> {
132
+ this.#pendingIndexesForJob.delete(jobId);
133
+ this.#lastFinalizedIndexesForJob.delete(jobId);
134
+ return Promise.resolve();
36
135
  }
37
136
 
38
137
  /**
@@ -43,6 +142,7 @@ export class SenderTaggingStore {
43
142
  * @param preTags - The pre-tags containing the directional app tagging secrets and the indexes that are to be
44
143
  * stored in the db.
45
144
  * @param txHash - The tx in which the pretags were used in private logs.
145
+ * @param jobId - job context for staged writes to this store. See `JobCoordinator` for more details.
46
146
  * @throws If any two pre-tags contain the same directional app tagging secret. This is enforced because we care
47
147
  * only about the highest index for a given secret that was used in the tx. Hence this check is a good way to catch
48
148
  * bugs.
@@ -56,7 +156,7 @@ export class SenderTaggingStore {
56
156
  * This is enforced because this should never happen if the syncing is done correctly as we look for logs from higher
57
157
  * indexes than finalized ones.
58
158
  */
59
- async storePendingIndexes(preTags: PreTag[], txHash: TxHash) {
159
+ async storePendingIndexes(preTags: PreTag[], txHash: TxHash, jobId: string) {
60
160
  // The secrets in pre-tags should be unique because we always store just the highest index per given secret-txHash
61
161
  // pair. Below we check that this is the case.
62
162
  const secretsSet = new Set(preTags.map(preTag => preTag.secret.toString()));
@@ -67,7 +167,7 @@ export class SenderTaggingStore {
67
167
  for (const { secret, index } of preTags) {
68
168
  // First we check that for any secret the highest used index in tx is not further than window length from
69
169
  // the highest finalized index.
70
- const finalizedIndex = (await this.getLastFinalizedIndex(secret)) ?? 0;
170
+ const finalizedIndex = (await this.getLastFinalizedIndex(secret, jobId)) ?? 0;
71
171
  if (index > finalizedIndex + UNFINALIZED_TAGGING_INDEXES_WINDOW_LEN) {
72
172
  throw new Error(
73
173
  `Highest used index ${index} is further than window length from the highest finalized index ${finalizedIndex}.
@@ -78,7 +178,7 @@ export class SenderTaggingStore {
78
178
 
79
179
  // Throw if the new pending index is lower than or equal to the last finalized index
80
180
  const secretStr = secret.toString();
81
- const lastFinalizedIndex = await this.#lastFinalizedIndexes.getAsync(secretStr);
181
+ const lastFinalizedIndex = await this.#readLastFinalizedIndex(jobId, secretStr);
82
182
  if (lastFinalizedIndex !== undefined && index <= lastFinalizedIndex) {
83
183
  throw new Error(
84
184
  `Cannot store pending index ${index} for secret ${secretStr}: ` +
@@ -88,7 +188,7 @@ export class SenderTaggingStore {
88
188
 
89
189
  // Check if this secret + txHash combination already exists
90
190
  const txHashStr = txHash.toString();
91
- const existingForSecret = (await this.#pendingIndexes.getAsync(secretStr)) ?? [];
191
+ const existingForSecret = await this.#readPendingIndexes(jobId, secretStr);
92
192
  const existingForSecretAndTx = existingForSecret.find(entry => entry.txHash === txHashStr);
93
193
 
94
194
  if (existingForSecretAndTx) {
@@ -102,7 +202,7 @@ export class SenderTaggingStore {
102
202
  // If it exists with the same index, ignore the update (no-op)
103
203
  } else {
104
204
  // If it doesn't exist, add it
105
- await this.#pendingIndexes.set(secretStr, [...existingForSecret, { index, txHash: txHashStr }]);
205
+ this.#writePendingIndexes(jobId, secretStr, [...existingForSecret, { index, txHash: txHashStr }]);
106
206
  }
107
207
  }
108
208
  }
@@ -120,8 +220,9 @@ export class SenderTaggingStore {
120
220
  secret: DirectionalAppTaggingSecret,
121
221
  startIndex: number,
122
222
  endIndex: number,
223
+ jobId: string,
123
224
  ): Promise<TxHash[]> {
124
- const existing = (await this.#pendingIndexes.getAsync(secret.toString())) ?? [];
225
+ const existing = await this.#readPendingIndexes(jobId, secret.toString());
125
226
  const txHashes = existing
126
227
  .filter(entry => entry.index >= startIndex && entry.index < endIndex)
127
228
  .map(entry => entry.txHash);
@@ -133,8 +234,8 @@ export class SenderTaggingStore {
133
234
  * @param secret - The secret to get the last finalized index for.
134
235
  * @returns The last (highest) finalized index for the given secret.
135
236
  */
136
- getLastFinalizedIndex(secret: DirectionalAppTaggingSecret): Promise<number | undefined> {
137
- return this.#lastFinalizedIndexes.getAsync(secret.toString());
237
+ getLastFinalizedIndex(secret: DirectionalAppTaggingSecret, jobId: string): Promise<number | undefined> {
238
+ return this.#readLastFinalizedIndex(jobId, secret.toString());
138
239
  }
139
240
 
140
241
  /**
@@ -143,13 +244,13 @@ export class SenderTaggingStore {
143
244
  * @param secret - The directional app tagging secret to query the last used index for.
144
245
  * @returns The last used index.
145
246
  */
146
- async getLastUsedIndex(secret: DirectionalAppTaggingSecret): Promise<number | undefined> {
247
+ async getLastUsedIndex(secret: DirectionalAppTaggingSecret, jobId: string): Promise<number | undefined> {
147
248
  const secretStr = secret.toString();
148
- const pendingTxScopedIndexes = (await this.#pendingIndexes.getAsync(secretStr)) ?? [];
249
+ const pendingTxScopedIndexes = await this.#readPendingIndexes(jobId, secretStr);
149
250
  const pendingIndexes = pendingTxScopedIndexes.map(entry => entry.index);
150
251
 
151
252
  if (pendingTxScopedIndexes.length === 0) {
152
- return this.#lastFinalizedIndexes.getAsync(secretStr);
253
+ return this.#readLastFinalizedIndex(jobId, secretStr);
153
254
  }
154
255
 
155
256
  // As the last used index we return the highest one from the pending indexes. Note that this value will be always
@@ -160,23 +261,23 @@ export class SenderTaggingStore {
160
261
  /**
161
262
  * Drops all pending indexes corresponding to the given transaction hashes.
162
263
  */
163
- async dropPendingIndexes(txHashes: TxHash[]) {
264
+ async dropPendingIndexes(txHashes: TxHash[], jobId: string) {
164
265
  if (txHashes.length === 0) {
165
266
  return;
166
267
  }
167
268
 
168
- const txHashStrs = new Set<string>(txHashes.map(txHash => txHash.toString()));
169
- const allSecrets = await toArray(this.#pendingIndexes.keysAsync());
269
+ const txHashStrings = new Set<string>(txHashes.map(txHash => txHash.toString()));
270
+ const allSecrets = await this.#readSecretsWithPendingIndexes(jobId);
170
271
 
171
272
  for (const secret of allSecrets) {
172
- const pendingData = await this.#pendingIndexes.getAsync(secret);
273
+ const pendingData = await this.#readPendingIndexes(jobId, secret);
173
274
  if (pendingData) {
174
- const filtered = pendingData.filter(item => !txHashStrs.has(item.txHash));
275
+ const filtered = pendingData.filter(item => !txHashStrings.has(item.txHash));
175
276
  if (filtered.length === 0) {
176
- await this.#pendingIndexes.delete(secret);
277
+ this.#writePendingIndexes(jobId, secret, []);
177
278
  } else if (filtered.length !== pendingData.length) {
178
279
  // Some items were filtered out, so update the pending data
179
- await this.#pendingIndexes.set(secret, filtered);
280
+ this.#writePendingIndexes(jobId, secret, filtered);
180
281
  }
181
282
  // else: No items were filtered out (txHashes not found for this secret) --> no-op
182
283
  }
@@ -187,7 +288,7 @@ export class SenderTaggingStore {
187
288
  * Updates pending indexes corresponding to the given transaction hashes to be finalized and prunes any lower pending
188
289
  * indexes.
189
290
  */
190
- async finalizePendingIndexes(txHashes: TxHash[]) {
291
+ async finalizePendingIndexes(txHashes: TxHash[], jobId: string) {
191
292
  if (txHashes.length === 0) {
192
293
  return;
193
294
  }
@@ -195,10 +296,10 @@ export class SenderTaggingStore {
195
296
  for (const txHash of txHashes) {
196
297
  const txHashStr = txHash.toString();
197
298
 
198
- const allSecrets = await toArray(this.#pendingIndexes.keysAsync());
299
+ const allSecrets = await this.#readSecretsWithPendingIndexes(jobId);
199
300
 
200
301
  for (const secret of allSecrets) {
201
- const pendingData = await this.#pendingIndexes.getAsync(secret);
302
+ const pendingData = await this.#readPendingIndexes(jobId, secret);
202
303
  if (!pendingData) {
203
304
  continue;
204
305
  }
@@ -214,7 +315,7 @@ export class SenderTaggingStore {
214
315
  throw new Error(`Multiple pending indexes found for tx hash ${txHashStr} and secret ${secret}`);
215
316
  }
216
317
 
217
- let lastFinalized = await this.#lastFinalizedIndexes.getAsync(secret);
318
+ let lastFinalized = await this.#readLastFinalizedIndex(jobId, secret);
218
319
  const newFinalized = matchingIndexes[0];
219
320
 
220
321
  if (newFinalized < (lastFinalized ?? 0)) {
@@ -225,7 +326,7 @@ export class SenderTaggingStore {
225
326
  );
226
327
  }
227
328
 
228
- await this.#lastFinalizedIndexes.set(secret, newFinalized);
329
+ this.#writeLastFinalizedIndex(jobId, secret, newFinalized);
229
330
  lastFinalized = newFinalized;
230
331
 
231
332
  // When we add pending indexes, we ensure they are higher than the last finalized index. However, because we
@@ -234,9 +335,9 @@ export class SenderTaggingStore {
234
335
  // outdated pending indexes.
235
336
  const remainingItemsOfHigherIndex = pendingData.filter(item => item.index > (lastFinalized ?? 0));
236
337
  if (remainingItemsOfHigherIndex.length === 0) {
237
- await this.#pendingIndexes.delete(secret);
338
+ this.#writePendingIndexes(jobId, secret, []);
238
339
  } else {
239
- await this.#pendingIndexes.set(secret, remainingItemsOfHigherIndex);
340
+ this.#writePendingIndexes(jobId, secret, remainingItemsOfHigherIndex);
240
341
  }
241
342
  }
242
343
  }
@@ -0,0 +1,10 @@
1
+ // This window has to be as large as the largest expected number of logs emitted in a tx for a given directional app
2
+ // tagging secret. If we get more tag indexes consumed than this window, an error is thrown in `PXE::proveTx` function.
3
+ // This is set to a larger value than MAX_PRIVATE_LOGS_PER_TX (currently 64) because there could be more than
4
+ // MAX_PRIVATE_LOGS_PER_TX indexes consumed in case the logs are squashed. This happens when the log contains a note
5
+ // and the note is nullified in the same tx.
6
+ //
7
+ // Having a large window significantly slowed down `e2e_l1_with_wall_time` test as there we perform sync for more than
8
+ // 1000 secrets. For this reason we set it to a relatively low value of 20. 20 should be sufficient for all the use
9
+ // cases.
10
+ export const UNFINALIZED_TAGGING_INDEXES_WINDOW_LEN = 20;
@@ -0,0 +1,68 @@
1
+ import type { AztecAddress } from '@aztec/stdlib/aztec-address';
2
+ import type { L2BlockHash } from '@aztec/stdlib/block';
3
+ import { MAX_LOGS_PER_TAG } from '@aztec/stdlib/interfaces/api-limit';
4
+ import type { AztecNode } from '@aztec/stdlib/interfaces/client';
5
+ import type { SiloedTag, Tag, TxScopedL2Log } from '@aztec/stdlib/logs';
6
+
7
+ /**
8
+ * Generic pagination helper that fetches all pages of results.
9
+ * @param numTags - The number of tags being queried (determines result array size).
10
+ * @param fetchPage - Function that fetches a single page of results given a page number.
11
+ * @returns An array of arrays, one per tag, containing all results across all pages.
12
+ */
13
+ async function getAllPages<T>(numTags: number, fetchPage: (page: number) => Promise<T[][]>): Promise<T[][]> {
14
+ const allResultsPerTag: T[][] = Array.from({ length: numTags }, () => []);
15
+ let page = 0;
16
+ let hasMore = true;
17
+
18
+ while (hasMore) {
19
+ const resultsPage = await fetchPage(page);
20
+ hasMore = false;
21
+
22
+ for (let i = 0; i < resultsPage.length; i++) {
23
+ allResultsPerTag[i].push(...resultsPage[i]);
24
+ if (resultsPage[i].length === MAX_LOGS_PER_TAG) {
25
+ hasMore = true;
26
+ }
27
+ }
28
+ page++;
29
+ }
30
+
31
+ return allResultsPerTag;
32
+ }
33
+
34
+ /**
35
+ * Fetches all private logs for the given tags, automatically paginating through all pages.
36
+ * @param aztecNode - The Aztec node to query.
37
+ * @param tags - The siloed tags to search for.
38
+ * @param anchorBlockHash - reference block for the Aztec node query, throws if block is not found there (typically
39
+ * because of reorgs).
40
+ * @returns An array of log arrays, one per tag, containing all logs across all pages.
41
+ */
42
+ export function getAllPrivateLogsByTags(
43
+ aztecNode: AztecNode,
44
+ tags: SiloedTag[],
45
+ anchorBlockHash: L2BlockHash,
46
+ ): Promise<TxScopedL2Log[][]> {
47
+ return getAllPages(tags.length, page => aztecNode.getPrivateLogsByTags(tags, page, anchorBlockHash));
48
+ }
49
+
50
+ /**
51
+ * Fetches all public logs for the given tags from a contract, automatically paginating through all pages.
52
+ * @param aztecNode - The Aztec node to query.
53
+ * @param contractAddress - The contract address to search logs for.
54
+ * @param tags - The tags to search for.
55
+ * @param anchorBlockHash - reference block for the Aztec node query, throws if block is not found there (typically
56
+ * because of reorgs).
57
+ * @returns An array of log arrays, one per tag, containing all logs across all pages.
58
+ */
59
+ export function getAllPublicLogsByTagsFromContract(
60
+ aztecNode: AztecNode,
61
+ contractAddress: AztecAddress,
62
+ tags: Tag[],
63
+ anchorBlockHash: L2BlockHash,
64
+ ): Promise<TxScopedL2Log[][]> {
65
+ return getAllPages(tags.length, page =>
66
+ aztecNode.getPublicLogsByTagsFromContract(contractAddress, tags, page, anchorBlockHash),
67
+ );
68
+ }
@@ -11,17 +11,8 @@
11
11
 
12
12
  export { loadPrivateLogsForSenderRecipientPair } from './recipient_sync/load_private_logs_for_sender_recipient_pair.js';
13
13
  export { syncSenderTaggingIndexes } from './sender_sync/sync_sender_tagging_indexes.js';
14
-
15
- // This window has to be as large as the largest expected number of logs emitted in a tx for a given directional app
16
- // tagging secret. If we get more tag indexes consumed than this window, an error is thrown in `PXE::proveTx` function.
17
- // This is set to a larger value than MAX_PRIVATE_LOGS_PER_TX (currently 64) because there could be more than
18
- // MAX_PRIVATE_LOGS_PER_TX indexes consumed in case the logs are squashed. This happens when the log contains a note
19
- // and the note is nullified in the same tx.
20
- //
21
- // Having a large window significantly slowed down `e2e_l1_with_wall_time` test as there we perform sync for more than
22
- // 1000 secrets. For this reason we set it to a relatively low value of 20. 20 should be sufficient for all the use
23
- // cases.
24
- export const UNFINALIZED_TAGGING_INDEXES_WINDOW_LEN = 20;
14
+ export { UNFINALIZED_TAGGING_INDEXES_WINDOW_LEN } from './constants.js';
15
+ export { getAllPrivateLogsByTags, getAllPublicLogsByTagsFromContract } from './get_all_logs_by_tags.js';
25
16
 
26
17
  // Re-export tagging-related types from stdlib
27
18
  export { DirectionalAppTaggingSecret, Tag, SiloedTag } from '@aztec/stdlib/logs';
@@ -1,10 +1,11 @@
1
1
  import type { BlockNumber } from '@aztec/foundation/branded-types';
2
2
  import type { AztecAddress } from '@aztec/stdlib/aztec-address';
3
+ import type { L2BlockHash } from '@aztec/stdlib/block';
3
4
  import type { AztecNode } from '@aztec/stdlib/interfaces/client';
4
5
  import type { DirectionalAppTaggingSecret, TxScopedL2Log } from '@aztec/stdlib/logs';
5
6
 
6
7
  import type { RecipientTaggingStore } from '../../storage/tagging_store/recipient_tagging_store.js';
7
- import { UNFINALIZED_TAGGING_INDEXES_WINDOW_LEN } from '../index.js';
8
+ import { UNFINALIZED_TAGGING_INDEXES_WINDOW_LEN } from '../constants.js';
8
9
  import { findHighestIndexes } from './utils/find_highest_indexes.js';
9
10
  import { loadLogsForRange } from './utils/load_logs_for_range.js';
10
11
 
@@ -21,6 +22,8 @@ export async function loadPrivateLogsForSenderRecipientPair(
21
22
  aztecNode: AztecNode,
22
23
  taggingStore: RecipientTaggingStore,
23
24
  anchorBlockNumber: BlockNumber,
25
+ anchorBlockHash: L2BlockHash,
26
+ jobId: string,
24
27
  ): Promise<TxScopedL2Log[]> {
25
28
  // # Explanation of how the algorithm works
26
29
  // When we perform the sync we will look at logs that correspond to the tagging index range
@@ -68,13 +71,16 @@ export async function loadPrivateLogsForSenderRecipientPair(
68
71
  throw new Error('Node failed to return latest block header when syncing logs');
69
72
  }
70
73
 
71
- [finalizedBlockNumber, currentTimestamp] = [l2Tips.finalized.number, latestBlockHeader.globalVariables.timestamp];
74
+ [finalizedBlockNumber, currentTimestamp] = [
75
+ l2Tips.finalized.block.number,
76
+ latestBlockHeader.globalVariables.timestamp,
77
+ ];
72
78
  }
73
79
 
74
80
  let start: number, end: number;
75
81
  {
76
- const currentHighestAgedIndex = await taggingStore.getHighestAgedIndex(secret);
77
- const currentHighestFinalizedIndex = await taggingStore.getHighestFinalizedIndex(secret);
82
+ const currentHighestAgedIndex = await taggingStore.getHighestAgedIndex(secret, jobId);
83
+ const currentHighestFinalizedIndex = await taggingStore.getHighestFinalizedIndex(secret, jobId);
78
84
 
79
85
  // We don't want to include the highest aged index so we start from `currentHighestAgedIndex + 1` (or 0 if not set)
80
86
  start = currentHighestAgedIndex === undefined ? 0 : currentHighestAgedIndex + 1;
@@ -88,7 +94,15 @@ export async function loadPrivateLogsForSenderRecipientPair(
88
94
 
89
95
  while (true) {
90
96
  // Get private logs with their block timestamps and corresponding tagging indexes
91
- const privateLogsWithIndexes = await loadLogsForRange(secret, app, aztecNode, start, end, anchorBlockNumber);
97
+ const privateLogsWithIndexes = await loadLogsForRange(
98
+ secret,
99
+ app,
100
+ aztecNode,
101
+ start,
102
+ end,
103
+ anchorBlockNumber,
104
+ anchorBlockHash,
105
+ );
92
106
 
93
107
  if (privateLogsWithIndexes.length === 0) {
94
108
  break;
@@ -104,7 +118,7 @@ export async function loadPrivateLogsForSenderRecipientPair(
104
118
 
105
119
  // Store updates in data provider and update local variables
106
120
  if (highestAgedIndex !== undefined) {
107
- await taggingStore.updateHighestAgedIndex(secret, highestAgedIndex);
121
+ await taggingStore.updateHighestAgedIndex(secret, highestAgedIndex, jobId);
108
122
  }
109
123
 
110
124
  if (highestFinalizedIndex === undefined) {
@@ -117,7 +131,7 @@ export async function loadPrivateLogsForSenderRecipientPair(
117
131
  throw new Error('Highest aged index lower than highest finalized index invariant violated');
118
132
  }
119
133
 
120
- await taggingStore.updateHighestFinalizedIndex(secret, highestFinalizedIndex);
134
+ await taggingStore.updateHighestFinalizedIndex(secret, highestFinalizedIndex, jobId);
121
135
 
122
136
  // For the next iteration we want to look only at indexes for which we have not attempted to load logs yet while
123
137
  // ensuring that we do not look further than WINDOW_LEN ahead of the highest finalized index.
@@ -1,9 +1,12 @@
1
1
  import type { BlockNumber } from '@aztec/foundation/branded-types';
2
2
  import type { AztecAddress } from '@aztec/stdlib/aztec-address';
3
+ import type { L2BlockHash } from '@aztec/stdlib/block';
3
4
  import type { AztecNode } from '@aztec/stdlib/interfaces/client';
4
5
  import type { DirectionalAppTaggingSecret, PreTag, TxScopedL2Log } from '@aztec/stdlib/logs';
5
6
  import { SiloedTag, Tag } from '@aztec/stdlib/logs';
6
7
 
8
+ import { getAllPrivateLogsByTags } from '../../get_all_logs_by_tags.js';
9
+
7
10
  /**
8
11
  * Gets private logs with their corresponding block timestamps and tagging indexes for the given index range, `app` and
9
12
  * `secret`. At most load logs from blocks up to and including `anchorBlockNumber`. `start` is inclusive and `end` is
@@ -16,6 +19,7 @@ export async function loadLogsForRange(
16
19
  start: number,
17
20
  end: number,
18
21
  anchorBlockNumber: BlockNumber,
22
+ anchorBlockHash: L2BlockHash,
19
23
  ): Promise<Array<{ log: TxScopedL2Log; taggingIndex: number }>> {
20
24
  // Derive tags for the window
21
25
  const preTags: PreTag[] = Array(end - start)
@@ -25,7 +29,9 @@ export async function loadLogsForRange(
25
29
  Promise.all(tags.map(tag => SiloedTag.compute(tag, app))),
26
30
  );
27
31
 
28
- const logs = await aztecNode.getPrivateLogsByTags(siloedTags);
32
+ // We use the utility function below to retrieve all logs for the tags across all pages, so we don't need to handle
33
+ // pagination here.
34
+ const logs = await getAllPrivateLogsByTags(aztecNode, siloedTags, anchorBlockHash);
29
35
 
30
36
  // Pair logs with their corresponding tagging indexes
31
37
  const logsWithIndexes: Array<{ log: TxScopedL2Log; taggingIndex: number }> = [];