@aztec/pxe 0.0.1-commit.fcb71a6 → 0.0.1-commit.ff7989d6c
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/access_scopes.d.ts +9 -0
- package/dest/access_scopes.d.ts.map +1 -0
- package/dest/access_scopes.js +6 -0
- package/dest/bin/check_oracle_version.js +1 -1
- package/dest/block_synchronizer/block_synchronizer.d.ts +13 -5
- package/dest/block_synchronizer/block_synchronizer.d.ts.map +1 -1
- package/dest/block_synchronizer/block_synchronizer.js +74 -20
- 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 +57 -34
- package/dest/contract_function_simulator/contract_function_simulator.d.ts.map +1 -1
- package/dest/contract_function_simulator/contract_function_simulator.js +197 -82
- 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 +7 -4
- package/dest/contract_function_simulator/noir-structs/note_validation_request.d.ts +3 -3
- package/dest/contract_function_simulator/noir-structs/note_validation_request.d.ts.map +1 -1
- package/dest/contract_function_simulator/noir-structs/note_validation_request.js +2 -2
- 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 +17 -13
- 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 +12 -10
- package/dest/contract_function_simulator/oracle/oracle.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/oracle.js +67 -44
- 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 +44 -50
- package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/private_execution_oracle.js +83 -54
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts +67 -33
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.js +131 -110
- package/dest/contract_logging.d.ts +22 -0
- package/dest/contract_logging.d.ts.map +1 -0
- package/dest/contract_logging.js +23 -0
- package/dest/contract_sync/contract_sync_service.d.ts +43 -0
- package/dest/contract_sync/contract_sync_service.d.ts.map +1 -0
- package/dest/contract_sync/contract_sync_service.js +97 -0
- package/dest/contract_sync/helpers.d.ts +29 -0
- package/dest/contract_sync/helpers.d.ts.map +1 -0
- package/dest/contract_sync/helpers.js +55 -0
- package/dest/debug/pxe_debug_utils.d.ts +24 -10
- package/dest/debug/pxe_debug_utils.d.ts.map +1 -1
- package/dest/debug/pxe_debug_utils.js +28 -17
- package/dest/entrypoints/client/bundle/index.d.ts +4 -1
- package/dest/entrypoints/client/bundle/index.d.ts.map +1 -1
- package/dest/entrypoints/client/bundle/index.js +3 -0
- 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 +31 -8
- package/dest/entrypoints/client/lazy/index.d.ts +4 -1
- package/dest/entrypoints/client/lazy/index.d.ts.map +1 -1
- package/dest/entrypoints/client/lazy/index.js +3 -0
- package/dest/entrypoints/client/lazy/utils.d.ts +2 -2
- package/dest/entrypoints/client/lazy/utils.d.ts.map +1 -1
- package/dest/entrypoints/client/lazy/utils.js +32 -9
- package/dest/entrypoints/pxe_creation_options.d.ts +5 -3
- package/dest/entrypoints/pxe_creation_options.d.ts.map +1 -1
- package/dest/entrypoints/server/index.d.ts +5 -1
- package/dest/entrypoints/server/index.d.ts.map +1 -1
- package/dest/entrypoints/server/index.js +4 -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 +39 -16
- package/dest/events/event_service.d.ts +6 -6
- package/dest/events/event_service.d.ts.map +1 -1
- package/dest/events/event_service.js +19 -22
- 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 +75 -0
- package/dest/job_coordinator/job_coordinator.d.ts.map +1 -0
- package/dest/job_coordinator/job_coordinator.js +94 -0
- package/dest/logs/log_service.d.ts +8 -5
- package/dest/logs/log_service.d.ts.map +1 -1
- package/dest/logs/log_service.js +28 -30
- package/dest/notes/note_service.d.ts +10 -9
- package/dest/notes/note_service.d.ts.map +1 -1
- package/dest/notes/note_service.js +34 -38
- package/dest/notes_filter.d.ts +25 -0
- package/dest/notes_filter.d.ts.map +1 -0
- package/dest/notes_filter.js +4 -0
- 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/compute_tx_expiration_timestamp.d.ts +4 -0
- package/dest/private_kernel/hints/compute_tx_expiration_timestamp.d.ts.map +1 -0
- package/dest/private_kernel/hints/{compute_tx_include_by_timestamp.js → compute_tx_expiration_timestamp.js} +12 -12
- package/dest/private_kernel/hints/index.d.ts +3 -3
- package/dest/private_kernel/hints/index.d.ts.map +1 -1
- package/dest/private_kernel/hints/index.js +2 -2
- 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} +16 -10
- package/dest/private_kernel/private_kernel_execution_prover.d.ts +3 -2
- package/dest/private_kernel/private_kernel_execution_prover.d.ts.map +1 -1
- package/dest/private_kernel/private_kernel_execution_prover.js +12 -13
- package/dest/private_kernel/private_kernel_oracle.d.ts +24 -24
- package/dest/private_kernel/private_kernel_oracle.d.ts.map +1 -1
- package/dest/private_kernel/private_kernel_oracle.js +94 -2
- package/dest/pxe.d.ts +76 -58
- package/dest/pxe.d.ts.map +1 -1
- package/dest/pxe.js +149 -138
- package/dest/storage/address_store/address_store.d.ts +1 -1
- package/dest/storage/address_store/address_store.d.ts.map +1 -1
- package/dest/storage/address_store/address_store.js +12 -11
- package/dest/storage/anchor_block_store/anchor_block_store.d.ts +9 -1
- package/dest/storage/anchor_block_store/anchor_block_store.d.ts.map +1 -1
- package/dest/storage/anchor_block_store/anchor_block_store.js +8 -1
- 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 +130 -23
- package/dest/storage/contract_store/contract_store.d.ts +42 -16
- package/dest/storage/contract_store/contract_store.d.ts.map +1 -1
- package/dest/storage/contract_store/contract_store.js +157 -84
- package/dest/storage/metadata.d.ts +1 -1
- package/dest/storage/metadata.js +1 -1
- package/dest/storage/note_store/note_store.d.ts +50 -51
- package/dest/storage/note_store/note_store.d.ts.map +1 -1
- package/dest/storage/note_store/note_store.js +284 -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 +231 -73
- 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 +88 -19
- package/dest/storage/tagging_store/sender_address_book_store.d.ts +1 -1
- package/dest/storage/tagging_store/sender_address_book_store.d.ts.map +1 -1
- package/dest/storage/tagging_store/sender_address_book_store.js +20 -14
- 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 +253 -101
- 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 +60 -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 +12 -12
- package/dest/tagging/recipient_sync/utils/find_highest_indexes.js +2 -2
- 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 +27 -18
- package/src/access_scopes.ts +9 -0
- package/src/bin/check_oracle_version.ts +1 -0
- package/src/block_synchronizer/block_synchronizer.ts +93 -32
- 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 +350 -143
- 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 +6 -2
- package/src/contract_function_simulator/noir-structs/note_validation_request.ts +2 -2
- package/src/contract_function_simulator/noir-structs/utility_context.ts +6 -25
- package/src/contract_function_simulator/oracle/interfaces.ts +22 -12
- package/src/contract_function_simulator/oracle/note_packing_utils.ts +10 -10
- package/src/contract_function_simulator/oracle/oracle.ts +79 -47
- package/src/contract_function_simulator/oracle/private_execution.ts +1 -69
- package/src/contract_function_simulator/oracle/private_execution_oracle.ts +119 -137
- package/src/contract_function_simulator/oracle/utility_execution_oracle.ts +198 -115
- package/src/contract_logging.ts +39 -0
- package/src/contract_sync/contract_sync_service.ts +152 -0
- package/src/contract_sync/helpers.ts +98 -0
- package/src/debug/pxe_debug_utils.ts +63 -18
- package/src/entrypoints/client/bundle/index.ts +3 -0
- package/src/entrypoints/client/bundle/utils.ts +23 -16
- package/src/entrypoints/client/lazy/index.ts +3 -0
- package/src/entrypoints/client/lazy/utils.ts +24 -17
- package/src/entrypoints/pxe_creation_options.ts +4 -2
- package/src/entrypoints/server/index.ts +4 -0
- package/src/entrypoints/server/utils.ts +33 -41
- package/src/events/event_service.ts +19 -25
- package/src/events/private_event_filter_validator.ts +3 -5
- package/src/job_coordinator/job_coordinator.ts +150 -0
- package/src/logs/log_service.ts +40 -34
- package/src/notes/note_service.ts +41 -45
- package/src/notes_filter.ts +26 -0
- package/src/oracle_version.ts +4 -3
- package/src/private_kernel/hints/{compute_tx_include_by_timestamp.ts → compute_tx_expiration_timestamp.ts} +13 -13
- package/src/private_kernel/hints/index.ts +2 -2
- package/src/private_kernel/hints/{build_private_kernel_reset_private_inputs.ts → private_kernel_reset_private_inputs_builder.ts} +39 -28
- package/src/private_kernel/private_kernel_execution_prover.ts +15 -14
- package/src/private_kernel/private_kernel_oracle.ts +116 -36
- package/src/pxe.ts +280 -209
- package/src/storage/address_store/address_store.ts +15 -15
- package/src/storage/anchor_block_store/anchor_block_store.ts +8 -0
- package/src/storage/capsule_store/capsule_store.ts +159 -23
- package/src/storage/contract_store/contract_store.ts +186 -96
- package/src/storage/metadata.ts +1 -1
- package/src/storage/note_store/note_store.ts +326 -320
- package/src/storage/note_store/stored_note.ts +48 -0
- package/src/storage/private_event_store/private_event_store.ts +301 -79
- package/src/storage/private_event_store/stored_private_event.ts +73 -0
- package/src/storage/tagging_store/recipient_tagging_store.ts +106 -20
- package/src/storage/tagging_store/sender_address_book_store.ts +20 -14
- package/src/storage/tagging_store/sender_tagging_store.ts +294 -109
- package/src/tagging/constants.ts +10 -0
- package/src/tagging/get_all_logs_by_tags.ts +92 -0
- package/src/tagging/index.ts +2 -11
- package/src/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.ts +25 -11
- package/src/tagging/recipient_sync/utils/find_highest_indexes.ts +2 -2
- 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/hints/compute_tx_include_by_timestamp.d.ts +0 -4
- package/dest/private_kernel/hints/compute_tx_include_by_timestamp.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,16 +1,18 @@
|
|
|
1
|
-
import { toArray } from '@aztec/foundation/iterable';
|
|
2
1
|
import type { AztecAsyncKVStore, AztecAsyncMap } from '@aztec/kv-store';
|
|
3
2
|
import type { DirectionalAppTaggingSecret, PreTag } from '@aztec/stdlib/logs';
|
|
4
3
|
import { TxHash } from '@aztec/stdlib/tx';
|
|
5
4
|
|
|
6
|
-
import {
|
|
5
|
+
import type { StagedStore } from '../../job_coordinator/job_coordinator.js';
|
|
6
|
+
import { UNFINALIZED_TAGGING_INDEXES_WINDOW_LEN } from '../../tagging/constants.js';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* 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
|
|
10
|
+
* is called RecipientTaggingStore. We have the data stores separate for sender and recipient because
|
|
11
11
|
* the algorithms are completely disjoint and there is not data reuse between the two.
|
|
12
12
|
*/
|
|
13
|
-
export class SenderTaggingStore {
|
|
13
|
+
export class SenderTaggingStore implements StagedStore {
|
|
14
|
+
readonly storeName = 'sender_tagging';
|
|
15
|
+
|
|
14
16
|
#store: AztecAsyncKVStore;
|
|
15
17
|
|
|
16
18
|
// Stores the pending indexes for each directional app tagging secret. Pending here means that the tx that contained
|
|
@@ -21,18 +23,106 @@ export class SenderTaggingStore {
|
|
|
21
23
|
// the smaller ones are irrelevant due to tx atomicity.
|
|
22
24
|
//
|
|
23
25
|
// TODO(#17615): This assumes no logs are used in the non-revertible phase.
|
|
26
|
+
//
|
|
27
|
+
// directional app tagging secret => { pending index, txHash }[]
|
|
24
28
|
#pendingIndexes: AztecAsyncMap<string, { index: number; txHash: string }[]>;
|
|
25
29
|
|
|
30
|
+
// jobId => directional app tagging secret => { pending index, txHash }[]
|
|
31
|
+
#pendingIndexesForJob: Map<string, Map<string, { index: number; txHash: string }[]>>;
|
|
32
|
+
|
|
26
33
|
// Stores the last (highest) finalized index for each directional app tagging secret. We care only about the last
|
|
27
34
|
// index because unlike the pending indexes, it will never happen that a finalized index would be removed and hence
|
|
28
35
|
// we don't need to store the history.
|
|
36
|
+
//
|
|
37
|
+
// directional app tagging secret => highest finalized index
|
|
29
38
|
#lastFinalizedIndexes: AztecAsyncMap<string, number>;
|
|
30
39
|
|
|
40
|
+
// jobId => directional app tagging secret => highest finalized index
|
|
41
|
+
#lastFinalizedIndexesForJob: Map<string, Map<string, number>>;
|
|
42
|
+
|
|
31
43
|
constructor(store: AztecAsyncKVStore) {
|
|
32
44
|
this.#store = store;
|
|
33
45
|
|
|
34
46
|
this.#pendingIndexes = this.#store.openMap('pending_indexes');
|
|
35
47
|
this.#lastFinalizedIndexes = this.#store.openMap('last_finalized_indexes');
|
|
48
|
+
|
|
49
|
+
this.#pendingIndexesForJob = new Map();
|
|
50
|
+
this.#lastFinalizedIndexesForJob = new Map();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
#getPendingIndexesForJob(jobId: string): Map<string, { index: number; txHash: string }[]> {
|
|
54
|
+
let pendingIndexesForJob = this.#pendingIndexesForJob.get(jobId);
|
|
55
|
+
if (!pendingIndexesForJob) {
|
|
56
|
+
pendingIndexesForJob = new Map();
|
|
57
|
+
this.#pendingIndexesForJob.set(jobId, pendingIndexesForJob);
|
|
58
|
+
}
|
|
59
|
+
return pendingIndexesForJob;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
#getLastFinalizedIndexesForJob(jobId: string): Map<string, number> {
|
|
63
|
+
let jobStagedLastFinalizedIndexes = this.#lastFinalizedIndexesForJob.get(jobId);
|
|
64
|
+
if (!jobStagedLastFinalizedIndexes) {
|
|
65
|
+
jobStagedLastFinalizedIndexes = new Map();
|
|
66
|
+
this.#lastFinalizedIndexesForJob.set(jobId, jobStagedLastFinalizedIndexes);
|
|
67
|
+
}
|
|
68
|
+
return jobStagedLastFinalizedIndexes;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async #readPendingIndexes(jobId: string, secret: string): Promise<{ index: number; txHash: string }[]> {
|
|
72
|
+
// Always issue DB read to keep IndexedDB transaction alive (they auto-commit when a new micro-task starts and there
|
|
73
|
+
// are no pending read requests). The staged value still takes precedence if it exists.
|
|
74
|
+
const dbValue = await this.#pendingIndexes.getAsync(secret);
|
|
75
|
+
const staged = this.#getPendingIndexesForJob(jobId).get(secret);
|
|
76
|
+
return staged !== undefined ? staged : (dbValue ?? []);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
#writePendingIndexes(jobId: string, secret: string, pendingIndexes: { index: number; txHash: string }[]) {
|
|
80
|
+
this.#getPendingIndexesForJob(jobId).set(secret, pendingIndexes);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async #readLastFinalizedIndex(jobId: string, secret: string): Promise<number | undefined> {
|
|
84
|
+
// Always issue DB read to keep IndexedDB transaction alive (they auto-commit when a new micro-task starts and there
|
|
85
|
+
// are no pending read requests). The staged value still takes precedence if it exists.
|
|
86
|
+
const dbValue = await this.#lastFinalizedIndexes.getAsync(secret);
|
|
87
|
+
const staged = this.#getLastFinalizedIndexesForJob(jobId).get(secret);
|
|
88
|
+
return staged ?? dbValue;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
#writeLastFinalizedIndex(jobId: string, secret: string, lastFinalizedIndex: number) {
|
|
92
|
+
this.#getLastFinalizedIndexesForJob(jobId).set(secret, lastFinalizedIndex);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Writes all job-specific in-memory data to persistent storage.
|
|
97
|
+
*
|
|
98
|
+
* @remark This method must run in a DB transaction context. It's designed to be called from JobCoordinator#commitJob.
|
|
99
|
+
*/
|
|
100
|
+
async commit(jobId: string): Promise<void> {
|
|
101
|
+
const pendingIndexesForJob = this.#pendingIndexesForJob.get(jobId);
|
|
102
|
+
if (pendingIndexesForJob) {
|
|
103
|
+
for (const [secret, pendingIndexes] of pendingIndexesForJob.entries()) {
|
|
104
|
+
if (pendingIndexes.length === 0) {
|
|
105
|
+
await this.#pendingIndexes.delete(secret);
|
|
106
|
+
} else {
|
|
107
|
+
await this.#pendingIndexes.set(secret, pendingIndexes);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const lastFinalizedIndexesForJob = this.#lastFinalizedIndexesForJob.get(jobId);
|
|
113
|
+
if (lastFinalizedIndexesForJob) {
|
|
114
|
+
for (const [secret, lastFinalizedIndex] of lastFinalizedIndexesForJob.entries()) {
|
|
115
|
+
await this.#lastFinalizedIndexes.set(secret, lastFinalizedIndex);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return this.discardStaged(jobId);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
discardStaged(jobId: string): Promise<void> {
|
|
123
|
+
this.#pendingIndexesForJob.delete(jobId);
|
|
124
|
+
this.#lastFinalizedIndexesForJob.delete(jobId);
|
|
125
|
+
return Promise.resolve();
|
|
36
126
|
}
|
|
37
127
|
|
|
38
128
|
/**
|
|
@@ -43,6 +133,7 @@ export class SenderTaggingStore {
|
|
|
43
133
|
* @param preTags - The pre-tags containing the directional app tagging secrets and the indexes that are to be
|
|
44
134
|
* stored in the db.
|
|
45
135
|
* @param txHash - The tx in which the pretags were used in private logs.
|
|
136
|
+
* @param jobId - job context for staged writes to this store. See `JobCoordinator` for more details.
|
|
46
137
|
* @throws If any two pre-tags contain the same directional app tagging secret. This is enforced because we care
|
|
47
138
|
* 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
139
|
* bugs.
|
|
@@ -56,55 +147,80 @@ export class SenderTaggingStore {
|
|
|
56
147
|
* This is enforced because this should never happen if the syncing is done correctly as we look for logs from higher
|
|
57
148
|
* indexes than finalized ones.
|
|
58
149
|
*/
|
|
59
|
-
|
|
150
|
+
storePendingIndexes(preTags: PreTag[], txHash: TxHash, jobId: string): Promise<void> {
|
|
151
|
+
if (preTags.length === 0) {
|
|
152
|
+
return Promise.resolve();
|
|
153
|
+
}
|
|
154
|
+
|
|
60
155
|
// The secrets in pre-tags should be unique because we always store just the highest index per given secret-txHash
|
|
61
156
|
// pair. Below we check that this is the case.
|
|
62
157
|
const secretsSet = new Set(preTags.map(preTag => preTag.secret.toString()));
|
|
63
158
|
if (secretsSet.size !== preTags.length) {
|
|
64
|
-
|
|
159
|
+
return Promise.reject(new Error(`Duplicate secrets found when storing pending indexes`));
|
|
65
160
|
}
|
|
66
161
|
|
|
67
|
-
|
|
68
|
-
// First we check that for any secret the highest used index in tx is not further than window length from
|
|
69
|
-
// the highest finalized index.
|
|
70
|
-
const finalizedIndex = (await this.getLastFinalizedIndex(secret)) ?? 0;
|
|
71
|
-
if (index > finalizedIndex + UNFINALIZED_TAGGING_INDEXES_WINDOW_LEN) {
|
|
72
|
-
throw new Error(
|
|
73
|
-
`Highest used index ${index} is further than window length from the highest finalized index ${finalizedIndex}.
|
|
74
|
-
Tagging window length ${UNFINALIZED_TAGGING_INDEXES_WINDOW_LEN} is configured too low. Contact the Aztec team
|
|
75
|
-
to increase it!`,
|
|
76
|
-
);
|
|
77
|
-
}
|
|
162
|
+
const txHashStr = txHash.toString();
|
|
78
163
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
164
|
+
return this.#store.transactionAsync(async () => {
|
|
165
|
+
// Prefetch all data, start reads during iteration to keep IndexedDB transaction alive
|
|
166
|
+
const preTagReadPromises = preTags.map(({ secret, index }) => {
|
|
167
|
+
const secretStr = secret.toString();
|
|
168
|
+
return {
|
|
169
|
+
secret,
|
|
170
|
+
secretStr,
|
|
171
|
+
index,
|
|
172
|
+
pending: this.#readPendingIndexes(jobId, secretStr),
|
|
173
|
+
finalized: this.#readLastFinalizedIndex(jobId, secretStr),
|
|
174
|
+
};
|
|
175
|
+
});
|
|
88
176
|
|
|
89
|
-
//
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
177
|
+
// Await all reads together
|
|
178
|
+
const preTagData = await Promise.all(
|
|
179
|
+
preTagReadPromises.map(async item => ({
|
|
180
|
+
...item,
|
|
181
|
+
pendingData: await item.pending,
|
|
182
|
+
finalizedIndex: await item.finalized,
|
|
183
|
+
})),
|
|
184
|
+
);
|
|
93
185
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
186
|
+
// Process in memory and validate
|
|
187
|
+
for (const { secretStr, index, pendingData, finalizedIndex } of preTagData) {
|
|
188
|
+
// First we check that for any secret the highest used index in tx is not further than window length from
|
|
189
|
+
// the highest finalized index.
|
|
190
|
+
if (index > (finalizedIndex ?? 0) + UNFINALIZED_TAGGING_INDEXES_WINDOW_LEN) {
|
|
97
191
|
throw new Error(
|
|
98
|
-
`
|
|
99
|
-
|
|
192
|
+
`Highest used index ${index} is further than window length from the highest finalized index ${finalizedIndex ?? 0}.
|
|
193
|
+
Tagging window length ${UNFINALIZED_TAGGING_INDEXES_WINDOW_LEN} is configured too low. Contact the Aztec team
|
|
194
|
+
to increase it!`,
|
|
100
195
|
);
|
|
101
196
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
197
|
+
|
|
198
|
+
// Throw if the new pending index is lower than or equal to the last finalized index
|
|
199
|
+
if (finalizedIndex !== undefined && index <= finalizedIndex) {
|
|
200
|
+
throw new Error(
|
|
201
|
+
`Cannot store pending index ${index} for secret ${secretStr}: ` +
|
|
202
|
+
`it is lower than or equal to the last finalized index ${finalizedIndex}`,
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Check if this secret + txHash combination already exists
|
|
207
|
+
const existingForSecretAndTx = pendingData.find(entry => entry.txHash === txHashStr);
|
|
208
|
+
|
|
209
|
+
if (existingForSecretAndTx) {
|
|
210
|
+
// If it exists with a different index, throw an error
|
|
211
|
+
if (existingForSecretAndTx.index !== index) {
|
|
212
|
+
throw new Error(
|
|
213
|
+
`Cannot store index ${index} for secret ${secretStr} and txHash ${txHashStr}: ` +
|
|
214
|
+
`a different index ${existingForSecretAndTx.index} already exists for this secret-txHash pair`,
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
// If it exists with the same index, ignore the update (no-op)
|
|
218
|
+
} else {
|
|
219
|
+
// If it doesn't exist, add it
|
|
220
|
+
this.#writePendingIndexes(jobId, secretStr, [...pendingData, { index, txHash: txHashStr }]);
|
|
221
|
+
}
|
|
106
222
|
}
|
|
107
|
-
}
|
|
223
|
+
});
|
|
108
224
|
}
|
|
109
225
|
|
|
110
226
|
/**
|
|
@@ -116,16 +232,19 @@ export class SenderTaggingStore {
|
|
|
116
232
|
* @returns An array of unique transaction hashes for pending transactions that contain indexes in the range
|
|
117
233
|
* [startIndex, endIndex). Returns an empty array if no pending indexes exist in the range.
|
|
118
234
|
*/
|
|
119
|
-
|
|
235
|
+
getTxHashesOfPendingIndexes(
|
|
120
236
|
secret: DirectionalAppTaggingSecret,
|
|
121
237
|
startIndex: number,
|
|
122
238
|
endIndex: number,
|
|
239
|
+
jobId: string,
|
|
123
240
|
): Promise<TxHash[]> {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
241
|
+
return this.#store.transactionAsync(async () => {
|
|
242
|
+
const existing = await this.#readPendingIndexes(jobId, secret.toString());
|
|
243
|
+
const txHashes = existing
|
|
244
|
+
.filter(entry => entry.index >= startIndex && entry.index < endIndex)
|
|
245
|
+
.map(entry => entry.txHash);
|
|
246
|
+
return Array.from(new Set(txHashes)).map(TxHash.fromString);
|
|
247
|
+
});
|
|
129
248
|
}
|
|
130
249
|
|
|
131
250
|
/**
|
|
@@ -133,8 +252,8 @@ export class SenderTaggingStore {
|
|
|
133
252
|
* @param secret - The secret to get the last finalized index for.
|
|
134
253
|
* @returns The last (highest) finalized index for the given secret.
|
|
135
254
|
*/
|
|
136
|
-
getLastFinalizedIndex(secret: DirectionalAppTaggingSecret): Promise<number | undefined> {
|
|
137
|
-
return this.#
|
|
255
|
+
getLastFinalizedIndex(secret: DirectionalAppTaggingSecret, jobId: string): Promise<number | undefined> {
|
|
256
|
+
return this.#store.transactionAsync(() => this.#readLastFinalizedIndex(jobId, secret.toString()));
|
|
138
257
|
}
|
|
139
258
|
|
|
140
259
|
/**
|
|
@@ -143,102 +262,168 @@ export class SenderTaggingStore {
|
|
|
143
262
|
* @param secret - The directional app tagging secret to query the last used index for.
|
|
144
263
|
* @returns The last used index.
|
|
145
264
|
*/
|
|
146
|
-
|
|
265
|
+
getLastUsedIndex(secret: DirectionalAppTaggingSecret, jobId: string): Promise<number | undefined> {
|
|
147
266
|
const secretStr = secret.toString();
|
|
148
|
-
const pendingTxScopedIndexes = (await this.#pendingIndexes.getAsync(secretStr)) ?? [];
|
|
149
|
-
const pendingIndexes = pendingTxScopedIndexes.map(entry => entry.index);
|
|
150
267
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
268
|
+
return this.#store.transactionAsync(async () => {
|
|
269
|
+
const pendingPromise = this.#readPendingIndexes(jobId, secretStr);
|
|
270
|
+
const finalizedPromise = this.#readLastFinalizedIndex(jobId, secretStr);
|
|
271
|
+
|
|
272
|
+
const [pendingTxScopedIndexes, lastFinalized] = await Promise.all([pendingPromise, finalizedPromise]);
|
|
273
|
+
const pendingIndexes = pendingTxScopedIndexes.map(entry => entry.index);
|
|
154
274
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
275
|
+
if (pendingTxScopedIndexes.length === 0) {
|
|
276
|
+
return lastFinalized;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// As the last used index we return the highest one from the pending indexes. Note that this value will be always
|
|
280
|
+
// higher than the last finalized index because we prune lower pending indexes when a tx is finalized.
|
|
281
|
+
return Math.max(...pendingIndexes);
|
|
282
|
+
});
|
|
158
283
|
}
|
|
159
284
|
|
|
160
285
|
/**
|
|
161
286
|
* Drops all pending indexes corresponding to the given transaction hashes.
|
|
162
287
|
*/
|
|
163
|
-
|
|
288
|
+
dropPendingIndexes(txHashes: TxHash[], jobId: string): Promise<void> {
|
|
164
289
|
if (txHashes.length === 0) {
|
|
165
|
-
return;
|
|
290
|
+
return Promise.resolve();
|
|
166
291
|
}
|
|
167
292
|
|
|
168
|
-
const
|
|
169
|
-
const allSecrets = await toArray(this.#pendingIndexes.keysAsync());
|
|
293
|
+
const txHashStrings = new Set<string>(txHashes.map(txHash => txHash.toString()));
|
|
170
294
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
295
|
+
return this.#store.transactionAsync(async () => {
|
|
296
|
+
// Prefetch all data, start reads during iteration to keep IndexedDB transaction alive
|
|
297
|
+
const secretReadPromises: Map<string, Promise<{ index: number; txHash: string }[]>> = new Map();
|
|
298
|
+
|
|
299
|
+
for await (const secret of this.#pendingIndexes.keysAsync()) {
|
|
300
|
+
secretReadPromises.set(secret, this.#readPendingIndexes(jobId, secret));
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// Add staged-only secrets (sync, no DB)
|
|
304
|
+
for (const secret of this.#getPendingIndexesForJob(jobId).keys()) {
|
|
305
|
+
if (!secretReadPromises.has(secret)) {
|
|
306
|
+
secretReadPromises.set(secret, Promise.resolve(this.#getPendingIndexesForJob(jobId).get(secret) ?? []));
|
|
180
307
|
}
|
|
181
|
-
// else: No items were filtered out (txHashes not found for this secret) --> no-op
|
|
182
308
|
}
|
|
183
|
-
|
|
309
|
+
|
|
310
|
+
// Await all reads together
|
|
311
|
+
const secrets = [...secretReadPromises.keys()];
|
|
312
|
+
const pendingDataResults = await Promise.all(secretReadPromises.values());
|
|
313
|
+
|
|
314
|
+
// Process in memory
|
|
315
|
+
for (let i = 0; i < secrets.length; i++) {
|
|
316
|
+
const secret = secrets[i];
|
|
317
|
+
const pendingData = pendingDataResults[i];
|
|
318
|
+
|
|
319
|
+
if (pendingData && pendingData.length > 0) {
|
|
320
|
+
const filtered = pendingData.filter(item => !txHashStrings.has(item.txHash));
|
|
321
|
+
if (filtered.length === 0) {
|
|
322
|
+
this.#writePendingIndexes(jobId, secret, []);
|
|
323
|
+
} else if (filtered.length !== pendingData.length) {
|
|
324
|
+
// Some items were filtered out, so update the pending data
|
|
325
|
+
this.#writePendingIndexes(jobId, secret, filtered);
|
|
326
|
+
}
|
|
327
|
+
// else: No items were filtered out (txHashes not found for this secret) --> no-op
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
});
|
|
184
331
|
}
|
|
185
332
|
|
|
186
333
|
/**
|
|
187
334
|
* Updates pending indexes corresponding to the given transaction hashes to be finalized and prunes any lower pending
|
|
188
335
|
* indexes.
|
|
189
336
|
*/
|
|
190
|
-
|
|
337
|
+
finalizePendingIndexes(txHashes: TxHash[], jobId: string): Promise<void> {
|
|
191
338
|
if (txHashes.length === 0) {
|
|
192
|
-
return;
|
|
339
|
+
return Promise.resolve();
|
|
193
340
|
}
|
|
194
341
|
|
|
195
|
-
|
|
196
|
-
const txHashStr = txHash.toString();
|
|
342
|
+
const txHashStrings = new Set(txHashes.map(tx => tx.toString()));
|
|
197
343
|
|
|
198
|
-
|
|
344
|
+
return this.#store.transactionAsync(async () => {
|
|
345
|
+
// Prefetch all data, start reads during iteration to keep IndexedDB transaction alive
|
|
346
|
+
const secretDataPromises: Map<
|
|
347
|
+
string,
|
|
348
|
+
{ pending: Promise<{ index: number; txHash: string }[]>; finalized: Promise<number | undefined> }
|
|
349
|
+
> = new Map();
|
|
199
350
|
|
|
200
|
-
for (const secret of
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
351
|
+
for await (const secret of this.#pendingIndexes.keysAsync()) {
|
|
352
|
+
secretDataPromises.set(secret, {
|
|
353
|
+
pending: this.#readPendingIndexes(jobId, secret),
|
|
354
|
+
finalized: this.#readLastFinalizedIndex(jobId, secret),
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// Add staged-only secrets (sync, no DB)
|
|
359
|
+
for (const secret of this.#getPendingIndexesForJob(jobId).keys()) {
|
|
360
|
+
if (!secretDataPromises.has(secret)) {
|
|
361
|
+
secretDataPromises.set(secret, {
|
|
362
|
+
pending: Promise.resolve(this.#getPendingIndexesForJob(jobId).get(secret) ?? []),
|
|
363
|
+
finalized: Promise.resolve(this.#getLastFinalizedIndexesForJob(jobId).get(secret)),
|
|
364
|
+
});
|
|
204
365
|
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// Await all reads together
|
|
369
|
+
const secrets = [...secretDataPromises.keys()];
|
|
370
|
+
const dataResults = await Promise.all(
|
|
371
|
+
secrets.map(async secret => ({
|
|
372
|
+
secret,
|
|
373
|
+
pendingData: await secretDataPromises.get(secret)!.pending,
|
|
374
|
+
lastFinalized: await secretDataPromises.get(secret)!.finalized,
|
|
375
|
+
})),
|
|
376
|
+
);
|
|
205
377
|
|
|
206
|
-
|
|
207
|
-
|
|
378
|
+
// Process all txHashes for each secret in memory
|
|
379
|
+
for (const { secret, pendingData, lastFinalized } of dataResults) {
|
|
380
|
+
if (!pendingData || pendingData.length === 0) {
|
|
208
381
|
continue;
|
|
209
382
|
}
|
|
210
383
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
// values are irrelevant.
|
|
214
|
-
throw new Error(`Multiple pending indexes found for tx hash ${txHashStr} and secret ${secret}`);
|
|
215
|
-
}
|
|
384
|
+
let currentPending = pendingData;
|
|
385
|
+
let currentFinalized = lastFinalized;
|
|
216
386
|
|
|
217
|
-
|
|
218
|
-
const
|
|
387
|
+
// Process all txHashes for this secret
|
|
388
|
+
for (const txHashStr of txHashStrings) {
|
|
389
|
+
const matchingIndexes = currentPending.filter(item => item.txHash === txHashStr).map(item => item.index);
|
|
390
|
+
if (matchingIndexes.length === 0) {
|
|
391
|
+
continue;
|
|
392
|
+
}
|
|
219
393
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
);
|
|
226
|
-
}
|
|
394
|
+
if (matchingIndexes.length > 1) {
|
|
395
|
+
// We should always just store the highest pending index for a given tx hash and secret because the lower
|
|
396
|
+
// values are irrelevant.
|
|
397
|
+
throw new Error(`Multiple pending indexes found for tx hash ${txHashStr} and secret ${secret}`);
|
|
398
|
+
}
|
|
227
399
|
|
|
228
|
-
|
|
229
|
-
lastFinalized = newFinalized;
|
|
400
|
+
const newFinalized = matchingIndexes[0];
|
|
230
401
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
402
|
+
if (newFinalized < (currentFinalized ?? 0)) {
|
|
403
|
+
// This should never happen because when last finalized index was finalized we should have pruned the lower
|
|
404
|
+
// pending indexes.
|
|
405
|
+
throw new Error(
|
|
406
|
+
`New finalized index ${newFinalized} is smaller than the current last finalized index ${currentFinalized}`,
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
currentFinalized = newFinalized;
|
|
411
|
+
|
|
412
|
+
// When we add pending indexes, we ensure they are higher than the last finalized index. However, because we
|
|
413
|
+
// cannot control the order in which transactions are finalized, there may be pending indexes that are now
|
|
414
|
+
// obsolete because they are lower than the most recently finalized index. For this reason, we prune these
|
|
415
|
+
// outdated pending indexes.
|
|
416
|
+
currentPending = currentPending.filter(item => item.index > currentFinalized!);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// Write final state if changed
|
|
420
|
+
if (currentFinalized !== lastFinalized) {
|
|
421
|
+
this.#writeLastFinalizedIndex(jobId, secret, currentFinalized!);
|
|
422
|
+
}
|
|
423
|
+
if (currentPending !== pendingData) {
|
|
424
|
+
this.#writePendingIndexes(jobId, secret, currentPending);
|
|
240
425
|
}
|
|
241
426
|
}
|
|
242
|
-
}
|
|
427
|
+
});
|
|
243
428
|
}
|
|
244
429
|
}
|
|
@@ -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,92 @@
|
|
|
1
|
+
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
2
|
+
import type { BlockHash } from '@aztec/stdlib/block';
|
|
3
|
+
import { MAX_LOGS_PER_TAG, MAX_RPC_LEN } 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
|
+
* Splits tags into chunks of MAX_RPC_LEN, fetches logs for each chunk using getAllPages, then stitches the results
|
|
36
|
+
* back into a single array preserving the original tag order.
|
|
37
|
+
*/
|
|
38
|
+
async function getAllPagesInBatches<Tag, T>(
|
|
39
|
+
tags: Tag[],
|
|
40
|
+
fetchAllPagesForBatch: (batch: Tag[]) => Promise<T[][]>,
|
|
41
|
+
): Promise<T[][]> {
|
|
42
|
+
if (tags.length <= MAX_RPC_LEN) {
|
|
43
|
+
return fetchAllPagesForBatch(tags);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const batches: Tag[][] = [];
|
|
47
|
+
for (let i = 0; i < tags.length; i += MAX_RPC_LEN) {
|
|
48
|
+
batches.push(tags.slice(i, i + MAX_RPC_LEN));
|
|
49
|
+
}
|
|
50
|
+
const batchResults = await Promise.all(batches.map(fetchAllPagesForBatch));
|
|
51
|
+
return batchResults.flat();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Fetches all private logs for the given tags, automatically paginating through all pages.
|
|
56
|
+
* @param aztecNode - The Aztec node to query.
|
|
57
|
+
* @param tags - The siloed tags to search for.
|
|
58
|
+
* @param anchorBlockHash - reference block for the Aztec node query, throws if block is not found there (typically
|
|
59
|
+
* because of reorgs).
|
|
60
|
+
* @returns An array of log arrays, one per tag, containing all logs across all pages.
|
|
61
|
+
*/
|
|
62
|
+
export function getAllPrivateLogsByTags(
|
|
63
|
+
aztecNode: AztecNode,
|
|
64
|
+
tags: SiloedTag[],
|
|
65
|
+
anchorBlockHash: BlockHash,
|
|
66
|
+
): Promise<TxScopedL2Log[][]> {
|
|
67
|
+
return getAllPagesInBatches(tags, batch =>
|
|
68
|
+
getAllPages(batch.length, page => aztecNode.getPrivateLogsByTags(batch, page, anchorBlockHash)),
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Fetches all public logs for the given tags from a contract, automatically paginating through all pages.
|
|
74
|
+
* @param aztecNode - The Aztec node to query.
|
|
75
|
+
* @param contractAddress - The contract address to search logs for.
|
|
76
|
+
* @param tags - The tags to search for.
|
|
77
|
+
* @param anchorBlockHash - reference block for the Aztec node query, throws if block is not found there (typically
|
|
78
|
+
* because of reorgs).
|
|
79
|
+
* @returns An array of log arrays, one per tag, containing all logs across all pages.
|
|
80
|
+
*/
|
|
81
|
+
export function getAllPublicLogsByTagsFromContract(
|
|
82
|
+
aztecNode: AztecNode,
|
|
83
|
+
contractAddress: AztecAddress,
|
|
84
|
+
tags: Tag[],
|
|
85
|
+
anchorBlockHash: BlockHash,
|
|
86
|
+
): Promise<TxScopedL2Log[][]> {
|
|
87
|
+
return getAllPagesInBatches(tags, batch =>
|
|
88
|
+
getAllPages(batch.length, page =>
|
|
89
|
+
aztecNode.getPublicLogsByTagsFromContract(contractAddress, batch, page, anchorBlockHash),
|
|
90
|
+
),
|
|
91
|
+
);
|
|
92
|
+
}
|
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';
|