@aztec/pxe 0.0.1-commit.3100065 → 0.0.1-commit.321f6a9

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.
Files changed (152) hide show
  1. package/dest/bin/check_oracle_version.js +3 -8
  2. package/dest/bin/index.d.ts +2 -2
  3. package/dest/bin/index.d.ts.map +1 -1
  4. package/dest/bin/index.js +1 -1
  5. package/dest/bin/oracle_version_helpers.d.ts +8 -25
  6. package/dest/bin/oracle_version_helpers.d.ts.map +1 -1
  7. package/dest/bin/oracle_version_helpers.js +11 -219
  8. package/dest/config/package_info.js +1 -1
  9. package/dest/contract/helpers.d.ts +1 -1
  10. package/dest/contract/helpers.d.ts.map +1 -1
  11. package/dest/contract/helpers.js +3 -3
  12. package/dest/contract/skip_sync_contracts.d.ts +11 -0
  13. package/dest/contract/skip_sync_contracts.d.ts.map +1 -0
  14. package/dest/contract/skip_sync_contracts.js +18 -0
  15. package/dest/contract_function_simulator/contract_function_simulator.d.ts +1 -1
  16. package/dest/contract_function_simulator/contract_function_simulator.d.ts.map +1 -1
  17. package/dest/contract_function_simulator/contract_function_simulator.js +5 -3
  18. package/dest/contract_function_simulator/index.d.ts +3 -3
  19. package/dest/contract_function_simulator/index.d.ts.map +1 -1
  20. package/dest/contract_function_simulator/index.js +1 -2
  21. package/dest/contract_function_simulator/noir-structs/resolved_tx.d.ts +7 -9
  22. package/dest/contract_function_simulator/noir-structs/resolved_tx.d.ts.map +1 -1
  23. package/dest/contract_function_simulator/noir-structs/resolved_tx.js +3 -44
  24. package/dest/contract_function_simulator/noir-structs/tx_effect_data.d.ts +5 -4
  25. package/dest/contract_function_simulator/noir-structs/tx_effect_data.d.ts.map +1 -1
  26. package/dest/contract_function_simulator/noir-structs/tx_effect_data.js +2 -2
  27. package/dest/contract_function_simulator/oracle/oracle_registry.d.ts +4 -3
  28. package/dest/contract_function_simulator/oracle/oracle_registry.d.ts.map +1 -1
  29. package/dest/contract_function_simulator/oracle/oracle_registry.js +15 -6
  30. package/dest/contract_function_simulator/oracle/oracle_type_mappings.d.ts +87 -35
  31. package/dest/contract_function_simulator/oracle/oracle_type_mappings.d.ts.map +1 -1
  32. package/dest/contract_function_simulator/oracle/oracle_type_mappings.js +286 -286
  33. package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts +1 -1
  34. package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts.map +1 -1
  35. package/dest/contract_function_simulator/oracle/private_execution_oracle.js +5 -6
  36. package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts +6 -3
  37. package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts.map +1 -1
  38. package/dest/contract_function_simulator/oracle/utility_execution_oracle.js +41 -16
  39. package/dest/entrypoints/client/bundle/index.d.ts +2 -1
  40. package/dest/entrypoints/client/bundle/index.d.ts.map +1 -1
  41. package/dest/entrypoints/client/bundle/index.js +1 -0
  42. package/dest/entrypoints/client/bundle/utils.d.ts +1 -1
  43. package/dest/entrypoints/client/bundle/utils.d.ts.map +1 -1
  44. package/dest/entrypoints/client/bundle/utils.js +10 -4
  45. package/dest/entrypoints/client/lazy/index.d.ts +2 -1
  46. package/dest/entrypoints/client/lazy/index.d.ts.map +1 -1
  47. package/dest/entrypoints/client/lazy/index.js +1 -0
  48. package/dest/entrypoints/client/lazy/utils.d.ts +1 -1
  49. package/dest/entrypoints/client/lazy/utils.d.ts.map +1 -1
  50. package/dest/entrypoints/client/lazy/utils.js +10 -4
  51. package/dest/entrypoints/client/store.d.ts +14 -0
  52. package/dest/entrypoints/client/store.d.ts.map +1 -0
  53. package/dest/entrypoints/client/store.js +42 -0
  54. package/dest/entrypoints/server/index.d.ts +2 -1
  55. package/dest/entrypoints/server/index.d.ts.map +1 -1
  56. package/dest/entrypoints/server/index.js +1 -0
  57. package/dest/entrypoints/server/store.d.ts +18 -0
  58. package/dest/entrypoints/server/store.d.ts.map +1 -0
  59. package/dest/entrypoints/server/store.js +28 -0
  60. package/dest/entrypoints/server/utils.d.ts +1 -1
  61. package/dest/entrypoints/server/utils.d.ts.map +1 -1
  62. package/dest/entrypoints/server/utils.js +8 -2
  63. package/dest/logs/log_service.d.ts +3 -2
  64. package/dest/logs/log_service.d.ts.map +1 -1
  65. package/dest/logs/log_service.js +12 -3
  66. package/dest/messages/tx_resolver_service.d.ts +2 -2
  67. package/dest/messages/tx_resolver_service.d.ts.map +1 -1
  68. package/dest/messages/tx_resolver_service.js +7 -2
  69. package/dest/notes/note_service.d.ts +1 -1
  70. package/dest/notes/note_service.js +1 -1
  71. package/dest/oracle_version.d.ts +2 -2
  72. package/dest/oracle_version.js +3 -3
  73. package/dest/private_kernel/batch_planner.d.ts +1 -1
  74. package/dest/private_kernel/batch_planner.d.ts.map +1 -1
  75. package/dest/private_kernel/batch_planner.js +1 -1
  76. package/dest/private_kernel/private_kernel_execution_prover.d.ts +1 -1
  77. package/dest/private_kernel/private_kernel_execution_prover.d.ts.map +1 -1
  78. package/dest/private_kernel/private_kernel_execution_prover.js +45 -5
  79. package/dest/pxe.d.ts +1 -1
  80. package/dest/pxe.d.ts.map +1 -1
  81. package/dest/pxe.js +8 -5
  82. package/dest/storage/fact_store/fact_store.d.ts +1 -1
  83. package/dest/storage/fact_store/fact_store.js +1 -1
  84. package/dest/storage/fact_store/index.d.ts +2 -2
  85. package/dest/storage/fact_store/index.d.ts.map +1 -1
  86. package/dest/storage/fact_store/index.js +1 -1
  87. package/dest/storage/fact_store/origin_state.d.ts +3 -1
  88. package/dest/storage/fact_store/origin_state.d.ts.map +1 -1
  89. package/dest/storage/fact_store/origin_state.js +7 -0
  90. package/dest/storage/store_identity.d.ts +35 -0
  91. package/dest/storage/store_identity.d.ts.map +1 -0
  92. package/dest/storage/store_identity.js +44 -0
  93. package/dest/storage/tagging_store/sender_tagging_store.d.ts +19 -3
  94. package/dest/storage/tagging_store/sender_tagging_store.d.ts.map +1 -1
  95. package/dest/storage/tagging_store/sender_tagging_store.js +48 -11
  96. package/dest/tagging/constants.d.ts +2 -1
  97. package/dest/tagging/constants.d.ts.map +1 -1
  98. package/dest/tagging/constants.js +9 -0
  99. package/dest/tagging/index.d.ts +2 -2
  100. package/dest/tagging/index.d.ts.map +1 -1
  101. package/dest/tagging/index.js +1 -1
  102. package/dest/tagging/recipient_sync/sync_tagged_private_logs.d.ts +9 -4
  103. package/dest/tagging/recipient_sync/sync_tagged_private_logs.d.ts.map +1 -1
  104. package/dest/tagging/recipient_sync/sync_tagged_private_logs.js +60 -25
  105. package/dest/tagging/sender_sync/sync_sender_tagging_indexes.js +1 -1
  106. package/dest/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.d.ts +1 -1
  107. package/dest/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.d.ts.map +1 -1
  108. package/dest/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.js +6 -2
  109. package/dest/tagging/testing/tag_query_test_utils.d.ts +6 -0
  110. package/dest/tagging/testing/tag_query_test_utils.d.ts.map +1 -0
  111. package/dest/tagging/testing/tag_query_test_utils.js +10 -0
  112. package/package.json +17 -17
  113. package/src/bin/check_oracle_version.ts +3 -10
  114. package/src/bin/index.ts +1 -5
  115. package/src/bin/oracle_version_helpers.ts +11 -268
  116. package/src/config/package_info.ts +1 -1
  117. package/src/contract/helpers.ts +3 -3
  118. package/src/contract/skip_sync_contracts.ts +23 -0
  119. package/src/contract_function_simulator/contract_function_simulator.ts +5 -3
  120. package/src/contract_function_simulator/index.ts +23 -3
  121. package/src/contract_function_simulator/noir-structs/resolved_tx.ts +11 -45
  122. package/src/contract_function_simulator/noir-structs/tx_effect_data.ts +4 -3
  123. package/src/contract_function_simulator/oracle/oracle_registry.ts +12 -8
  124. package/src/contract_function_simulator/oracle/oracle_type_mappings.ts +285 -197
  125. package/src/contract_function_simulator/oracle/private_execution_oracle.ts +12 -7
  126. package/src/contract_function_simulator/oracle/utility_execution_oracle.ts +55 -17
  127. package/src/entrypoints/client/bundle/index.ts +1 -0
  128. package/src/entrypoints/client/bundle/utils.ts +15 -3
  129. package/src/entrypoints/client/lazy/index.ts +1 -0
  130. package/src/entrypoints/client/lazy/utils.ts +15 -3
  131. package/src/entrypoints/client/store.ts +54 -0
  132. package/src/entrypoints/server/index.ts +1 -0
  133. package/src/entrypoints/server/store.ts +47 -0
  134. package/src/entrypoints/server/utils.ts +21 -7
  135. package/src/logs/log_service.ts +11 -2
  136. package/src/messages/tx_resolver_service.ts +8 -8
  137. package/src/notes/note_service.ts +1 -1
  138. package/src/oracle_version.ts +3 -3
  139. package/src/private_kernel/batch_planner.ts +0 -1
  140. package/src/private_kernel/private_kernel_execution_prover.ts +90 -4
  141. package/src/pxe.ts +8 -5
  142. package/src/storage/fact_store/fact_store.ts +1 -1
  143. package/src/storage/fact_store/index.ts +1 -0
  144. package/src/storage/fact_store/origin_state.ts +9 -0
  145. package/src/storage/store_identity.ts +72 -0
  146. package/src/storage/tagging_store/sender_tagging_store.ts +62 -15
  147. package/src/tagging/constants.ts +10 -0
  148. package/src/tagging/index.ts +1 -1
  149. package/src/tagging/recipient_sync/sync_tagged_private_logs.ts +103 -46
  150. package/src/tagging/sender_sync/sync_sender_tagging_indexes.ts +1 -1
  151. package/src/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.ts +6 -2
  152. package/src/tagging/testing/tag_query_test_utils.ts +11 -0
@@ -36,6 +36,7 @@ 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
41
  import { syncSenderTaggingIndexes } from '../../tagging/index.js';
41
42
  import type { ExecutionNoteCache } from '../execution_note_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
- const extendedSecret = await this.#calculateAppTaggingSecret(this.contractAddress, sender, recipient);
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);
@@ -35,6 +35,7 @@ import {
35
35
  type Capsule,
36
36
  type IndexedTxEffect,
37
37
  type OffchainEffect,
38
+ type TxEffect,
38
39
  type TxHash,
39
40
  } from '@aztec/stdlib/tx';
40
41
 
@@ -48,6 +49,7 @@ import { TxResolverService } from '../../messages/tx_resolver_service.js';
48
49
  import { NoteService } 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';
@@ -612,6 +614,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
612
614
  this.recipientTaggingStore,
613
615
  this.taggingSecretSourcesStore,
614
616
  this.addressStore,
617
+ this.scopes,
615
618
  this.jobId,
616
619
  this.logger.getBindings(),
617
620
  );
@@ -683,21 +686,25 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
683
686
  throw new Error('Invalid tx hash passed into aztec_utl_getTxEffect oracle handler');
684
687
  }
685
688
 
686
- const receipt = await this.aztecNodeReadCache.getTxReceiptWithEffect(txHash);
687
- if (!receipt.isMined() || !receipt.txEffect || receipt.blockNumber > this.anchorBlockHeader.getBlockNumber()) {
688
- return Option.none();
689
+ return await this.#getTxEffectOption(txHash);
690
+ }
691
+
692
+ /** Fetches transaction effects for all hashes, preserving request order. */
693
+ public async getTxEffects(txHashes: EphemeralArray<TxHash>): Promise<EphemeralArray<Option<TxEffectData>>> {
694
+ const hashes = txHashes.readAll(this.ephemeralArrayService);
695
+ const invalidHash = hashes.find(txHash => txHash.hash.isZero());
696
+ if (invalidHash) {
697
+ throw new Error('Invalid tx hash passed into aztec_utl_getTxEffects oracle handler');
689
698
  }
690
699
 
691
- const txEffect = receipt.txEffect;
692
- return Option.some({
693
- ...txEffect,
694
- publicLogs: FlatPublicLogs.fromLogs(txEffect.publicLogs),
695
- contractClassLogs: txEffect.contractClassLogs.map(log => ({
696
- contractAddress: log.contractAddress,
697
- fields: log.fields.toFields(),
698
- emittedLength: log.emittedLength,
699
- })),
700
- });
700
+ const uniqueTxHashes = uniqueBy(hashes, h => h.toString());
701
+ const options = await Promise.all(uniqueTxHashes.map(txHash => this.#getTxEffectOption(txHash)));
702
+ const optionsByHash = new Map(uniqueTxHashes.map((txHash, i) => [txHash.toString(), options[i]]));
703
+
704
+ return EphemeralArray.fromValues(
705
+ this.ephemeralArrayService,
706
+ hashes.map(txHash => optionsByHash.get(txHash.toString())!),
707
+ );
701
708
  }
702
709
 
703
710
  public setCapsule(contractAddress: AztecAddress, slot: Fr, capsule: Fr[], scope: AztecAddress): void {
@@ -852,13 +859,17 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
852
859
  // TODO(#11849): consider replacing this oracle with a pure Noir implementation of aes decryption.
853
860
  public async decryptAes128(
854
861
  ciphertext: BoundedVec<number>,
855
- iv: Buffer,
856
- symKey: Buffer,
862
+ iv: number[],
863
+ symKey: number[],
857
864
  ): Promise<Option<BoundedVec<number>>> {
858
865
  const capacity = ciphertext.maxLength;
859
866
  try {
860
867
  const aes128 = new Aes128();
861
- const plaintext = await aes128.decryptBufferCBC(Buffer.from(ciphertext.data), iv, symKey);
868
+ const plaintext = await aes128.decryptBufferCBC(
869
+ Buffer.from(ciphertext.data),
870
+ Buffer.from(iv),
871
+ Buffer.from(symKey),
872
+ );
862
873
  return Option.some(BoundedVec.from<number>({ data: [...plaintext], maxLength: capacity }));
863
874
  } catch {
864
875
  return Option.none({ maxLength: capacity });
@@ -871,7 +882,8 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
871
882
  * @param ephPks - Ephemeral array containing the serialized Points.
872
883
  * @param contractAddress - The contract address for app-siloing (validated against execution context).
873
884
  * @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`, signaling that no secrets can be derived for it.
885
+ * hold the keys for `address`.
886
+ * @throws If `address` is not in the execution's allowed scopes.
875
887
  */
876
888
  public async getSharedSecrets(
877
889
  address: AztecAddress,
@@ -883,6 +895,11 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
883
895
  `getSharedSecrets called with contract address ${contractAddress}, expected ${this.contractAddress}`,
884
896
  );
885
897
  }
898
+
899
+ assertAllowedScope(address, this.scopes);
900
+
901
+ // An address can be in scope without the PXE holding its keys (e.g. syncing a registered but non-owned account),
902
+ // in which case no secrets can be derived and we return an empty array rather than failing.
886
903
  const recipientCompleteAddress = await this.addressStore.getCompleteAddress(address);
887
904
  if (!recipientCompleteAddress) {
888
905
  this.logger.warn(
@@ -1119,6 +1136,27 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
1119
1136
  );
1120
1137
  }
1121
1138
 
1139
+ async #getTxEffectOption(txHash: TxHash): Promise<Option<TxEffectData>> {
1140
+ const receipt = await this.aztecNodeReadCache.getTxReceiptWithEffect(txHash);
1141
+ if (!receipt.isMined() || !receipt.txEffect || receipt.blockNumber > this.anchorBlockHeader.getBlockNumber()) {
1142
+ return Option.none();
1143
+ }
1144
+ return Option.some(this.#toTxEffectData(receipt.txEffect));
1145
+ }
1146
+
1147
+ #toTxEffectData(txEffect: TxEffect): TxEffectData {
1148
+ return {
1149
+ ...txEffect,
1150
+ revertCode: txEffect.revertCode.getCode(),
1151
+ publicLogs: FlatPublicLogs.fromLogs(txEffect.publicLogs),
1152
+ contractClassLogs: txEffect.contractClassLogs.map(log => ({
1153
+ contractAddress: log.contractAddress,
1154
+ fields: log.fields.toFields(),
1155
+ emittedLength: log.emittedLength,
1156
+ })),
1157
+ };
1158
+ }
1159
+
1122
1160
  /** Runs a query concurrently with a validation that the block hash is not ahead of the anchor block. */
1123
1161
  async #queryWithBlockHashNotAfterAnchor<T>(blockHash: BlockHash, query: () => Promise<T>): Promise<T> {
1124
1162
  // Most contracts query state at the "current" block, which is the anchor. Skip the validation when we can.
@@ -6,3 +6,4 @@ export * from '../../../contract_logging.js';
6
6
  export * from '../../../storage/index.js';
7
7
  export * from './utils.js';
8
8
  export type { PXECreationOptions } from '../../pxe_creation_options.js';
9
+ export { openBrowserStore } from '../store.js';
@@ -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.getL1ContractAddresses();
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 ?? (await createStore('pxe_data', configWithContracts, PXE_DATA_SCHEMA_VERSION, storeLogger));
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 });
@@ -6,3 +6,4 @@ export * from '../../../error_enriching.js';
6
6
  export * from '../../../contract_logging.js';
7
7
  export * from './utils.js';
8
8
  export { type PXECreationOptions } from '../../pxe_creation_options.js';
9
+ export { openBrowserStore } from '../store.js';
@@ -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.getL1ContractAddresses();
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 ?? (await createStore('pxe_data', configWithContracts, PXE_DATA_SCHEMA_VERSION, storeLogger));
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';
@@ -0,0 +1,47 @@
1
+ import type { EthAddress } from '@aztec/foundation/eth-address';
2
+ import { type LoggerBindings, createLogger } from '@aztec/foundation/log';
3
+ import { type AztecLMDBStoreV2, openStoreAt } from '@aztec/kv-store/lmdb-v2';
4
+
5
+ import { mkdir } from 'fs/promises';
6
+ import { join } from 'path';
7
+
8
+ import { storeIdentitySlug } from '../../storage/store_identity.js';
9
+
10
+ /** Location and identity inputs for opening an identity-partitioned PXE-side store. */
11
+ export type IdentityStoreConfig = {
12
+ dataDirectory: string;
13
+ /** Maximum LMDB map size in KB. When omitted, the kv-store default map size applies. */
14
+ dataStoreMapSizeKb?: number;
15
+ l1ChainId: number;
16
+ rollupAddress: EthAddress;
17
+ };
18
+
19
+ /**
20
+ * Opens the persistent LMDB store selected by `name` and identity triple `(l1ChainId, rollupAddress, schemaVersion)`.
21
+ * A store exists per identity: reopening with the same identity returns the same data, a different identity selects
22
+ * a different (possibly fresh) store. Callers wanting an ephemeral store use `openTmpStore` explicitly instead.
23
+ */
24
+ export async function openStore(
25
+ name: string,
26
+ schemaVersion: number,
27
+ config: IdentityStoreConfig,
28
+ bindings?: LoggerBindings,
29
+ ): Promise<AztecLMDBStoreV2> {
30
+ // Stores live under `<dataDirectory>/<name>-stores/<l1ChainId>-<rollupAddress>-v<schemaVersion>`, a sibling of the
31
+ // legacy `<dataDirectory>/<name>` directory: older binaries reset the legacy directory on a rollup mismatch, so
32
+ // per-identity stores must not nest inside it.
33
+ const subDir = join(
34
+ config.dataDirectory,
35
+ `${name}-stores`,
36
+ storeIdentitySlug({ l1ChainId: config.l1ChainId, rollupAddress: config.rollupAddress, schemaVersion }),
37
+ );
38
+ await mkdir(subDir, { recursive: true });
39
+
40
+ createLogger(`pxe:data:${name}`, bindings).info(`Opening ${name} data store (LMDB v2)`, {
41
+ storeName: name,
42
+ subDir,
43
+ dataStoreMapSizeKb: config.dataStoreMapSizeKb,
44
+ });
45
+
46
+ return openStoreAt(subDir, config.dataStoreMapSizeKb, undefined, bindings);
47
+ }
@@ -1,7 +1,7 @@
1
1
  import { BBBundlePrivateKernelProver } from '@aztec/bb-prover/client/bundle';
2
2
  import type { L1ContractAddresses } from '@aztec/ethereum/l1-contract-addresses';
3
3
  import { createLogger } from '@aztec/foundation/log';
4
- import { createStore } from '@aztec/kv-store/lmdb-v2';
4
+ import { openTmpStore } from '@aztec/kv-store/lmdb-v2';
5
5
  import { BundledProtocolContractsProvider } from '@aztec/protocol-contracts/providers/bundle';
6
6
  import { WASMSimulator } from '@aztec/simulator/client';
7
7
  import { MemoryCircuitRecorder, SimulatorRecorderWrapper } from '@aztec/simulator/server';
@@ -15,6 +15,7 @@ import type { PXEConfig } from '../../config/index.js';
15
15
  import { PXE } from '../../pxe.js';
16
16
  import { PXE_DATA_SCHEMA_VERSION } from '../../storage/index.js';
17
17
  import { type PXECreationOptions, isPrivateKernelProver } from '../pxe_creation_options.js';
18
+ import { openStore } from './store.js';
18
19
 
19
20
  type PXEConfigWithoutDefaults = Omit<
20
21
  PXEConfig,
@@ -46,12 +47,25 @@ export async function createPXE(
46
47
 
47
48
  if (!options.store) {
48
49
  const storeLogger = loggers.store ?? createLogger('pxe:data:lmdb', { actor });
49
- options.store = await createStore(
50
- 'pxe_data',
51
- PXE_DATA_SCHEMA_VERSION,
52
- configWithContracts,
53
- storeLogger.getBindings(),
54
- );
50
+ options.store = configWithContracts.dataDirectory
51
+ ? await openStore(
52
+ 'pxe_data',
53
+ PXE_DATA_SCHEMA_VERSION,
54
+ {
55
+ dataDirectory: configWithContracts.dataDirectory,
56
+ dataStoreMapSizeKb: configWithContracts.dataStoreMapSizeKb,
57
+ l1ChainId,
58
+ rollupAddress: l1ContractAddresses.rollupAddress,
59
+ },
60
+ storeLogger.getBindings(),
61
+ )
62
+ : await openTmpStore(
63
+ 'pxe_data',
64
+ true,
65
+ configWithContracts.dataStoreMapSizeKb,
66
+ undefined,
67
+ storeLogger.getBindings(),
68
+ );
55
69
  }
56
70
  const proverLogger = loggers.prover ?? createLogger('pxe:bb:native', { actor });
57
71
 
@@ -22,8 +22,8 @@ import {
22
22
  } from '../contract_function_simulator/noir-structs/log_retrieval_request.js';
23
23
  import type { LogRetrievalResponse } from '../contract_function_simulator/noir-structs/log_retrieval_response.js';
24
24
  import type { PendingTaggedLog } from '../contract_function_simulator/noir-structs/pending_tagged_log.js';
25
- import { ResolvedTx } from '../contract_function_simulator/noir-structs/resolved_tx.js';
26
25
  import { AddressStore } from '../storage/address_store/address_store.js';
26
+ import { assertAllowedScope } from '../storage/allowed_scopes.js';
27
27
  import type { RecipientTaggingStore } from '../storage/tagging_store/recipient_tagging_store.js';
28
28
  import type { TaggingSecretSourcesStore } from '../storage/tagging_store/tagging_secret_sources_store.js';
29
29
  import {
@@ -47,6 +47,7 @@ export class LogService {
47
47
  private readonly recipientTaggingStore: RecipientTaggingStore,
48
48
  private readonly taggingSecretSourcesStore: TaggingSecretSourcesStore,
49
49
  private readonly addressStore: AddressStore,
50
+ private readonly scopes: AztecAddress[],
50
51
  private readonly jobId: string,
51
52
  bindings?: LoggerBindings,
52
53
  ) {
@@ -189,6 +190,8 @@ export class LogService {
189
190
  recipient: AztecAddress,
190
191
  providedSecrets: AppTaggingSecret[],
191
192
  ): Promise<PendingTaggedLog[]> {
193
+ assertAllowedScope(recipient, this.scopes);
194
+
192
195
  this.log.verbose(
193
196
  `Fetching tagged logs for contract ${contractAddress.toString()} and recipient ${recipient.toString()}`,
194
197
  );
@@ -221,7 +224,13 @@ export class LogService {
221
224
  }
222
225
  return {
223
226
  log: log.logData,
224
- context: new ResolvedTx(log.txHash, noteHashes, nullifiers[0], log.blockNumber, log.blockHash.toFr()),
227
+ context: {
228
+ txHash: log.txHash,
229
+ uniqueNoteHashesInTx: noteHashes,
230
+ firstNullifierInTx: nullifiers[0],
231
+ blockNumber: log.blockNumber,
232
+ blockHash: log.blockHash.toFr(),
233
+ },
225
234
  };
226
235
  });
227
236
  }
@@ -3,7 +3,7 @@ import { Fr } from '@aztec/foundation/curves/bn254';
3
3
  import type { AztecNode } from '@aztec/stdlib/interfaces/server';
4
4
  import { type IndexedTxEffect, TxHash } from '@aztec/stdlib/tx';
5
5
 
6
- import { ResolvedTx } from '../contract_function_simulator/noir-structs/resolved_tx.js';
6
+ import type { ResolvedTx } from '../contract_function_simulator/noir-structs/resolved_tx.js';
7
7
 
8
8
  /** Resolves transaction hashes into their on-chain context (note hashes, first nullifier, and mined block). */
9
9
  export class TxResolverService {
@@ -57,13 +57,13 @@ export class TxResolverService {
57
57
  throw new Error(`Tx effect for ${txHash} has no nullifiers`);
58
58
  }
59
59
 
60
- return new ResolvedTx(
61
- data.txHash,
62
- data.noteHashes,
63
- data.nullifiers[0],
64
- txEffect.l2BlockNumber,
65
- txEffect.l2BlockHash.toFr(),
66
- );
60
+ return {
61
+ txHash: data.txHash,
62
+ uniqueNoteHashesInTx: data.noteHashes,
63
+ firstNullifierInTx: data.nullifiers[0],
64
+ blockNumber: txEffect.l2BlockNumber,
65
+ blockHash: txEffect.l2BlockHash.toFr(),
66
+ };
67
67
  });
68
68
  }
69
69
  }
@@ -26,7 +26,7 @@ export class NoteService {
26
26
  *
27
27
  * @param owner - The owner of the notes. If undefined, returns notes for all known owners.
28
28
  * @param status - The status of notes to fetch.
29
- * @param scopes - The accounts whose notes we can access in this call. Currently optional and will default to all.
29
+ * @param scopes - The accounts whose notes we can access in this call. An empty list matches no notes.
30
30
  */
31
31
  public async getNotes(
32
32
  contractAddress: AztecAddress,
@@ -11,12 +11,12 @@
11
11
  /// if AZTEC_NR_MINOR > PXE_MINOR because if a contract is updated to use a newer Aztec.nr dependency without actually
12
12
  /// using any of the new oracles then there is no reason to throw.
13
13
  export const ORACLE_VERSION_MAJOR = 30;
14
- export const ORACLE_VERSION_MINOR = 7;
14
+ export const ORACLE_VERSION_MINOR = 8;
15
15
 
16
- /// This hash is computed from the `ORACLE_REGISTRY` declaration (each oracle's name, ordered parameter names and
16
+ /// This hash is computed from `ORACLE_REGISTRY` (each oracle's name, ordered parameter names and
17
17
  /// types, and return type) and is used to detect when the oracle interface changes. When it does, you need to either:
18
18
  /// - increment `ORACLE_VERSION_MAJOR` and reset `ORACLE_VERSION_MINOR` to zero if the change is breaking, or
19
19
  /// - increment only `ORACLE_VERSION_MINOR` if the change is additive (a new oracle was added).
20
20
  ///
21
21
  /// These constants must be kept in sync between this file and `noir-projects/aztec-nr/aztec/src/oracle/version.nr`.
22
- export const ORACLE_INTERFACE_HASH = '416b0e7d3e6dca5803ebe2a65ea93f1e79759dc39ef8ec4c52eeba5e2b0f3fca';
22
+ export const ORACLE_INTERFACE_HASH = 'fec4d3a95fc57a62a20bfeb659bb3bfd91b31cd93e07f8cf97b368f9f55cc67b';
@@ -150,7 +150,6 @@ export function appendApp(
150
150
  acc.feePayer,
151
151
  acc.expirationTimestamp,
152
152
  acc.isPrivateOnly,
153
- acc.claimedFirstNullifier,
154
153
  acc.claimedRevertibleCounter,
155
154
  );
156
155
  }