@aztec/pxe 0.0.1-commit.96bb3f7 → 0.0.1-commit.a072138
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 +9 -5
- package/dest/block_synchronizer/block_synchronizer.d.ts.map +1 -1
- package/dest/block_synchronizer/block_synchronizer.js +66 -21
- 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/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 +6 -10
- package/dest/contract_function_simulator/contract_function_simulator.d.ts.map +1 -1
- package/dest/contract_function_simulator/contract_function_simulator.js +33 -25
- 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 +1 -1
- package/dest/contract_function_simulator/noir-structs/event_validation_request.js +1 -1
- 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 +44 -33
- 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 +0 -35
- package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts +11 -3
- package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/private_execution_oracle.js +22 -10
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts +33 -20
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.js +78 -76
- 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 +16 -6
- package/dest/debug/pxe_debug_utils.d.ts.map +1 -1
- package/dest/debug/pxe_debug_utils.js +20 -10
- 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 +12 -6
- 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 +13 -7
- 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 +19 -8
- 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 +3 -2
- package/dest/job_coordinator/job_coordinator.d.ts.map +1 -1
- package/dest/job_coordinator/job_coordinator.js +3 -2
- package/dest/logs/log_service.d.ts +6 -4
- package/dest/logs/log_service.d.ts.map +1 -1
- package/dest/logs/log_service.js +21 -16
- package/dest/notes/note_service.d.ts +7 -7
- package/dest/notes/note_service.d.ts.map +1 -1
- package/dest/notes/note_service.js +31 -36
- 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} +12 -6
- 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 +3 -3
- package/dest/private_kernel/private_kernel_oracle.d.ts +23 -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 +7 -36
- package/dest/pxe.d.ts.map +1 -1
- package/dest/pxe.js +43 -83
- 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 +1 -2
- package/dest/storage/contract_store/contract_store.d.ts.map +1 -1
- package/dest/storage/contract_store/contract_store.js +22 -25
- package/dest/storage/metadata.d.ts +1 -1
- package/dest/storage/metadata.js +1 -1
- package/dest/storage/note_store/note_store.d.ts +51 -52
- package/dest/storage/note_store/note_store.d.ts.map +1 -1
- package/dest/storage/note_store/note_store.js +282 -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 +43 -8
- package/dest/storage/private_event_store/private_event_store.d.ts.map +1 -1
- package/dest/storage/private_event_store/private_event_store.js +226 -111
- 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 +252 -100
- 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 +2 -1
- package/dest/tagging/index.d.ts.map +1 -1
- package/dest/tagging/index.js +1 -0
- 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 +6 -6
- 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 +7 -7
- 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 +85 -33
- package/src/config/index.ts +14 -0
- package/src/contract_function_simulator/benchmarked_node.ts +103 -0
- package/src/contract_function_simulator/contract_function_simulator.ts +34 -28
- 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 +1 -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 +65 -40
- package/src/contract_function_simulator/oracle/private_execution.ts +1 -67
- package/src/contract_function_simulator/oracle/private_execution_oracle.ts +35 -12
- package/src/contract_function_simulator/oracle/utility_execution_oracle.ts +100 -82
- package/src/contract_sync/index.ts +98 -0
- package/src/debug/pxe_debug_utils.ts +26 -11
- package/src/entrypoints/client/bundle/utils.ts +7 -14
- package/src/entrypoints/client/lazy/utils.ts +8 -14
- package/src/entrypoints/pxe_creation_options.ts +2 -1
- package/src/entrypoints/server/index.ts +2 -0
- package/src/entrypoints/server/utils.ts +15 -19
- package/src/events/event_service.ts +17 -25
- package/src/events/private_event_filter_validator.ts +3 -5
- package/src/job_coordinator/job_coordinator.ts +4 -3
- package/src/logs/log_service.ts +32 -14
- package/src/notes/note_service.ts +38 -43
- 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} +32 -20
- package/src/private_kernel/private_kernel_execution_prover.ts +7 -4
- package/src/private_kernel/private_kernel_oracle.ts +116 -37
- package/src/pxe.ts +77 -118
- 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 +22 -31
- package/src/storage/metadata.ts +1 -1
- package/src/storage/note_store/note_store.ts +317 -318
- package/src/storage/note_store/stored_note.ts +48 -0
- package/src/storage/private_event_store/private_event_store.ts +292 -124
- 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 +293 -108
- package/src/tagging/get_all_logs_by_tags.ts +68 -0
- package/src/tagging/index.ts +1 -0
- package/src/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.ts +16 -5
- package/src/tagging/recipient_sync/utils/load_logs_for_range.ts +7 -1
- package/src/tagging/sender_sync/sync_sender_tagging_indexes.ts +9 -6
- package/src/tagging/sender_sync/utils/get_status_change_of_pending.ts +5 -17
- 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 -85
- 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 -127
- 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
|
|
|
5
|
+
import type { StagedStore } from '../../job_coordinator/job_coordinator.js';
|
|
6
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,68 @@
|
|
|
1
|
+
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
2
|
+
import type { BlockHash } 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: BlockHash,
|
|
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: BlockHash,
|
|
64
|
+
): Promise<TxScopedL2Log[][]> {
|
|
65
|
+
return getAllPages(tags.length, page =>
|
|
66
|
+
aztecNode.getPublicLogsByTagsFromContract(contractAddress, tags, page, anchorBlockHash),
|
|
67
|
+
);
|
|
68
|
+
}
|
package/src/tagging/index.ts
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
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
14
|
export { UNFINALIZED_TAGGING_INDEXES_WINDOW_LEN } from './constants.js';
|
|
15
|
+
export { getAllPrivateLogsByTags, getAllPublicLogsByTagsFromContract } from './get_all_logs_by_tags.js';
|
|
15
16
|
|
|
16
17
|
// Re-export tagging-related types from stdlib
|
|
17
18
|
export { DirectionalAppTaggingSecret, Tag, SiloedTag } from '@aztec/stdlib/logs';
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { BlockNumber } from '@aztec/foundation/branded-types';
|
|
2
2
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
3
|
+
import type { BlockHash } 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
|
|
|
@@ -21,6 +22,8 @@ export async function loadPrivateLogsForSenderRecipientPair(
|
|
|
21
22
|
aztecNode: AztecNode,
|
|
22
23
|
taggingStore: RecipientTaggingStore,
|
|
23
24
|
anchorBlockNumber: BlockNumber,
|
|
25
|
+
anchorBlockHash: BlockHash,
|
|
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
|
|
@@ -76,8 +79,8 @@ export async function loadPrivateLogsForSenderRecipientPair(
|
|
|
76
79
|
|
|
77
80
|
let start: number, end: number;
|
|
78
81
|
{
|
|
79
|
-
const currentHighestAgedIndex = await taggingStore.getHighestAgedIndex(secret);
|
|
80
|
-
const currentHighestFinalizedIndex = await taggingStore.getHighestFinalizedIndex(secret);
|
|
82
|
+
const currentHighestAgedIndex = await taggingStore.getHighestAgedIndex(secret, jobId);
|
|
83
|
+
const currentHighestFinalizedIndex = await taggingStore.getHighestFinalizedIndex(secret, jobId);
|
|
81
84
|
|
|
82
85
|
// We don't want to include the highest aged index so we start from `currentHighestAgedIndex + 1` (or 0 if not set)
|
|
83
86
|
start = currentHighestAgedIndex === undefined ? 0 : currentHighestAgedIndex + 1;
|
|
@@ -91,7 +94,15 @@ export async function loadPrivateLogsForSenderRecipientPair(
|
|
|
91
94
|
|
|
92
95
|
while (true) {
|
|
93
96
|
// Get private logs with their block timestamps and corresponding tagging indexes
|
|
94
|
-
const privateLogsWithIndexes = await loadLogsForRange(
|
|
97
|
+
const privateLogsWithIndexes = await loadLogsForRange(
|
|
98
|
+
secret,
|
|
99
|
+
app,
|
|
100
|
+
aztecNode,
|
|
101
|
+
start,
|
|
102
|
+
end,
|
|
103
|
+
anchorBlockNumber,
|
|
104
|
+
anchorBlockHash,
|
|
105
|
+
);
|
|
95
106
|
|
|
96
107
|
if (privateLogsWithIndexes.length === 0) {
|
|
97
108
|
break;
|
|
@@ -107,7 +118,7 @@ export async function loadPrivateLogsForSenderRecipientPair(
|
|
|
107
118
|
|
|
108
119
|
// Store updates in data provider and update local variables
|
|
109
120
|
if (highestAgedIndex !== undefined) {
|
|
110
|
-
await taggingStore.updateHighestAgedIndex(secret, highestAgedIndex);
|
|
121
|
+
await taggingStore.updateHighestAgedIndex(secret, highestAgedIndex, jobId);
|
|
111
122
|
}
|
|
112
123
|
|
|
113
124
|
if (highestFinalizedIndex === undefined) {
|
|
@@ -120,7 +131,7 @@ export async function loadPrivateLogsForSenderRecipientPair(
|
|
|
120
131
|
throw new Error('Highest aged index lower than highest finalized index invariant violated');
|
|
121
132
|
}
|
|
122
133
|
|
|
123
|
-
await taggingStore.updateHighestFinalizedIndex(secret, highestFinalizedIndex);
|
|
134
|
+
await taggingStore.updateHighestFinalizedIndex(secret, highestFinalizedIndex, jobId);
|
|
124
135
|
|
|
125
136
|
// For the next iteration we want to look only at indexes for which we have not attempted to load logs yet while
|
|
126
137
|
// ensuring that we do not look further than WINDOW_LEN ahead of the highest finalized index.
|