@aztec/pxe 0.0.1-commit.1142ef1 → 0.0.1-commit.1bea0213
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 +8 -4
- package/dest/block_synchronizer/block_synchronizer.d.ts.map +1 -1
- package/dest/block_synchronizer/block_synchronizer.js +64 -19
- 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 +5 -7
- package/dest/contract_function_simulator/contract_function_simulator.d.ts.map +1 -1
- package/dest/contract_function_simulator/contract_function_simulator.js +26 -16
- 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 +43 -32
- package/dest/contract_function_simulator/oracle/private_execution.d.ts +2 -26
- package/dest/contract_function_simulator/oracle/private_execution.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/private_execution.js +0 -35
- package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts +10 -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 +19 -7
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts +25 -16
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.js +69 -71
- package/dest/contract_sync/index.d.ts +23 -0
- package/dest/contract_sync/index.d.ts.map +1 -0
- package/dest/contract_sync/index.js +54 -0
- package/dest/debug/pxe_debug_utils.d.ts +1 -1
- package/dest/debug/pxe_debug_utils.d.ts.map +1 -1
- package/dest/debug/pxe_debug_utils.js +3 -2
- package/dest/entrypoints/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/events/event_service.d.ts +4 -3
- package/dest/events/event_service.d.ts.map +1 -1
- package/dest/events/event_service.js +17 -19
- package/dest/events/private_event_filter_validator.d.ts +5 -5
- package/dest/events/private_event_filter_validator.d.ts.map +1 -1
- package/dest/events/private_event_filter_validator.js +5 -6
- package/dest/logs/log_service.d.ts +3 -2
- package/dest/logs/log_service.d.ts.map +1 -1
- package/dest/logs/log_service.js +21 -13
- package/dest/notes/note_service.d.ts +5 -4
- package/dest/notes/note_service.d.ts.map +1 -1
- package/dest/notes/note_service.js +30 -34
- package/dest/oracle_version.d.ts +3 -3
- package/dest/oracle_version.d.ts.map +1 -1
- package/dest/oracle_version.js +4 -3
- package/dest/private_kernel/hints/index.d.ts +2 -2
- package/dest/private_kernel/hints/index.d.ts.map +1 -1
- package/dest/private_kernel/hints/index.js +1 -1
- package/dest/private_kernel/hints/private_kernel_reset_private_inputs_builder.d.ts +28 -0
- package/dest/private_kernel/hints/private_kernel_reset_private_inputs_builder.d.ts.map +1 -0
- package/dest/private_kernel/hints/{build_private_kernel_reset_private_inputs.js → private_kernel_reset_private_inputs_builder.js} +12 -6
- package/dest/private_kernel/private_kernel_execution_prover.js +1 -1
- 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 +37 -79
- package/dest/storage/capsule_store/capsule_store.d.ts +24 -9
- package/dest/storage/capsule_store/capsule_store.d.ts.map +1 -1
- package/dest/storage/capsule_store/capsule_store.js +132 -23
- package/dest/storage/contract_store/contract_store.d.ts +1 -2
- package/dest/storage/contract_store/contract_store.d.ts.map +1 -1
- package/dest/storage/contract_store/contract_store.js +0 -12
- package/dest/storage/note_store/note_store.d.ts +45 -56
- package/dest/storage/note_store/note_store.d.ts.map +1 -1
- package/dest/storage/note_store/note_store.js +244 -263
- package/dest/storage/note_store/stored_note.d.ts +16 -0
- package/dest/storage/note_store/stored_note.d.ts.map +1 -0
- package/dest/storage/note_store/stored_note.js +43 -0
- package/dest/storage/private_event_store/private_event_store.d.ts +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 +196 -104
- package/dest/storage/private_event_store/stored_private_event.d.ts +23 -0
- package/dest/storage/private_event_store/stored_private_event.d.ts.map +1 -0
- package/dest/storage/private_event_store/stored_private_event.js +56 -0
- package/dest/storage/tagging_store/recipient_tagging_store.d.ts +15 -8
- package/dest/storage/tagging_store/recipient_tagging_store.d.ts.map +1 -1
- package/dest/storage/tagging_store/recipient_tagging_store.js +69 -12
- package/dest/storage/tagging_store/sender_tagging_store.d.ts +19 -9
- package/dest/storage/tagging_store/sender_tagging_store.d.ts.map +1 -1
- package/dest/storage/tagging_store/sender_tagging_store.js +109 -27
- 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 +70 -21
- 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 +28 -22
- 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 +56 -41
- package/src/contract_function_simulator/oracle/private_execution.ts +1 -67
- package/src/contract_function_simulator/oracle/private_execution_oracle.ts +35 -8
- package/src/contract_function_simulator/oracle/utility_execution_oracle.ts +88 -76
- package/src/contract_sync/index.ts +98 -0
- package/src/debug/pxe_debug_utils.ts +3 -2
- package/src/entrypoints/server/index.ts +2 -0
- package/src/events/event_service.ts +15 -21
- package/src/events/private_event_filter_validator.ts +3 -5
- package/src/logs/log_service.ts +27 -9
- package/src/notes/note_service.ts +37 -40
- package/src/oracle_version.ts +4 -3
- package/src/private_kernel/hints/index.ts +1 -1
- package/src/private_kernel/hints/{build_private_kernel_reset_private_inputs.ts → private_kernel_reset_private_inputs_builder.ts} +32 -20
- package/src/private_kernel/private_kernel_execution_prover.ts +1 -1
- package/src/private_kernel/private_kernel_oracle.ts +116 -37
- package/src/pxe.ts +63 -112
- package/src/storage/capsule_store/capsule_store.ts +159 -23
- package/src/storage/contract_store/contract_store.ts +0 -20
- package/src/storage/note_store/note_store.ts +286 -317
- package/src/storage/note_store/stored_note.ts +48 -0
- package/src/storage/private_event_store/private_event_store.ts +266 -119
- package/src/storage/private_event_store/stored_private_event.ts +73 -0
- package/src/storage/tagging_store/recipient_tagging_store.ts +89 -13
- package/src/storage/tagging_store/sender_tagging_store.ts +128 -27
- 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
package/src/pxe.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { PrivateEventFilter } from '@aztec/aztec.js/wallet';
|
|
2
|
+
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
2
3
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
3
4
|
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
4
5
|
import { SerialQueue } from '@aztec/foundation/queue';
|
|
@@ -19,14 +20,12 @@ import type { AuthWitness } from '@aztec/stdlib/auth-witness';
|
|
|
19
20
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
20
21
|
import {
|
|
21
22
|
CompleteAddress,
|
|
22
|
-
type ContractClassWithId,
|
|
23
23
|
type ContractInstanceWithAddress,
|
|
24
24
|
type PartialAddress,
|
|
25
25
|
computeContractAddressFromInstance,
|
|
26
26
|
getContractClassFromArtifact,
|
|
27
27
|
} from '@aztec/stdlib/contract';
|
|
28
28
|
import { SimulationError } from '@aztec/stdlib/errors';
|
|
29
|
-
import { computeProtocolNullifier, siloNullifier } from '@aztec/stdlib/hash';
|
|
30
29
|
import type { AztecNode, PrivateKernelProver } from '@aztec/stdlib/interfaces/client';
|
|
31
30
|
import type {
|
|
32
31
|
PrivateExecutionStep,
|
|
@@ -54,13 +53,13 @@ import { inspect } from 'util';
|
|
|
54
53
|
|
|
55
54
|
import { BlockSynchronizer } from './block_synchronizer/index.js';
|
|
56
55
|
import type { PXEConfig } from './config/index.js';
|
|
56
|
+
import { BenchmarkedNodeFactory } from './contract_function_simulator/benchmarked_node.js';
|
|
57
57
|
import {
|
|
58
58
|
ContractFunctionSimulator,
|
|
59
59
|
generateSimulatedProvingResult,
|
|
60
60
|
} from './contract_function_simulator/contract_function_simulator.js';
|
|
61
|
-
import { readCurrentClassId } from './contract_function_simulator/oracle/private_execution.js';
|
|
62
61
|
import { ProxiedContractStoreFactory } from './contract_function_simulator/proxied_contract_data_source.js';
|
|
63
|
-
import {
|
|
62
|
+
import { ensureContractSynced, readCurrentClassId } from './contract_sync/index.js';
|
|
64
63
|
import { PXEDebugUtils } from './debug/pxe_debug_utils.js';
|
|
65
64
|
import { enrichPublicSimulationError, enrichSimulationError } from './error_enriching.js';
|
|
66
65
|
import { PrivateEventFilterValidator } from './events/private_event_filter_validator.js';
|
|
@@ -69,7 +68,7 @@ import {
|
|
|
69
68
|
PrivateKernelExecutionProver,
|
|
70
69
|
type PrivateKernelExecutionProverConfig,
|
|
71
70
|
} from './private_kernel/private_kernel_execution_prover.js';
|
|
72
|
-
import {
|
|
71
|
+
import { PrivateKernelOracle } from './private_kernel/private_kernel_oracle.js';
|
|
73
72
|
import { AddressStore } from './storage/address_store/address_store.js';
|
|
74
73
|
import { AnchorBlockStore } from './storage/anchor_block_store/anchor_block_store.js';
|
|
75
74
|
import { CapsuleStore } from './storage/capsule_store/capsule_store.js';
|
|
@@ -138,7 +137,7 @@ export class PXE {
|
|
|
138
137
|
const addressStore = new AddressStore(store);
|
|
139
138
|
const privateEventStore = new PrivateEventStore(store);
|
|
140
139
|
const contractStore = new ContractStore(store);
|
|
141
|
-
const noteStore =
|
|
140
|
+
const noteStore = new NoteStore(store);
|
|
142
141
|
const anchorBlockStore = new AnchorBlockStore(store);
|
|
143
142
|
const senderTaggingStore = new SenderTaggingStore(store);
|
|
144
143
|
const senderAddressBookStore = new SenderAddressBookStore(store);
|
|
@@ -148,6 +147,7 @@ export class PXE {
|
|
|
148
147
|
const tipsStore = new L2TipsKVStore(store, 'pxe');
|
|
149
148
|
const synchronizer = new BlockSynchronizer(
|
|
150
149
|
node,
|
|
150
|
+
store,
|
|
151
151
|
anchorBlockStore,
|
|
152
152
|
noteStore,
|
|
153
153
|
privateEventStore,
|
|
@@ -157,6 +157,13 @@ export class PXE {
|
|
|
157
157
|
);
|
|
158
158
|
|
|
159
159
|
const jobCoordinator = new JobCoordinator(store);
|
|
160
|
+
jobCoordinator.registerStores([
|
|
161
|
+
capsuleStore,
|
|
162
|
+
senderTaggingStore,
|
|
163
|
+
recipientTaggingStore,
|
|
164
|
+
privateEventStore,
|
|
165
|
+
noteStore,
|
|
166
|
+
]);
|
|
160
167
|
|
|
161
168
|
const debugUtils = new PXEDebugUtils(contractStore, noteStore);
|
|
162
169
|
|
|
@@ -205,7 +212,7 @@ export class PXE {
|
|
|
205
212
|
this.noteStore,
|
|
206
213
|
this.keyStore,
|
|
207
214
|
this.addressStore,
|
|
208
|
-
|
|
215
|
+
BenchmarkedNodeFactory.create(this.node),
|
|
209
216
|
this.anchorBlockStore,
|
|
210
217
|
this.senderTaggingStore,
|
|
211
218
|
this.recipientTaggingStore,
|
|
@@ -274,19 +281,6 @@ export class PXE {
|
|
|
274
281
|
this.log.verbose(`Registered protocol contracts in pxe`, registered);
|
|
275
282
|
}
|
|
276
283
|
|
|
277
|
-
async #isContractClassPubliclyRegistered(id: Fr): Promise<boolean> {
|
|
278
|
-
return !!(await this.node.getContractClass(id));
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
async #isContractPublished(address: AztecAddress): Promise<boolean> {
|
|
282
|
-
return !!(await this.node.getContract(address));
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
async #isContractInitialized(address: AztecAddress): Promise<boolean> {
|
|
286
|
-
const initNullifier = await siloNullifier(address, address.toField());
|
|
287
|
-
return !!(await this.node.getNullifierMembershipWitness('latest', initNullifier));
|
|
288
|
-
}
|
|
289
|
-
|
|
290
284
|
// Executes the entrypoint private function, as well as all nested private
|
|
291
285
|
// functions that might arise.
|
|
292
286
|
async #executePrivate(
|
|
@@ -300,6 +294,15 @@ export class PXE {
|
|
|
300
294
|
try {
|
|
301
295
|
const anchorBlockHeader = await this.anchorBlockStore.getBlockHeader();
|
|
302
296
|
|
|
297
|
+
await ensureContractSynced(
|
|
298
|
+
contractAddress,
|
|
299
|
+
functionSelector,
|
|
300
|
+
privateSyncCall => this.#simulateUtility(contractFunctionSimulator, privateSyncCall, [], undefined, jobId),
|
|
301
|
+
this.node,
|
|
302
|
+
this.contractStore,
|
|
303
|
+
anchorBlockHeader,
|
|
304
|
+
);
|
|
305
|
+
|
|
303
306
|
const result = await contractFunctionSimulator.run(
|
|
304
307
|
txRequest,
|
|
305
308
|
contractAddress,
|
|
@@ -394,13 +397,9 @@ export class PXE {
|
|
|
394
397
|
privateExecutionResult: PrivateExecutionResult,
|
|
395
398
|
config: PrivateKernelExecutionProverConfig,
|
|
396
399
|
): Promise<PrivateKernelExecutionProofOutput<PrivateKernelTailCircuitPublicInputs>> {
|
|
397
|
-
const
|
|
398
|
-
const
|
|
399
|
-
|
|
400
|
-
this.keyStore,
|
|
401
|
-
this.node,
|
|
402
|
-
simulationAnchorBlock,
|
|
403
|
-
);
|
|
400
|
+
const anchorBlockHeader = await this.anchorBlockStore.getBlockHeader();
|
|
401
|
+
const anchorBlockHash = await anchorBlockHeader.hash();
|
|
402
|
+
const kernelOracle = new PrivateKernelOracle(this.contractStore, this.keyStore, this.node, anchorBlockHash);
|
|
404
403
|
const kernelTraceProver = new PrivateKernelExecutionProver(kernelOracle, proofCreator, !this.proverEnabled);
|
|
405
404
|
this.log.debug(`Executing kernel trace prover (${JSON.stringify(config)})...`);
|
|
406
405
|
return await kernelTraceProver.proveWithKernels(txExecutionRequest.toTxRequest(), privateExecutionResult, config);
|
|
@@ -413,66 +412,12 @@ export class PXE {
|
|
|
413
412
|
}
|
|
414
413
|
|
|
415
414
|
/**
|
|
416
|
-
* Returns the contract
|
|
417
|
-
*
|
|
418
|
-
* @
|
|
419
|
-
* @param id - Identifier of the class.
|
|
420
|
-
* @param includeArtifact - Identifier of the class.
|
|
421
|
-
* @returns - It returns the contract class metadata, with the artifact field being optional, and will only be returned if true is passed in
|
|
422
|
-
* for `includeArtifact`
|
|
423
|
-
* TODO(@spalladino): The PXE actually holds artifacts and not classes, what should we return? Also,
|
|
424
|
-
* should the pxe query the node for contract public info, and merge it with its own definitions?
|
|
425
|
-
* TODO(@spalladino): This method is strictly needed to decide whether to publicly register a class or not
|
|
426
|
-
* during a public deployment. We probably want a nicer and more general API for this, but it'll have to
|
|
427
|
-
* do for the time being.
|
|
415
|
+
* Returns the contract artifact for a given contract class id, if it's registered in the PXE.
|
|
416
|
+
* @param id - Identifier of the contract class.
|
|
417
|
+
* @returns The contract artifact if found, undefined otherwise.
|
|
428
418
|
*/
|
|
429
|
-
public async
|
|
430
|
-
id
|
|
431
|
-
includeArtifact: boolean = false,
|
|
432
|
-
): Promise<{
|
|
433
|
-
contractClass: ContractClassWithId | undefined;
|
|
434
|
-
isContractClassPubliclyRegistered: boolean;
|
|
435
|
-
artifact: ContractArtifact | undefined;
|
|
436
|
-
}> {
|
|
437
|
-
const artifact = await this.contractStore.getContractArtifact(id);
|
|
438
|
-
if (!artifact) {
|
|
439
|
-
this.log.warn(`No artifact found for contract class ${id.toString()} when looking for its metadata`);
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
return {
|
|
443
|
-
contractClass: artifact && (await getContractClassFromArtifact(artifact)),
|
|
444
|
-
isContractClassPubliclyRegistered: await this.#isContractClassPubliclyRegistered(id),
|
|
445
|
-
artifact: includeArtifact ? artifact : undefined,
|
|
446
|
-
};
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
/**
|
|
450
|
-
* Returns the contract metadata given an address.
|
|
451
|
-
* The metadata consists of its contract instance, which includes the contract class identifier,
|
|
452
|
-
* initialization hash, deployment salt, and public keys hash; whether the contract instance has been initialized;
|
|
453
|
-
* and whether the contract instance with the given address has been publicly deployed.
|
|
454
|
-
* @remark - it queries the node to check whether the contract instance has been initialized / publicly deployed through a node.
|
|
455
|
-
* This query is not dependent on the PXE.
|
|
456
|
-
* @param address - The address that the contract instance resides at.
|
|
457
|
-
* @returns - It returns the contract metadata
|
|
458
|
-
* TODO(@spalladino): Should we return the public keys in plain as well here?
|
|
459
|
-
*/
|
|
460
|
-
public async getContractMetadata(address: AztecAddress): Promise<{
|
|
461
|
-
contractInstance: ContractInstanceWithAddress | undefined;
|
|
462
|
-
isContractInitialized: boolean;
|
|
463
|
-
isContractPublished: boolean;
|
|
464
|
-
}> {
|
|
465
|
-
let instance;
|
|
466
|
-
try {
|
|
467
|
-
instance = await this.contractStore.getContractInstance(address);
|
|
468
|
-
} catch {
|
|
469
|
-
this.log.warn(`No instance found for contract ${address.toString()} when looking for its metadata`);
|
|
470
|
-
}
|
|
471
|
-
return {
|
|
472
|
-
contractInstance: instance,
|
|
473
|
-
isContractInitialized: await this.#isContractInitialized(address),
|
|
474
|
-
isContractPublished: await this.#isContractPublished(address),
|
|
475
|
-
};
|
|
419
|
+
public async getContractArtifact(id: Fr): Promise<ContractArtifact | undefined> {
|
|
420
|
+
return await this.contractStore.getContractArtifact(id);
|
|
476
421
|
}
|
|
477
422
|
|
|
478
423
|
/**
|
|
@@ -497,7 +442,6 @@ export class PXE {
|
|
|
497
442
|
}
|
|
498
443
|
|
|
499
444
|
await this.addressStore.addCompleteAddress(accountCompleteAddress);
|
|
500
|
-
await this.noteStore.addScope(accountCompleteAddress.address);
|
|
501
445
|
return accountCompleteAddress;
|
|
502
446
|
}
|
|
503
447
|
|
|
@@ -645,13 +589,7 @@ export class PXE {
|
|
|
645
589
|
|
|
646
590
|
const header = await this.anchorBlockStore.getBlockHeader();
|
|
647
591
|
|
|
648
|
-
const currentClassId = await readCurrentClassId(
|
|
649
|
-
contractAddress,
|
|
650
|
-
currentInstance,
|
|
651
|
-
this.node,
|
|
652
|
-
header.globalVariables.blockNumber,
|
|
653
|
-
header.globalVariables.timestamp,
|
|
654
|
-
);
|
|
592
|
+
const currentClassId = await readCurrentClassId(contractAddress, currentInstance, this.node, header);
|
|
655
593
|
if (!contractClass.id.equals(currentClassId)) {
|
|
656
594
|
throw new Error('Could not update contract to a class different from the current one.');
|
|
657
595
|
}
|
|
@@ -744,7 +682,7 @@ export class PXE {
|
|
|
744
682
|
// TODO(benesjan): The following is an expensive operation. Figure out a way to avoid it.
|
|
745
683
|
const txHash = (await txProvingResult.toTx()).txHash;
|
|
746
684
|
|
|
747
|
-
await this.senderTaggingStore.storePendingIndexes(preTagsUsedInTheTx, txHash);
|
|
685
|
+
await this.senderTaggingStore.storePendingIndexes(preTagsUsedInTheTx, txHash, jobId);
|
|
748
686
|
this.log.debug(`Stored used pre-tags as sender for the tx`, {
|
|
749
687
|
preTagsUsedInTheTx,
|
|
750
688
|
});
|
|
@@ -911,14 +849,8 @@ export class PXE {
|
|
|
911
849
|
let executionSteps: PrivateExecutionStep[] = [];
|
|
912
850
|
|
|
913
851
|
if (skipKernels) {
|
|
914
|
-
// According to the protocol rules, the nonce generator for the note hashes
|
|
915
|
-
// can either be the first nullifier in the tx or the protocol nullifier if there are none.
|
|
916
|
-
const nonceGenerator = privateExecutionResult.firstNullifier.equals(Fr.ZERO)
|
|
917
|
-
? await computeProtocolNullifier(await txRequest.toTxRequest().hash())
|
|
918
|
-
: privateExecutionResult.firstNullifier;
|
|
919
852
|
({ publicInputs, executionSteps } = await generateSimulatedProvingResult(
|
|
920
853
|
privateExecutionResult,
|
|
921
|
-
nonceGenerator,
|
|
922
854
|
this.contractStore,
|
|
923
855
|
));
|
|
924
856
|
} else {
|
|
@@ -1029,8 +961,14 @@ export class PXE {
|
|
|
1029
961
|
const functionTimer = new Timer();
|
|
1030
962
|
const contractFunctionSimulator = this.#getSimulatorForTx();
|
|
1031
963
|
|
|
1032
|
-
await this.
|
|
1033
|
-
|
|
964
|
+
const anchorBlockHeader = await this.anchorBlockStore.getBlockHeader();
|
|
965
|
+
await ensureContractSynced(
|
|
966
|
+
call.to,
|
|
967
|
+
call.selector,
|
|
968
|
+
privateSyncCall => this.#simulateUtility(contractFunctionSimulator, privateSyncCall, [], undefined, jobId),
|
|
969
|
+
this.node,
|
|
970
|
+
this.contractStore,
|
|
971
|
+
anchorBlockHeader,
|
|
1034
972
|
);
|
|
1035
973
|
|
|
1036
974
|
const executionResult = await this.#simulateUtility(
|
|
@@ -1080,26 +1018,39 @@ export class PXE {
|
|
|
1080
1018
|
* Defaults to the latest known block to PXE + 1.
|
|
1081
1019
|
* @returns - The packed events with block and tx metadata.
|
|
1082
1020
|
*/
|
|
1083
|
-
public getPrivateEvents(
|
|
1084
|
-
|
|
1021
|
+
public async getPrivateEvents(
|
|
1022
|
+
eventSelector: EventSelector,
|
|
1023
|
+
filter: PrivateEventFilter,
|
|
1024
|
+
): Promise<PackedPrivateEvent[]> {
|
|
1025
|
+
let anchorBlockNumber: BlockNumber;
|
|
1026
|
+
|
|
1027
|
+
await this.#putInJobQueue(async jobId => {
|
|
1085
1028
|
await this.blockStateSynchronizer.sync();
|
|
1029
|
+
|
|
1030
|
+
const anchorBlockHeader = await this.anchorBlockStore.getBlockHeader();
|
|
1031
|
+
anchorBlockNumber = anchorBlockHeader.getBlockNumber();
|
|
1032
|
+
|
|
1086
1033
|
const contractFunctionSimulator = this.#getSimulatorForTx();
|
|
1087
1034
|
|
|
1088
|
-
await
|
|
1035
|
+
await ensureContractSynced(
|
|
1089
1036
|
filter.contractAddress,
|
|
1090
1037
|
null,
|
|
1091
1038
|
async privateSyncCall =>
|
|
1092
1039
|
await this.#simulateUtility(contractFunctionSimulator, privateSyncCall, [], undefined, jobId),
|
|
1040
|
+
this.node,
|
|
1041
|
+
this.contractStore,
|
|
1042
|
+
anchorBlockHeader,
|
|
1093
1043
|
);
|
|
1044
|
+
});
|
|
1094
1045
|
|
|
1095
|
-
|
|
1046
|
+
// anchorBlockNumber is set during the job and fixed to whatever it is after a block sync
|
|
1047
|
+
const sanitizedFilter = new PrivateEventFilterValidator(anchorBlockNumber!).validate(filter);
|
|
1096
1048
|
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1049
|
+
this.log.debug(
|
|
1050
|
+
`Getting private events for ${sanitizedFilter.contractAddress.toString()} from ${sanitizedFilter.fromBlock} to ${sanitizedFilter.toBlock}`,
|
|
1051
|
+
);
|
|
1100
1052
|
|
|
1101
|
-
|
|
1102
|
-
});
|
|
1053
|
+
return this.privateEventStore.getPrivateEvents(eventSelector, sanitizedFilter);
|
|
1103
1054
|
}
|
|
1104
1055
|
|
|
1105
1056
|
/**
|
|
@@ -3,12 +3,21 @@ import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
|
3
3
|
import type { AztecAsyncKVStore, AztecAsyncMap } from '@aztec/kv-store';
|
|
4
4
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
import type { StagedStore } from '../../job_coordinator/job_coordinator.js';
|
|
7
|
+
|
|
8
|
+
export class CapsuleStore implements StagedStore {
|
|
9
|
+
readonly storeName = 'capsule';
|
|
10
|
+
|
|
7
11
|
#store: AztecAsyncKVStore;
|
|
8
12
|
|
|
9
13
|
// Arbitrary data stored by contracts. Key is computed as `${contractAddress}:${key}`
|
|
10
14
|
#capsules: AztecAsyncMap<string, Buffer>;
|
|
11
15
|
|
|
16
|
+
// jobId => `${contractAddress}:${key}` => capsule data
|
|
17
|
+
// when `#stagedCapsules.get('some-job-id').get('${some-contract-address:some-key') === null`,
|
|
18
|
+
// it signals that the capsule was deleted during the job, so it needs to be deleted on commit
|
|
19
|
+
#stagedCapsules: Map<string, Map<string, Buffer | null>>;
|
|
20
|
+
|
|
12
21
|
logger: Logger;
|
|
13
22
|
|
|
14
23
|
constructor(store: AztecAsyncKVStore) {
|
|
@@ -16,21 +25,120 @@ export class CapsuleStore {
|
|
|
16
25
|
|
|
17
26
|
this.#capsules = this.#store.openMap('capsules');
|
|
18
27
|
|
|
28
|
+
this.#stagedCapsules = new Map();
|
|
29
|
+
|
|
19
30
|
this.logger = createLogger('pxe:capsule-data-provider');
|
|
20
31
|
}
|
|
21
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Given a job denoted by `jobId`, it returns the
|
|
35
|
+
* capsules that said job has interacted with.
|
|
36
|
+
*
|
|
37
|
+
* Capsules that haven't been committed to persistence KV storage
|
|
38
|
+
* are kept in-memory in `#stagedCapsules`, this method provides a convenient
|
|
39
|
+
* way to access that in-memory collection of data.
|
|
40
|
+
*
|
|
41
|
+
* @param jobId
|
|
42
|
+
* @returns
|
|
43
|
+
*/
|
|
44
|
+
#getJobStagedCapsules(jobId: string): Map<string, Buffer | null> {
|
|
45
|
+
let jobStagedCapsules = this.#stagedCapsules.get(jobId);
|
|
46
|
+
if (!jobStagedCapsules) {
|
|
47
|
+
jobStagedCapsules = new Map();
|
|
48
|
+
this.#stagedCapsules.set(jobId, jobStagedCapsules);
|
|
49
|
+
}
|
|
50
|
+
return jobStagedCapsules;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Reads a capsule's slot from the staged version of the data associated to the given jobId.
|
|
55
|
+
*
|
|
56
|
+
* If it is not there, it reads it from the KV store.
|
|
57
|
+
*/
|
|
58
|
+
async #getFromStage(jobId: string, dbSlotKey: string): Promise<Buffer | null | undefined> {
|
|
59
|
+
const jobStagedCapsules = this.#getJobStagedCapsules(jobId);
|
|
60
|
+
let staged: Buffer | null | undefined = jobStagedCapsules.get(dbSlotKey);
|
|
61
|
+
// Note that if staged === null, we marked it for deletion, so we don't want to
|
|
62
|
+
// re-read it from DB
|
|
63
|
+
if (staged === undefined) {
|
|
64
|
+
// If we don't have a staged version of this dbSlotKey, first we check if there's one in DB
|
|
65
|
+
staged = await this.#loadCapsuleFromDb(dbSlotKey);
|
|
66
|
+
}
|
|
67
|
+
return staged;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Writes a capsule to the stage of a job.
|
|
72
|
+
*/
|
|
73
|
+
#setOnStage(jobId: string, dbSlotKey: string, capsuleData: Buffer) {
|
|
74
|
+
this.#getJobStagedCapsules(jobId).set(dbSlotKey, capsuleData);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Deletes a capsule on the stage of a job. Note the capsule will still
|
|
79
|
+
* exist in storage until the job is committed.
|
|
80
|
+
*/
|
|
81
|
+
#deleteOnStage(jobId: string, dbSlotKey: string) {
|
|
82
|
+
this.#getJobStagedCapsules(jobId).set(dbSlotKey, null);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async #loadCapsuleFromDb(dbSlotKey: string): Promise<Buffer | null> {
|
|
86
|
+
const dataBuffer = await this.#capsules.getAsync(dbSlotKey);
|
|
87
|
+
if (!dataBuffer) {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return dataBuffer;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Commits staged data to main storage.
|
|
96
|
+
* Called by JobCoordinator when a job completes successfully.
|
|
97
|
+
* Note: JobCoordinator wraps all commits in a single transaction, so we don't
|
|
98
|
+
* need our own transactionAsync here (and using one would deadlock on IndexedDB).
|
|
99
|
+
* @param jobId - The jobId identifying which staged data to commit
|
|
100
|
+
*/
|
|
101
|
+
async commit(jobId: string): Promise<void> {
|
|
102
|
+
const jobStagedCapsules = this.#getJobStagedCapsules(jobId);
|
|
103
|
+
|
|
104
|
+
for (const [key, value] of jobStagedCapsules) {
|
|
105
|
+
// In the write stage, we represent deleted capsules with null
|
|
106
|
+
// (as opposed to undefined, which denotes there was never a capsule there to begin with).
|
|
107
|
+
// So we delete from actual KV store here.
|
|
108
|
+
if (value === null) {
|
|
109
|
+
await this.#capsules.delete(key);
|
|
110
|
+
} else {
|
|
111
|
+
await this.#capsules.set(key, value);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
this.#stagedCapsules.delete(jobId);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Discards staged data without committing.
|
|
120
|
+
*/
|
|
121
|
+
discardStaged(jobId: string): Promise<void> {
|
|
122
|
+
this.#stagedCapsules.delete(jobId);
|
|
123
|
+
return Promise.resolve();
|
|
124
|
+
}
|
|
125
|
+
|
|
22
126
|
/**
|
|
23
127
|
* Stores arbitrary information in a per-contract non-volatile database, which can later be retrieved with `loadCapsule`.
|
|
24
128
|
* * If data was already stored at this slot, it is overwritten.
|
|
25
129
|
* @param contractAddress - The contract address to scope the data under.
|
|
26
130
|
* @param slot - The slot in the database in which to store the value. Slots need not be contiguous.
|
|
27
131
|
* @param capsule - An array of field elements representing the capsule.
|
|
132
|
+
* @param jobId - The context in which this store will be visible until PXE decides to persist it to underlying KV store
|
|
28
133
|
* @remarks A capsule is a "blob" of data that is passed to the contract through an oracle. It works similarly
|
|
29
134
|
* to public contract storage in that it's indexed by the contract address and storage slot but instead of the global
|
|
30
135
|
* network state it's backed by local PXE db.
|
|
31
136
|
*/
|
|
32
|
-
|
|
33
|
-
|
|
137
|
+
storeCapsule(contractAddress: AztecAddress, slot: Fr, capsule: Fr[], jobId: string) {
|
|
138
|
+
const dbSlotKey = dbSlotToKey(contractAddress, slot);
|
|
139
|
+
|
|
140
|
+
// A store overrides any pre-existing data on the slot
|
|
141
|
+
this.#setOnStage(jobId, dbSlotKey, Buffer.concat(capsule.map(value => value.toBuffer())));
|
|
34
142
|
}
|
|
35
143
|
|
|
36
144
|
/**
|
|
@@ -39,8 +147,8 @@ export class CapsuleStore {
|
|
|
39
147
|
* @param slot - The slot in the database to read.
|
|
40
148
|
* @returns The stored data or `null` if no data is stored under the slot.
|
|
41
149
|
*/
|
|
42
|
-
async loadCapsule(contractAddress: AztecAddress, slot: Fr): Promise<Fr[] | null> {
|
|
43
|
-
const dataBuffer = await this.#
|
|
150
|
+
async loadCapsule(contractAddress: AztecAddress, slot: Fr, jobId: string): Promise<Fr[] | null> {
|
|
151
|
+
const dataBuffer = await this.#getFromStage(jobId, dbSlotToKey(contractAddress, slot));
|
|
44
152
|
if (!dataBuffer) {
|
|
45
153
|
this.logger.trace(`Data not found for contract ${contractAddress.toString()} and slot ${slot.toString()}`);
|
|
46
154
|
return null;
|
|
@@ -57,8 +165,9 @@ export class CapsuleStore {
|
|
|
57
165
|
* @param contractAddress - The contract address under which the data is scoped.
|
|
58
166
|
* @param slot - The slot in the database to delete.
|
|
59
167
|
*/
|
|
60
|
-
|
|
61
|
-
|
|
168
|
+
deleteCapsule(contractAddress: AztecAddress, slot: Fr, jobId: string) {
|
|
169
|
+
// When we commit this, we will interpret null as a deletion, so we'll propagate the delete to the KV store
|
|
170
|
+
this.#deleteOnStage(jobId, dbSlotToKey(contractAddress, slot));
|
|
62
171
|
}
|
|
63
172
|
|
|
64
173
|
/**
|
|
@@ -72,13 +181,22 @@ export class CapsuleStore {
|
|
|
72
181
|
* @param dstSlot - The first slot to copy to.
|
|
73
182
|
* @param numEntries - The number of entries to copy.
|
|
74
183
|
*/
|
|
75
|
-
copyCapsule(
|
|
184
|
+
copyCapsule(
|
|
185
|
+
contractAddress: AztecAddress,
|
|
186
|
+
srcSlot: Fr,
|
|
187
|
+
dstSlot: Fr,
|
|
188
|
+
numEntries: number,
|
|
189
|
+
jobId: string,
|
|
190
|
+
): Promise<void> {
|
|
191
|
+
// This transactional context gives us "copy atomicity":
|
|
192
|
+
// there shouldn't be concurrent writes to what's being copied here.
|
|
193
|
+
// Equally important: this in practice is expected to perform thousands of DB operations
|
|
194
|
+
// and not using a transaction here would heavily impact performance.
|
|
76
195
|
return this.#store.transactionAsync(async () => {
|
|
77
196
|
// In order to support overlapping source and destination regions, we need to check the relative positions of source
|
|
78
197
|
// and destination. If destination is ahead of source, then by the time we overwrite source elements using forward
|
|
79
198
|
// indexes we'll have already read those. On the contrary, if source is ahead of destination we need to use backward
|
|
80
199
|
// indexes to avoid reading elements that've been overwritten.
|
|
81
|
-
|
|
82
200
|
const indexes = Array.from(Array(numEntries).keys());
|
|
83
201
|
if (srcSlot.lt(dstSlot)) {
|
|
84
202
|
indexes.reverse();
|
|
@@ -88,12 +206,12 @@ export class CapsuleStore {
|
|
|
88
206
|
const currentSrcSlot = dbSlotToKey(contractAddress, srcSlot.add(new Fr(i)));
|
|
89
207
|
const currentDstSlot = dbSlotToKey(contractAddress, dstSlot.add(new Fr(i)));
|
|
90
208
|
|
|
91
|
-
const toCopy = await this.#
|
|
209
|
+
const toCopy = await this.#getFromStage(jobId, currentSrcSlot);
|
|
92
210
|
if (!toCopy) {
|
|
93
211
|
throw new Error(`Attempted to copy empty slot ${currentSrcSlot} for contract ${contractAddress.toString()}`);
|
|
94
212
|
}
|
|
95
213
|
|
|
96
|
-
|
|
214
|
+
this.#setOnStage(jobId, currentDstSlot, toCopy);
|
|
97
215
|
}
|
|
98
216
|
});
|
|
99
217
|
}
|
|
@@ -106,35 +224,45 @@ export class CapsuleStore {
|
|
|
106
224
|
* @param baseSlot - The slot where the array length is stored
|
|
107
225
|
* @param content - Array of capsule data to append
|
|
108
226
|
*/
|
|
109
|
-
appendToCapsuleArray(contractAddress: AztecAddress, baseSlot: Fr, content: Fr[][]): Promise<void> {
|
|
227
|
+
appendToCapsuleArray(contractAddress: AztecAddress, baseSlot: Fr, content: Fr[][], jobId: string): Promise<void> {
|
|
228
|
+
// We wrap this in a transaction to serialize concurrent calls from Promise.all.
|
|
229
|
+
// Without this, concurrent appends to the same array could race: both read length=0,
|
|
230
|
+
// both write at the same slots, one overwrites the other.
|
|
231
|
+
// Equally important: this in practice is expected to perform thousands of DB operations
|
|
232
|
+
// and not using a transaction here would heavily impact performance.
|
|
110
233
|
return this.#store.transactionAsync(async () => {
|
|
111
234
|
// Load current length, defaulting to 0 if not found
|
|
112
|
-
const lengthData = await this.loadCapsule(contractAddress, baseSlot);
|
|
235
|
+
const lengthData = await this.loadCapsule(contractAddress, baseSlot, jobId);
|
|
113
236
|
const currentLength = lengthData ? lengthData[0].toNumber() : 0;
|
|
114
237
|
|
|
115
238
|
// Store each capsule at consecutive slots after baseSlot + 1 + currentLength
|
|
116
239
|
for (let i = 0; i < content.length; i++) {
|
|
117
240
|
const nextSlot = arraySlot(baseSlot, currentLength + i);
|
|
118
|
-
|
|
241
|
+
this.storeCapsule(contractAddress, nextSlot, content[i], jobId);
|
|
119
242
|
}
|
|
120
243
|
|
|
121
244
|
// Update length to include all new capsules
|
|
122
245
|
const newLength = currentLength + content.length;
|
|
123
|
-
|
|
246
|
+
this.storeCapsule(contractAddress, baseSlot, [new Fr(newLength)], jobId);
|
|
124
247
|
});
|
|
125
248
|
}
|
|
126
249
|
|
|
127
|
-
readCapsuleArray(contractAddress: AztecAddress, baseSlot: Fr): Promise<Fr[][]> {
|
|
250
|
+
readCapsuleArray(contractAddress: AztecAddress, baseSlot: Fr, jobId: string): Promise<Fr[][]> {
|
|
251
|
+
// I'm leaving this transactional context here though because I'm assuming this
|
|
252
|
+
// gives us "read array atomicity": there shouldn't be concurrent writes to what's being copied
|
|
253
|
+
// here.
|
|
254
|
+
// This is one point we should revisit in the future if we want to relax the concurrency
|
|
255
|
+
// of jobs: different calls running concurrently on the same contract may cause trouble.
|
|
128
256
|
return this.#store.transactionAsync(async () => {
|
|
129
257
|
// Load length, defaulting to 0 if not found
|
|
130
|
-
const maybeLength = await this.loadCapsule(contractAddress, baseSlot);
|
|
258
|
+
const maybeLength = await this.loadCapsule(contractAddress, baseSlot, jobId);
|
|
131
259
|
const length = maybeLength ? maybeLength[0].toBigInt() : 0n;
|
|
132
260
|
|
|
133
261
|
const values: Fr[][] = [];
|
|
134
262
|
|
|
135
263
|
// Read each capsule at consecutive slots after baseSlot
|
|
136
264
|
for (let i = 0; i < length; i++) {
|
|
137
|
-
const currentValue = await this.loadCapsule(contractAddress, arraySlot(baseSlot, i));
|
|
265
|
+
const currentValue = await this.loadCapsule(contractAddress, arraySlot(baseSlot, i), jobId);
|
|
138
266
|
if (currentValue == undefined) {
|
|
139
267
|
throw new Error(
|
|
140
268
|
`Expected non-empty value at capsule array in base slot ${baseSlot} at index ${i} for contract ${contractAddress}`,
|
|
@@ -148,23 +276,31 @@ export class CapsuleStore {
|
|
|
148
276
|
});
|
|
149
277
|
}
|
|
150
278
|
|
|
151
|
-
setCapsuleArray(contractAddress: AztecAddress, baseSlot: Fr, content: Fr[][]) {
|
|
279
|
+
setCapsuleArray(contractAddress: AztecAddress, baseSlot: Fr, content: Fr[][], jobId: string) {
|
|
280
|
+
// This transactional context in theory isn't so critical now because we aren't
|
|
281
|
+
// writing to DB so if there's exceptions midway and it blows up, no visible impact
|
|
282
|
+
// to persistent storage will happen.
|
|
283
|
+
// I'm leaving this transactional context here though because I'm assuming this
|
|
284
|
+
// gives us "write array atomicity": there shouldn't be concurrent writes to what's being copied
|
|
285
|
+
// here.
|
|
286
|
+
// This is one point we should revisit in the future if we want to relax the concurrency
|
|
287
|
+
// of jobs: different calls running concurrently on the same contract may cause trouble.
|
|
152
288
|
return this.#store.transactionAsync(async () => {
|
|
153
289
|
// Load current length, defaulting to 0 if not found
|
|
154
|
-
const maybeLength = await this.loadCapsule(contractAddress, baseSlot);
|
|
290
|
+
const maybeLength = await this.loadCapsule(contractAddress, baseSlot, jobId);
|
|
155
291
|
const originalLength = maybeLength ? maybeLength[0].toNumber() : 0;
|
|
156
292
|
|
|
157
293
|
// Set the new length
|
|
158
|
-
|
|
294
|
+
this.storeCapsule(contractAddress, baseSlot, [new Fr(content.length)], jobId);
|
|
159
295
|
|
|
160
296
|
// Store the new content, possibly overwriting existing values
|
|
161
297
|
for (let i = 0; i < content.length; i++) {
|
|
162
|
-
|
|
298
|
+
this.storeCapsule(contractAddress, arraySlot(baseSlot, i), content[i], jobId);
|
|
163
299
|
}
|
|
164
300
|
|
|
165
301
|
// Clear any stragglers
|
|
166
302
|
for (let i = content.length; i < originalLength; i++) {
|
|
167
|
-
|
|
303
|
+
this.deleteCapsule(contractAddress, arraySlot(baseSlot, i), jobId);
|
|
168
304
|
}
|
|
169
305
|
});
|
|
170
306
|
}
|
|
@@ -3,7 +3,6 @@ import type { Fr } from '@aztec/foundation/curves/bn254';
|
|
|
3
3
|
import { toArray } from '@aztec/foundation/iterable';
|
|
4
4
|
import type { MembershipWitness } from '@aztec/foundation/trees';
|
|
5
5
|
import type { AztecAsyncKVStore, AztecAsyncMap } from '@aztec/kv-store';
|
|
6
|
-
import { isProtocolContract } from '@aztec/protocol-contracts';
|
|
7
6
|
import {
|
|
8
7
|
type ContractArtifact,
|
|
9
8
|
type FunctionAbi,
|
|
@@ -317,23 +316,4 @@ export class ContractStore {
|
|
|
317
316
|
returnTypes: functionDao.returnTypes,
|
|
318
317
|
};
|
|
319
318
|
}
|
|
320
|
-
|
|
321
|
-
// Synchronize target contract data
|
|
322
|
-
public async syncPrivateState(
|
|
323
|
-
contractAddress: AztecAddress,
|
|
324
|
-
functionToInvokeAfterSync: FunctionSelector | null,
|
|
325
|
-
utilityExecutor: (privateSyncCall: FunctionCall) => Promise<any>,
|
|
326
|
-
) {
|
|
327
|
-
// Protocol contracts don't have private state to sync
|
|
328
|
-
if (!isProtocolContract(contractAddress)) {
|
|
329
|
-
const syncPrivateStateFunctionCall = await this.getFunctionCall('sync_private_state', [], contractAddress);
|
|
330
|
-
if (functionToInvokeAfterSync && functionToInvokeAfterSync.equals(syncPrivateStateFunctionCall.selector)) {
|
|
331
|
-
throw new Error(
|
|
332
|
-
'Forbidden `sync_private_state` invocation. `sync_private_state` can only be invoked by PXE, manual execution can lead to inconsistencies.',
|
|
333
|
-
);
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
return utilityExecutor(syncPrivateStateFunctionCall);
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
319
|
}
|