@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
|
@@ -36,8 +36,9 @@ import {
|
|
|
36
36
|
type TaggingSecretStrategy,
|
|
37
37
|
} from '../../hooks/resolve_tagging_secret_strategy.js';
|
|
38
38
|
import { NoteService } from '../../notes/note_service.js';
|
|
39
|
+
import { assertAllowedScope } from '../../storage/allowed_scopes.js';
|
|
39
40
|
import type { SenderTaggingStore } from '../../storage/tagging_store/sender_tagging_store.js';
|
|
40
|
-
import { syncSenderTaggingIndexes } from '../../tagging/index.js';
|
|
41
|
+
import { logQueryAnchorOf, syncSenderTaggingIndexes } from '../../tagging/index.js';
|
|
41
42
|
import type { ExecutionNoteCache } from '../execution_note_cache.js';
|
|
42
43
|
import { ExecutionTaggingIndexCache } from '../execution_tagging_index_cache.js';
|
|
43
44
|
import type { HashedValuesCache } from '../hashed_values_cache.js';
|
|
@@ -321,7 +322,17 @@ export class PrivateExecutionOracle extends UtilityExecutionOracle implements IP
|
|
|
321
322
|
* @returns The app tagging secret, or `None` if the recipient is invalid.
|
|
322
323
|
*/
|
|
323
324
|
public async getAppTaggingSecret(sender: AztecAddress, recipient: AztecAddress): Promise<Option<Fr>> {
|
|
324
|
-
|
|
325
|
+
assertAllowedScope(sender, this.scopes);
|
|
326
|
+
|
|
327
|
+
const senderCompleteAddress = await this.getCompleteAddressOrFail(sender);
|
|
328
|
+
const senderIvsk = await this.keyStore.getMasterIncomingViewingSecretKey(sender);
|
|
329
|
+
const extendedSecret = await AppTaggingSecret.computeViaEcdh(
|
|
330
|
+
senderCompleteAddress,
|
|
331
|
+
senderIvsk,
|
|
332
|
+
recipient,
|
|
333
|
+
this.contractAddress,
|
|
334
|
+
recipient,
|
|
335
|
+
);
|
|
325
336
|
|
|
326
337
|
if (!extendedSecret) {
|
|
327
338
|
this.logger.warn(`Computing a tagging secret for invalid recipient ${recipient} - returning no secret`, {
|
|
@@ -354,12 +365,6 @@ export class PrivateExecutionOracle extends UtilityExecutionOracle implements IP
|
|
|
354
365
|
return index;
|
|
355
366
|
}
|
|
356
367
|
|
|
357
|
-
async #calculateAppTaggingSecret(contractAddress: AztecAddress, sender: AztecAddress, recipient: AztecAddress) {
|
|
358
|
-
const senderCompleteAddress = await this.getCompleteAddressOrFail(sender);
|
|
359
|
-
const senderIvsk = await this.keyStore.getMasterIncomingViewingSecretKey(sender);
|
|
360
|
-
return AppTaggingSecret.computeViaEcdh(senderCompleteAddress, senderIvsk, recipient, contractAddress, recipient);
|
|
361
|
-
}
|
|
362
|
-
|
|
363
368
|
async #getIndexToUseForSecret(secret: AppTaggingSecret): Promise<number> {
|
|
364
369
|
// If we have the tagging index in the cache, we use it. If not we obtain it from the execution data provider.
|
|
365
370
|
const lastUsedIndexInTx = this.taggingIndexCache.getLastUsedIndex(secret);
|
|
@@ -370,11 +375,16 @@ export class PrivateExecutionOracle extends UtilityExecutionOracle implements IP
|
|
|
370
375
|
// This is a tagging secret we've not yet used in this tx, so first sync our store to make sure its indices
|
|
371
376
|
// are up to date. We do this here because this store is not synced as part of the global sync because
|
|
372
377
|
// that'd be wasteful as most tagging secrets are not used in each tx.
|
|
378
|
+
const [{ finalized }, anchor] = await Promise.all([
|
|
379
|
+
this.l2TipsStore.getL2Tips(),
|
|
380
|
+
logQueryAnchorOf(this.anchorBlockHeader),
|
|
381
|
+
]);
|
|
373
382
|
await syncSenderTaggingIndexes(
|
|
374
383
|
secret,
|
|
375
384
|
this.aztecNode,
|
|
376
385
|
this.senderTaggingStore,
|
|
377
|
-
|
|
386
|
+
finalized.block.number,
|
|
387
|
+
anchor,
|
|
378
388
|
this.jobId,
|
|
379
389
|
);
|
|
380
390
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ARCHIVE_HEIGHT, type NOTE_HASH_TREE_HEIGHT } from '@aztec/constants';
|
|
1
|
+
import { ARCHIVE_HEIGHT, type NOTE_HASH_TREE_HEIGHT, PRIVATE_LOG_CIPHERTEXT_LEN } from '@aztec/constants';
|
|
2
2
|
import type { BlockNumber } from '@aztec/foundation/branded-types';
|
|
3
3
|
import { uniqueBy } from '@aztec/foundation/collection';
|
|
4
4
|
import { Aes128 } from '@aztec/foundation/crypto/aes128';
|
|
@@ -33,21 +33,23 @@ import {
|
|
|
33
33
|
type BlockHeader,
|
|
34
34
|
CallContext,
|
|
35
35
|
type Capsule,
|
|
36
|
-
type IndexedTxEffect,
|
|
37
36
|
type OffchainEffect,
|
|
37
|
+
type TxEffect,
|
|
38
38
|
type TxHash,
|
|
39
|
+
type TxReceipt,
|
|
39
40
|
} from '@aztec/stdlib/tx';
|
|
40
41
|
|
|
41
42
|
import type { ContractSyncService } from '../../contract/contract_sync_service.js';
|
|
42
43
|
import { createContractLogger, logContractMessage, stripAztecnrLogPrefix } from '../../contract_logging.js';
|
|
43
|
-
import { EventService } from '../../events/event_service.js';
|
|
44
|
+
import { EventService, type EventValidationTxData } from '../../events/event_service.js';
|
|
44
45
|
import type { UtilityCallAuthorizationRequest } from '../../hooks/authorize_utility_call.js';
|
|
45
46
|
import type { ExecutionHooks } from '../../hooks/index.js';
|
|
46
|
-
import { LogService } from '../../logs/log_service.js';
|
|
47
|
-
import { TxResolverService } from '../../messages/tx_resolver_service.js';
|
|
48
|
-
import { NoteService } from '../../notes/note_service.js';
|
|
47
|
+
import { LogService, type RetrievedTaggedLog } from '../../logs/log_service.js';
|
|
48
|
+
import { type TxOnchainContext, TxResolverService } from '../../messages/tx_resolver_service.js';
|
|
49
|
+
import { NoteService, type NoteValidationTxData } from '../../notes/note_service.js';
|
|
49
50
|
import { ORACLE_VERSION_MAJOR } from '../../oracle_version.js';
|
|
50
51
|
import type { AddressStore } from '../../storage/address_store/address_store.js';
|
|
52
|
+
import { assertAllowedScope } from '../../storage/allowed_scopes.js';
|
|
51
53
|
import type { CapsuleService } from '../../storage/capsule_store/capsule_service.js';
|
|
52
54
|
import { FactCollectionKey, FactCollectionTypeKey, anchoredTipBlockNumbers } from '../../storage/fact_store/index.js';
|
|
53
55
|
import type { FactService, OriginBlock } from '../../storage/fact_store/index.js';
|
|
@@ -56,7 +58,6 @@ import type { PrivateEventStore } from '../../storage/private_event_store/privat
|
|
|
56
58
|
import type { RecipientTaggingStore } from '../../storage/tagging_store/recipient_tagging_store.js';
|
|
57
59
|
import type { TaggingSecretSourcesStore } from '../../storage/tagging_store/tagging_secret_sources_store.js';
|
|
58
60
|
import type { AnchoredContractData } from '../anchored_contract_data.js';
|
|
59
|
-
import { AztecNodeReadCache } from '../aztec_node_read_cache.js';
|
|
60
61
|
import { EphemeralArrayService } from '../ephemeral_array_service.js';
|
|
61
62
|
import { BoundedVec } from '../noir-structs/bounded_vec.js';
|
|
62
63
|
import type { EmbeddedCurvePoint } from '../noir-structs/embedded_curve_point.js';
|
|
@@ -120,7 +121,15 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
120
121
|
private offchainEffects: OffchainEffect[] = [];
|
|
121
122
|
private readonly ephemeralArrayService = new EphemeralArrayService();
|
|
122
123
|
protected readonly transientArrayService: TransientArrayService;
|
|
123
|
-
|
|
124
|
+
/** Keyed by tx hash string. */
|
|
125
|
+
private readonly txReceiptsCache = new Map<string, Promise<TxReceipt<{ includeTxEffect: true }>>>();
|
|
126
|
+
/**
|
|
127
|
+
* Information that can be used to validate the existence of a note or an event, keyed by tx hash string. It is
|
|
128
|
+
* populated by the node queries that precede validation (tagged log retrieval, tx resolution), which already return
|
|
129
|
+
* everything validation needs, so validating a note or event created in one of those txs costs no node roundtrip.
|
|
130
|
+
* Notes and events reached through other paths (e.g. offchain inbox messages) still need a receipt.
|
|
131
|
+
*/
|
|
132
|
+
private readonly validationTxDataCache = new Map<string, ValidationTxData>();
|
|
124
133
|
|
|
125
134
|
// We store oracle version to be able to show a nice error message when an oracle handler is missing.
|
|
126
135
|
private contractOracleVersion: { major: number; minor: number } | undefined;
|
|
@@ -174,7 +183,6 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
174
183
|
this.hooks = args.hooks;
|
|
175
184
|
this.utilityExecutor = args.utilityExecutor;
|
|
176
185
|
this.transientArrayService = args.transientArrayService;
|
|
177
|
-
this.aztecNodeReadCache = new AztecNodeReadCache(args.aztecNode);
|
|
178
186
|
}
|
|
179
187
|
|
|
180
188
|
public assertCompatibleOracleVersion(major: number, minor: number): void {
|
|
@@ -268,7 +276,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
268
276
|
// hash at all. If the block hash did not exist by the reference block hash, then the node will not return the
|
|
269
277
|
// membership witness as there is none.
|
|
270
278
|
const witness = await this.#queryWithBlockHashNotAfterAnchor(referenceBlockHash, () =>
|
|
271
|
-
this.
|
|
279
|
+
this.aztecNode.getBlockHashMembershipWitness(referenceBlockHash, blockHash),
|
|
272
280
|
);
|
|
273
281
|
return witness ? Option.some(witness) : Option.none();
|
|
274
282
|
}
|
|
@@ -282,7 +290,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
282
290
|
const memberships = await this.#queryWithBlockHashNotAfterAnchor(referenceBlockHash, () =>
|
|
283
291
|
Promise.all(
|
|
284
292
|
hashes.map(blockHash =>
|
|
285
|
-
this.
|
|
293
|
+
this.aztecNode.getBlockHashMembershipWitness(referenceBlockHash, blockHash).then(Boolean),
|
|
286
294
|
),
|
|
287
295
|
),
|
|
288
296
|
);
|
|
@@ -337,7 +345,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
337
345
|
*/
|
|
338
346
|
public async getPublicDataWitness(blockHash: BlockHash, leafSlot: Fr): Promise<PublicDataWitness> {
|
|
339
347
|
const witness = await this.#queryWithBlockHashNotAfterAnchor(blockHash, () =>
|
|
340
|
-
this.
|
|
348
|
+
this.aztecNode.getPublicDataWitness(blockHash, leafSlot),
|
|
341
349
|
);
|
|
342
350
|
if (!witness) {
|
|
343
351
|
throw new Error(`Public data witness not found for slot ${leafSlot} at block hash ${blockHash.toString()}.`);
|
|
@@ -528,11 +536,11 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
528
536
|
numberOfElements: number,
|
|
529
537
|
) {
|
|
530
538
|
return this.#queryWithBlockHashNotAfterAnchor(blockHash, async () => {
|
|
531
|
-
const
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
539
|
+
const slots = Array(numberOfElements)
|
|
540
|
+
.fill(0)
|
|
541
|
+
.map((_, i) => new Fr(startStorageSlot.toBigInt() + BigInt(i)));
|
|
542
|
+
const values = await Promise.all(
|
|
543
|
+
slots.map(storageSlot => this.aztecNode.getPublicStorageAt(blockHash, contractAddress, storageSlot)),
|
|
536
544
|
);
|
|
537
545
|
|
|
538
546
|
this.logger.debug(
|
|
@@ -599,8 +607,11 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
599
607
|
.map(ps => new AppTaggingSecret(ps.secret, this.contractAddress, ps.mode));
|
|
600
608
|
|
|
601
609
|
const logService = this.#createLogService();
|
|
602
|
-
const
|
|
603
|
-
|
|
610
|
+
const retrievedLogs = await logService.fetchTaggedLogs(this.contractAddress, scope, secrets);
|
|
611
|
+
|
|
612
|
+
this.#cacheValidationTxData(retrievedLogs);
|
|
613
|
+
|
|
614
|
+
return EphemeralArray.fromValues(this.ephemeralArrayService, retrievedLogs.map(toPendingTaggedLog));
|
|
604
615
|
}
|
|
605
616
|
|
|
606
617
|
#createLogService(): LogService {
|
|
@@ -612,6 +623,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
612
623
|
this.recipientTaggingStore,
|
|
613
624
|
this.taggingSecretSourcesStore,
|
|
614
625
|
this.addressStore,
|
|
626
|
+
this.scopes,
|
|
615
627
|
this.jobId,
|
|
616
628
|
this.logger.getBindings(),
|
|
617
629
|
);
|
|
@@ -634,7 +646,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
634
646
|
eventValidationRequests: EventValidationRequest[],
|
|
635
647
|
scope: AztecAddress,
|
|
636
648
|
) {
|
|
637
|
-
const
|
|
649
|
+
const validationTxData = await this.#getValidationTxData([
|
|
638
650
|
...noteValidationRequests.map(r => r.txHash),
|
|
639
651
|
...eventValidationRequests.map(r => r.txHash),
|
|
640
652
|
]);
|
|
@@ -643,8 +655,8 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
643
655
|
const eventService = new EventService(this.anchorBlockHeader, this.aztecNode, this.privateEventStore, this.jobId);
|
|
644
656
|
|
|
645
657
|
await Promise.all([
|
|
646
|
-
noteService.validateAndStoreNotes(noteValidationRequests, scope,
|
|
647
|
-
eventService.validateAndStoreEvents(eventValidationRequests, scope,
|
|
658
|
+
noteService.validateAndStoreNotes(noteValidationRequests, scope, validationTxData),
|
|
659
|
+
eventService.validateAndStoreEvents(eventValidationRequests, scope, validationTxData),
|
|
648
660
|
]);
|
|
649
661
|
}
|
|
650
662
|
|
|
@@ -654,11 +666,13 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
654
666
|
const logRetrievalRequests = requests.readAll(this.ephemeralArrayService);
|
|
655
667
|
const logService = this.#createLogService();
|
|
656
668
|
|
|
657
|
-
const
|
|
669
|
+
const retrievedLogsPerRequest = await logService.fetchLogsByTag(this.contractAddress, logRetrievalRequests);
|
|
670
|
+
|
|
671
|
+
this.#cacheValidationTxData(retrievedLogsPerRequest.flat());
|
|
658
672
|
|
|
659
673
|
// Create an inner ephemeral array for each request's matching logs, then wrap all slots in an outer array.
|
|
660
|
-
const innerArrays =
|
|
661
|
-
EphemeralArray.fromValues(this.ephemeralArrayService,
|
|
674
|
+
const innerArrays = retrievedLogsPerRequest.map(retrievedLogs =>
|
|
675
|
+
EphemeralArray.fromValues(this.ephemeralArrayService, retrievedLogs.map(toLogRetrievalResponse)),
|
|
662
676
|
);
|
|
663
677
|
|
|
664
678
|
return EphemeralArray.fromValues(this.ephemeralArrayService, innerArrays);
|
|
@@ -670,7 +684,9 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
670
684
|
|
|
671
685
|
const resolved = await this.txResolver.resolveTxs(txHashes, this.anchorBlockHeader.getBlockNumber());
|
|
672
686
|
|
|
673
|
-
|
|
687
|
+
this.#cacheValidationTxData(resolved.filter(tx => tx !== null));
|
|
688
|
+
|
|
689
|
+
const options = resolved.map(tx => (tx ? Option.some(toResolvedTx(tx)) : Option.none<ResolvedTx>()));
|
|
674
690
|
return EphemeralArray.fromValues(this.ephemeralArrayService, options);
|
|
675
691
|
}
|
|
676
692
|
|
|
@@ -683,21 +699,25 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
683
699
|
throw new Error('Invalid tx hash passed into aztec_utl_getTxEffect oracle handler');
|
|
684
700
|
}
|
|
685
701
|
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
702
|
+
return await this.#getTxEffectOption(txHash);
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
/** Fetches transaction effects for all hashes, preserving request order. */
|
|
706
|
+
public async getTxEffects(txHashes: EphemeralArray<TxHash>): Promise<EphemeralArray<Option<TxEffectData>>> {
|
|
707
|
+
const hashes = txHashes.readAll(this.ephemeralArrayService);
|
|
708
|
+
const invalidHash = hashes.find(txHash => txHash.hash.isZero());
|
|
709
|
+
if (invalidHash) {
|
|
710
|
+
throw new Error('Invalid tx hash passed into aztec_utl_getTxEffects oracle handler');
|
|
689
711
|
}
|
|
690
712
|
|
|
691
|
-
const
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
})),
|
|
700
|
-
});
|
|
713
|
+
const uniqueTxHashes = uniqueBy(hashes, h => h.toString());
|
|
714
|
+
const options = await Promise.all(uniqueTxHashes.map(txHash => this.#getTxEffectOption(txHash)));
|
|
715
|
+
const optionsByHash = new Map(uniqueTxHashes.map((txHash, i) => [txHash.toString(), options[i]]));
|
|
716
|
+
|
|
717
|
+
return EphemeralArray.fromValues(
|
|
718
|
+
this.ephemeralArrayService,
|
|
719
|
+
hashes.map(txHash => optionsByHash.get(txHash.toString())!),
|
|
720
|
+
);
|
|
701
721
|
}
|
|
702
722
|
|
|
703
723
|
public setCapsule(contractAddress: AztecAddress, slot: Fr, capsule: Fr[], scope: AztecAddress): void {
|
|
@@ -852,13 +872,17 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
852
872
|
// TODO(#11849): consider replacing this oracle with a pure Noir implementation of aes decryption.
|
|
853
873
|
public async decryptAes128(
|
|
854
874
|
ciphertext: BoundedVec<number>,
|
|
855
|
-
iv:
|
|
856
|
-
symKey:
|
|
875
|
+
iv: number[],
|
|
876
|
+
symKey: number[],
|
|
857
877
|
): Promise<Option<BoundedVec<number>>> {
|
|
858
878
|
const capacity = ciphertext.maxLength;
|
|
859
879
|
try {
|
|
860
880
|
const aes128 = new Aes128();
|
|
861
|
-
const plaintext = await aes128.decryptBufferCBC(
|
|
881
|
+
const plaintext = await aes128.decryptBufferCBC(
|
|
882
|
+
Buffer.from(ciphertext.data),
|
|
883
|
+
Buffer.from(iv),
|
|
884
|
+
Buffer.from(symKey),
|
|
885
|
+
);
|
|
862
886
|
return Option.some(BoundedVec.from<number>({ data: [...plaintext], maxLength: capacity }));
|
|
863
887
|
} catch {
|
|
864
888
|
return Option.none({ maxLength: capacity });
|
|
@@ -871,7 +895,8 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
871
895
|
* @param ephPks - Ephemeral array containing the serialized Points.
|
|
872
896
|
* @param contractAddress - The contract address for app-siloing (validated against execution context).
|
|
873
897
|
* @returns A new ephemeral array containing the computed shared secrets, or an empty array when the PXE does not
|
|
874
|
-
* hold the keys for `address
|
|
898
|
+
* hold the keys for `address`.
|
|
899
|
+
* @throws If `address` is not in the execution's allowed scopes.
|
|
875
900
|
*/
|
|
876
901
|
public async getSharedSecrets(
|
|
877
902
|
address: AztecAddress,
|
|
@@ -883,6 +908,11 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
883
908
|
`getSharedSecrets called with contract address ${contractAddress}, expected ${this.contractAddress}`,
|
|
884
909
|
);
|
|
885
910
|
}
|
|
911
|
+
|
|
912
|
+
assertAllowedScope(address, this.scopes);
|
|
913
|
+
|
|
914
|
+
// An address can be in scope without the PXE holding its keys (e.g. syncing a registered but non-owned account),
|
|
915
|
+
// in which case no secrets can be derived and we return an empty array rather than failing.
|
|
886
916
|
const recipientCompleteAddress = await this.addressStore.getCompleteAddress(address);
|
|
887
917
|
if (!recipientCompleteAddress) {
|
|
888
918
|
this.logger.warn(
|
|
@@ -1090,16 +1120,34 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
1090
1120
|
return this.offchainEffects;
|
|
1091
1121
|
}
|
|
1092
1122
|
|
|
1123
|
+
/** Stores the onchain context of the given txs, so that validating the notes and events they created is free. */
|
|
1124
|
+
#cacheValidationTxData(txs: TxOnchainContext[]) {
|
|
1125
|
+
txs.forEach(tx => this.validationTxDataCache.set(tx.txHash.toString(), toValidationTxData(tx)));
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1093
1128
|
/**
|
|
1094
|
-
*
|
|
1095
|
-
*
|
|
1129
|
+
* Returns the information needed to validate the notes and events created in the given txs, keyed by
|
|
1130
|
+
* `TxHash.toString()`. Txs already in {@link validationTxDataCache} cost no node request, and the rest are read from
|
|
1131
|
+
* the node. Txs with no tx effect are absent from the returned map.
|
|
1096
1132
|
*/
|
|
1097
|
-
async #
|
|
1098
|
-
const
|
|
1099
|
-
const
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1133
|
+
async #getValidationTxData(txHashes: TxHash[]): Promise<Map<string, ValidationTxData>> {
|
|
1134
|
+
const known: [string, ValidationTxData][] = [];
|
|
1135
|
+
const misses: TxHash[] = [];
|
|
1136
|
+
for (const txHash of uniqueBy(txHashes, h => h.toString())) {
|
|
1137
|
+
const key = txHash.toString();
|
|
1138
|
+
const cached = this.validationTxDataCache.get(key);
|
|
1139
|
+
if (cached) {
|
|
1140
|
+
known.push([key, cached]);
|
|
1141
|
+
} else {
|
|
1142
|
+
misses.push(txHash);
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
const fetched = await Promise.all(misses.map(h => this.#getTxReceiptWithEffect(h)));
|
|
1147
|
+
return new Map([
|
|
1148
|
+
...known,
|
|
1149
|
+
...misses
|
|
1150
|
+
.map((h, i): [string, ValidationTxData | undefined] => {
|
|
1103
1151
|
const receipt = fetched[i];
|
|
1104
1152
|
if (!receipt.isMined() || !receipt.txEffect) {
|
|
1105
1153
|
return [h.toString(), undefined];
|
|
@@ -1107,16 +1155,58 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
1107
1155
|
return [
|
|
1108
1156
|
h.toString(),
|
|
1109
1157
|
{
|
|
1110
|
-
|
|
1158
|
+
noteHashes: receipt.txEffect.noteHashes,
|
|
1159
|
+
nullifiers: receipt.txEffect.nullifiers,
|
|
1111
1160
|
l2BlockNumber: receipt.blockNumber,
|
|
1112
1161
|
l2BlockHash: receipt.blockHash,
|
|
1113
1162
|
txIndexInBlock: receipt.txIndexInBlock,
|
|
1114
|
-
slotNumber: receipt.slotNumber,
|
|
1115
1163
|
},
|
|
1116
1164
|
];
|
|
1117
1165
|
})
|
|
1118
|
-
.filter((entry): entry is [string,
|
|
1119
|
-
);
|
|
1166
|
+
.filter((entry): entry is [string, ValidationTxData] => entry[1] !== undefined),
|
|
1167
|
+
]);
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
/**
|
|
1171
|
+
* Reads a receipt with its effect, at most once per tx for the lifetime of this execution.
|
|
1172
|
+
*
|
|
1173
|
+
* A receipt is not cacheable in general, since pending, mined and dropped are all correct answers to the same call
|
|
1174
|
+
* over time. Within one execution it is: the execution is anchored at a fixed block, and validation runs in several
|
|
1175
|
+
* batches that name overlapping tx hashes, so re-reading would both cost extra requests and let one execution see a
|
|
1176
|
+
* tx as included in one batch and absent in the next.
|
|
1177
|
+
*/
|
|
1178
|
+
#getTxReceiptWithEffect(txHash: TxHash) {
|
|
1179
|
+
const key = txHash.toString();
|
|
1180
|
+
let receipt = this.txReceiptsCache.get(key);
|
|
1181
|
+
if (!receipt) {
|
|
1182
|
+
receipt = this.aztecNode.getTxReceipt(txHash, { includeTxEffect: true }).catch(err => {
|
|
1183
|
+
this.txReceiptsCache.delete(key);
|
|
1184
|
+
throw err;
|
|
1185
|
+
});
|
|
1186
|
+
this.txReceiptsCache.set(key, receipt);
|
|
1187
|
+
}
|
|
1188
|
+
return receipt;
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
async #getTxEffectOption(txHash: TxHash): Promise<Option<TxEffectData>> {
|
|
1192
|
+
const receipt = await this.#getTxReceiptWithEffect(txHash);
|
|
1193
|
+
if (!receipt.isMined() || !receipt.txEffect || receipt.blockNumber > this.anchorBlockHeader.getBlockNumber()) {
|
|
1194
|
+
return Option.none();
|
|
1195
|
+
}
|
|
1196
|
+
return Option.some(this.#toTxEffectData(receipt.txEffect));
|
|
1197
|
+
}
|
|
1198
|
+
|
|
1199
|
+
#toTxEffectData(txEffect: TxEffect): TxEffectData {
|
|
1200
|
+
return {
|
|
1201
|
+
...txEffect,
|
|
1202
|
+
revertCode: txEffect.revertCode.getCode(),
|
|
1203
|
+
publicLogs: FlatPublicLogs.fromLogs(txEffect.publicLogs),
|
|
1204
|
+
contractClassLogs: txEffect.contractClassLogs.map(log => ({
|
|
1205
|
+
contractAddress: log.contractAddress,
|
|
1206
|
+
fields: log.fields.toFields(),
|
|
1207
|
+
emittedLength: log.emittedLength,
|
|
1208
|
+
})),
|
|
1209
|
+
};
|
|
1120
1210
|
}
|
|
1121
1211
|
|
|
1122
1212
|
/** Runs a query concurrently with a validation that the block hash is not ahead of the anchor block. */
|
|
@@ -1130,7 +1220,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
|
|
|
1130
1220
|
const [response] = await Promise.all([
|
|
1131
1221
|
query(),
|
|
1132
1222
|
(async () => {
|
|
1133
|
-
const block = await this.
|
|
1223
|
+
const block = await this.aztecNode.getBlock(blockHash);
|
|
1134
1224
|
const header = block?.header;
|
|
1135
1225
|
if (!header) {
|
|
1136
1226
|
throw new Error(`Could not find block header for block hash ${blockHash}`);
|
|
@@ -1191,3 +1281,41 @@ async function isStandardHandshakeRegistryUtilityRead(
|
|
|
1191
1281
|
);
|
|
1192
1282
|
return matches.some(Boolean);
|
|
1193
1283
|
}
|
|
1284
|
+
|
|
1285
|
+
function toPendingTaggedLog(retrievedLog: RetrievedTaggedLog): PendingTaggedLog {
|
|
1286
|
+
return { log: retrievedLog.logData, context: toResolvedTx(retrievedLog) };
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1289
|
+
function toResolvedTx(tx: TxOnchainContext): ResolvedTx {
|
|
1290
|
+
const { txHash, blockNumber, blockHash, noteHashes, nullifiers } = tx;
|
|
1291
|
+
return {
|
|
1292
|
+
txHash,
|
|
1293
|
+
uniqueNoteHashesInTx: noteHashes,
|
|
1294
|
+
firstNullifierInTx: nullifiers[0],
|
|
1295
|
+
blockNumber,
|
|
1296
|
+
blockHash: blockHash.toFr(),
|
|
1297
|
+
};
|
|
1298
|
+
}
|
|
1299
|
+
|
|
1300
|
+
function toLogRetrievalResponse(retrievedLog: RetrievedTaggedLog): LogRetrievalResponse {
|
|
1301
|
+
const { logData, txHash, blockNumber, blockHash, blockTimestamp, noteHashes, nullifiers } = retrievedLog;
|
|
1302
|
+
return {
|
|
1303
|
+
// Skip the tag, and clip to the wire cap: public logs can exceed PRIVATE_LOG_CIPHERTEXT_LEN, which is the fixed
|
|
1304
|
+
// size of the oracle's BoundedVec slot. A no-op for private logs, which are already within the cap.
|
|
1305
|
+
logPayload: logData.slice(1, 1 + PRIVATE_LOG_CIPHERTEXT_LEN),
|
|
1306
|
+
txHash,
|
|
1307
|
+
uniqueNoteHashesInTx: noteHashes,
|
|
1308
|
+
firstNullifierInTx: nullifiers[0],
|
|
1309
|
+
blockNumber,
|
|
1310
|
+
blockTimestamp,
|
|
1311
|
+
blockHash,
|
|
1312
|
+
};
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1315
|
+
function toValidationTxData(tx: TxOnchainContext): ValidationTxData {
|
|
1316
|
+
const { blockNumber, blockHash, txIndexInBlock, noteHashes, nullifiers } = tx;
|
|
1317
|
+
return { noteHashes, nullifiers, l2BlockNumber: blockNumber, l2BlockHash: blockHash, txIndexInBlock };
|
|
1318
|
+
}
|
|
1319
|
+
|
|
1320
|
+
/** The onchain context of a tx served to note and event validation: the union of what the two services read. */
|
|
1321
|
+
type ValidationTxData = NoteValidationTxData & EventValidationTxData;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { BBBundlePrivateKernelProver } from '@aztec/bb-prover/client/bundle';
|
|
2
2
|
import { createLogger } from '@aztec/foundation/log';
|
|
3
|
-
import { createStore } from '@aztec/kv-store/sqlite-opfs';
|
|
4
3
|
import { BundledProtocolContractsProvider } from '@aztec/protocol-contracts/providers/bundle';
|
|
5
4
|
import { WASMSimulator } from '@aztec/simulator/client';
|
|
6
5
|
import { getStandardAuthRegistry } from '@aztec/standard-contracts/auth-registry';
|
|
@@ -12,6 +11,7 @@ import type { PXEConfig } from '../../../config/index.js';
|
|
|
12
11
|
import { PXE } from '../../../pxe.js';
|
|
13
12
|
import { PXE_DATA_SCHEMA_VERSION } from '../../../storage/metadata.js';
|
|
14
13
|
import { type PXECreationOptions, isPrivateKernelProver } from '../../pxe_creation_options.js';
|
|
14
|
+
import { openBrowserStore } from '../store.js';
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* Create and start an PXE instance with the given AztecNode.
|
|
@@ -31,16 +31,28 @@ export async function createPXE(
|
|
|
31
31
|
const actor = options.loggerActorLabel;
|
|
32
32
|
const loggers = options.loggers ?? {};
|
|
33
33
|
|
|
34
|
-
const l1ContractAddresses = await aztecNode.
|
|
34
|
+
const { l1ChainId, l1ContractAddresses, rollupVersion } = await aztecNode.getNodeInfo();
|
|
35
35
|
const configWithContracts = {
|
|
36
36
|
...config,
|
|
37
37
|
...l1ContractAddresses,
|
|
38
|
+
l1ChainId,
|
|
39
|
+
rollupVersion,
|
|
38
40
|
} as PXEConfig;
|
|
39
41
|
|
|
40
42
|
const storeLogger = loggers.store ?? createLogger('pxe:data', { actor });
|
|
41
43
|
|
|
42
44
|
const store =
|
|
43
|
-
options.store ??
|
|
45
|
+
options.store ??
|
|
46
|
+
(await openBrowserStore(
|
|
47
|
+
'pxe_data',
|
|
48
|
+
PXE_DATA_SCHEMA_VERSION,
|
|
49
|
+
{
|
|
50
|
+
l1ChainId,
|
|
51
|
+
rollupAddress: l1ContractAddresses.rollupAddress,
|
|
52
|
+
dataStoreMapSizeKb: configWithContracts.dataStoreMapSizeKb,
|
|
53
|
+
},
|
|
54
|
+
storeLogger,
|
|
55
|
+
));
|
|
44
56
|
|
|
45
57
|
const simulator = options.simulator ?? new WASMSimulator();
|
|
46
58
|
const proverLogger = loggers.prover ?? createLogger('pxe:bb:wasm:bundle', { actor });
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { BBLazyPrivateKernelProver } from '@aztec/bb-prover/client/lazy';
|
|
2
2
|
import { createLogger } from '@aztec/foundation/log';
|
|
3
|
-
import { createStore } from '@aztec/kv-store/sqlite-opfs';
|
|
4
3
|
import { LazyProtocolContractsProvider } from '@aztec/protocol-contracts/providers/lazy';
|
|
5
4
|
import { WASMSimulator } from '@aztec/simulator/client';
|
|
6
5
|
import { getStandardAuthRegistry } from '@aztec/standard-contracts/auth-registry/lazy';
|
|
@@ -12,6 +11,7 @@ import type { PXEConfig } from '../../../config/index.js';
|
|
|
12
11
|
import { PXE } from '../../../pxe.js';
|
|
13
12
|
import { PXE_DATA_SCHEMA_VERSION } from '../../../storage/metadata.js';
|
|
14
13
|
import { type PXECreationOptions, isPrivateKernelProver } from '../../pxe_creation_options.js';
|
|
14
|
+
import { openBrowserStore } from '../store.js';
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* Create and start an PXE instance with the given AztecNode.
|
|
@@ -29,10 +29,12 @@ export async function createPXE(
|
|
|
29
29
|
) {
|
|
30
30
|
const actor = options.loggerActorLabel;
|
|
31
31
|
|
|
32
|
-
const l1ContractAddresses = await aztecNode.
|
|
32
|
+
const { l1ChainId, l1ContractAddresses, rollupVersion } = await aztecNode.getNodeInfo();
|
|
33
33
|
const configWithContracts = {
|
|
34
34
|
...config,
|
|
35
35
|
...l1ContractAddresses,
|
|
36
|
+
l1ChainId,
|
|
37
|
+
rollupVersion,
|
|
36
38
|
} as PXEConfig;
|
|
37
39
|
|
|
38
40
|
const loggers = options.loggers ?? {};
|
|
@@ -40,7 +42,17 @@ export async function createPXE(
|
|
|
40
42
|
const storeLogger = loggers.store ?? createLogger('pxe:data', { actor });
|
|
41
43
|
|
|
42
44
|
const store =
|
|
43
|
-
options.store ??
|
|
45
|
+
options.store ??
|
|
46
|
+
(await openBrowserStore(
|
|
47
|
+
'pxe_data',
|
|
48
|
+
PXE_DATA_SCHEMA_VERSION,
|
|
49
|
+
{
|
|
50
|
+
l1ChainId,
|
|
51
|
+
rollupAddress: l1ContractAddresses.rollupAddress,
|
|
52
|
+
dataStoreMapSizeKb: configWithContracts.dataStoreMapSizeKb,
|
|
53
|
+
},
|
|
54
|
+
storeLogger,
|
|
55
|
+
));
|
|
44
56
|
|
|
45
57
|
const simulator = options.simulator ?? new WASMSimulator();
|
|
46
58
|
const proverLogger = loggers.prover ?? createLogger('pxe:bb:wasm:bundle', { actor });
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { EthAddress } from '@aztec/foundation/eth-address';
|
|
2
|
+
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
3
|
+
import {
|
|
4
|
+
AztecSQLiteOPFSStore,
|
|
5
|
+
SqliteCorruptionError,
|
|
6
|
+
deleteStore,
|
|
7
|
+
storePoolDirectory,
|
|
8
|
+
} from '@aztec/kv-store/sqlite-opfs';
|
|
9
|
+
|
|
10
|
+
import { assertStoreIdentity, effectiveStoreName } from '../../storage/store_identity.js';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Opens the persistent browser (sqlite-opfs) store selected by `name` and identity `(config.l1ChainId,
|
|
14
|
+
* config.rollupAddress, schemaVersion)` triple. A store exists per identity: reopening with the same identity returns
|
|
15
|
+
* the same data, a different identity selects a different (possibly fresh) store.
|
|
16
|
+
*/
|
|
17
|
+
export async function openBrowserStore(
|
|
18
|
+
name: string,
|
|
19
|
+
schemaVersion: number,
|
|
20
|
+
config: { l1ChainId: number; rollupAddress: EthAddress; dataStoreMapSizeKb?: number },
|
|
21
|
+
log: Logger = createLogger('pxe:data'),
|
|
22
|
+
): Promise<AztecSQLiteOPFSStore> {
|
|
23
|
+
const identity = { l1ChainId: config.l1ChainId, rollupAddress: config.rollupAddress, schemaVersion };
|
|
24
|
+
const storeName = effectiveStoreName(name, identity);
|
|
25
|
+
log.info(`Creating ${storeName} SQLite-OPFS data store`, {
|
|
26
|
+
storeName,
|
|
27
|
+
dataStoreMapSizeKb: config.dataStoreMapSizeKb,
|
|
28
|
+
});
|
|
29
|
+
const openStore = () =>
|
|
30
|
+
AztecSQLiteOPFSStore.open(createLogger('kv-store:sqlite-opfs'), storeName, false, storePoolDirectory(storeName));
|
|
31
|
+
|
|
32
|
+
let store: AztecSQLiteOPFSStore;
|
|
33
|
+
try {
|
|
34
|
+
store = await openStore();
|
|
35
|
+
} catch (err) {
|
|
36
|
+
if (!(err instanceof SqliteCorruptionError)) {
|
|
37
|
+
throw err;
|
|
38
|
+
}
|
|
39
|
+
// A corrupt image is unrecoverable — no retry against the same bytes helps. Wipe the store's OPFS directory
|
|
40
|
+
// (safe: the failed open left no SAH-pool lock behind) and reopen a fresh, empty one, so the browser self-heals
|
|
41
|
+
// into a normal first-run rather than dead-ending on "database disk image is malformed" every load.
|
|
42
|
+
log.warn(`${storeName} store is corrupt (${err.message}); wiping and reopening fresh`);
|
|
43
|
+
await deleteStore(storeName);
|
|
44
|
+
store = await openStore();
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
await assertStoreIdentity(store, storeName, identity);
|
|
48
|
+
} catch (err) {
|
|
49
|
+
// The store handle owns a worker and OPFS locks; release them before surfacing the refusal.
|
|
50
|
+
await store.close().catch(() => {});
|
|
51
|
+
throw err;
|
|
52
|
+
}
|
|
53
|
+
return store;
|
|
54
|
+
}
|
|
@@ -6,6 +6,7 @@ export * from '../../config/index.js';
|
|
|
6
6
|
export * from '../../error_enriching.js';
|
|
7
7
|
export * from '../../storage/index.js';
|
|
8
8
|
export * from './utils.js';
|
|
9
|
+
export * from './store.js';
|
|
9
10
|
export { NoteService } from '../../notes/note_service.js';
|
|
10
11
|
export { ORACLE_VERSION_MAJOR, ORACLE_VERSION_MINOR } from '../../oracle_version.js';
|
|
11
12
|
export { type PXECreationOptions } from '../pxe_creation_options.js';
|