@aztec/pxe 0.0.1-commit.b8a057fa → 0.0.1-commit.be03c316

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 (167) 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/contract/helpers.d.ts +1 -1
  9. package/dest/contract/helpers.d.ts.map +1 -1
  10. package/dest/contract/helpers.js +3 -3
  11. package/dest/contract/skip_sync_contracts.d.ts +11 -0
  12. package/dest/contract/skip_sync_contracts.d.ts.map +1 -0
  13. package/dest/contract/skip_sync_contracts.js +18 -0
  14. package/dest/contract_function_simulator/aztec_node_read_cache.d.ts +39 -0
  15. package/dest/contract_function_simulator/aztec_node_read_cache.d.ts.map +1 -0
  16. package/dest/contract_function_simulator/aztec_node_read_cache.js +60 -0
  17. package/dest/contract_function_simulator/index.d.ts +3 -3
  18. package/dest/contract_function_simulator/index.d.ts.map +1 -1
  19. package/dest/contract_function_simulator/index.js +1 -2
  20. package/dest/contract_function_simulator/noir-structs/resolved_tagging_strategy.d.ts +1 -1
  21. package/dest/contract_function_simulator/noir-structs/resolved_tagging_strategy.d.ts.map +1 -1
  22. package/dest/contract_function_simulator/noir-structs/resolved_tagging_strategy.js +7 -0
  23. package/dest/contract_function_simulator/noir-structs/resolved_tx.d.ts +7 -9
  24. package/dest/contract_function_simulator/noir-structs/resolved_tx.d.ts.map +1 -1
  25. package/dest/contract_function_simulator/noir-structs/resolved_tx.js +3 -44
  26. package/dest/contract_function_simulator/noir-structs/tx_effect_data.d.ts +5 -4
  27. package/dest/contract_function_simulator/noir-structs/tx_effect_data.d.ts.map +1 -1
  28. package/dest/contract_function_simulator/noir-structs/tx_effect_data.js +2 -2
  29. package/dest/contract_function_simulator/oracle/acir_callback.js +1 -1
  30. package/dest/contract_function_simulator/oracle/legacy_oracle_registry.d.ts +3 -3
  31. package/dest/contract_function_simulator/oracle/legacy_oracle_registry.d.ts.map +1 -1
  32. package/dest/contract_function_simulator/oracle/legacy_oracle_registry.js +34 -1
  33. package/dest/contract_function_simulator/oracle/oracle_registry.d.ts +7 -4
  34. package/dest/contract_function_simulator/oracle/oracle_registry.d.ts.map +1 -1
  35. package/dest/contract_function_simulator/oracle/oracle_registry.js +40 -13
  36. package/dest/contract_function_simulator/oracle/oracle_type_mappings.d.ts +87 -35
  37. package/dest/contract_function_simulator/oracle/oracle_type_mappings.d.ts.map +1 -1
  38. package/dest/contract_function_simulator/oracle/oracle_type_mappings.js +286 -286
  39. package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts +1 -1
  40. package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts.map +1 -1
  41. package/dest/contract_function_simulator/oracle/private_execution_oracle.js +7 -10
  42. package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts +14 -8
  43. package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts.map +1 -1
  44. package/dest/contract_function_simulator/oracle/utility_execution_oracle.js +61 -34
  45. package/dest/entrypoints/client/bundle/index.d.ts +2 -1
  46. package/dest/entrypoints/client/bundle/index.d.ts.map +1 -1
  47. package/dest/entrypoints/client/bundle/index.js +1 -0
  48. package/dest/entrypoints/client/bundle/utils.d.ts +1 -1
  49. package/dest/entrypoints/client/bundle/utils.d.ts.map +1 -1
  50. package/dest/entrypoints/client/bundle/utils.js +10 -4
  51. package/dest/entrypoints/client/lazy/index.d.ts +2 -1
  52. package/dest/entrypoints/client/lazy/index.d.ts.map +1 -1
  53. package/dest/entrypoints/client/lazy/index.js +1 -0
  54. package/dest/entrypoints/client/lazy/utils.d.ts +1 -1
  55. package/dest/entrypoints/client/lazy/utils.d.ts.map +1 -1
  56. package/dest/entrypoints/client/lazy/utils.js +10 -4
  57. package/dest/entrypoints/client/store.d.ts +14 -0
  58. package/dest/entrypoints/client/store.d.ts.map +1 -0
  59. package/dest/entrypoints/client/store.js +42 -0
  60. package/dest/entrypoints/server/index.d.ts +2 -1
  61. package/dest/entrypoints/server/index.d.ts.map +1 -1
  62. package/dest/entrypoints/server/index.js +1 -0
  63. package/dest/entrypoints/server/store.d.ts +18 -0
  64. package/dest/entrypoints/server/store.d.ts.map +1 -0
  65. package/dest/entrypoints/server/store.js +28 -0
  66. package/dest/entrypoints/server/utils.d.ts +1 -1
  67. package/dest/entrypoints/server/utils.d.ts.map +1 -1
  68. package/dest/entrypoints/server/utils.js +8 -2
  69. package/dest/hooks/index.d.ts +2 -2
  70. package/dest/hooks/index.d.ts.map +1 -1
  71. package/dest/hooks/index.js +1 -0
  72. package/dest/hooks/resolve_tagging_secret_strategy.d.ts +3 -1
  73. package/dest/hooks/resolve_tagging_secret_strategy.d.ts.map +1 -1
  74. package/dest/hooks/resolve_tagging_secret_strategy.js +3 -3
  75. package/dest/logs/log_service.d.ts +3 -2
  76. package/dest/logs/log_service.d.ts.map +1 -1
  77. package/dest/logs/log_service.js +12 -3
  78. package/dest/messages/tx_resolver_service.d.ts +2 -2
  79. package/dest/messages/tx_resolver_service.d.ts.map +1 -1
  80. package/dest/messages/tx_resolver_service.js +7 -2
  81. package/dest/notes/note_service.d.ts +1 -1
  82. package/dest/notes/note_service.js +1 -1
  83. package/dest/oracle_version.d.ts +2 -2
  84. package/dest/oracle_version.js +3 -3
  85. package/dest/pxe.d.ts +1 -1
  86. package/dest/pxe.d.ts.map +1 -1
  87. package/dest/pxe.js +8 -5
  88. package/dest/storage/backwards_compatibility_tests/schema_tests.d.ts +1 -1
  89. package/dest/storage/backwards_compatibility_tests/schema_tests.d.ts.map +1 -1
  90. package/dest/storage/backwards_compatibility_tests/schema_tests.js +26 -2
  91. package/dest/storage/fact_store/index.d.ts +2 -2
  92. package/dest/storage/fact_store/index.d.ts.map +1 -1
  93. package/dest/storage/fact_store/index.js +1 -1
  94. package/dest/storage/fact_store/origin_state.d.ts +3 -1
  95. package/dest/storage/fact_store/origin_state.d.ts.map +1 -1
  96. package/dest/storage/fact_store/origin_state.js +7 -0
  97. package/dest/storage/metadata.d.ts +1 -1
  98. package/dest/storage/metadata.js +1 -1
  99. package/dest/storage/store_identity.d.ts +35 -0
  100. package/dest/storage/store_identity.d.ts.map +1 -0
  101. package/dest/storage/store_identity.js +44 -0
  102. package/dest/storage/tagging_store/sender_tagging_store.d.ts +19 -3
  103. package/dest/storage/tagging_store/sender_tagging_store.d.ts.map +1 -1
  104. package/dest/storage/tagging_store/sender_tagging_store.js +48 -11
  105. package/dest/tagging/constants.d.ts +3 -2
  106. package/dest/tagging/constants.d.ts.map +1 -1
  107. package/dest/tagging/constants.js +26 -5
  108. package/dest/tagging/index.d.ts +2 -2
  109. package/dest/tagging/index.d.ts.map +1 -1
  110. package/dest/tagging/index.js +1 -1
  111. package/dest/tagging/recipient_sync/sync_tagged_private_logs.d.ts +9 -4
  112. package/dest/tagging/recipient_sync/sync_tagged_private_logs.d.ts.map +1 -1
  113. package/dest/tagging/recipient_sync/sync_tagged_private_logs.js +60 -25
  114. package/dest/tagging/sender_sync/sync_sender_tagging_indexes.js +1 -1
  115. package/dest/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.d.ts +1 -1
  116. package/dest/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.d.ts.map +1 -1
  117. package/dest/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.js +6 -2
  118. package/dest/tagging/testing/tag_query_test_utils.d.ts +6 -0
  119. package/dest/tagging/testing/tag_query_test_utils.d.ts.map +1 -0
  120. package/dest/tagging/testing/tag_query_test_utils.js +10 -0
  121. package/package.json +17 -17
  122. package/src/bin/check_oracle_version.ts +3 -10
  123. package/src/bin/index.ts +1 -5
  124. package/src/bin/oracle_version_helpers.ts +11 -268
  125. package/src/contract/helpers.ts +3 -3
  126. package/src/contract/skip_sync_contracts.ts +23 -0
  127. package/src/contract_function_simulator/aztec_node_read_cache.ts +89 -0
  128. package/src/contract_function_simulator/index.ts +23 -3
  129. package/src/contract_function_simulator/noir-structs/resolved_tagging_strategy.ts +8 -0
  130. package/src/contract_function_simulator/noir-structs/resolved_tx.ts +11 -45
  131. package/src/contract_function_simulator/noir-structs/tx_effect_data.ts +4 -3
  132. package/src/contract_function_simulator/oracle/acir_callback.ts +1 -1
  133. package/src/contract_function_simulator/oracle/legacy_oracle_registry.ts +30 -3
  134. package/src/contract_function_simulator/oracle/oracle_registry.ts +32 -11
  135. package/src/contract_function_simulator/oracle/oracle_type_mappings.ts +285 -197
  136. package/src/contract_function_simulator/oracle/private_execution_oracle.ts +17 -12
  137. package/src/contract_function_simulator/oracle/utility_execution_oracle.ts +92 -39
  138. package/src/entrypoints/client/bundle/index.ts +1 -0
  139. package/src/entrypoints/client/bundle/utils.ts +15 -3
  140. package/src/entrypoints/client/lazy/index.ts +1 -0
  141. package/src/entrypoints/client/lazy/utils.ts +15 -3
  142. package/src/entrypoints/client/store.ts +54 -0
  143. package/src/entrypoints/server/index.ts +1 -0
  144. package/src/entrypoints/server/store.ts +47 -0
  145. package/src/entrypoints/server/utils.ts +21 -7
  146. package/src/hooks/index.ts +1 -0
  147. package/src/hooks/resolve_tagging_secret_strategy.ts +3 -0
  148. package/src/logs/log_service.ts +11 -2
  149. package/src/messages/tx_resolver_service.ts +8 -8
  150. package/src/notes/note_service.ts +1 -1
  151. package/src/oracle_version.ts +3 -3
  152. package/src/pxe.ts +8 -5
  153. package/src/storage/backwards_compatibility_tests/__snapshots__/RecipientTaggingStore.json +11 -3
  154. package/src/storage/backwards_compatibility_tests/__snapshots__/SenderTaggingStore.json +12 -4
  155. package/src/storage/backwards_compatibility_tests/__snapshots__/opened_stores.json +1 -1
  156. package/src/storage/backwards_compatibility_tests/schema_tests.ts +30 -1
  157. package/src/storage/fact_store/index.ts +1 -0
  158. package/src/storage/fact_store/origin_state.ts +9 -0
  159. package/src/storage/metadata.ts +1 -1
  160. package/src/storage/store_identity.ts +72 -0
  161. package/src/storage/tagging_store/sender_tagging_store.ts +62 -15
  162. package/src/tagging/constants.ts +27 -5
  163. package/src/tagging/index.ts +1 -1
  164. package/src/tagging/recipient_sync/sync_tagged_private_logs.ts +103 -46
  165. package/src/tagging/sender_sync/sync_sender_tagging_indexes.ts +1 -1
  166. package/src/tagging/sender_sync/utils/load_and_store_new_tagging_indexes.ts +6 -2
  167. package/src/tagging/testing/tag_query_test_utils.ts +11 -0
@@ -30,11 +30,13 @@ import {
30
30
  } from '@aztec/stdlib/tx';
31
31
 
32
32
  import type { ResolveCustomRequest } from '../../hooks/resolve_custom_request.js';
33
- import type {
34
- ResolveTaggingSecretStrategy,
35
- TaggingSecretStrategy,
33
+ import {
34
+ DEFAULT_TAGGING_SECRET_STRATEGY,
35
+ type ResolveTaggingSecretStrategy,
36
+ type TaggingSecretStrategy,
36
37
  } from '../../hooks/resolve_tagging_secret_strategy.js';
37
38
  import { NoteService } from '../../notes/note_service.js';
39
+ import { assertAllowedScope } from '../../storage/allowed_scopes.js';
38
40
  import type { SenderTaggingStore } from '../../storage/tagging_store/sender_tagging_store.js';
39
41
  import { syncSenderTaggingIndexes } from '../../tagging/index.js';
40
42
  import type { ExecutionNoteCache } from '../execution_note_cache.js';
@@ -237,8 +239,7 @@ export class PrivateExecutionOracle extends UtilityExecutionOracle implements IP
237
239
  ): Promise<TaggingSecretStrategy> {
238
240
  const hook: ResolveTaggingSecretStrategy | undefined = this.hooks?.resolveTaggingSecretStrategy;
239
241
  if (!hook) {
240
- // With no hook, both delivery modes default to a non-interactive handshake
241
- return { type: 'non-interactive-handshake' };
242
+ return DEFAULT_TAGGING_SECRET_STRATEGY;
242
243
  }
243
244
 
244
245
  const contractClassId = await this.#getCurrentContractClassId(this.contractAddress);
@@ -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);
@@ -26,7 +26,7 @@ import type { AztecNode } from '@aztec/stdlib/interfaces/server';
26
26
  import type { KeyValidationRequest } from '@aztec/stdlib/kernel';
27
27
  import { PublicKeys, computeAddressSecret, hashPublicKey } from '@aztec/stdlib/keys';
28
28
  import { AppTaggingSecret, FlatPublicLogs, appSiloEcdhSharedSecret } from '@aztec/stdlib/logs';
29
- import { getNonNullifiedL1ToL2MessageWitness } from '@aztec/stdlib/messaging';
29
+ import { type UnsiloedMessageNullifier, getL1ToL2MessageWitness } from '@aztec/stdlib/messaging';
30
30
  import type { NoteStatus } from '@aztec/stdlib/note';
31
31
  import { MerkleTreeId, type NullifierMembershipWitness, PublicDataWitness } from '@aztec/stdlib/trees';
32
32
  import {
@@ -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';
@@ -56,6 +58,7 @@ 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';
61
+ import { AztecNodeReadCache } from '../aztec_node_read_cache.js';
59
62
  import { EphemeralArrayService } from '../ephemeral_array_service.js';
60
63
  import { BoundedVec } from '../noir-structs/bounded_vec.js';
61
64
  import type { EmbeddedCurvePoint } from '../noir-structs/embedded_curve_point.js';
@@ -119,6 +122,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
119
122
  private offchainEffects: OffchainEffect[] = [];
120
123
  private readonly ephemeralArrayService = new EphemeralArrayService();
121
124
  protected readonly transientArrayService: TransientArrayService;
125
+ private readonly aztecNodeReadCache: AztecNodeReadCache;
122
126
 
123
127
  // We store oracle version to be able to show a nice error message when an oracle handler is missing.
124
128
  private contractOracleVersion: { major: number; minor: number } | undefined;
@@ -172,6 +176,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
172
176
  this.hooks = args.hooks;
173
177
  this.utilityExecutor = args.utilityExecutor;
174
178
  this.transientArrayService = args.transientArrayService;
179
+ this.aztecNodeReadCache = new AztecNodeReadCache(args.aztecNode);
175
180
  }
176
181
 
177
182
  public assertCompatibleOracleVersion(major: number, minor: number): void {
@@ -265,11 +270,27 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
265
270
  // hash at all. If the block hash did not exist by the reference block hash, then the node will not return the
266
271
  // membership witness as there is none.
267
272
  const witness = await this.#queryWithBlockHashNotAfterAnchor(referenceBlockHash, () =>
268
- this.aztecNode.getBlockHashMembershipWitness(referenceBlockHash, blockHash),
273
+ this.aztecNodeReadCache.getBlockHashMembershipWitness(referenceBlockHash, blockHash),
269
274
  );
270
275
  return witness ? Option.some(witness) : Option.none();
271
276
  }
272
277
 
278
+ /** Returns whether each block hash is present in the archive tree at the referenced block. */
279
+ public async areBlockHashesInArchive(
280
+ referenceBlockHash: BlockHash,
281
+ blockHashes: EphemeralArray<BlockHash>,
282
+ ): Promise<EphemeralArray<boolean>> {
283
+ const hashes = blockHashes.readAll(this.ephemeralArrayService);
284
+ const memberships = await this.#queryWithBlockHashNotAfterAnchor(referenceBlockHash, () =>
285
+ Promise.all(
286
+ hashes.map(blockHash =>
287
+ this.aztecNodeReadCache.getBlockHashMembershipWitness(referenceBlockHash, blockHash).then(Boolean),
288
+ ),
289
+ ),
290
+ );
291
+ return EphemeralArray.fromValues(this.ephemeralArrayService, memberships);
292
+ }
293
+
273
294
  /**
274
295
  * Returns a nullifier membership witness for a given nullifier at a given block.
275
296
  * @param blockHash - The block hash at which to get the index.
@@ -318,7 +339,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
318
339
  */
319
340
  public async getPublicDataWitness(blockHash: BlockHash, leafSlot: Fr): Promise<PublicDataWitness> {
320
341
  const witness = await this.#queryWithBlockHashNotAfterAnchor(blockHash, () =>
321
- this.aztecNode.getPublicDataWitness(blockHash, leafSlot),
342
+ this.aztecNodeReadCache.getPublicDataWitness(blockHash, leafSlot),
322
343
  );
323
344
  if (!witness) {
324
345
  throw new Error(`Public data witness not found for slot ${leafSlot} at block hash ${blockHash.toString()}.`);
@@ -478,19 +499,17 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
478
499
  }
479
500
 
480
501
  /**
481
- * Returns the membership witness of an un-nullified L1 to L2 message.
482
- * @param contractAddress - Address of a contract by which the message was emitted.
502
+ * Returns the membership witness of an L1 to L2 message.
483
503
  * @param messageHash - Hash of the message.
484
- * @param secret - Secret used to compute a nullifier.
485
- * @dev Contract address and secret are only used to compute the nullifier to get non-nullified messages
504
+ * @param nullifier - When present, the unsiloed nullifier of the message and the address to silo it with. The witness
505
+ * is only returned if the siloed nullifier is absent from the nullifier tree, i.e. the message has not been consumed.
486
506
  * @returns The l1 to l2 membership witness (index of message in the tree and sibling path).
487
507
  */
488
- public async getL1ToL2MembershipWitness(contractAddress: AztecAddress, messageHash: Fr, secret: Fr) {
489
- const [messageIndex, siblingPath] = await getNonNullifiedL1ToL2MessageWitness(
508
+ public async getL1ToL2MembershipWitnessV2(messageHash: Fr, nullifier: Option<UnsiloedMessageNullifier>) {
509
+ const [messageIndex, siblingPath] = await getL1ToL2MessageWitness(
490
510
  this.aztecNode,
491
- contractAddress,
492
511
  messageHash,
493
- secret,
512
+ nullifier.value,
494
513
  await this.anchorBlockHeader.hash(),
495
514
  );
496
515
 
@@ -511,16 +530,16 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
511
530
  numberOfElements: number,
512
531
  ) {
513
532
  return this.#queryWithBlockHashNotAfterAnchor(blockHash, async () => {
514
- const slots = Array(numberOfElements)
515
- .fill(0)
516
- .map((_, i) => new Fr(startStorageSlot.value + BigInt(i)));
517
-
518
- const values = await Promise.all(
519
- slots.map(storageSlot => this.aztecNode.getPublicStorageAt(blockHash, contractAddress, storageSlot)),
533
+ const values = await this.aztecNodeReadCache.getPublicStorageRange(
534
+ blockHash,
535
+ contractAddress,
536
+ startStorageSlot,
537
+ numberOfElements,
520
538
  );
521
539
 
522
540
  this.logger.debug(
523
- `Oracle storage read: slots=[${slots.map(slot => slot.toString()).join(', ')}] address=${contractAddress.toString()} values=[${values.join(', ')}]`,
541
+ `Oracle storage read: start=${startStorageSlot.toString()} count=${numberOfElements} ` +
542
+ `address=${contractAddress.toString()} values=[${values.join(', ')}]`,
524
543
  );
525
544
 
526
545
  return values;
@@ -595,6 +614,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
595
614
  this.recipientTaggingStore,
596
615
  this.taggingSecretSourcesStore,
597
616
  this.addressStore,
617
+ this.scopes,
598
618
  this.jobId,
599
619
  this.logger.getBindings(),
600
620
  );
@@ -666,21 +686,25 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
666
686
  throw new Error('Invalid tx hash passed into aztec_utl_getTxEffect oracle handler');
667
687
  }
668
688
 
669
- const receipt = await this.aztecNode.getTxReceipt(txHash, { includeTxEffect: true });
670
- if (!receipt.isMined() || !receipt.txEffect || receipt.blockNumber > this.anchorBlockHeader.getBlockNumber()) {
671
- 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');
672
698
  }
673
699
 
674
- const txEffect = receipt.txEffect;
675
- return Option.some({
676
- ...txEffect,
677
- publicLogs: FlatPublicLogs.fromLogs(txEffect.publicLogs),
678
- contractClassLogs: txEffect.contractClassLogs.map(log => ({
679
- contractAddress: log.contractAddress,
680
- fields: log.fields.toFields(),
681
- emittedLength: log.emittedLength,
682
- })),
683
- });
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
+ );
684
708
  }
685
709
 
686
710
  public setCapsule(contractAddress: AztecAddress, slot: Fr, capsule: Fr[], scope: AztecAddress): void {
@@ -835,13 +859,17 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
835
859
  // TODO(#11849): consider replacing this oracle with a pure Noir implementation of aes decryption.
836
860
  public async decryptAes128(
837
861
  ciphertext: BoundedVec<number>,
838
- iv: Buffer,
839
- symKey: Buffer,
862
+ iv: number[],
863
+ symKey: number[],
840
864
  ): Promise<Option<BoundedVec<number>>> {
841
865
  const capacity = ciphertext.maxLength;
842
866
  try {
843
867
  const aes128 = new Aes128();
844
- 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
+ );
845
873
  return Option.some(BoundedVec.from<number>({ data: [...plaintext], maxLength: capacity }));
846
874
  } catch {
847
875
  return Option.none({ maxLength: capacity });
@@ -854,7 +882,8 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
854
882
  * @param ephPks - Ephemeral array containing the serialized Points.
855
883
  * @param contractAddress - The contract address for app-siloing (validated against execution context).
856
884
  * @returns A new ephemeral array containing the computed shared secrets, or an empty array when the PXE does not
857
- * 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.
858
887
  */
859
888
  public async getSharedSecrets(
860
889
  address: AztecAddress,
@@ -866,6 +895,11 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
866
895
  `getSharedSecrets called with contract address ${contractAddress}, expected ${this.contractAddress}`,
867
896
  );
868
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.
869
903
  const recipientCompleteAddress = await this.addressStore.getCompleteAddress(address);
870
904
  if (!recipientCompleteAddress) {
871
905
  this.logger.warn(
@@ -1079,9 +1113,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
1079
1113
  */
1080
1114
  async #fetchTxEffects(txHashes: TxHash[]): Promise<Map<string, IndexedTxEffect>> {
1081
1115
  const uniqueTxHashes = uniqueBy(txHashes, h => h.toString());
1082
- const fetched = await Promise.all(
1083
- uniqueTxHashes.map(h => this.aztecNode.getTxReceipt(h, { includeTxEffect: true })),
1084
- );
1116
+ const fetched = await Promise.all(uniqueTxHashes.map(h => this.aztecNodeReadCache.getTxReceiptWithEffect(h)));
1085
1117
  return new Map(
1086
1118
  uniqueTxHashes
1087
1119
  .map((h, i): [string, IndexedTxEffect | undefined] => {
@@ -1104,6 +1136,27 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
1104
1136
  );
1105
1137
  }
1106
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
+
1107
1160
  /** Runs a query concurrently with a validation that the block hash is not ahead of the anchor block. */
1108
1161
  async #queryWithBlockHashNotAfterAnchor<T>(blockHash: BlockHash, query: () => Promise<T>): Promise<T> {
1109
1162
  // Most contracts query state at the "current" block, which is the anchor. Skip the validation when we can.
@@ -1115,7 +1168,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
1115
1168
  const [response] = await Promise.all([
1116
1169
  query(),
1117
1170
  (async () => {
1118
- const block = await this.aztecNode.getBlock(blockHash);
1171
+ const block = await this.aztecNodeReadCache.getBlock(blockHash);
1119
1172
  const header = block?.header;
1120
1173
  if (!header) {
1121
1174
  throw new Error(`Could not find block header for block hash ${blockHash}`);
@@ -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
 
@@ -6,6 +6,7 @@ export type {
6
6
  export { type ExecutionHooks, composeHooks } from './execution_hooks.js';
7
7
  export { type CustomRequest, type ResolveCustomRequest } from './resolve_custom_request.js';
8
8
  export {
9
+ DEFAULT_TAGGING_SECRET_STRATEGY,
9
10
  type ResolveTaggingSecretStrategy,
10
11
  type TaggingSecretStrategy,
11
12
  type TaggingSecretStrategyRequest,
@@ -39,6 +39,9 @@ export type TaggingSecretStrategy =
39
39
  secret: Point;
40
40
  };
41
41
 
42
+ /** The strategy PXE applies to both delivery modes when no `resolveTaggingSecretStrategy` hook is configured. */
43
+ export const DEFAULT_TAGGING_SECRET_STRATEGY: TaggingSecretStrategy = { type: 'non-interactive-handshake' };
44
+
42
45
  /** Information about the message delivery requesting a tagging secret strategy. */
43
46
  export type TaggingSecretStrategyRequest = {
44
47
  contractAddress: AztecAddress;
@@ -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
  }