@aztec/pxe 0.0.1-commit.6c91f13 → 0.0.1-commit.6d3c34e
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/block_synchronizer/block_synchronizer.d.ts +4 -2
- package/dest/block_synchronizer/block_synchronizer.d.ts.map +1 -1
- package/dest/block_synchronizer/block_synchronizer.js +6 -3
- package/dest/config/package_info.js +1 -1
- package/dest/contract_function_simulator/contract_function_simulator.d.ts +4 -3
- package/dest/contract_function_simulator/contract_function_simulator.d.ts.map +1 -1
- package/dest/contract_function_simulator/contract_function_simulator.js +7 -6
- package/dest/contract_function_simulator/noir-structs/event_validation_request.d.ts +3 -2
- 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 +5 -2
- package/dest/contract_function_simulator/oracle/private_execution.d.ts +1 -1
- package/dest/contract_function_simulator/oracle/private_execution.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/private_execution.js +1 -2
- package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts +2 -17
- package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/private_execution_oracle.js +4 -32
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts +3 -2
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.js +4 -2
- package/dest/entrypoints/client/bundle/utils.d.ts +1 -1
- package/dest/entrypoints/client/bundle/utils.d.ts.map +1 -1
- package/dest/entrypoints/client/bundle/utils.js +10 -1
- package/dest/entrypoints/client/lazy/utils.d.ts +1 -1
- package/dest/entrypoints/client/lazy/utils.d.ts.map +1 -1
- package/dest/entrypoints/client/lazy/utils.js +10 -1
- package/dest/entrypoints/pxe_creation_options.d.ts +3 -2
- package/dest/entrypoints/pxe_creation_options.d.ts.map +1 -1
- package/dest/entrypoints/server/utils.d.ts +1 -1
- package/dest/entrypoints/server/utils.d.ts.map +1 -1
- package/dest/entrypoints/server/utils.js +11 -7
- package/dest/events/event_service.d.ts +2 -2
- package/dest/events/event_service.d.ts.map +1 -1
- package/dest/events/event_service.js +2 -2
- package/dest/job_coordinator/job_coordinator.d.ts +74 -0
- package/dest/job_coordinator/job_coordinator.d.ts.map +1 -0
- package/dest/job_coordinator/job_coordinator.js +93 -0
- package/dest/private_kernel/hints/build_private_kernel_reset_private_inputs.d.ts +2 -2
- package/dest/private_kernel/hints/build_private_kernel_reset_private_inputs.d.ts.map +1 -1
- package/dest/private_kernel/hints/build_private_kernel_reset_private_inputs.js +2 -2
- 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 +3 -4
- package/dest/private_kernel/private_kernel_oracle.d.ts +3 -2
- package/dest/private_kernel/private_kernel_oracle.d.ts.map +1 -1
- package/dest/private_kernel/private_kernel_oracle_impl.d.ts +2 -2
- package/dest/private_kernel/private_kernel_oracle_impl.d.ts.map +1 -1
- package/dest/private_kernel/private_kernel_oracle_impl.js +2 -3
- package/dest/pxe.d.ts +2 -1
- package/dest/pxe.d.ts.map +1 -1
- package/dest/pxe.js +39 -20
- package/dest/storage/private_event_store/private_event_store.d.ts +7 -2
- package/dest/storage/private_event_store/private_event_store.d.ts.map +1 -1
- package/dest/storage/private_event_store/private_event_store.js +57 -14
- package/dest/storage/tagging_store/sender_tagging_store.js +1 -1
- 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/index.d.ts +2 -2
- package/dest/tagging/index.d.ts.map +1 -1
- package/dest/tagging/index.js +1 -10
- package/dest/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.d.ts +1 -1
- 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 +2 -2
- package/dest/tagging/sender_sync/sync_sender_tagging_indexes.js +1 -1
- 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 +2 -2
- package/package.json +16 -16
- package/src/block_synchronizer/block_synchronizer.ts +5 -2
- package/src/config/package_info.ts +1 -1
- package/src/contract_function_simulator/contract_function_simulator.ts +10 -5
- package/src/contract_function_simulator/noir-structs/event_validation_request.ts +4 -0
- package/src/contract_function_simulator/oracle/private_execution.ts +0 -2
- package/src/contract_function_simulator/oracle/private_execution_oracle.ts +4 -36
- package/src/contract_function_simulator/oracle/utility_execution_oracle.ts +2 -0
- package/src/entrypoints/client/bundle/utils.ts +7 -1
- package/src/entrypoints/client/lazy/utils.ts +7 -2
- package/src/entrypoints/pxe_creation_options.ts +2 -1
- package/src/entrypoints/server/utils.ts +11 -15
- package/src/events/event_service.ts +2 -0
- package/src/job_coordinator/job_coordinator.ts +149 -0
- package/src/private_kernel/hints/build_private_kernel_reset_private_inputs.ts +1 -2
- package/src/private_kernel/private_kernel_execution_prover.ts +2 -4
- package/src/private_kernel/private_kernel_oracle.ts +2 -1
- package/src/private_kernel/private_kernel_oracle_impl.ts +2 -8
- package/src/pxe.ts +64 -19
- package/src/storage/private_event_store/private_event_store.ts +68 -14
- package/src/storage/tagging_store/sender_tagging_store.ts +1 -1
- package/src/tagging/constants.ts +10 -0
- package/src/tagging/index.ts +1 -11
- package/src/tagging/recipient_sync/load_private_logs_for_sender_recipient_pair.ts +5 -2
- package/src/tagging/sender_sync/sync_sender_tagging_indexes.ts +1 -1
- package/src/tagging/sender_sync/utils/get_status_change_of_pending.ts +6 -2
package/src/pxe.ts
CHANGED
|
@@ -60,9 +60,11 @@ import {
|
|
|
60
60
|
} from './contract_function_simulator/contract_function_simulator.js';
|
|
61
61
|
import { readCurrentClassId } from './contract_function_simulator/oracle/private_execution.js';
|
|
62
62
|
import { ProxiedContractStoreFactory } from './contract_function_simulator/proxied_contract_data_source.js';
|
|
63
|
+
import { ProxiedNodeFactory } from './contract_function_simulator/proxied_node.js';
|
|
63
64
|
import { PXEDebugUtils } from './debug/pxe_debug_utils.js';
|
|
64
65
|
import { enrichPublicSimulationError, enrichSimulationError } from './error_enriching.js';
|
|
65
66
|
import { PrivateEventFilterValidator } from './events/private_event_filter_validator.js';
|
|
67
|
+
import { JobCoordinator } from './job_coordinator/job_coordinator.js';
|
|
66
68
|
import {
|
|
67
69
|
PrivateKernelExecutionProver,
|
|
68
70
|
type PrivateKernelExecutionProverConfig,
|
|
@@ -107,6 +109,7 @@ export class PXE {
|
|
|
107
109
|
private protocolContractsProvider: ProtocolContractsProvider,
|
|
108
110
|
private log: Logger,
|
|
109
111
|
private jobQueue: SerialQueue,
|
|
112
|
+
private jobCoordinator: JobCoordinator,
|
|
110
113
|
public debug: PXEDebugUtils,
|
|
111
114
|
) {}
|
|
112
115
|
|
|
@@ -143,7 +146,17 @@ export class PXE {
|
|
|
143
146
|
const capsuleStore = new CapsuleStore(store);
|
|
144
147
|
const keyStore = new KeyStore(store);
|
|
145
148
|
const tipsStore = new L2TipsKVStore(store, 'pxe');
|
|
146
|
-
const synchronizer = new BlockSynchronizer(
|
|
149
|
+
const synchronizer = new BlockSynchronizer(
|
|
150
|
+
node,
|
|
151
|
+
anchorBlockStore,
|
|
152
|
+
noteStore,
|
|
153
|
+
privateEventStore,
|
|
154
|
+
tipsStore,
|
|
155
|
+
config,
|
|
156
|
+
loggerOrSuffix,
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
const jobCoordinator = new JobCoordinator(store);
|
|
147
160
|
|
|
148
161
|
const debugUtils = new PXEDebugUtils(contractStore, noteStore);
|
|
149
162
|
|
|
@@ -168,6 +181,7 @@ export class PXE {
|
|
|
168
181
|
protocolContractsProvider,
|
|
169
182
|
log,
|
|
170
183
|
jobQueue,
|
|
184
|
+
jobCoordinator,
|
|
171
185
|
debugUtils,
|
|
172
186
|
);
|
|
173
187
|
|
|
@@ -191,7 +205,7 @@ export class PXE {
|
|
|
191
205
|
this.noteStore,
|
|
192
206
|
this.keyStore,
|
|
193
207
|
this.addressStore,
|
|
194
|
-
this.node,
|
|
208
|
+
ProxiedNodeFactory.create(this.node),
|
|
195
209
|
this.anchorBlockStore,
|
|
196
210
|
this.senderTaggingStore,
|
|
197
211
|
this.recipientTaggingStore,
|
|
@@ -222,7 +236,7 @@ export class PXE {
|
|
|
222
236
|
*
|
|
223
237
|
* Useful for tasks that cannot run concurrently, such as contract function simulation.
|
|
224
238
|
*/
|
|
225
|
-
#putInJobQueue<T>(fn: () => Promise<T>): Promise<T> {
|
|
239
|
+
#putInJobQueue<T>(fn: (jobId: string) => Promise<T>): Promise<T> {
|
|
226
240
|
// TODO(#12636): relax the conditions under which we forbid concurrency.
|
|
227
241
|
if (this.jobQueue.length() != 0) {
|
|
228
242
|
this.log.warn(
|
|
@@ -230,7 +244,22 @@ export class PXE {
|
|
|
230
244
|
);
|
|
231
245
|
}
|
|
232
246
|
|
|
233
|
-
return this.jobQueue.put(
|
|
247
|
+
return this.jobQueue.put(async () => {
|
|
248
|
+
const jobId = this.jobCoordinator.beginJob();
|
|
249
|
+
this.log.verbose(`Beginning job ${jobId}`);
|
|
250
|
+
|
|
251
|
+
try {
|
|
252
|
+
const result = await fn(jobId);
|
|
253
|
+
this.log.verbose(`Committing job ${jobId}`);
|
|
254
|
+
|
|
255
|
+
await this.jobCoordinator.commitJob(jobId);
|
|
256
|
+
return result;
|
|
257
|
+
} catch (err) {
|
|
258
|
+
this.log.verbose(`Aborting job ${jobId}`);
|
|
259
|
+
await this.jobCoordinator.abortJob(jobId);
|
|
260
|
+
throw err;
|
|
261
|
+
}
|
|
262
|
+
});
|
|
234
263
|
}
|
|
235
264
|
|
|
236
265
|
async #registerProtocolContracts() {
|
|
@@ -263,7 +292,8 @@ export class PXE {
|
|
|
263
292
|
async #executePrivate(
|
|
264
293
|
contractFunctionSimulator: ContractFunctionSimulator,
|
|
265
294
|
txRequest: TxExecutionRequest,
|
|
266
|
-
scopes
|
|
295
|
+
scopes: AztecAddress[] | undefined,
|
|
296
|
+
jobId: string,
|
|
267
297
|
): Promise<PrivateExecutionResult> {
|
|
268
298
|
const { origin: contractAddress, functionSelector } = txRequest;
|
|
269
299
|
|
|
@@ -280,6 +310,7 @@ export class PXE {
|
|
|
280
310
|
// contract entrypoint
|
|
281
311
|
undefined, // senderForTags
|
|
282
312
|
scopes,
|
|
313
|
+
jobId,
|
|
283
314
|
);
|
|
284
315
|
this.log.debug(`Private simulation completed for ${contractAddress.toString()}:${functionSelector}`);
|
|
285
316
|
return result;
|
|
@@ -298,17 +329,19 @@ export class PXE {
|
|
|
298
329
|
* @param authWitnesses - Authentication witnesses required for the function call.
|
|
299
330
|
* @param scopes - Optional array of account addresses whose notes can be accessed in this call. Defaults to all
|
|
300
331
|
* accounts if not specified.
|
|
332
|
+
* @param jobId - The job ID for staged writes.
|
|
301
333
|
* @returns The simulation result containing the outputs of the utility function.
|
|
302
334
|
*/
|
|
303
335
|
async #simulateUtility(
|
|
304
336
|
contractFunctionSimulator: ContractFunctionSimulator,
|
|
305
337
|
call: FunctionCall,
|
|
306
|
-
authWitnesses
|
|
307
|
-
scopes
|
|
338
|
+
authWitnesses: AuthWitness[] | undefined,
|
|
339
|
+
scopes: AztecAddress[] | undefined,
|
|
340
|
+
jobId: string,
|
|
308
341
|
) {
|
|
309
342
|
try {
|
|
310
343
|
const anchorBlockHeader = await this.anchorBlockStore.getBlockHeader();
|
|
311
|
-
return contractFunctionSimulator.runUtility(call, authWitnesses ?? [], anchorBlockHeader, scopes);
|
|
344
|
+
return contractFunctionSimulator.runUtility(call, authWitnesses ?? [], anchorBlockHeader, scopes, jobId);
|
|
312
345
|
} catch (err) {
|
|
313
346
|
if (err instanceof SimulationError) {
|
|
314
347
|
await enrichSimulationError(err, this.contractStore, this.log);
|
|
@@ -657,14 +690,14 @@ export class PXE {
|
|
|
657
690
|
let privateExecutionResult: PrivateExecutionResult;
|
|
658
691
|
// We disable proving concurrently mostly out of caution, since it accesses some of our stores. Proving is so
|
|
659
692
|
// computationally demanding that it'd be rare for someone to try to do it concurrently regardless.
|
|
660
|
-
return this.#putInJobQueue(async
|
|
693
|
+
return this.#putInJobQueue(async jobId => {
|
|
661
694
|
const totalTimer = new Timer();
|
|
662
695
|
try {
|
|
663
696
|
const syncTimer = new Timer();
|
|
664
697
|
await this.blockStateSynchronizer.sync();
|
|
665
698
|
const syncTime = syncTimer.ms();
|
|
666
699
|
const contractFunctionSimulator = this.#getSimulatorForTx();
|
|
667
|
-
privateExecutionResult = await this.#executePrivate(contractFunctionSimulator, txRequest);
|
|
700
|
+
privateExecutionResult = await this.#executePrivate(contractFunctionSimulator, txRequest, undefined, jobId);
|
|
668
701
|
|
|
669
702
|
const {
|
|
670
703
|
publicInputs,
|
|
@@ -741,7 +774,7 @@ export class PXE {
|
|
|
741
774
|
skipProofGeneration: boolean = true,
|
|
742
775
|
): Promise<TxProfileResult> {
|
|
743
776
|
// We disable concurrent profiles for consistency with simulateTx.
|
|
744
|
-
return this.#putInJobQueue(async
|
|
777
|
+
return this.#putInJobQueue(async jobId => {
|
|
745
778
|
const totalTimer = new Timer();
|
|
746
779
|
try {
|
|
747
780
|
const txInfo = {
|
|
@@ -761,7 +794,12 @@ export class PXE {
|
|
|
761
794
|
const syncTime = syncTimer.ms();
|
|
762
795
|
|
|
763
796
|
const contractFunctionSimulator = this.#getSimulatorForTx();
|
|
764
|
-
const privateExecutionResult = await this.#executePrivate(
|
|
797
|
+
const privateExecutionResult = await this.#executePrivate(
|
|
798
|
+
contractFunctionSimulator,
|
|
799
|
+
txRequest,
|
|
800
|
+
undefined,
|
|
801
|
+
jobId,
|
|
802
|
+
);
|
|
765
803
|
|
|
766
804
|
const { executionSteps, timings: { proving } = {} } = await this.#prove(
|
|
767
805
|
txRequest,
|
|
@@ -841,7 +879,7 @@ export class PXE {
|
|
|
841
879
|
// We disable concurrent simulations since those might execute oracles which read and write to the PXE stores (e.g.
|
|
842
880
|
// to the capsules), and we need to prevent concurrent runs from interfering with one another (e.g. attempting to
|
|
843
881
|
// delete the same read value, or reading values that another simulation is currently modifying).
|
|
844
|
-
return this.#putInJobQueue(async
|
|
882
|
+
return this.#putInJobQueue(async jobId => {
|
|
845
883
|
try {
|
|
846
884
|
const totalTimer = new Timer();
|
|
847
885
|
const txInfo = {
|
|
@@ -867,7 +905,7 @@ export class PXE {
|
|
|
867
905
|
const skipKernels = overrides?.contracts !== undefined && Object.keys(overrides.contracts ?? {}).length > 0;
|
|
868
906
|
|
|
869
907
|
// Execution of private functions only; no proving, and no kernel logic.
|
|
870
|
-
const privateExecutionResult = await this.#executePrivate(contractFunctionSimulator, txRequest, scopes);
|
|
908
|
+
const privateExecutionResult = await this.#executePrivate(contractFunctionSimulator, txRequest, scopes, jobId);
|
|
871
909
|
|
|
872
910
|
let publicInputs: PrivateKernelTailCircuitPublicInputs | undefined;
|
|
873
911
|
let executionSteps: PrivateExecutionStep[] = [];
|
|
@@ -982,7 +1020,7 @@ export class PXE {
|
|
|
982
1020
|
// We disable concurrent simulations since those might execute oracles which read and write to the PXE stores (e.g.
|
|
983
1021
|
// to the capsules), and we need to prevent concurrent runs from interfering with one another (e.g. attempting to
|
|
984
1022
|
// delete the same read value, or reading values that another simulation is currently modifying).
|
|
985
|
-
return this.#putInJobQueue(async
|
|
1023
|
+
return this.#putInJobQueue(async jobId => {
|
|
986
1024
|
try {
|
|
987
1025
|
const totalTimer = new Timer();
|
|
988
1026
|
const syncTimer = new Timer();
|
|
@@ -992,10 +1030,16 @@ export class PXE {
|
|
|
992
1030
|
const contractFunctionSimulator = this.#getSimulatorForTx();
|
|
993
1031
|
|
|
994
1032
|
await this.contractStore.syncPrivateState(call.to, call.selector, privateSyncCall =>
|
|
995
|
-
this.#simulateUtility(contractFunctionSimulator, privateSyncCall),
|
|
1033
|
+
this.#simulateUtility(contractFunctionSimulator, privateSyncCall, [], undefined, jobId),
|
|
996
1034
|
);
|
|
997
1035
|
|
|
998
|
-
const executionResult = await this.#simulateUtility(
|
|
1036
|
+
const executionResult = await this.#simulateUtility(
|
|
1037
|
+
contractFunctionSimulator,
|
|
1038
|
+
call,
|
|
1039
|
+
authwits ?? [],
|
|
1040
|
+
scopes,
|
|
1041
|
+
jobId,
|
|
1042
|
+
);
|
|
999
1043
|
const functionTime = functionTimer.ms();
|
|
1000
1044
|
|
|
1001
1045
|
const totalTime = totalTimer.ms();
|
|
@@ -1037,14 +1081,15 @@ export class PXE {
|
|
|
1037
1081
|
* @returns - The packed events with block and tx metadata.
|
|
1038
1082
|
*/
|
|
1039
1083
|
public getPrivateEvents(eventSelector: EventSelector, filter: PrivateEventFilter): Promise<PackedPrivateEvent[]> {
|
|
1040
|
-
return this.#putInJobQueue(async
|
|
1084
|
+
return this.#putInJobQueue(async jobId => {
|
|
1041
1085
|
await this.blockStateSynchronizer.sync();
|
|
1042
1086
|
const contractFunctionSimulator = this.#getSimulatorForTx();
|
|
1043
1087
|
|
|
1044
1088
|
await this.contractStore.syncPrivateState(
|
|
1045
1089
|
filter.contractAddress,
|
|
1046
1090
|
null,
|
|
1047
|
-
async privateSyncCall =>
|
|
1091
|
+
async privateSyncCall =>
|
|
1092
|
+
await this.#simulateUtility(contractFunctionSimulator, privateSyncCall, [], undefined, jobId),
|
|
1048
1093
|
);
|
|
1049
1094
|
|
|
1050
1095
|
const sanitizedFilter = await new PrivateEventFilterValidator(this.anchorBlockStore).validate(filter);
|
|
@@ -2,7 +2,7 @@ import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
|
2
2
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
3
3
|
import { createLogger } from '@aztec/foundation/log';
|
|
4
4
|
import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';
|
|
5
|
-
import type {
|
|
5
|
+
import type { AztecAsyncKVStore, AztecAsyncMap } from '@aztec/kv-store';
|
|
6
6
|
import type { EventSelector } from '@aztec/stdlib/abi';
|
|
7
7
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
8
8
|
import { L2BlockHash } from '@aztec/stdlib/block';
|
|
@@ -19,11 +19,14 @@ export type PrivateEventStoreFilter = {
|
|
|
19
19
|
};
|
|
20
20
|
|
|
21
21
|
type PrivateEventEntry = {
|
|
22
|
+
randomness: Fr; // Note that this value is currently not being returned on queries and is therefore temporarily unused
|
|
22
23
|
msgContent: Buffer;
|
|
23
24
|
eventCommitmentIndex: number;
|
|
24
25
|
l2BlockNumber: number;
|
|
25
26
|
l2BlockHash: Buffer;
|
|
26
27
|
txHash: Buffer;
|
|
28
|
+
/** The lookup key for #eventsByContractScopeSelector, used for cleanup during rollback */
|
|
29
|
+
lookupKey: string;
|
|
27
30
|
};
|
|
28
31
|
|
|
29
32
|
type PrivateEventMetadata = InTx & {
|
|
@@ -36,10 +39,12 @@ type PrivateEventMetadata = InTx & {
|
|
|
36
39
|
*/
|
|
37
40
|
export class PrivateEventStore {
|
|
38
41
|
#store: AztecAsyncKVStore;
|
|
39
|
-
/**
|
|
40
|
-
#eventLogs:
|
|
41
|
-
/** Map from
|
|
42
|
-
#
|
|
42
|
+
/** Map storing the actual private event log entries, keyed by eventCommitmentIndex */
|
|
43
|
+
#eventLogs: AztecAsyncMap<number, PrivateEventEntry>;
|
|
44
|
+
/** Map from contractAddress_scope_eventSelector to eventCommitmentIndex[] for efficient lookup */
|
|
45
|
+
#eventsByContractScopeSelector: AztecAsyncMap<string, number[]>;
|
|
46
|
+
/** Map from block number to eventCommitmentIndex[] for rollback support */
|
|
47
|
+
#eventsByBlockNumber: AztecAsyncMap<number, number[]>;
|
|
43
48
|
/** Map from eventCommitmentIndex to boolean indicating if log has been seen. */
|
|
44
49
|
#seenLogs: AztecAsyncMap<number, boolean>;
|
|
45
50
|
|
|
@@ -47,9 +52,10 @@ export class PrivateEventStore {
|
|
|
47
52
|
|
|
48
53
|
constructor(store: AztecAsyncKVStore) {
|
|
49
54
|
this.#store = store;
|
|
50
|
-
this.#eventLogs = this.#store.
|
|
51
|
-
this.#
|
|
55
|
+
this.#eventLogs = this.#store.openMap('private_event_logs');
|
|
56
|
+
this.#eventsByContractScopeSelector = this.#store.openMap('events_by_contract_scope_selector');
|
|
52
57
|
this.#seenLogs = this.#store.openMap('seen_logs');
|
|
58
|
+
this.#eventsByBlockNumber = this.#store.openMap('events_by_block_number');
|
|
53
59
|
}
|
|
54
60
|
|
|
55
61
|
#keyFor(contractAddress: AztecAddress, scope: AztecAddress, eventSelector: EventSelector): string {
|
|
@@ -69,6 +75,7 @@ export class PrivateEventStore {
|
|
|
69
75
|
*/
|
|
70
76
|
storePrivateEventLog(
|
|
71
77
|
eventSelector: EventSelector,
|
|
78
|
+
randomness: Fr,
|
|
72
79
|
msgContent: Fr[],
|
|
73
80
|
eventCommitmentIndex: number,
|
|
74
81
|
metadata: PrivateEventMetadata,
|
|
@@ -87,17 +94,21 @@ export class PrivateEventStore {
|
|
|
87
94
|
|
|
88
95
|
this.logger.verbose('storing private event log', { contractAddress, scope, msgContent, l2BlockNumber });
|
|
89
96
|
|
|
90
|
-
|
|
91
|
-
|
|
97
|
+
await this.#eventLogs.set(eventCommitmentIndex, {
|
|
98
|
+
randomness,
|
|
92
99
|
msgContent: serializeToBuffer(msgContent),
|
|
93
100
|
l2BlockNumber,
|
|
94
101
|
l2BlockHash: l2BlockHash.toBuffer(),
|
|
95
102
|
eventCommitmentIndex,
|
|
96
103
|
txHash: txHash.toBuffer(),
|
|
104
|
+
lookupKey: key,
|
|
97
105
|
});
|
|
98
106
|
|
|
99
|
-
const existingIndices = (await this.#
|
|
100
|
-
await this.#
|
|
107
|
+
const existingIndices = (await this.#eventsByContractScopeSelector.getAsync(key)) || [];
|
|
108
|
+
await this.#eventsByContractScopeSelector.set(key, [...existingIndices, eventCommitmentIndex]);
|
|
109
|
+
|
|
110
|
+
const existingBlockIndices = (await this.#eventsByBlockNumber.getAsync(l2BlockNumber)) || [];
|
|
111
|
+
await this.#eventsByBlockNumber.set(l2BlockNumber, [...existingBlockIndices, eventCommitmentIndex]);
|
|
101
112
|
|
|
102
113
|
// Mark this log as seen using eventCommitmentIndex
|
|
103
114
|
await this.#seenLogs.set(eventCommitmentIndex, true);
|
|
@@ -123,10 +134,10 @@ export class PrivateEventStore {
|
|
|
123
134
|
|
|
124
135
|
for (const scope of filter.scopes) {
|
|
125
136
|
const key = this.#keyFor(filter.contractAddress, scope, eventSelector);
|
|
126
|
-
const
|
|
137
|
+
const eventCommitmentIndices = (await this.#eventsByContractScopeSelector.getAsync(key)) || [];
|
|
127
138
|
|
|
128
|
-
for (const
|
|
129
|
-
const entry = await this.#eventLogs.
|
|
139
|
+
for (const eventCommitmentIndex of eventCommitmentIndices) {
|
|
140
|
+
const entry = await this.#eventLogs.getAsync(eventCommitmentIndex);
|
|
130
141
|
if (!entry || entry.l2BlockNumber < filter.fromBlock || entry.l2BlockNumber >= filter.toBlock) {
|
|
131
142
|
continue;
|
|
132
143
|
}
|
|
@@ -159,4 +170,47 @@ export class PrivateEventStore {
|
|
|
159
170
|
events.sort((a, b) => a.eventCommitmentIndex - b.eventCommitmentIndex);
|
|
160
171
|
return events.map(ev => ev.event);
|
|
161
172
|
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Rolls back private events that were stored after a given `blockNumber` and up to `synchedBlockNumber` (the block
|
|
176
|
+
* number up to which PXE managed to sync before the reorg happened).
|
|
177
|
+
*/
|
|
178
|
+
public async rollbackEventsAfterBlock(blockNumber: number, synchedBlockNumber: number): Promise<void> {
|
|
179
|
+
await this.#store.transactionAsync(async () => {
|
|
180
|
+
let removedCount = 0;
|
|
181
|
+
|
|
182
|
+
for (let block = blockNumber + 1; block <= synchedBlockNumber; block++) {
|
|
183
|
+
const indices = await this.#eventsByBlockNumber.getAsync(block);
|
|
184
|
+
if (indices) {
|
|
185
|
+
await this.#eventsByBlockNumber.delete(block);
|
|
186
|
+
|
|
187
|
+
for (const eventCommitmentIndex of indices) {
|
|
188
|
+
const entry = await this.#eventLogs.getAsync(eventCommitmentIndex);
|
|
189
|
+
if (!entry) {
|
|
190
|
+
throw new Error(`Event log not found for eventCommitmentIndex ${eventCommitmentIndex}`);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
await this.#eventLogs.delete(eventCommitmentIndex);
|
|
194
|
+
await this.#seenLogs.delete(eventCommitmentIndex);
|
|
195
|
+
|
|
196
|
+
// Update #eventsByContractScopeSelector using the stored lookupKey
|
|
197
|
+
const existingIndices = await this.#eventsByContractScopeSelector.getAsync(entry.lookupKey);
|
|
198
|
+
if (!existingIndices || existingIndices.length === 0) {
|
|
199
|
+
throw new Error(`No indices found in #eventsByContractScopeSelector for key ${entry.lookupKey}`);
|
|
200
|
+
}
|
|
201
|
+
const filteredIndices = existingIndices.filter(idx => idx !== eventCommitmentIndex);
|
|
202
|
+
if (filteredIndices.length === 0) {
|
|
203
|
+
await this.#eventsByContractScopeSelector.delete(entry.lookupKey);
|
|
204
|
+
} else {
|
|
205
|
+
await this.#eventsByContractScopeSelector.set(entry.lookupKey, filteredIndices);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
removedCount++;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
this.logger.verbose(`Rolled back ${removedCount} private events after block ${blockNumber}`);
|
|
214
|
+
});
|
|
215
|
+
}
|
|
162
216
|
}
|
|
@@ -3,7 +3,7 @@ import type { AztecAsyncKVStore, AztecAsyncMap } from '@aztec/kv-store';
|
|
|
3
3
|
import type { DirectionalAppTaggingSecret, PreTag } from '@aztec/stdlib/logs';
|
|
4
4
|
import { TxHash } from '@aztec/stdlib/tx';
|
|
5
5
|
|
|
6
|
-
import { UNFINALIZED_TAGGING_INDEXES_WINDOW_LEN } from '../../tagging/
|
|
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
|
|
@@ -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;
|
package/src/tagging/index.ts
CHANGED
|
@@ -11,17 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
export { loadPrivateLogsForSenderRecipientPair } from './recipient_sync/load_private_logs_for_sender_recipient_pair.js';
|
|
13
13
|
export { syncSenderTaggingIndexes } from './sender_sync/sync_sender_tagging_indexes.js';
|
|
14
|
-
|
|
15
|
-
// This window has to be as large as the largest expected number of logs emitted in a tx for a given directional app
|
|
16
|
-
// tagging secret. If we get more tag indexes consumed than this window, an error is thrown in `PXE::proveTx` function.
|
|
17
|
-
// This is set to a larger value than MAX_PRIVATE_LOGS_PER_TX (currently 64) because there could be more than
|
|
18
|
-
// MAX_PRIVATE_LOGS_PER_TX indexes consumed in case the logs are squashed. This happens when the log contains a note
|
|
19
|
-
// and the note is nullified in the same tx.
|
|
20
|
-
//
|
|
21
|
-
// Having a large window significantly slowed down `e2e_l1_with_wall_time` test as there we perform sync for more than
|
|
22
|
-
// 1000 secrets. For this reason we set it to a relatively low value of 20. 20 should be sufficient for all the use
|
|
23
|
-
// cases.
|
|
24
|
-
export const UNFINALIZED_TAGGING_INDEXES_WINDOW_LEN = 20;
|
|
14
|
+
export { UNFINALIZED_TAGGING_INDEXES_WINDOW_LEN } from './constants.js';
|
|
25
15
|
|
|
26
16
|
// Re-export tagging-related types from stdlib
|
|
27
17
|
export { DirectionalAppTaggingSecret, Tag, SiloedTag } from '@aztec/stdlib/logs';
|
|
@@ -4,7 +4,7 @@ import type { AztecNode } from '@aztec/stdlib/interfaces/client';
|
|
|
4
4
|
import type { DirectionalAppTaggingSecret, TxScopedL2Log } from '@aztec/stdlib/logs';
|
|
5
5
|
|
|
6
6
|
import type { RecipientTaggingStore } from '../../storage/tagging_store/recipient_tagging_store.js';
|
|
7
|
-
import { UNFINALIZED_TAGGING_INDEXES_WINDOW_LEN } from '../
|
|
7
|
+
import { UNFINALIZED_TAGGING_INDEXES_WINDOW_LEN } from '../constants.js';
|
|
8
8
|
import { findHighestIndexes } from './utils/find_highest_indexes.js';
|
|
9
9
|
import { loadLogsForRange } from './utils/load_logs_for_range.js';
|
|
10
10
|
|
|
@@ -68,7 +68,10 @@ export async function loadPrivateLogsForSenderRecipientPair(
|
|
|
68
68
|
throw new Error('Node failed to return latest block header when syncing logs');
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
[finalizedBlockNumber, currentTimestamp] = [
|
|
71
|
+
[finalizedBlockNumber, currentTimestamp] = [
|
|
72
|
+
l2Tips.finalized.block.number,
|
|
73
|
+
latestBlockHeader.globalVariables.timestamp,
|
|
74
|
+
];
|
|
72
75
|
}
|
|
73
76
|
|
|
74
77
|
let start: number, end: number;
|
|
@@ -3,7 +3,7 @@ import type { AztecNode } from '@aztec/stdlib/interfaces/server';
|
|
|
3
3
|
import type { DirectionalAppTaggingSecret } from '@aztec/stdlib/logs';
|
|
4
4
|
|
|
5
5
|
import type { SenderTaggingStore } from '../../storage/tagging_store/sender_tagging_store.js';
|
|
6
|
-
import { UNFINALIZED_TAGGING_INDEXES_WINDOW_LEN } from '../
|
|
6
|
+
import { UNFINALIZED_TAGGING_INDEXES_WINDOW_LEN } from '../constants.js';
|
|
7
7
|
import { getStatusChangeOfPending } from './utils/get_status_change_of_pending.js';
|
|
8
8
|
import { loadAndStoreNewTaggingIndexes } from './utils/load_and_store_new_tagging_indexes.js';
|
|
9
9
|
|
|
@@ -10,7 +10,7 @@ export async function getStatusChangeOfPending(
|
|
|
10
10
|
aztecNode: AztecNode,
|
|
11
11
|
): Promise<{ txHashesToFinalize: TxHash[]; txHashesToDrop: TxHash[] }> {
|
|
12
12
|
// Get receipts for all pending tx hashes and the finalized block number.
|
|
13
|
-
const [receipts,
|
|
13
|
+
const [receipts, tips] = await Promise.all([
|
|
14
14
|
Promise.all(pending.map(pendingTxHash => aztecNode.getTxReceipt(pendingTxHash))),
|
|
15
15
|
aztecNode.getL2Tips(),
|
|
16
16
|
]);
|
|
@@ -22,7 +22,11 @@ export async function getStatusChangeOfPending(
|
|
|
22
22
|
const receipt = receipts[i];
|
|
23
23
|
const txHash = pending[i];
|
|
24
24
|
|
|
25
|
-
if (
|
|
25
|
+
if (
|
|
26
|
+
receipt.status === TxStatus.SUCCESS &&
|
|
27
|
+
receipt.blockNumber &&
|
|
28
|
+
receipt.blockNumber <= tips.finalized.block.number
|
|
29
|
+
) {
|
|
26
30
|
// Tx has been included in a block and the corresponding block is finalized --> we mark the indexes as
|
|
27
31
|
// finalized.
|
|
28
32
|
txHashesToFinalize.push(txHash);
|