@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.
- package/dest/bin/check_oracle_version.js +1 -1
- package/dest/block_synchronizer/block_synchronizer.d.ts +10 -4
- package/dest/block_synchronizer/block_synchronizer.d.ts.map +1 -1
- package/dest/block_synchronizer/block_synchronizer.js +66 -18
- package/dest/config/index.d.ts +3 -1
- package/dest/config/index.d.ts.map +1 -1
- package/dest/config/index.js +17 -0
- package/dest/config/package_info.js +1 -1
- package/dest/contract_function_simulator/benchmarked_node.d.ts +9 -0
- package/dest/contract_function_simulator/benchmarked_node.d.ts.map +1 -0
- package/dest/contract_function_simulator/benchmarked_node.js +77 -0
- package/dest/contract_function_simulator/contract_function_simulator.d.ts +8 -9
- package/dest/contract_function_simulator/contract_function_simulator.d.ts.map +1 -1
- package/dest/contract_function_simulator/contract_function_simulator.js +32 -21
- package/dest/contract_function_simulator/execution_note_cache.d.ts +18 -9
- package/dest/contract_function_simulator/execution_note_cache.d.ts.map +1 -1
- package/dest/contract_function_simulator/execution_note_cache.js +45 -28
- package/dest/contract_function_simulator/index.d.ts +2 -2
- package/dest/contract_function_simulator/index.d.ts.map +1 -1
- package/dest/contract_function_simulator/index.js +1 -1
- package/dest/contract_function_simulator/noir-structs/event_validation_request.d.ts +4 -3
- package/dest/contract_function_simulator/noir-structs/event_validation_request.d.ts.map +1 -1
- package/dest/contract_function_simulator/noir-structs/event_validation_request.js +6 -3
- package/dest/contract_function_simulator/noir-structs/note_validation_request.d.ts +1 -1
- package/dest/contract_function_simulator/noir-structs/note_validation_request.js +1 -1
- package/dest/contract_function_simulator/noir-structs/utility_context.d.ts +4 -10
- package/dest/contract_function_simulator/noir-structs/utility_context.d.ts.map +1 -1
- package/dest/contract_function_simulator/noir-structs/utility_context.js +7 -18
- package/dest/contract_function_simulator/oracle/interfaces.d.ts +15 -11
- package/dest/contract_function_simulator/oracle/interfaces.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/message_load_oracle_inputs.d.ts +3 -1
- package/dest/contract_function_simulator/oracle/message_load_oracle_inputs.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/note_packing_utils.d.ts +6 -6
- package/dest/contract_function_simulator/oracle/note_packing_utils.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/note_packing_utils.js +8 -8
- package/dest/contract_function_simulator/oracle/oracle.d.ts +10 -8
- package/dest/contract_function_simulator/oracle/oracle.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/oracle.js +43 -32
- package/dest/contract_function_simulator/oracle/private_execution.d.ts +2 -26
- package/dest/contract_function_simulator/oracle/private_execution.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/private_execution.js +1 -37
- package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts +11 -17
- package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/private_execution_oracle.js +23 -39
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts +27 -17
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.js +72 -72
- package/dest/contract_sync/index.d.ts +23 -0
- package/dest/contract_sync/index.d.ts.map +1 -0
- package/dest/contract_sync/index.js +54 -0
- package/dest/debug/pxe_debug_utils.d.ts +1 -1
- package/dest/debug/pxe_debug_utils.d.ts.map +1 -1
- package/dest/debug/pxe_debug_utils.js +3 -2
- package/dest/entrypoints/client/bundle/utils.d.ts +1 -1
- package/dest/entrypoints/client/bundle/utils.d.ts.map +1 -1
- package/dest/entrypoints/client/bundle/utils.js +10 -1
- package/dest/entrypoints/client/lazy/utils.d.ts +1 -1
- package/dest/entrypoints/client/lazy/utils.d.ts.map +1 -1
- package/dest/entrypoints/client/lazy/utils.js +10 -1
- package/dest/entrypoints/pxe_creation_options.d.ts +3 -2
- package/dest/entrypoints/pxe_creation_options.d.ts.map +1 -1
- package/dest/entrypoints/server/index.d.ts +3 -1
- package/dest/entrypoints/server/index.d.ts.map +1 -1
- package/dest/entrypoints/server/index.js +2 -0
- package/dest/entrypoints/server/utils.d.ts +1 -1
- package/dest/entrypoints/server/utils.d.ts.map +1 -1
- package/dest/entrypoints/server/utils.js +11 -7
- package/dest/events/event_service.d.ts +4 -3
- package/dest/events/event_service.d.ts.map +1 -1
- package/dest/events/event_service.js +17 -19
- package/dest/events/private_event_filter_validator.d.ts +5 -5
- package/dest/events/private_event_filter_validator.d.ts.map +1 -1
- package/dest/events/private_event_filter_validator.js +5 -6
- package/dest/job_coordinator/job_coordinator.d.ts +74 -0
- package/dest/job_coordinator/job_coordinator.d.ts.map +1 -0
- package/dest/job_coordinator/job_coordinator.js +93 -0
- package/dest/logs/log_service.d.ts +3 -2
- package/dest/logs/log_service.d.ts.map +1 -1
- package/dest/logs/log_service.js +21 -13
- package/dest/notes/note_service.d.ts +5 -4
- package/dest/notes/note_service.d.ts.map +1 -1
- package/dest/notes/note_service.js +30 -34
- package/dest/oracle_version.d.ts +3 -3
- package/dest/oracle_version.d.ts.map +1 -1
- package/dest/oracle_version.js +4 -3
- package/dest/private_kernel/hints/index.d.ts +2 -2
- package/dest/private_kernel/hints/index.d.ts.map +1 -1
- package/dest/private_kernel/hints/index.js +1 -1
- package/dest/private_kernel/hints/private_kernel_reset_private_inputs_builder.d.ts +28 -0
- package/dest/private_kernel/hints/private_kernel_reset_private_inputs_builder.d.ts.map +1 -0
- package/dest/private_kernel/hints/{build_private_kernel_reset_private_inputs.js → private_kernel_reset_private_inputs_builder.js} +13 -7
- package/dest/private_kernel/private_kernel_execution_prover.d.ts +1 -1
- package/dest/private_kernel/private_kernel_execution_prover.d.ts.map +1 -1
- package/dest/private_kernel/private_kernel_execution_prover.js +4 -5
- package/dest/private_kernel/private_kernel_oracle.d.ts +24 -28
- package/dest/private_kernel/private_kernel_oracle.d.ts.map +1 -1
- package/dest/private_kernel/private_kernel_oracle.js +90 -2
- package/dest/pxe.d.ts +8 -36
- package/dest/pxe.d.ts.map +1 -1
- package/dest/pxe.js +70 -93
- package/dest/storage/capsule_store/capsule_store.d.ts +24 -9
- package/dest/storage/capsule_store/capsule_store.d.ts.map +1 -1
- package/dest/storage/capsule_store/capsule_store.js +132 -23
- package/dest/storage/contract_store/contract_store.d.ts +1 -2
- package/dest/storage/contract_store/contract_store.d.ts.map +1 -1
- package/dest/storage/contract_store/contract_store.js +0 -12
- package/dest/storage/note_store/note_store.d.ts +45 -56
- package/dest/storage/note_store/note_store.d.ts.map +1 -1
- package/dest/storage/note_store/note_store.js +244 -263
- package/dest/storage/note_store/stored_note.d.ts +16 -0
- package/dest/storage/note_store/stored_note.d.ts.map +1 -0
- package/dest/storage/note_store/stored_note.js +43 -0
- package/dest/storage/private_event_store/private_event_store.d.ts +47 -7
- package/dest/storage/private_event_store/private_event_store.d.ts.map +1 -1
- package/dest/storage/private_event_store/private_event_store.js +203 -68
- package/dest/storage/private_event_store/stored_private_event.d.ts +23 -0
- package/dest/storage/private_event_store/stored_private_event.d.ts.map +1 -0
- package/dest/storage/private_event_store/stored_private_event.js +56 -0
- package/dest/storage/tagging_store/recipient_tagging_store.d.ts +15 -8
- package/dest/storage/tagging_store/recipient_tagging_store.d.ts.map +1 -1
- package/dest/storage/tagging_store/recipient_tagging_store.js +69 -12
- package/dest/storage/tagging_store/sender_tagging_store.d.ts +19 -9
- package/dest/storage/tagging_store/sender_tagging_store.d.ts.map +1 -1
- package/dest/storage/tagging_store/sender_tagging_store.js +110 -28
- package/dest/tagging/constants.d.ts +2 -0
- package/dest/tagging/constants.d.ts.map +1 -0
- package/dest/tagging/constants.js +10 -0
- package/dest/tagging/get_all_logs_by_tags.d.ts +24 -0
- package/dest/tagging/get_all_logs_by_tags.d.ts.map +1 -0
- package/dest/tagging/get_all_logs_by_tags.js +46 -0
- package/dest/tagging/index.d.ts +3 -2
- package/dest/tagging/index.d.ts.map +1 -1
- package/dest/tagging/index.js +2 -10
- package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.d.ts +3 -2
- package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.d.ts.map +1 -1
- package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.js +8 -8
- package/dest/tagging/recipient_sync/utils/load_logs_for_range.d.ts +3 -2
- package/dest/tagging/recipient_sync/utils/load_logs_for_range.d.ts.map +1 -1
- package/dest/tagging/recipient_sync/utils/load_logs_for_range.js +5 -2
- package/dest/tagging/sender_sync/sync_sender_tagging_indexes.d.ts +3 -2
- package/dest/tagging/sender_sync/sync_sender_tagging_indexes.d.ts.map +1 -1
- package/dest/tagging/sender_sync/sync_sender_tagging_indexes.js +8 -8
- package/dest/tagging/sender_sync/utils/get_status_change_of_pending.d.ts +1 -1
- package/dest/tagging/sender_sync/utils/get_status_change_of_pending.d.ts.map +1 -1
- package/dest/tagging/sender_sync/utils/get_status_change_of_pending.js +5 -8
- package/dest/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.d.ts +5 -2
- package/dest/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.d.ts.map +1 -1
- package/dest/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.js +10 -5
- package/package.json +18 -18
- package/src/bin/check_oracle_version.ts +1 -0
- package/src/block_synchronizer/block_synchronizer.ts +77 -20
- package/src/config/index.ts +14 -0
- package/src/config/package_info.ts +1 -1
- package/src/contract_function_simulator/benchmarked_node.ts +103 -0
- package/src/contract_function_simulator/contract_function_simulator.ts +37 -26
- package/src/contract_function_simulator/execution_note_cache.ts +44 -25
- package/src/contract_function_simulator/index.ts +1 -1
- package/src/contract_function_simulator/noir-structs/event_validation_request.ts +5 -1
- package/src/contract_function_simulator/noir-structs/note_validation_request.ts +1 -1
- package/src/contract_function_simulator/noir-structs/utility_context.ts +6 -25
- package/src/contract_function_simulator/oracle/interfaces.ts +20 -10
- package/src/contract_function_simulator/oracle/note_packing_utils.ts +10 -10
- package/src/contract_function_simulator/oracle/oracle.ts +56 -41
- package/src/contract_function_simulator/oracle/private_execution.ts +1 -69
- package/src/contract_function_simulator/oracle/private_execution_oracle.ts +39 -44
- package/src/contract_function_simulator/oracle/utility_execution_oracle.ts +90 -76
- package/src/contract_sync/index.ts +98 -0
- package/src/debug/pxe_debug_utils.ts +3 -2
- package/src/entrypoints/client/bundle/utils.ts +7 -1
- package/src/entrypoints/client/lazy/utils.ts +7 -2
- package/src/entrypoints/pxe_creation_options.ts +2 -1
- package/src/entrypoints/server/index.ts +2 -0
- package/src/entrypoints/server/utils.ts +11 -15
- package/src/events/event_service.ts +17 -21
- package/src/events/private_event_filter_validator.ts +3 -5
- package/src/job_coordinator/job_coordinator.ts +149 -0
- package/src/logs/log_service.ts +27 -9
- package/src/notes/note_service.ts +37 -40
- package/src/oracle_version.ts +4 -3
- package/src/private_kernel/hints/index.ts +1 -1
- package/src/private_kernel/hints/{build_private_kernel_reset_private_inputs.ts → private_kernel_reset_private_inputs_builder.ts} +33 -22
- package/src/private_kernel/private_kernel_execution_prover.ts +3 -5
- package/src/private_kernel/private_kernel_oracle.ts +116 -36
- package/src/pxe.ts +123 -127
- package/src/storage/capsule_store/capsule_store.ts +159 -23
- package/src/storage/contract_store/contract_store.ts +0 -20
- package/src/storage/note_store/note_store.ts +286 -317
- package/src/storage/note_store/stored_note.ts +48 -0
- package/src/storage/private_event_store/private_event_store.ts +277 -76
- package/src/storage/private_event_store/stored_private_event.ts +73 -0
- package/src/storage/tagging_store/recipient_tagging_store.ts +89 -13
- package/src/storage/tagging_store/sender_tagging_store.ts +129 -28
- package/src/tagging/constants.ts +10 -0
- package/src/tagging/get_all_logs_by_tags.ts +68 -0
- package/src/tagging/index.ts +2 -11
- package/src/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.ts +21 -7
- package/src/tagging/recipient_sync/utils/load_logs_for_range.ts +7 -1
- package/src/tagging/sender_sync/sync_sender_tagging_indexes.ts +10 -7
- package/src/tagging/sender_sync/utils/get_status_change_of_pending.ts +5 -13
- package/src/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.ts +16 -4
- package/dest/contract_function_simulator/proxied_node.d.ts +0 -9
- package/dest/contract_function_simulator/proxied_node.d.ts.map +0 -1
- package/dest/contract_function_simulator/proxied_node.js +0 -27
- package/dest/private_kernel/hints/build_private_kernel_reset_private_inputs.d.ts +0 -28
- package/dest/private_kernel/hints/build_private_kernel_reset_private_inputs.d.ts.map +0 -1
- package/dest/private_kernel/private_kernel_oracle_impl.d.ts +0 -46
- package/dest/private_kernel/private_kernel_oracle_impl.d.ts.map +0 -1
- package/dest/private_kernel/private_kernel_oracle_impl.js +0 -86
- package/dest/public_storage/public_storage_service.d.ts +0 -24
- package/dest/public_storage/public_storage_service.d.ts.map +0 -1
- package/dest/public_storage/public_storage_service.js +0 -26
- package/dest/tree_membership/tree_membership_service.d.ts +0 -52
- package/dest/tree_membership/tree_membership_service.d.ts.map +0 -1
- package/dest/tree_membership/tree_membership_service.js +0 -84
- package/src/contract_function_simulator/proxied_node.ts +0 -33
- package/src/private_kernel/private_kernel_oracle_impl.ts +0 -133
- package/src/public_storage/public_storage_service.ts +0 -33
- 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.#
|
|
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.#
|
|
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
|
-
|
|
113
|
+
this.#writeHighestAgedIndex(jobId, secret.toString(), index);
|
|
38
114
|
}
|
|
39
115
|
|
|
40
|
-
getHighestFinalizedIndex(secret: DirectionalAppTaggingSecret): Promise<number | undefined> {
|
|
41
|
-
return this.#
|
|
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.#
|
|
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
|
-
|
|
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 {
|
|
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
|
|
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.#
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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.#
|
|
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 =
|
|
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.#
|
|
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
|
|
169
|
-
const allSecrets = await
|
|
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.#
|
|
273
|
+
const pendingData = await this.#readPendingIndexes(jobId, secret);
|
|
173
274
|
if (pendingData) {
|
|
174
|
-
const filtered = pendingData.filter(item => !
|
|
275
|
+
const filtered = pendingData.filter(item => !txHashStrings.has(item.txHash));
|
|
175
276
|
if (filtered.length === 0) {
|
|
176
|
-
|
|
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
|
-
|
|
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
|
|
299
|
+
const allSecrets = await this.#readSecretsWithPendingIndexes(jobId);
|
|
199
300
|
|
|
200
301
|
for (const secret of allSecrets) {
|
|
201
|
-
const pendingData = await this.#
|
|
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.#
|
|
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
|
-
|
|
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
|
-
|
|
338
|
+
this.#writePendingIndexes(jobId, secret, []);
|
|
238
339
|
} else {
|
|
239
|
-
|
|
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
|
+
}
|
package/src/tagging/index.ts
CHANGED
|
@@ -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
|
-
|
|
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 '../
|
|
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] = [
|
|
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(
|
|
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
|
-
|
|
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 }> = [];
|