@aztec/pxe 0.0.1-commit.e0f15ab9b → 0.0.1-commit.e304674f1

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 (138) hide show
  1. package/dest/block_synchronizer/block_synchronizer.d.ts +1 -1
  2. package/dest/block_synchronizer/block_synchronizer.d.ts.map +1 -1
  3. package/dest/block_synchronizer/block_synchronizer.js +6 -0
  4. package/dest/contract_function_simulator/contract_function_simulator.d.ts +3 -4
  5. package/dest/contract_function_simulator/contract_function_simulator.d.ts.map +1 -1
  6. package/dest/contract_function_simulator/contract_function_simulator.js +4 -3
  7. package/dest/contract_function_simulator/noir-structs/event_validation_request.d.ts +2 -3
  8. package/dest/contract_function_simulator/noir-structs/event_validation_request.d.ts.map +1 -1
  9. package/dest/contract_function_simulator/noir-structs/event_validation_request.js +2 -5
  10. package/dest/contract_function_simulator/noir-structs/note_validation_request.d.ts +2 -3
  11. package/dest/contract_function_simulator/noir-structs/note_validation_request.d.ts.map +1 -1
  12. package/dest/contract_function_simulator/noir-structs/note_validation_request.js +2 -5
  13. package/dest/contract_function_simulator/oracle/interfaces.d.ts +19 -19
  14. package/dest/contract_function_simulator/oracle/interfaces.d.ts.map +1 -1
  15. package/dest/contract_function_simulator/oracle/legacy_oracle_mappings.d.ts +1 -1
  16. package/dest/contract_function_simulator/oracle/legacy_oracle_mappings.d.ts.map +1 -1
  17. package/dest/contract_function_simulator/oracle/legacy_oracle_mappings.js +18 -22
  18. package/dest/contract_function_simulator/oracle/oracle.d.ts +38 -19
  19. package/dest/contract_function_simulator/oracle/oracle.d.ts.map +1 -1
  20. package/dest/contract_function_simulator/oracle/oracle.js +60 -39
  21. package/dest/contract_function_simulator/oracle/private_execution.js +1 -1
  22. package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts +7 -8
  23. package/dest/contract_function_simulator/oracle/private_execution_oracle.d.ts.map +1 -1
  24. package/dest/contract_function_simulator/oracle/private_execution_oracle.js +16 -7
  25. package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts +30 -29
  26. package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts.map +1 -1
  27. package/dest/contract_function_simulator/oracle/utility_execution_oracle.js +115 -79
  28. package/dest/contract_function_simulator/pick_notes.d.ts +1 -1
  29. package/dest/contract_function_simulator/pick_notes.d.ts.map +1 -1
  30. package/dest/contract_function_simulator/pick_notes.js +9 -2
  31. package/dest/contract_logging.d.ts +9 -4
  32. package/dest/contract_logging.d.ts.map +1 -1
  33. package/dest/contract_logging.js +21 -6
  34. package/dest/contract_sync/contract_sync_service.d.ts +3 -4
  35. package/dest/contract_sync/contract_sync_service.d.ts.map +1 -1
  36. package/dest/contract_sync/contract_sync_service.js +12 -22
  37. package/dest/contract_sync/helpers.d.ts +2 -3
  38. package/dest/contract_sync/helpers.d.ts.map +1 -1
  39. package/dest/contract_sync/helpers.js +7 -2
  40. package/dest/debug/pxe_debug_utils.d.ts +3 -3
  41. package/dest/debug/pxe_debug_utils.d.ts.map +1 -1
  42. package/dest/entrypoints/client/bundle/index.d.ts +1 -2
  43. package/dest/entrypoints/client/bundle/index.d.ts.map +1 -1
  44. package/dest/entrypoints/client/bundle/index.js +0 -1
  45. package/dest/entrypoints/client/bundle/utils.d.ts +2 -2
  46. package/dest/entrypoints/client/bundle/utils.d.ts.map +1 -1
  47. package/dest/entrypoints/client/bundle/utils.js +2 -2
  48. package/dest/entrypoints/client/lazy/index.d.ts +1 -2
  49. package/dest/entrypoints/client/lazy/index.d.ts.map +1 -1
  50. package/dest/entrypoints/client/lazy/index.js +0 -1
  51. package/dest/entrypoints/client/lazy/utils.d.ts +2 -2
  52. package/dest/entrypoints/client/lazy/utils.d.ts.map +1 -1
  53. package/dest/entrypoints/client/lazy/utils.js +2 -2
  54. package/dest/entrypoints/pxe_creation_options.d.ts +3 -1
  55. package/dest/entrypoints/pxe_creation_options.d.ts.map +1 -1
  56. package/dest/entrypoints/pxe_creation_options.js +3 -1
  57. package/dest/entrypoints/server/index.d.ts +1 -2
  58. package/dest/entrypoints/server/index.d.ts.map +1 -1
  59. package/dest/entrypoints/server/index.js +0 -1
  60. package/dest/entrypoints/server/utils.d.ts +2 -2
  61. package/dest/entrypoints/server/utils.d.ts.map +1 -1
  62. package/dest/entrypoints/server/utils.js +2 -2
  63. package/dest/events/event_service.d.ts +3 -2
  64. package/dest/events/event_service.d.ts.map +1 -1
  65. package/dest/events/event_service.js +16 -4
  66. package/dest/logs/log_service.d.ts +6 -7
  67. package/dest/logs/log_service.d.ts.map +1 -1
  68. package/dest/logs/log_service.js +32 -30
  69. package/dest/messages/message_context_service.d.ts +3 -3
  70. package/dest/messages/message_context_service.d.ts.map +1 -1
  71. package/dest/messages/message_context_service.js +3 -3
  72. package/dest/notes/note_service.d.ts +4 -5
  73. package/dest/notes/note_service.d.ts.map +1 -1
  74. package/dest/notes/note_service.js +14 -5
  75. package/dest/notes_filter.d.ts +2 -3
  76. package/dest/notes_filter.d.ts.map +1 -1
  77. package/dest/oracle_version.d.ts +2 -2
  78. package/dest/oracle_version.js +2 -2
  79. package/dest/pxe.d.ts +4 -5
  80. package/dest/pxe.d.ts.map +1 -1
  81. package/dest/pxe.js +6 -4
  82. package/dest/storage/capsule_store/capsule_service.d.ts +21 -0
  83. package/dest/storage/capsule_store/capsule_service.d.ts.map +1 -0
  84. package/dest/storage/capsule_store/capsule_service.js +50 -0
  85. package/dest/storage/capsule_store/capsule_store.d.ts +9 -9
  86. package/dest/storage/capsule_store/capsule_store.d.ts.map +1 -1
  87. package/dest/storage/capsule_store/capsule_store.js +33 -28
  88. package/dest/storage/capsule_store/index.d.ts +2 -1
  89. package/dest/storage/capsule_store/index.d.ts.map +1 -1
  90. package/dest/storage/capsule_store/index.js +1 -0
  91. package/dest/storage/metadata.d.ts +1 -1
  92. package/dest/storage/metadata.js +1 -1
  93. package/dest/storage/note_store/note_store.d.ts +1 -1
  94. package/dest/storage/note_store/note_store.d.ts.map +1 -1
  95. package/dest/storage/note_store/note_store.js +2 -2
  96. package/package.json +16 -16
  97. package/src/block_synchronizer/block_synchronizer.ts +6 -0
  98. package/src/contract_function_simulator/contract_function_simulator.ts +6 -6
  99. package/src/contract_function_simulator/noir-structs/event_validation_request.ts +0 -3
  100. package/src/contract_function_simulator/noir-structs/note_validation_request.ts +0 -3
  101. package/src/contract_function_simulator/oracle/interfaces.ts +26 -17
  102. package/src/contract_function_simulator/oracle/legacy_oracle_mappings.ts +13 -50
  103. package/src/contract_function_simulator/oracle/oracle.ts +79 -33
  104. package/src/contract_function_simulator/oracle/private_execution.ts +1 -1
  105. package/src/contract_function_simulator/oracle/private_execution_oracle.ts +19 -10
  106. package/src/contract_function_simulator/oracle/utility_execution_oracle.ts +204 -91
  107. package/src/contract_function_simulator/pick_notes.ts +9 -2
  108. package/src/contract_logging.ts +18 -5
  109. package/src/contract_sync/contract_sync_service.ts +32 -43
  110. package/src/contract_sync/helpers.ts +4 -4
  111. package/src/debug/pxe_debug_utils.ts +3 -3
  112. package/src/entrypoints/client/bundle/index.ts +0 -1
  113. package/src/entrypoints/client/bundle/utils.ts +2 -3
  114. package/src/entrypoints/client/lazy/index.ts +0 -1
  115. package/src/entrypoints/client/lazy/utils.ts +2 -3
  116. package/src/entrypoints/pxe_creation_options.ts +7 -0
  117. package/src/entrypoints/server/index.ts +0 -1
  118. package/src/entrypoints/server/utils.ts +2 -3
  119. package/src/events/event_service.ts +17 -4
  120. package/src/logs/log_service.ts +63 -48
  121. package/src/messages/message_context_service.ts +3 -4
  122. package/src/notes/note_service.ts +18 -8
  123. package/src/notes_filter.ts +1 -3
  124. package/src/oracle_version.ts +2 -2
  125. package/src/pxe.ts +11 -10
  126. package/src/storage/capsule_store/capsule_service.ts +90 -0
  127. package/src/storage/capsule_store/capsule_store.ts +34 -26
  128. package/src/storage/capsule_store/index.ts +1 -0
  129. package/src/storage/metadata.ts +1 -1
  130. package/src/storage/note_store/note_store.ts +2 -5
  131. package/dest/access_scopes.d.ts +0 -9
  132. package/dest/access_scopes.d.ts.map +0 -1
  133. package/dest/access_scopes.js +0 -6
  134. package/dest/contract_function_simulator/noir-structs/message_tx_context.d.ts +0 -16
  135. package/dest/contract_function_simulator/noir-structs/message_tx_context.d.ts.map +0 -1
  136. package/dest/contract_function_simulator/noir-structs/message_tx_context.js +0 -57
  137. package/src/access_scopes.ts +0 -9
  138. package/src/contract_function_simulator/noir-structs/message_tx_context.ts +0 -55
@@ -15,14 +15,13 @@ import { siloNullifier } from '@aztec/stdlib/hash';
15
15
  import type { AztecNode } from '@aztec/stdlib/interfaces/server';
16
16
  import type { KeyValidationRequest } from '@aztec/stdlib/kernel';
17
17
  import { type PublicKeys, computeAddressSecret } from '@aztec/stdlib/keys';
18
- import { deriveEcdhSharedSecret } from '@aztec/stdlib/logs';
18
+ import { MessageContext, deriveAppSiloedSharedSecret } from '@aztec/stdlib/logs';
19
19
  import { getNonNullifiedL1ToL2MessageWitness } from '@aztec/stdlib/messaging';
20
20
  import type { NoteStatus } from '@aztec/stdlib/note';
21
21
  import { MerkleTreeId, type NullifierMembershipWitness, PublicDataWitness } from '@aztec/stdlib/trees';
22
22
  import type { BlockHeader, Capsule, OffchainEffect } from '@aztec/stdlib/tx';
23
23
 
24
- import type { AccessScopes } from '../../access_scopes.js';
25
- import { createContractLogger, logContractMessage } from '../../contract_logging.js';
24
+ import { createContractLogger, logContractMessage, stripAztecnrLogPrefix } from '../../contract_logging.js';
26
25
  import type { ContractSyncService } from '../../contract_sync/contract_sync_service.js';
27
26
  import { EventService } from '../../events/event_service.js';
28
27
  import { LogService } from '../../logs/log_service.js';
@@ -30,7 +29,7 @@ import { MessageContextService } from '../../messages/message_context_service.js
30
29
  import { NoteService } from '../../notes/note_service.js';
31
30
  import { ORACLE_VERSION } from '../../oracle_version.js';
32
31
  import type { AddressStore } from '../../storage/address_store/address_store.js';
33
- import type { CapsuleStore } from '../../storage/capsule_store/capsule_store.js';
32
+ import type { CapsuleService } from '../../storage/capsule_store/capsule_service.js';
34
33
  import type { ContractStore } from '../../storage/contract_store/contract_store.js';
35
34
  import type { NoteStore } from '../../storage/note_store/note_store.js';
36
35
  import type { PrivateEventStore } from '../../storage/private_event_store/private_event_store.js';
@@ -39,7 +38,6 @@ import type { SenderAddressBookStore } from '../../storage/tagging_store/sender_
39
38
  import { EventValidationRequest } from '../noir-structs/event_validation_request.js';
40
39
  import { LogRetrievalRequest } from '../noir-structs/log_retrieval_request.js';
41
40
  import { LogRetrievalResponse } from '../noir-structs/log_retrieval_response.js';
42
- import { MessageTxContext } from '../noir-structs/message_tx_context.js';
43
41
  import { NoteValidationRequest } from '../noir-structs/note_validation_request.js';
44
42
  import { UtilityContext } from '../noir-structs/utility_context.js';
45
43
  import { pickNotes } from '../pick_notes.js';
@@ -60,13 +58,13 @@ export type UtilityExecutionOracleArgs = {
60
58
  aztecNode: AztecNode;
61
59
  recipientTaggingStore: RecipientTaggingStore;
62
60
  senderAddressBookStore: SenderAddressBookStore;
63
- capsuleStore: CapsuleStore;
61
+ capsuleService: CapsuleService;
64
62
  privateEventStore: PrivateEventStore;
65
63
  messageContextService: MessageContextService;
66
64
  contractSyncService: ContractSyncService;
67
65
  jobId: string;
68
66
  log?: ReturnType<typeof createLogger>;
69
- scopes: AccessScopes;
67
+ scopes: AztecAddress[];
70
68
  };
71
69
 
72
70
  /**
@@ -77,6 +75,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
77
75
  isUtility = true as const;
78
76
 
79
77
  private contractLogger: Logger | undefined;
78
+ private aztecnrLogger: Logger | undefined;
80
79
  private offchainEffects: OffchainEffect[] = [];
81
80
 
82
81
  protected readonly contractAddress: AztecAddress;
@@ -90,13 +89,13 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
90
89
  protected readonly aztecNode: AztecNode;
91
90
  protected readonly recipientTaggingStore: RecipientTaggingStore;
92
91
  protected readonly senderAddressBookStore: SenderAddressBookStore;
93
- protected readonly capsuleStore: CapsuleStore;
92
+ protected readonly capsuleService: CapsuleService;
94
93
  protected readonly privateEventStore: PrivateEventStore;
95
94
  protected readonly messageContextService: MessageContextService;
96
95
  protected readonly contractSyncService: ContractSyncService;
97
96
  protected readonly jobId: string;
98
97
  protected logger: ReturnType<typeof createLogger>;
99
- protected readonly scopes: AccessScopes;
98
+ protected readonly scopes: AztecAddress[];
100
99
 
101
100
  constructor(args: UtilityExecutionOracleArgs) {
102
101
  this.contractAddress = args.contractAddress;
@@ -110,7 +109,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
110
109
  this.aztecNode = args.aztecNode;
111
110
  this.recipientTaggingStore = args.recipientTaggingStore;
112
111
  this.senderAddressBookStore = args.senderAddressBookStore;
113
- this.capsuleStore = args.capsuleStore;
112
+ this.capsuleService = args.capsuleService;
114
113
  this.privateEventStore = args.privateEventStore;
115
114
  this.messageContextService = args.messageContextService;
116
115
  this.contractSyncService = args.contractSyncService;
@@ -128,15 +127,25 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
128
127
  const LEGACY_ORACLE_VERSION = 12;
129
128
  if (isProtocolContract(this.contractAddress)) {
130
129
  if (version !== LEGACY_ORACLE_VERSION && version !== ORACLE_VERSION) {
130
+ const hint =
131
+ version > ORACLE_VERSION
132
+ ? 'The contract was compiled with a newer version of Aztec.nr than your private environment supports. Upgrade your private environment to a compatible version.'
133
+ : 'The contract was compiled with an older version of Aztec.nr than your private environment supports. Recompile the contract with a compatible version of Aztec.nr.';
131
134
  throw new Error(
132
- `Expected legacy oracle version ${LEGACY_ORACLE_VERSION} or current oracle version ${ORACLE_VERSION} for alpha payload contract at ${this.contractAddress}, got ${version}.`,
135
+ `Incompatible private environment version: ${hint} See https://docs.aztec.network/errors/8 (expected oracle version ${LEGACY_ORACLE_VERSION} or ${ORACLE_VERSION}, got ${version})`,
133
136
  );
134
137
  }
135
138
  return;
136
139
  }
137
140
 
138
141
  if (version !== ORACLE_VERSION) {
139
- throw new Error(`Incompatible oracle version. Expected version ${ORACLE_VERSION}, got ${version}.`);
142
+ const hint =
143
+ version > ORACLE_VERSION
144
+ ? 'The contract was compiled with a newer version of Aztec.nr than your private environment supports. Upgrade your private environment to a compatible version.'
145
+ : 'The contract was compiled with an older version of Aztec.nr than your private environment supports. Recompile the contract with a compatible version of Aztec.nr.';
146
+ throw new Error(
147
+ `Incompatible private environment version: ${hint} See https://docs.aztec.network/errors/8 (expected oracle version ${ORACLE_VERSION}, got ${version})`,
148
+ );
140
149
  }
141
150
  }
142
151
 
@@ -156,33 +165,32 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
156
165
  * @throws If scopes are defined and the account is not in the scopes.
157
166
  */
158
167
  public async getKeyValidationRequest(pkMHash: Fr): Promise<KeyValidationRequest> {
159
- // If scopes are defined, check that the key belongs to an account in the scopes.
160
- if (this.scopes !== 'ALL_SCOPES' && this.scopes.length > 0) {
161
- let hasAccess = false;
162
- for (let i = 0; i < this.scopes.length && !hasAccess; i++) {
163
- if (await this.keyStore.accountHasKey(this.scopes[i], pkMHash)) {
164
- hasAccess = true;
165
- }
166
- }
167
- if (!hasAccess) {
168
- throw new Error(`Key validation request denied: no scoped account has a key with hash ${pkMHash.toString()}.`);
168
+ let hasAccess = false;
169
+ for (let i = 0; i < this.scopes.length && !hasAccess; i++) {
170
+ if (await this.keyStore.accountHasKey(this.scopes[i], pkMHash)) {
171
+ hasAccess = true;
169
172
  }
170
173
  }
174
+ if (!hasAccess) {
175
+ throw new Error(`Key validation request denied: no scoped account has a key with hash ${pkMHash.toString()}.`);
176
+ }
171
177
  return this.keyStore.getKeyValidationRequest(pkMHash, this.contractAddress);
172
178
  }
173
179
 
174
180
  /**
175
181
  * Fetches the index and sibling path of a leaf at a given block from the note hash tree.
176
- * @param anchorBlockHash - The hash of a block that contains the note hash tree root in which to find the membership
177
- * witness.
182
+ * @param blockHash - The hash of a block that contains the note hash tree root in which to find the
183
+ * membership witness.
178
184
  * @param noteHash - The note hash to find in the note hash tree.
179
185
  * @returns The membership witness containing the leaf index and sibling path
180
186
  */
181
187
  public getNoteHashMembershipWitness(
182
- anchorBlockHash: BlockHash,
188
+ blockHash: BlockHash,
183
189
  noteHash: Fr,
184
190
  ): Promise<MembershipWitness<typeof NOTE_HASH_TREE_HEIGHT> | undefined> {
185
- return this.aztecNode.getNoteHashMembershipWitness(anchorBlockHash, noteHash);
191
+ return this.#queryWithBlockHashNotAfterAnchor(blockHash, () =>
192
+ this.aztecNode.getNoteHashMembershipWitness(blockHash, noteHash),
193
+ );
186
194
  }
187
195
 
188
196
  /**
@@ -191,16 +199,21 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
191
199
  * Block hashes are the leaves of the archive tree. Each time a new block is added to the chain,
192
200
  * its block hash is appended as a new leaf to the archive tree.
193
201
  *
194
- * @param anchorBlockHash - The hash of a block that contains the archive tree root in which to find the membership
202
+ * @param referenceBlockHash - The hash of a block that contains the archive tree root in which to find the membership
195
203
  * witness.
196
204
  * @param blockHash - The block hash to find in the archive tree.
197
205
  * @returns The membership witness containing the leaf index and sibling path
198
206
  */
199
207
  public getBlockHashMembershipWitness(
200
- anchorBlockHash: BlockHash,
208
+ referenceBlockHash: BlockHash,
201
209
  blockHash: BlockHash,
202
210
  ): Promise<MembershipWitness<typeof ARCHIVE_HEIGHT> | undefined> {
203
- return this.aztecNode.getBlockHashMembershipWitness(anchorBlockHash, blockHash);
211
+ // Note that we validate that the reference block hash is at or before the anchor block - we don't test the block
212
+ // hash at all. If the block hash did not exist by the reference block hash, then the node will not return the
213
+ // membership witness as there is none.
214
+ return this.#queryWithBlockHashNotAfterAnchor(referenceBlockHash, () =>
215
+ this.aztecNode.getBlockHashMembershipWitness(referenceBlockHash, blockHash),
216
+ );
204
217
  }
205
218
 
206
219
  /**
@@ -213,7 +226,9 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
213
226
  blockHash: BlockHash,
214
227
  nullifier: Fr,
215
228
  ): Promise<NullifierMembershipWitness | undefined> {
216
- return this.aztecNode.getNullifierMembershipWitness(blockHash, nullifier);
229
+ return this.#queryWithBlockHashNotAfterAnchor(blockHash, () =>
230
+ this.aztecNode.getNullifierMembershipWitness(blockHash, nullifier),
231
+ );
217
232
  }
218
233
 
219
234
  /**
@@ -229,7 +244,9 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
229
244
  blockHash: BlockHash,
230
245
  nullifier: Fr,
231
246
  ): Promise<NullifierMembershipWitness | undefined> {
232
- return this.aztecNode.getLowNullifierMembershipWitness(blockHash, nullifier);
247
+ return this.#queryWithBlockHashNotAfterAnchor(blockHash, () =>
248
+ this.aztecNode.getLowNullifierMembershipWitness(blockHash, nullifier),
249
+ );
233
250
  }
234
251
 
235
252
  /**
@@ -239,7 +256,9 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
239
256
  * @returns - The witness
240
257
  */
241
258
  public getPublicDataWitness(blockHash: BlockHash, leafSlot: Fr): Promise<PublicDataWitness | undefined> {
242
- return this.aztecNode.getPublicDataWitness(blockHash, leafSlot);
259
+ return this.#queryWithBlockHashNotAfterAnchor(blockHash, () =>
260
+ this.aztecNode.getPublicDataWitness(blockHash, leafSlot),
261
+ );
243
262
  }
244
263
 
245
264
  /**
@@ -262,7 +281,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
262
281
  * @param account - The account address.
263
282
  * @returns The public keys and partial address, or `undefined` if the account is not registered.
264
283
  */
265
- public async tryGetPublicKeysAndPartialAddress(
284
+ public async getPublicKeysAndPartialAddress(
266
285
  account: AztecAddress,
267
286
  ): Promise<{ publicKeys: PublicKeys; partialAddress: PartialAddress } | undefined> {
268
287
  const completeAddress = await this.addressStore.getCompleteAddress(account);
@@ -368,7 +387,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
368
387
  * @param innerNullifier - The inner nullifier.
369
388
  * @returns A boolean indicating whether the nullifier exists in the tree or not.
370
389
  */
371
- public async checkNullifierExists(innerNullifier: Fr) {
390
+ public async doesNullifierExist(innerNullifier: Fr) {
372
391
  const [nullifier, anchorBlockHash] = await Promise.all([
373
392
  siloNullifier(this.contractAddress, innerNullifier!),
374
393
  this.anchorBlockHeader.hash(),
@@ -380,7 +399,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
380
399
  }
381
400
 
382
401
  /**
383
- * Fetches a message from the executionStore, given its key.
402
+ * Returns the membership witness of an un-nullified L1 to L2 message.
384
403
  * @param contractAddress - Address of a contract by which the message was emitted.
385
404
  * @param messageHash - Hash of the message.
386
405
  * @param secret - Secret used to compute a nullifier.
@@ -393,6 +412,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
393
412
  contractAddress,
394
413
  messageHash,
395
414
  secret,
415
+ await this.anchorBlockHeader.hash(),
396
416
  );
397
417
 
398
418
  return new MessageLoadOracleInputs(messageIndex, siblingPath);
@@ -405,29 +425,31 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
405
425
  * @param startStorageSlot - The starting storage slot.
406
426
  * @param numberOfElements - Number of elements to read from the starting storage slot.
407
427
  */
408
- public async storageRead(
428
+ public getFromPublicStorage(
409
429
  blockHash: BlockHash,
410
430
  contractAddress: AztecAddress,
411
431
  startStorageSlot: Fr,
412
432
  numberOfElements: number,
413
433
  ) {
414
- const slots = Array(numberOfElements)
415
- .fill(0)
416
- .map((_, i) => new Fr(startStorageSlot.value + BigInt(i)));
434
+ return this.#queryWithBlockHashNotAfterAnchor(blockHash, async () => {
435
+ const slots = Array(numberOfElements)
436
+ .fill(0)
437
+ .map((_, i) => new Fr(startStorageSlot.value + BigInt(i)));
417
438
 
418
- const values = await Promise.all(
419
- slots.map(storageSlot => this.aztecNode.getPublicStorageAt(blockHash, contractAddress, storageSlot)),
420
- );
439
+ const values = await Promise.all(
440
+ slots.map(storageSlot => this.aztecNode.getPublicStorageAt(blockHash, contractAddress, storageSlot)),
441
+ );
421
442
 
422
- this.logger.debug(
423
- `Oracle storage read: slots=[${slots.map(slot => slot.toString()).join(', ')}] address=${contractAddress.toString()} values=[${values.join(', ')}]`,
424
- );
443
+ this.logger.debug(
444
+ `Oracle storage read: slots=[${slots.map(slot => slot.toString()).join(', ')}] address=${contractAddress.toString()} values=[${values.join(', ')}]`,
445
+ );
425
446
 
426
- return values;
447
+ return values;
448
+ });
427
449
  }
428
450
 
429
451
  /**
430
- * Returns a per-contract logger whose output is prefixed with `contract_log::<name>(<addrAbbrev>)`.
452
+ * Returns a per-contract logger whose output is prefixed with `contract:<name>(<addrAbbrev>)`.
431
453
  */
432
454
  async #getContractLogger(): Promise<Logger> {
433
455
  if (!this.contractLogger) {
@@ -436,26 +458,47 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
436
458
  this.contractLogger = await createContractLogger(
437
459
  this.contractAddress,
438
460
  addr => this.contractStore.getDebugContractName(addr),
461
+ 'user',
439
462
  { instanceId: this.jobId },
440
463
  );
441
464
  }
442
465
  return this.contractLogger;
443
466
  }
444
467
 
468
+ /**
469
+ * Returns a per-contract logger whose output is prefixed with `aztecnr:<name>(<addrAbbrev>)`.
470
+ */
471
+ async #getAztecnrLogger(): Promise<Logger> {
472
+ if (!this.aztecnrLogger) {
473
+ // Purpose of instanceId is to distinguish logs from different instances of the same component. It makes sense
474
+ // to re-use jobId as instanceId here as executions of different PXE jobs are isolated.
475
+ this.aztecnrLogger = await createContractLogger(
476
+ this.contractAddress,
477
+ addr => this.contractStore.getDebugContractName(addr),
478
+ 'aztecnr',
479
+ { instanceId: this.jobId },
480
+ );
481
+ }
482
+ return this.aztecnrLogger;
483
+ }
484
+
445
485
  public async log(level: number, message: string, fields: Fr[]): Promise<void> {
446
486
  if (!LogLevels[level]) {
447
487
  throw new Error(`Invalid log level: ${level}`);
448
488
  }
449
- const logger = await this.#getContractLogger();
450
- logContractMessage(logger, LogLevels[level], message, fields);
489
+
490
+ const { kind, message: strippedMessage } = stripAztecnrLogPrefix(message);
491
+
492
+ const logger = kind == 'aztecnr' ? await this.#getAztecnrLogger() : await this.#getContractLogger();
493
+ logContractMessage(logger, LogLevels[level], strippedMessage, fields);
451
494
  }
452
495
 
453
- public async fetchTaggedLogs(pendingTaggedLogArrayBaseSlot: Fr) {
496
+ public async getPendingTaggedLogs(pendingTaggedLogArrayBaseSlot: Fr, scope: AztecAddress) {
454
497
  const logService = new LogService(
455
498
  this.aztecNode,
456
499
  this.anchorBlockHeader,
457
500
  this.keyStore,
458
- this.capsuleStore,
501
+ this.capsuleService,
459
502
  this.recipientTaggingStore,
460
503
  this.senderAddressBookStore,
461
504
  this.addressStore,
@@ -463,7 +506,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
463
506
  this.logger.getBindings(),
464
507
  );
465
508
 
466
- await logService.fetchTaggedLogs(this.contractAddress, pendingTaggedLogArrayBaseSlot, this.scopes);
509
+ await logService.fetchTaggedLogs(this.contractAddress, pendingTaggedLogArrayBaseSlot, scope);
467
510
  }
468
511
 
469
512
  /**
@@ -482,6 +525,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
482
525
  eventValidationRequestsArrayBaseSlot: Fr,
483
526
  maxNotePackedLen: number,
484
527
  maxEventSerializedLen: number,
528
+ scope: AztecAddress,
485
529
  ) {
486
530
  // TODO(#10727): allow other contracts to store notes
487
531
  if (!this.contractAddress.equals(contractAddress)) {
@@ -491,11 +535,21 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
491
535
  // We read all note and event validation requests and process them all concurrently. This makes the process much
492
536
  // faster as we don't need to wait for the network round-trip.
493
537
  const noteValidationRequests = (
494
- await this.capsuleStore.readCapsuleArray(contractAddress, noteValidationRequestsArrayBaseSlot, this.jobId)
538
+ await this.capsuleService.readCapsuleArray(
539
+ contractAddress,
540
+ noteValidationRequestsArrayBaseSlot,
541
+ this.jobId,
542
+ scope,
543
+ )
495
544
  ).map(fields => NoteValidationRequest.fromFields(fields, maxNotePackedLen));
496
545
 
497
546
  const eventValidationRequests = (
498
- await this.capsuleStore.readCapsuleArray(contractAddress, eventValidationRequestsArrayBaseSlot, this.jobId)
547
+ await this.capsuleService.readCapsuleArray(
548
+ contractAddress,
549
+ eventValidationRequestsArrayBaseSlot,
550
+ this.jobId,
551
+ scope,
552
+ )
499
553
  ).map(fields => EventValidationRequest.fromFields(fields, maxEventSerializedLen));
500
554
 
501
555
  const noteService = new NoteService(this.noteStore, this.aztecNode, this.anchorBlockHeader, this.jobId);
@@ -510,7 +564,7 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
510
564
  request.noteHash,
511
565
  request.nullifier,
512
566
  request.txHash,
513
- request.recipient,
567
+ scope,
514
568
  ),
515
569
  );
516
570
 
@@ -523,21 +577,34 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
523
577
  request.serializedEvent,
524
578
  request.eventCommitment,
525
579
  request.txHash,
526
- request.recipient,
580
+ scope,
527
581
  ),
528
582
  );
529
583
 
530
584
  await Promise.all([...noteStorePromises, ...eventStorePromises]);
531
585
 
532
586
  // Requests are cleared once we're done.
533
- await this.capsuleStore.setCapsuleArray(contractAddress, noteValidationRequestsArrayBaseSlot, [], this.jobId);
534
- await this.capsuleStore.setCapsuleArray(contractAddress, eventValidationRequestsArrayBaseSlot, [], this.jobId);
587
+ await this.capsuleService.setCapsuleArray(
588
+ contractAddress,
589
+ noteValidationRequestsArrayBaseSlot,
590
+ [],
591
+ this.jobId,
592
+ scope,
593
+ );
594
+ await this.capsuleService.setCapsuleArray(
595
+ contractAddress,
596
+ eventValidationRequestsArrayBaseSlot,
597
+ [],
598
+ this.jobId,
599
+ scope,
600
+ );
535
601
  }
536
602
 
537
- public async bulkRetrieveLogs(
603
+ public async getLogsByTag(
538
604
  contractAddress: AztecAddress,
539
605
  logRetrievalRequestsArrayBaseSlot: Fr,
540
606
  logRetrievalResponsesArrayBaseSlot: Fr,
607
+ scope: AztecAddress,
541
608
  ) {
542
609
  // TODO(#10727): allow other contracts to process partial notes
543
610
  if (!this.contractAddress.equals(contractAddress)) {
@@ -547,14 +614,14 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
547
614
  // We read all log retrieval requests and process them all concurrently. This makes the process much faster as we
548
615
  // don't need to wait for the network round-trip.
549
616
  const logRetrievalRequests = (
550
- await this.capsuleStore.readCapsuleArray(contractAddress, logRetrievalRequestsArrayBaseSlot, this.jobId)
617
+ await this.capsuleService.readCapsuleArray(contractAddress, logRetrievalRequestsArrayBaseSlot, this.jobId, scope)
551
618
  ).map(LogRetrievalRequest.fromFields);
552
619
 
553
620
  const logService = new LogService(
554
621
  this.aztecNode,
555
622
  this.anchorBlockHeader,
556
623
  this.keyStore,
557
- this.capsuleStore,
624
+ this.capsuleService,
558
625
  this.recipientTaggingStore,
559
626
  this.senderAddressBookStore,
560
627
  this.addressStore,
@@ -562,33 +629,47 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
562
629
  this.logger.getBindings(),
563
630
  );
564
631
 
565
- const maybeLogRetrievalResponses = await logService.bulkRetrieveLogs(logRetrievalRequests);
632
+ const maybeLogRetrievalResponses = await logService.fetchLogsByTag(contractAddress, logRetrievalRequests);
566
633
 
567
634
  // Requests are cleared once we're done.
568
- await this.capsuleStore.setCapsuleArray(contractAddress, logRetrievalRequestsArrayBaseSlot, [], this.jobId);
635
+ await this.capsuleService.setCapsuleArray(
636
+ contractAddress,
637
+ logRetrievalRequestsArrayBaseSlot,
638
+ [],
639
+ this.jobId,
640
+ scope,
641
+ );
569
642
 
570
643
  // The responses are stored as Option<LogRetrievalResponse> in a second CapsuleArray.
571
- await this.capsuleStore.setCapsuleArray(
644
+ await this.capsuleService.setCapsuleArray(
572
645
  contractAddress,
573
646
  logRetrievalResponsesArrayBaseSlot,
574
647
  maybeLogRetrievalResponses.map(LogRetrievalResponse.toSerializedOption),
575
648
  this.jobId,
649
+ scope,
576
650
  );
577
651
  }
578
652
 
579
- public async utilityResolveMessageContexts(
653
+ public async getMessageContextsByTxHash(
580
654
  contractAddress: AztecAddress,
581
655
  messageContextRequestsArrayBaseSlot: Fr,
582
656
  messageContextResponsesArrayBaseSlot: Fr,
657
+ scope: AztecAddress,
583
658
  ) {
584
659
  try {
585
660
  if (!this.contractAddress.equals(contractAddress)) {
586
661
  throw new Error(`Got a message context request from ${contractAddress}, expected ${this.contractAddress}`);
587
662
  }
588
- const requestCapsules = await this.capsuleStore.readCapsuleArray(
663
+
664
+ // TODO(@mverzilli): this is a prime example of where using a volatile array would make much more sense, we don't
665
+ // need scopes here, we just need a bit of shared memory to cross boundaries between Noir and TS.
666
+ // At the same time, we don't want to allow any global scope access other than where backwards compatibility
667
+ // forces us to. Hence we need the scope here to be artificial.
668
+ const requestCapsules = await this.capsuleService.readCapsuleArray(
589
669
  contractAddress,
590
670
  messageContextRequestsArrayBaseSlot,
591
671
  this.jobId,
672
+ scope,
592
673
  );
593
674
 
594
675
  const txHashes = requestCapsules.map((fields, i) => {
@@ -600,66 +681,73 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
600
681
  return fields[0];
601
682
  });
602
683
 
603
- const maybeMessageContexts = await this.messageContextService.resolveMessageContexts(
684
+ const maybeMessageContexts = await this.messageContextService.getMessageContextsByTxHash(
604
685
  txHashes,
605
686
  this.anchorBlockHeader.getBlockNumber(),
606
687
  );
607
688
 
608
689
  // Leave response in response capsule array.
609
- await this.capsuleStore.setCapsuleArray(
690
+ await this.capsuleService.setCapsuleArray(
610
691
  contractAddress,
611
692
  messageContextResponsesArrayBaseSlot,
612
- maybeMessageContexts.map(MessageTxContext.toSerializedOption),
693
+ maybeMessageContexts.map(MessageContext.toSerializedOption),
613
694
  this.jobId,
695
+ scope,
614
696
  );
615
697
  } finally {
616
- await this.capsuleStore.setCapsuleArray(contractAddress, messageContextRequestsArrayBaseSlot, [], this.jobId);
698
+ await this.capsuleService.setCapsuleArray(
699
+ contractAddress,
700
+ messageContextRequestsArrayBaseSlot,
701
+ [],
702
+ this.jobId,
703
+ scope,
704
+ );
617
705
  }
618
706
  }
619
707
 
620
- public storeCapsule(contractAddress: AztecAddress, slot: Fr, capsule: Fr[]): Promise<void> {
708
+ public setCapsule(contractAddress: AztecAddress, slot: Fr, capsule: Fr[], scope: AztecAddress): void {
621
709
  if (!contractAddress.equals(this.contractAddress)) {
622
710
  // TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
623
711
  throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
624
712
  }
625
- this.capsuleStore.storeCapsule(this.contractAddress, slot, capsule, this.jobId);
626
- return Promise.resolve();
713
+ this.capsuleService.setCapsule(contractAddress, slot, capsule, this.jobId, scope);
627
714
  }
628
715
 
629
- public async loadCapsule(contractAddress: AztecAddress, slot: Fr): Promise<Fr[] | null> {
716
+ public getCapsule(contractAddress: AztecAddress, slot: Fr, scope: AztecAddress): Promise<Fr[] | null> {
630
717
  if (!contractAddress.equals(this.contractAddress)) {
631
718
  // TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
632
719
  throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
633
720
  }
634
- return (
635
- // TODO(#12425): On the following line, the pertinent capsule gets overshadowed by the transient one. Tackle this.
636
- this.capsules.find(c => c.contractAddress.equals(contractAddress) && c.storageSlot.equals(slot))?.data ??
637
- (await this.capsuleStore.loadCapsule(this.contractAddress, slot, this.jobId))
638
- );
721
+ return this.capsuleService.getCapsule(contractAddress, slot, this.jobId, scope, this.capsules);
639
722
  }
640
723
 
641
- public deleteCapsule(contractAddress: AztecAddress, slot: Fr): Promise<void> {
724
+ public deleteCapsule(contractAddress: AztecAddress, slot: Fr, scope: AztecAddress): void {
642
725
  if (!contractAddress.equals(this.contractAddress)) {
643
726
  // TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
644
727
  throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
645
728
  }
646
- this.capsuleStore.deleteCapsule(this.contractAddress, slot, this.jobId);
647
- return Promise.resolve();
729
+ this.capsuleService.deleteCapsule(contractAddress, slot, this.jobId, scope);
648
730
  }
649
731
 
650
- public copyCapsule(contractAddress: AztecAddress, srcSlot: Fr, dstSlot: Fr, numEntries: number): Promise<void> {
732
+ public copyCapsule(
733
+ contractAddress: AztecAddress,
734
+ srcSlot: Fr,
735
+ dstSlot: Fr,
736
+ numEntries: number,
737
+ scope: AztecAddress,
738
+ ): Promise<void> {
651
739
  if (!contractAddress.equals(this.contractAddress)) {
652
740
  // TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
653
741
  throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
654
742
  }
655
- return this.capsuleStore.copyCapsule(this.contractAddress, srcSlot, dstSlot, numEntries, this.jobId);
743
+ return this.capsuleService.copyCapsule(contractAddress, srcSlot, dstSlot, numEntries, this.jobId, scope);
656
744
  }
657
745
 
658
746
  /**
659
747
  * Clears cached sync state for a contract for a set of scopes, forcing re-sync on the next query so that newly
660
748
  * stored notes or events are discovered.
661
749
  */
662
- public invalidateContractSyncCache(contractAddress: AztecAddress, scopes: AztecAddress[]): void {
750
+ public setContractSyncCacheInvalid(contractAddress: AztecAddress, scopes: AztecAddress[]): void {
663
751
  if (!contractAddress.equals(this.contractAddress)) {
664
752
  throw new Error(`Contract ${this.contractAddress} cannot invalidate sync cache of ${contractAddress}`);
665
753
  }
@@ -667,25 +755,30 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
667
755
  }
668
756
 
669
757
  // TODO(#11849): consider replacing this oracle with a pure Noir implementation of aes decryption.
670
- public aes128Decrypt(ciphertext: Buffer, iv: Buffer, symKey: Buffer): Promise<Buffer> {
758
+ public decryptAes128(ciphertext: Buffer, iv: Buffer, symKey: Buffer): Promise<Buffer> {
671
759
  const aes128 = new Aes128();
672
760
  return aes128.decryptBufferCBC(ciphertext, iv, symKey);
673
761
  }
674
762
 
675
763
  /**
676
- * Retrieves the shared secret for a given address and ephemeral public key.
764
+ * Retrieves the app-siloed shared secret for a given address and ephemeral public key.
677
765
  * @param address - The address to get the secret for.
678
766
  * @param ephPk - The ephemeral public key to get the secret for.
679
- * @returns The secret for the given address.
767
+ * @param contractAddress - The contract address for app-siloing (validated against execution context).
768
+ * @returns The app-siloed shared secret as a Field.
680
769
  */
681
- public async getSharedSecret(address: AztecAddress, ephPk: Point): Promise<Point> {
682
- // TODO(#12656): return an app-siloed secret
770
+ public async getSharedSecret(address: AztecAddress, ephPk: Point, contractAddress: AztecAddress): Promise<Fr> {
771
+ if (!contractAddress.equals(this.contractAddress)) {
772
+ throw new Error(
773
+ `getSharedSecret called with contract address ${contractAddress}, expected ${this.contractAddress}`,
774
+ );
775
+ }
683
776
  const recipientCompleteAddress = await this.getCompleteAddressOrFail(address);
684
777
  const ivskM = await this.keyStore.getMasterSecretKey(
685
778
  recipientCompleteAddress.publicKeys.masterIncomingViewingPublicKey,
686
779
  );
687
780
  const addressSecret = await computeAddressSecret(await recipientCompleteAddress.getPreaddress(), ivskM);
688
- return deriveEcdhSharedSecret(addressSecret, ephPk);
781
+ return deriveAppSiloedSharedSecret(addressSecret, ephPk, this.contractAddress);
689
782
  }
690
783
 
691
784
  public emitOffchainEffect(data: Fr[]): Promise<void> {
@@ -697,4 +790,24 @@ export class UtilityExecutionOracle implements IMiscOracle, IUtilityExecutionOra
697
790
  public getOffchainEffects(): OffchainEffect[] {
698
791
  return this.offchainEffects;
699
792
  }
793
+
794
+ /** Runs a query concurrently with a validation that the block hash is not ahead of the anchor block. */
795
+ async #queryWithBlockHashNotAfterAnchor<T>(blockHash: BlockHash, query: () => Promise<T>): Promise<T> {
796
+ const [response] = await Promise.all([
797
+ query(),
798
+ (async () => {
799
+ const header = await this.aztecNode.getBlockHeader(blockHash);
800
+ if (!header) {
801
+ throw new Error(`Could not find block header for block hash ${blockHash}`);
802
+ }
803
+
804
+ if (header.getBlockNumber() > this.anchorBlockHeader.getBlockNumber()) {
805
+ throw new Error(
806
+ `Made a node query with a reference block hash ${blockHash} with block number ${header.getBlockNumber()}, which is ahead of the anchor block number ${this.anchorBlockHeader.getBlockNumber()} (from anchor block hash ${await this.anchorBlockHeader.hash()}).`,
807
+ );
808
+ }
809
+ })(),
810
+ ]);
811
+ return response;
812
+ }
700
813
  }