@aztec/pxe 0.0.1-commit.3100065 → 0.0.1-commit.330febf
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 +5 -46
- package/dest/bin/index.d.ts +2 -2
- package/dest/bin/index.d.ts.map +1 -1
- package/dest/bin/index.js +1 -1
- package/dest/bin/oracle_version_helpers.d.ts +8 -39
- package/dest/bin/oracle_version_helpers.d.ts.map +1 -1
- package/dest/bin/oracle_version_helpers.js +10 -239
- package/dest/block_synchronizer/block_synchronizer.d.ts +3 -5
- package/dest/block_synchronizer/block_synchronizer.d.ts.map +1 -1
- package/dest/block_synchronizer/block_synchronizer.js +5 -18
- package/dest/config/package_info.js +1 -1
- package/dest/contract/contract_class_service.d.ts +1 -8
- package/dest/contract/contract_class_service.d.ts.map +1 -1
- package/dest/contract/contract_class_service.js +8 -40
- package/dest/contract/helpers.d.ts +1 -1
- package/dest/contract/helpers.d.ts.map +1 -1
- package/dest/contract/helpers.js +3 -3
- package/dest/contract/skip_sync_contracts.d.ts +11 -0
- package/dest/contract/skip_sync_contracts.d.ts.map +1 -0
- package/dest/contract/skip_sync_contracts.js +18 -0
- package/dest/contract_function_simulator/contract_function_simulator.d.ts +1 -8
- package/dest/contract_function_simulator/contract_function_simulator.d.ts.map +1 -1
- package/dest/contract_function_simulator/contract_function_simulator.js +5 -20
- package/dest/contract_function_simulator/index.d.ts +3 -3
- package/dest/contract_function_simulator/index.d.ts.map +1 -1
- package/dest/contract_function_simulator/index.js +1 -2
- package/dest/contract_function_simulator/noir-structs/resolved_tx.d.ts +7 -9
- package/dest/contract_function_simulator/noir-structs/resolved_tx.d.ts.map +1 -1
- package/dest/contract_function_simulator/noir-structs/resolved_tx.js +3 -44
- package/dest/contract_function_simulator/noir-structs/tx_effect_data.d.ts +5 -4
- package/dest/contract_function_simulator/noir-structs/tx_effect_data.d.ts.map +1 -1
- package/dest/contract_function_simulator/noir-structs/tx_effect_data.js +2 -2
- package/dest/contract_function_simulator/oracle/oracle_registry.d.ts +4 -3
- package/dest/contract_function_simulator/oracle/oracle_registry.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/oracle_registry.js +15 -6
- package/dest/contract_function_simulator/oracle/oracle_type_mappings.d.ts +87 -35
- package/dest/contract_function_simulator/oracle/oracle_type_mappings.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/oracle_type_mappings.js +297 -287
- package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts +1 -1
- package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/private_execution_oracle.js +11 -8
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts +15 -4
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.js +168 -53
- package/dest/entrypoints/client/bundle/index.d.ts +2 -1
- package/dest/entrypoints/client/bundle/index.d.ts.map +1 -1
- package/dest/entrypoints/client/bundle/index.js +1 -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 +10 -4
- package/dest/entrypoints/client/lazy/index.d.ts +2 -1
- package/dest/entrypoints/client/lazy/index.d.ts.map +1 -1
- package/dest/entrypoints/client/lazy/index.js +1 -0
- package/dest/entrypoints/client/lazy/utils.d.ts +1 -1
- package/dest/entrypoints/client/lazy/utils.d.ts.map +1 -1
- package/dest/entrypoints/client/lazy/utils.js +10 -4
- package/dest/entrypoints/client/store.d.ts +14 -0
- package/dest/entrypoints/client/store.d.ts.map +1 -0
- package/dest/entrypoints/client/store.js +42 -0
- package/dest/entrypoints/server/index.d.ts +2 -1
- package/dest/entrypoints/server/index.d.ts.map +1 -1
- package/dest/entrypoints/server/index.js +1 -0
- package/dest/entrypoints/server/store.d.ts +18 -0
- package/dest/entrypoints/server/store.d.ts.map +1 -0
- package/dest/entrypoints/server/store.js +28 -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 +8 -2
- package/dest/events/event_service.d.ts +13 -6
- package/dest/events/event_service.d.ts.map +1 -1
- package/dest/events/event_service.js +13 -13
- package/dest/logs/log_service.d.ts +15 -6
- package/dest/logs/log_service.d.ts.map +1 -1
- package/dest/logs/log_service.js +25 -32
- package/dest/messages/tx_resolver_service.d.ts +18 -7
- package/dest/messages/tx_resolver_service.d.ts.map +1 -1
- package/dest/messages/tx_resolver_service.js +13 -7
- package/dest/node/benchmarked_node.d.ts +20 -0
- package/dest/node/benchmarked_node.d.ts.map +1 -0
- package/dest/node/benchmarked_node.js +94 -0
- package/dest/node/caching_aztec_node.d.ts +24 -0
- package/dest/node/caching_aztec_node.d.ts.map +1 -0
- package/dest/node/caching_aztec_node.js +267 -0
- package/dest/notes/note_service.d.ts +13 -7
- package/dest/notes/note_service.d.ts.map +1 -1
- package/dest/notes/note_service.js +10 -10
- package/dest/oracle_version.d.ts +2 -2
- package/dest/oracle_version.js +5 -5
- package/dest/private_kernel/batch_planner.d.ts +1 -1
- package/dest/private_kernel/batch_planner.d.ts.map +1 -1
- package/dest/private_kernel/batch_planner.js +1 -1
- package/dest/private_kernel/private_kernel_execution_prover.d.ts +1 -1
- package/dest/private_kernel/private_kernel_execution_prover.d.ts.map +1 -1
- package/dest/private_kernel/private_kernel_execution_prover.js +45 -5
- package/dest/pxe.d.ts +1 -1
- package/dest/pxe.d.ts.map +1 -1
- package/dest/pxe.js +39 -19
- package/dest/storage/contract_store/contract_store.d.ts +1 -1
- package/dest/storage/contract_store/contract_store.d.ts.map +1 -1
- package/dest/storage/contract_store/contract_store.js +2 -2
- package/dest/storage/fact_store/fact_store.d.ts +1 -1
- package/dest/storage/fact_store/fact_store.js +1 -1
- package/dest/storage/fact_store/index.d.ts +2 -2
- package/dest/storage/fact_store/index.d.ts.map +1 -1
- package/dest/storage/fact_store/index.js +1 -1
- package/dest/storage/fact_store/origin_state.d.ts +4 -2
- package/dest/storage/fact_store/origin_state.d.ts.map +1 -1
- package/dest/storage/fact_store/origin_state.js +8 -1
- package/dest/storage/store_identity.d.ts +35 -0
- package/dest/storage/store_identity.d.ts.map +1 -0
- package/dest/storage/store_identity.js +44 -0
- package/dest/storage/tagging_store/sender_tagging_store.d.ts +41 -10
- package/dest/storage/tagging_store/sender_tagging_store.d.ts.map +1 -1
- package/dest/storage/tagging_store/sender_tagging_store.js +81 -29
- package/dest/tagging/constants.d.ts +10 -1
- package/dest/tagging/constants.d.ts.map +1 -1
- package/dest/tagging/constants.js +19 -0
- package/dest/tagging/get_all_logs_by_tags.d.ts +29 -8
- package/dest/tagging/get_all_logs_by_tags.d.ts.map +1 -1
- package/dest/tagging/get_all_logs_by_tags.js +29 -10
- package/dest/tagging/index.d.ts +3 -3
- package/dest/tagging/index.d.ts.map +1 -1
- package/dest/tagging/index.js +2 -2
- package/dest/tagging/recipient_sync/sync_tagged_private_logs.d.ts +10 -5
- package/dest/tagging/recipient_sync/sync_tagged_private_logs.d.ts.map +1 -1
- package/dest/tagging/recipient_sync/sync_tagged_private_logs.js +69 -38
- package/dest/tagging/sender_sync/sync_sender_tagging_indexes.d.ts +6 -3
- package/dest/tagging/sender_sync/sync_sender_tagging_indexes.d.ts.map +1 -1
- package/dest/tagging/sender_sync/sync_sender_tagging_indexes.js +23 -38
- package/dest/tagging/sender_sync/utils/classify_pending_txs.d.ts +22 -0
- package/dest/tagging/sender_sync/utils/classify_pending_txs.d.ts.map +1 -0
- package/dest/tagging/sender_sync/utils/classify_pending_txs.js +61 -0
- package/dest/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.d.ts +15 -5
- 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 +36 -35
- package/dest/tagging/sender_sync/utils/resolve_pending_txs.d.ts +29 -0
- package/dest/tagging/sender_sync/utils/resolve_pending_txs.d.ts.map +1 -0
- package/dest/tagging/sender_sync/utils/resolve_pending_txs.js +41 -0
- package/dest/tagging/sender_sync/utils/test_utils.d.ts +16 -0
- package/dest/tagging/sender_sync/utils/test_utils.d.ts.map +1 -0
- package/dest/tagging/sender_sync/utils/test_utils.js +24 -0
- package/dest/tagging/testing/tag_query_test_utils.d.ts +6 -0
- package/dest/tagging/testing/tag_query_test_utils.d.ts.map +1 -0
- package/dest/tagging/testing/tag_query_test_utils.js +10 -0
- package/package.json +17 -17
- package/src/bin/check_oracle_version.ts +5 -56
- package/src/bin/index.ts +1 -5
- package/src/bin/oracle_version_helpers.ts +11 -292
- package/src/block_synchronizer/block_synchronizer.ts +6 -23
- package/src/config/package_info.ts +1 -1
- package/src/contract/contract_class_service.ts +8 -46
- package/src/contract/helpers.ts +3 -3
- package/src/contract/skip_sync_contracts.ts +23 -0
- package/src/contract_function_simulator/contract_function_simulator.ts +5 -20
- package/src/contract_function_simulator/index.ts +23 -3
- package/src/contract_function_simulator/noir-structs/resolved_tx.ts +11 -45
- package/src/contract_function_simulator/noir-structs/tx_effect_data.ts +4 -3
- package/src/contract_function_simulator/oracle/oracle_registry.ts +12 -8
- package/src/contract_function_simulator/oracle/oracle_type_mappings.ts +301 -198
- package/src/contract_function_simulator/oracle/private_execution_oracle.ts +19 -9
- package/src/contract_function_simulator/oracle/utility_execution_oracle.ts +184 -56
- package/src/entrypoints/client/bundle/index.ts +1 -0
- package/src/entrypoints/client/bundle/utils.ts +15 -3
- package/src/entrypoints/client/lazy/index.ts +1 -0
- package/src/entrypoints/client/lazy/utils.ts +15 -3
- package/src/entrypoints/client/store.ts +54 -0
- package/src/entrypoints/server/index.ts +1 -0
- package/src/entrypoints/server/store.ts +47 -0
- package/src/entrypoints/server/utils.ts +21 -7
- package/src/events/event_service.ts +24 -14
- package/src/logs/log_service.ts +41 -39
- package/src/messages/tx_resolver_service.ts +26 -15
- package/src/node/benchmarked_node.ts +140 -0
- package/src/node/caching_aztec_node.ts +406 -0
- package/src/notes/note_service.ts +20 -14
- package/src/oracle_version.ts +5 -5
- package/src/private_kernel/batch_planner.ts +0 -1
- package/src/private_kernel/private_kernel_execution_prover.ts +90 -4
- package/src/pxe.ts +40 -21
- package/src/storage/contract_store/contract_store.ts +2 -1
- package/src/storage/fact_store/fact_store.ts +1 -1
- package/src/storage/fact_store/index.ts +1 -0
- package/src/storage/fact_store/origin_state.ts +10 -1
- package/src/storage/store_identity.ts +72 -0
- package/src/storage/tagging_store/sender_tagging_store.ts +113 -41
- package/src/tagging/constants.ts +22 -0
- package/src/tagging/get_all_logs_by_tags.ts +47 -11
- package/src/tagging/index.ts +7 -2
- package/src/tagging/recipient_sync/sync_tagged_private_logs.ts +116 -62
- package/src/tagging/sender_sync/sync_sender_tagging_indexes.ts +27 -57
- package/src/tagging/sender_sync/utils/classify_pending_txs.ts +91 -0
- package/src/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.ts +46 -40
- package/src/tagging/sender_sync/utils/resolve_pending_txs.ts +64 -0
- package/src/tagging/sender_sync/utils/test_utils.ts +46 -0
- package/src/tagging/testing/tag_query_test_utils.ts +11 -0
- package/dest/contract_function_simulator/aztec_node_read_cache.d.ts +0 -39
- package/dest/contract_function_simulator/aztec_node_read_cache.d.ts.map +0 -1
- package/dest/contract_function_simulator/aztec_node_read_cache.js +0 -60
- package/dest/contract_function_simulator/benchmarked_node.d.ts +0 -9
- package/dest/contract_function_simulator/benchmarked_node.d.ts.map +0 -1
- package/dest/contract_function_simulator/benchmarked_node.js +0 -77
- package/dest/tagging/sender_sync/utils/get_status_change_of_pending.d.ts +0 -17
- package/dest/tagging/sender_sync/utils/get_status_change_of_pending.d.ts.map +0 -1
- package/dest/tagging/sender_sync/utils/get_status_change_of_pending.js +0 -60
- package/src/contract_function_simulator/aztec_node_read_cache.ts +0 -89
- package/src/contract_function_simulator/benchmarked_node.ts +0 -103
- package/src/tagging/sender_sync/utils/get_status_change_of_pending.ts +0 -66
|
@@ -3,10 +3,13 @@ import { AppTaggingSecret, SiloedTag, type TaggingIndexRange } from '@aztec/stdl
|
|
|
3
3
|
import { TxEffect, TxHash } from '@aztec/stdlib/tx';
|
|
4
4
|
|
|
5
5
|
import type { StagedStore } from '../../job_coordinator/job_coordinator.js';
|
|
6
|
-
import { UNFINALIZED_TAGGING_INDEXES_WINDOW_LEN } from '../../tagging/constants.js';
|
|
6
|
+
import { UNFINALIZED_TAGGING_INDEXES_WINDOW_LEN, unfinalizedTaggingIndexesWindowEnd } from '../../tagging/constants.js';
|
|
7
|
+
|
|
8
|
+
/** A tx still awaiting finalization, and the highest tagging index it used for one secret. */
|
|
9
|
+
export type PendingTx = { txHash: string; highestIndex: number };
|
|
7
10
|
|
|
8
11
|
/** Internal representation of a pending index range entry. */
|
|
9
|
-
type PendingIndexesEntry = { lowestIndex: number
|
|
12
|
+
type PendingIndexesEntry = PendingTx & { lowestIndex: number };
|
|
10
13
|
|
|
11
14
|
/**
|
|
12
15
|
* Data provider of tagging data used when syncing the sender tagging indexes. The recipient counterpart of this class
|
|
@@ -128,10 +131,11 @@ export class SenderTaggingStore implements StagedStore {
|
|
|
128
131
|
}
|
|
129
132
|
|
|
130
133
|
/**
|
|
131
|
-
* Stores pending index ranges.
|
|
134
|
+
* Stores pending index ranges, rejecting any range that disagrees with an already-stored one.
|
|
132
135
|
* @remarks If the same (secret, txHash) pair already exists in the db with an equal range, it's a no-op. This is
|
|
133
136
|
* expected to happen because whenever we start sync we start from the last finalized index and we can have pending
|
|
134
|
-
* ranges already stored from previous syncs. If the ranges differ, it throws an error as that indicates a bug
|
|
137
|
+
* ranges already stored from previous syncs. If the ranges differ, it throws an error as that indicates a bug in
|
|
138
|
+
* callers that record indexes at prove time. Discovery from onchain logs must use `mergePendingIndexes` instead.
|
|
135
139
|
* @param ranges - The tagging index ranges containing the directional app tagging secrets and the index ranges that are
|
|
136
140
|
* to be stored in the db.
|
|
137
141
|
* @param txHash - The tx in which the tagging indexes were used in private logs.
|
|
@@ -141,6 +145,33 @@ export class SenderTaggingStore implements StagedStore {
|
|
|
141
145
|
* @throws If a different range already exists for the same (secret, txHash) pair.
|
|
142
146
|
*/
|
|
143
147
|
storePendingIndexes(ranges: TaggingIndexRange[], txHash: TxHash, jobId: string): Promise<void> {
|
|
148
|
+
return this.#storePendingIndexes(ranges, txHash, jobId, false);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Stores pending index ranges, widening an existing entry for the same (secret, txHash) pair to the union of the
|
|
153
|
+
* stored and incoming ranges instead of throwing on a mismatch. Discovery from onchain logs needs this: it may see
|
|
154
|
+
* only the surviving (non-revertible phase) sub-range of a partially reverted tx recorded at prove time (the
|
|
155
|
+
* finalized receipt step of the sync resolves that difference), or indexes beyond a partially discovered entry
|
|
156
|
+
* when a tx from another PXE straddles a sync window boundary. Callers that record indexes at prove time must use
|
|
157
|
+
* `storePendingIndexes` instead, so that a range disagreement surfaces as a bug rather than being absorbed.
|
|
158
|
+
* @param ranges - The tagging index ranges containing the directional app tagging secrets and the index ranges that are
|
|
159
|
+
* to be stored in the db.
|
|
160
|
+
* @param txHash - The tx in which the tagging indexes were used in private logs.
|
|
161
|
+
* @param jobId - job context for staged writes to this store. See `JobCoordinator` for more details.
|
|
162
|
+
* @throws If the highestIndex is further than window length from the highest finalized index for the same secret.
|
|
163
|
+
* @throws If the lowestIndex is lower than or equal to the last finalized index for the same secret.
|
|
164
|
+
*/
|
|
165
|
+
mergePendingIndexes(ranges: TaggingIndexRange[], txHash: TxHash, jobId: string): Promise<void> {
|
|
166
|
+
return this.#storePendingIndexes(ranges, txHash, jobId, true);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
#storePendingIndexes(
|
|
170
|
+
ranges: TaggingIndexRange[],
|
|
171
|
+
txHash: TxHash,
|
|
172
|
+
jobId: string,
|
|
173
|
+
mergeExisting: boolean,
|
|
174
|
+
): Promise<void> {
|
|
144
175
|
if (ranges.length === 0) {
|
|
145
176
|
return Promise.resolve();
|
|
146
177
|
}
|
|
@@ -167,13 +198,9 @@ export class SenderTaggingStore implements StagedStore {
|
|
|
167
198
|
|
|
168
199
|
// Process in memory and validate
|
|
169
200
|
for (const { range, secretStr, pendingData, finalizedIndex } of rangeData) {
|
|
170
|
-
|
|
171
|
-
if (range.highestIndex
|
|
172
|
-
throw
|
|
173
|
-
`Highest used index ${range.highestIndex} is further than window length from the highest finalized index ${finalizedIndex ?? 0}.
|
|
174
|
-
Tagging window length ${UNFINALIZED_TAGGING_INDEXES_WINDOW_LEN} is configured too low. Contact the Aztec team
|
|
175
|
-
to increase it!`,
|
|
176
|
-
);
|
|
201
|
+
const windowEnd = unfinalizedTaggingIndexesWindowEnd(finalizedIndex);
|
|
202
|
+
if (range.highestIndex >= windowEnd) {
|
|
203
|
+
throw windowExceededError(range.highestIndex, windowEnd, finalizedIndex);
|
|
177
204
|
}
|
|
178
205
|
|
|
179
206
|
// Throw if the lowest index is lower than or equal to the last finalized index
|
|
@@ -187,48 +214,60 @@ export class SenderTaggingStore implements StagedStore {
|
|
|
187
214
|
// Check if an entry with the same txHash already exists
|
|
188
215
|
const existingEntry = pendingData.find(entry => entry.txHash === txHashStr);
|
|
189
216
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
throw new Error(
|
|
194
|
-
`Conflicting range for secret ${secretStr} and txHash ${txHashStr}: ` +
|
|
195
|
-
`existing [${existingEntry.lowestIndex}, ${existingEntry.highestIndex}] vs ` +
|
|
196
|
-
`new [${range.lowestIndex}, ${range.highestIndex}]`,
|
|
197
|
-
);
|
|
198
|
-
}
|
|
199
|
-
// Exact duplicate — skip
|
|
200
|
-
} else {
|
|
201
|
-
this.#writePendingIndexes(jobId, secretStr, [
|
|
217
|
+
let updatedPending: PendingIndexesEntry[] | undefined;
|
|
218
|
+
if (!existingEntry) {
|
|
219
|
+
updatedPending = [
|
|
202
220
|
...pendingData,
|
|
203
221
|
{ lowestIndex: range.lowestIndex, highestIndex: range.highestIndex, txHash: txHashStr },
|
|
204
|
-
]
|
|
222
|
+
];
|
|
223
|
+
} else if (mergeExisting) {
|
|
224
|
+
// Widen the entry to the union of both ranges, never shrink it: replacing would drop prove-time
|
|
225
|
+
// indexes the chain doesn't show (partially reverted tx), and skipping would drop onchain indexes
|
|
226
|
+
// discovered in a later sync window (tx straddling the window boundary).
|
|
227
|
+
const lowestIndex = Math.min(existingEntry.lowestIndex, range.lowestIndex);
|
|
228
|
+
const highestIndex = Math.max(existingEntry.highestIndex, range.highestIndex);
|
|
229
|
+
if (lowestIndex !== existingEntry.lowestIndex || highestIndex !== existingEntry.highestIndex) {
|
|
230
|
+
updatedPending = pendingData.map(entry =>
|
|
231
|
+
entry === existingEntry ? { lowestIndex, highestIndex, txHash: entry.txHash } : entry,
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
} else if (
|
|
235
|
+
existingEntry.lowestIndex !== range.lowestIndex ||
|
|
236
|
+
existingEntry.highestIndex !== range.highestIndex
|
|
237
|
+
) {
|
|
238
|
+
// Different ranges for the same (secret, txHash) indicate a bug in callers that record indexes at prove
|
|
239
|
+
// time.
|
|
240
|
+
throw new Error(
|
|
241
|
+
`Conflicting range for secret ${secretStr} and txHash ${txHashStr}: ` +
|
|
242
|
+
`existing [${existingEntry.lowestIndex}, ${existingEntry.highestIndex}] vs ` +
|
|
243
|
+
`new [${range.lowestIndex}, ${range.highestIndex}]`,
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
// Remaining cases (a merge whose union equals the stored range, or an identical range without
|
|
247
|
+
// mergeExisting): duplicate evidence, nothing to write.
|
|
248
|
+
|
|
249
|
+
if (updatedPending) {
|
|
250
|
+
this.#writePendingIndexes(jobId, secretStr, updatedPending);
|
|
205
251
|
}
|
|
206
252
|
}
|
|
207
253
|
});
|
|
208
254
|
}
|
|
209
255
|
|
|
210
256
|
/**
|
|
211
|
-
* Returns the
|
|
212
|
-
*
|
|
213
|
-
*
|
|
257
|
+
* Returns the pending txs whose highest index falls within [startIndex, endIndex) for a given directional app
|
|
258
|
+
* tagging secret. The highest index is what decides whether a tx belongs to the window, so it alone is matched
|
|
259
|
+
* against the bounds, and it is also the only index a caller needs: a tx whose highest index is onchain has every
|
|
260
|
+
* lower one onchain too. A secret holds at most one entry per tx hash, so no tx hash appears twice in the result.
|
|
214
261
|
* @param secret - The directional app tagging secret to query pending indexes for.
|
|
215
262
|
* @param startIndex - The lower bound of the index range (inclusive).
|
|
216
263
|
* @param endIndex - The upper bound of the index range (exclusive).
|
|
217
|
-
* @returns An array of unique transaction hashes for pending transactions that contain indexes in the range
|
|
218
|
-
* [startIndex, endIndex). Returns an empty array if no pending indexes exist in the range.
|
|
219
264
|
*/
|
|
220
|
-
|
|
221
|
-
secret: AppTaggingSecret,
|
|
222
|
-
startIndex: number,
|
|
223
|
-
endIndex: number,
|
|
224
|
-
jobId: string,
|
|
225
|
-
): Promise<TxHash[]> {
|
|
265
|
+
getPendingTxs(secret: AppTaggingSecret, startIndex: number, endIndex: number, jobId: string): Promise<PendingTx[]> {
|
|
226
266
|
return this.#store.transactionAsync(async () => {
|
|
227
267
|
const existing = await this.#readPendingIndexes(jobId, secret.toString());
|
|
228
|
-
|
|
268
|
+
return existing
|
|
229
269
|
.filter(entry => entry.highestIndex >= startIndex && entry.highestIndex < endIndex)
|
|
230
|
-
.map(entry => entry.txHash);
|
|
231
|
-
return Array.from(new Set(txHashes)).map(TxHash.fromString);
|
|
270
|
+
.map(entry => ({ txHash: entry.txHash, highestIndex: entry.highestIndex }));
|
|
232
271
|
});
|
|
233
272
|
}
|
|
234
273
|
|
|
@@ -358,15 +397,33 @@ export class SenderTaggingStore implements StagedStore {
|
|
|
358
397
|
|
|
359
398
|
/**
|
|
360
399
|
* Updates pending indexes corresponding to the given transaction hashes to be finalized and prunes any lower pending
|
|
361
|
-
* indexes.
|
|
400
|
+
* indexes. Applies to every secret the txs used, so the caller must hold tx-level evidence that the whole tx
|
|
401
|
+
* finalized. Callers holding evidence about a single secret must use {@link finalizePendingIndexesOfSecret} instead.
|
|
402
|
+
*/
|
|
403
|
+
finalizePendingIndexes(txHashes: TxHash[], jobId: string): Promise<void> {
|
|
404
|
+
return this.#finalizePendingIndexes(txHashes, jobId);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* Same as {@link finalizePendingIndexes}, but restricted to the pending indexes of a single secret.
|
|
409
|
+
*
|
|
410
|
+
* Finalizing every secret off single-secret evidence would be unsound: a tx whose execution partially reverted can
|
|
411
|
+
* have all of one secret's tags onchain and none of another's, and the second secret's indexes must not be recorded
|
|
412
|
+
* as finalized when they never reached the chain.
|
|
362
413
|
*/
|
|
363
|
-
|
|
414
|
+
finalizePendingIndexesOfSecret(secret: AppTaggingSecret, txHashes: TxHash[], jobId: string): Promise<void> {
|
|
415
|
+
return this.#finalizePendingIndexes(txHashes, jobId, secret.toString());
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
async #finalizePendingIndexes(txHashes: TxHash[], jobId: string, onlySecret?: string): Promise<void> {
|
|
364
419
|
if (txHashes.length === 0) {
|
|
365
420
|
return;
|
|
366
421
|
}
|
|
367
422
|
|
|
368
423
|
const txHashStrings = new Set(txHashes.map(tx => tx.toString()));
|
|
369
|
-
const secretsWithData = await this.#getSecretsWithPendingData(jobId)
|
|
424
|
+
const secretsWithData = (await this.#getSecretsWithPendingData(jobId)).filter(
|
|
425
|
+
({ secret }) => onlySecret === undefined || secret === onlySecret,
|
|
426
|
+
);
|
|
370
427
|
|
|
371
428
|
for (const { secret, pendingData, lastFinalized } of secretsWithData) {
|
|
372
429
|
let currentPending = pendingData;
|
|
@@ -474,3 +531,18 @@ export class SenderTaggingStore implements StagedStore {
|
|
|
474
531
|
}
|
|
475
532
|
}
|
|
476
533
|
}
|
|
534
|
+
|
|
535
|
+
/** Builds the error thrown when a pending tag index is at or past the unfinalized tagging window end. */
|
|
536
|
+
export function windowExceededError(
|
|
537
|
+
highestIndex: number,
|
|
538
|
+
windowEnd: number,
|
|
539
|
+
finalizedIndex: number | undefined,
|
|
540
|
+
): Error {
|
|
541
|
+
const finalizedDescription =
|
|
542
|
+
finalizedIndex === undefined ? 'no index finalized yet' : `highest finalized index ${finalizedIndex}`;
|
|
543
|
+
return new Error(
|
|
544
|
+
`Highest used index ${highestIndex} is at or past the window end ${windowEnd} (${finalizedDescription}). ` +
|
|
545
|
+
`Tagging window length ${UNFINALIZED_TAGGING_INDEXES_WINDOW_LEN} is configured too low. ` +
|
|
546
|
+
`Contact the Aztec team to increase it!`,
|
|
547
|
+
);
|
|
548
|
+
}
|
package/src/tagging/constants.ts
CHANGED
|
@@ -18,3 +18,25 @@ import { MAX_PRIVATE_LOGS_PER_TX } from '@aztec/constants';
|
|
|
18
18
|
// reserved at log emission time, before squashing is decided, and the kernel's reset/squash loop is not bounded by
|
|
19
19
|
// MAX_PRIVATE_LOGS_PER_TX. No fixed window value closes that gap.
|
|
20
20
|
export const UNFINALIZED_TAGGING_INDEXES_WINDOW_LEN = MAX_PRIVATE_LOGS_PER_TX + 20;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Exclusive upper bound of the tag indexes that can exist for a secret whose highest finalized index is
|
|
24
|
+
* `finalizedIndex` (undefined when nothing is finalized yet). The sender store refuses pending indexes at or past it,
|
|
25
|
+
* and both sender and recipient sync scan exactly up to it. Every absolute window bound must come from this helper:
|
|
26
|
+
* a site with a wider or narrower bound lets a tx land at an index the syncs never scan, so two stores sharing the
|
|
27
|
+
* secret could later pick a colliding index.
|
|
28
|
+
*/
|
|
29
|
+
export function unfinalizedTaggingIndexesWindowEnd(finalizedIndex: number | undefined): number {
|
|
30
|
+
const windowStart = finalizedIndex === undefined ? 0 : finalizedIndex + 1;
|
|
31
|
+
return windowStart + UNFINALIZED_TAGGING_INDEXES_WINDOW_LEN;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// The number of tags probed per constrained secret in the first round.
|
|
35
|
+
//
|
|
36
|
+
// The probe doubles each round (2, 4, 8, ..., capped at UNFINALIZED_TAGGING_INDEXES_WINDOW_LEN) while every probed
|
|
37
|
+
// index is a hit, stopping at the first missing tag. Constrained delivery is gapless, so a single missing tag proves
|
|
38
|
+
// the stream has ended: at steady state this turns a full WINDOW_LEN probe into two tags. A secret K logs behind
|
|
39
|
+
// catches up in ~log2(K) round-trips while the probe is still doubling (2, 4, 8, 16, 32), but once it saturates the cap
|
|
40
|
+
// and advances WINDOW_LEN tags per round, deeper catch-up is linear at ~K/WINDOW_LEN rounds. Either way it beats both
|
|
41
|
+
// the full window every round and one round per log.
|
|
42
|
+
export const INITIAL_CONSTRAINED_PROBE_LEN = 2;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
2
2
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
3
3
|
import type { BlockHash } from '@aztec/stdlib/block';
|
|
4
4
|
import { MAX_RPC_LEN } from '@aztec/stdlib/interfaces/api-limit';
|
|
@@ -11,6 +11,31 @@ import {
|
|
|
11
11
|
queryAllPrivateLogsByTags,
|
|
12
12
|
queryAllPublicLogsByTags,
|
|
13
13
|
} from '@aztec/stdlib/logs';
|
|
14
|
+
import type { BlockHeader } from '@aztec/stdlib/tx';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* The block a tag query is anchored to.
|
|
18
|
+
*
|
|
19
|
+
* Both fields come from one header (see {@link logQueryAnchorOf}), which is what keeps the bound and the reorg check
|
|
20
|
+
* talking about the same block.
|
|
21
|
+
*/
|
|
22
|
+
export type LogQueryAnchor = {
|
|
23
|
+
/**
|
|
24
|
+
* Hash of the anchor block, naming the chain the query must be answered on: the node throws if that block is gone,
|
|
25
|
+
* which is how a reorg surfaces.
|
|
26
|
+
*/
|
|
27
|
+
hash: BlockHash;
|
|
28
|
+
/** Height of the anchor block, bounding the query to blocks at or below it. */
|
|
29
|
+
number: BlockNumber;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* The {@link LogQueryAnchor} naming `anchorBlockHeader`: its hash and its height. Callers build it once and reuse
|
|
34
|
+
* it across every query anchored to that block, so the header is hashed only once.
|
|
35
|
+
*/
|
|
36
|
+
export async function logQueryAnchorOf(anchorBlockHeader: BlockHeader): Promise<LogQueryAnchor> {
|
|
37
|
+
return { hash: await anchorBlockHeader.hash(), number: anchorBlockHeader.getBlockNumber() };
|
|
38
|
+
}
|
|
14
39
|
|
|
15
40
|
/** Optional block-range, effects opt-in, and pagination cap shared by both wrappers. */
|
|
16
41
|
export type GetAllLogsByTagsOptions = {
|
|
@@ -61,15 +86,15 @@ async function getAllPagesInBatches<T extends Tag | SiloedTag, Opts extends LogI
|
|
|
61
86
|
*
|
|
62
87
|
* @param aztecNode - The Aztec node to query.
|
|
63
88
|
* @param tags - The siloed tags to search for.
|
|
64
|
-
* @param
|
|
65
|
-
* because of reorgs).
|
|
89
|
+
* @param anchor - Block the query is anchored to: results stop there, and the call throws if that block is not found
|
|
90
|
+
* (typically because of reorgs).
|
|
66
91
|
* @param options - Optional `fromBlock`/`toBlock` range and `includeEffects` opt-in.
|
|
67
92
|
* @returns An array of log arrays, one per tag, containing all logs across all pages.
|
|
68
93
|
*/
|
|
69
94
|
export function getAllPrivateLogsByTags<Opts extends GetAllLogsByTagsOptions = GetAllLogsByTagsOptions>(
|
|
70
95
|
aztecNode: AztecNode,
|
|
71
96
|
tags: SiloedTag[],
|
|
72
|
-
|
|
97
|
+
anchor: LogQueryAnchor,
|
|
73
98
|
options: Opts = {} as Opts,
|
|
74
99
|
): Promise<LogResult<Opts>[][]> {
|
|
75
100
|
return getAllPagesInBatches<SiloedTag, Opts>(
|
|
@@ -77,9 +102,9 @@ export function getAllPrivateLogsByTags<Opts extends GetAllLogsByTagsOptions = G
|
|
|
77
102
|
batch =>
|
|
78
103
|
queryAllPrivateLogsByTags(aztecNode, {
|
|
79
104
|
tags: batch,
|
|
80
|
-
referenceBlock:
|
|
105
|
+
referenceBlock: anchor.hash,
|
|
81
106
|
fromBlock: options.fromBlock,
|
|
82
|
-
toBlock: options.toBlock,
|
|
107
|
+
toBlock: exclusiveUpperBound(anchor, options.toBlock),
|
|
83
108
|
includeEffects: options.includeEffects ?? false,
|
|
84
109
|
limitPerTag: options.limitPerTag,
|
|
85
110
|
}) as Promise<LogResult<Opts>[][]>,
|
|
@@ -92,8 +117,8 @@ export function getAllPrivateLogsByTags<Opts extends GetAllLogsByTagsOptions = G
|
|
|
92
117
|
* @param aztecNode - The Aztec node to query.
|
|
93
118
|
* @param contractAddress - The contract address to search logs for.
|
|
94
119
|
* @param tags - The tags to search for.
|
|
95
|
-
* @param
|
|
96
|
-
* because of reorgs).
|
|
120
|
+
* @param anchor - Block the query is anchored to: results stop there, and the call throws if that block is not found
|
|
121
|
+
* (typically because of reorgs).
|
|
97
122
|
* @param options - Optional `fromBlock`/`toBlock` range and `includeEffects` opt-in.
|
|
98
123
|
* @returns An array of log arrays, one per tag, containing all logs across all pages.
|
|
99
124
|
*/
|
|
@@ -101,7 +126,7 @@ export function getAllPublicLogsByTagsFromContract<Opts extends GetAllLogsByTags
|
|
|
101
126
|
aztecNode: AztecNode,
|
|
102
127
|
contractAddress: AztecAddress,
|
|
103
128
|
tags: Tag[],
|
|
104
|
-
|
|
129
|
+
anchor: LogQueryAnchor,
|
|
105
130
|
options: Opts = {} as Opts,
|
|
106
131
|
): Promise<LogResult<Opts>[][]> {
|
|
107
132
|
return getAllPagesInBatches<Tag, Opts>(
|
|
@@ -110,11 +135,22 @@ export function getAllPublicLogsByTagsFromContract<Opts extends GetAllLogsByTags
|
|
|
110
135
|
queryAllPublicLogsByTags(aztecNode, {
|
|
111
136
|
contractAddress,
|
|
112
137
|
tags: batch,
|
|
113
|
-
referenceBlock:
|
|
138
|
+
referenceBlock: anchor.hash,
|
|
114
139
|
fromBlock: options.fromBlock,
|
|
115
|
-
toBlock: options.toBlock,
|
|
140
|
+
toBlock: exclusiveUpperBound(anchor, options.toBlock),
|
|
116
141
|
includeEffects: options.includeEffects ?? false,
|
|
117
142
|
limitPerTag: options.limitPerTag,
|
|
118
143
|
}) as Promise<LogResult<Opts>[][]>,
|
|
119
144
|
);
|
|
120
145
|
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Exclusive upper block bound for a query anchored at `anchor`: one past the anchor block, or the caller's own
|
|
149
|
+
* `toBlock` when that is tighter.
|
|
150
|
+
*
|
|
151
|
+
* The bound is spelled out in the request rather than left implicit in `referenceBlock`, so the request itself
|
|
152
|
+
* names a fixed block range that no later block can widen.
|
|
153
|
+
*/
|
|
154
|
+
function exclusiveUpperBound(anchor: LogQueryAnchor, toBlock: BlockNumber | undefined): BlockNumber {
|
|
155
|
+
return BlockNumber(Math.min(toBlock ?? Infinity, anchor.number + 1));
|
|
156
|
+
}
|
package/src/tagging/index.ts
CHANGED
|
@@ -12,8 +12,13 @@
|
|
|
12
12
|
export { syncTaggedPrivateLogs } from './recipient_sync/sync_tagged_private_logs.js';
|
|
13
13
|
export { syncSenderTaggingIndexes } from './sender_sync/sync_sender_tagging_indexes.js';
|
|
14
14
|
export { persistSenderTaggingIndexRangesForTx } from './persist_sender_tagging_index_ranges.js';
|
|
15
|
-
export { UNFINALIZED_TAGGING_INDEXES_WINDOW_LEN } from './constants.js';
|
|
16
|
-
export {
|
|
15
|
+
export { UNFINALIZED_TAGGING_INDEXES_WINDOW_LEN, INITIAL_CONSTRAINED_PROBE_LEN } from './constants.js';
|
|
16
|
+
export {
|
|
17
|
+
type LogQueryAnchor,
|
|
18
|
+
getAllPrivateLogsByTags,
|
|
19
|
+
getAllPublicLogsByTagsFromContract,
|
|
20
|
+
logQueryAnchorOf,
|
|
21
|
+
} from './get_all_logs_by_tags.js';
|
|
17
22
|
|
|
18
23
|
// Re-export tagging-related types from stdlib
|
|
19
24
|
export { AppTaggingSecret, Tag, SiloedTag } from '@aztec/stdlib/logs';
|