@aztec/txe 0.0.1-commit.993d240 → 0.0.1-commit.9a89641

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 (144) hide show
  1. package/dest/AuthRegistry-QVGDDH5X.js +3 -0
  2. package/dest/AuthRegistry-QVGDDH5X.js.map +7 -0
  3. package/dest/ContractClassRegistry-PVNCKGG7.js +3 -0
  4. package/dest/ContractClassRegistry-PVNCKGG7.js.map +7 -0
  5. package/dest/ContractInstanceRegistry-WLOZKTR6.js +3 -0
  6. package/dest/ContractInstanceRegistry-WLOZKTR6.js.map +7 -0
  7. package/dest/FeeJuice-MAQJU53K.js +3 -0
  8. package/dest/FeeJuice-MAQJU53K.js.map +7 -0
  9. package/dest/HandshakeRegistry-GY5CPEPS.js +3 -0
  10. package/dest/HandshakeRegistry-GY5CPEPS.js.map +7 -0
  11. package/dest/MultiCallEntrypoint-QG5H33ZZ.js +3 -0
  12. package/dest/MultiCallEntrypoint-QG5H33ZZ.js.map +7 -0
  13. package/dest/SchnorrAccount-ADD65DYA.js +3 -0
  14. package/dest/SchnorrAccount-ADD65DYA.js.map +7 -0
  15. package/dest/SchnorrInitializerlessAccount-TWGKRUSY.js +3 -0
  16. package/dest/SchnorrInitializerlessAccount-TWGKRUSY.js.map +7 -0
  17. package/dest/bin/check_txe_oracle_version.js +9 -19
  18. package/dest/bin/index.js +1 -1
  19. package/dest/bin/oracle_test_server.d.ts +3 -0
  20. package/dest/bin/oracle_test_server.d.ts.map +1 -0
  21. package/dest/bin/oracle_test_server.js +41 -0
  22. package/dest/chunk-32UHX7YY.js +3 -0
  23. package/dest/{chunk-DF6RMOC6.js → chunk-RVEPNDEP.js} +2 -2
  24. package/dest/{chunk-DF6RMOC6.js.map → chunk-RVEPNDEP.js.map} +3 -3
  25. package/dest/chunk-XWIMXLKD.js +258 -0
  26. package/dest/chunk-XWIMXLKD.js.map +7 -0
  27. package/dest/constants.d.ts +3 -1
  28. package/dest/constants.d.ts.map +1 -1
  29. package/dest/constants.js +5 -2
  30. package/dest/dispatcher_pool.d.ts +2 -2
  31. package/dest/dispatcher_pool.d.ts.map +1 -1
  32. package/dest/dispatcher_pool.js +5 -3
  33. package/dest/index.d.ts +6 -143
  34. package/dest/index.d.ts.map +1 -1
  35. package/dest/index.js +12 -169
  36. package/dest/metafile.json +10267 -9581
  37. package/dest/oracle/interfaces.d.ts +38 -11
  38. package/dest/oracle/interfaces.d.ts.map +1 -1
  39. package/dest/oracle/tagging_secret_strategy.d.ts +12 -0
  40. package/dest/oracle/tagging_secret_strategy.d.ts.map +1 -0
  41. package/dest/oracle/tagging_secret_strategy.js +12 -0
  42. package/dest/oracle/test-resolver/default_fixtures.d.ts +16 -0
  43. package/dest/oracle/test-resolver/default_fixtures.d.ts.map +1 -0
  44. package/dest/oracle/test-resolver/default_fixtures.js +200 -0
  45. package/dest/oracle/test-resolver/index.d.ts +9 -0
  46. package/dest/oracle/test-resolver/index.d.ts.map +1 -0
  47. package/dest/oracle/test-resolver/index.js +32 -0
  48. package/dest/oracle/test-resolver/resolver.d.ts +48 -0
  49. package/dest/oracle/test-resolver/resolver.d.ts.map +1 -0
  50. package/dest/oracle/test-resolver/resolver.js +181 -0
  51. package/dest/oracle/txe_oracle_public_context.d.ts +25 -6
  52. package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
  53. package/dest/oracle/txe_oracle_public_context.js +34 -1
  54. package/dest/oracle/txe_oracle_registry.d.ts +172 -0
  55. package/dest/oracle/txe_oracle_registry.d.ts.map +1 -0
  56. package/dest/oracle/txe_oracle_registry.js +767 -0
  57. package/dest/oracle/txe_oracle_top_level_context.d.ts +39 -14
  58. package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
  59. package/dest/oracle/txe_oracle_top_level_context.js +489 -289
  60. package/dest/{txe_oracle_version.d.ts → oracle/txe_oracle_version.d.ts} +5 -5
  61. package/dest/oracle/txe_oracle_version.d.ts.map +1 -0
  62. package/dest/{txe_oracle_version.js → oracle/txe_oracle_version.js} +4 -4
  63. package/dest/rpc_translator.d.ts +116 -284
  64. package/dest/rpc_translator.d.ts.map +1 -1
  65. package/dest/rpc_translator.js +809 -860
  66. package/dest/server.bundle.js +1 -1
  67. package/dest/state_machine/archiver.d.ts +3 -2
  68. package/dest/state_machine/archiver.d.ts.map +1 -1
  69. package/dest/state_machine/archiver.js +9 -3
  70. package/dest/state_machine/dummy_p2p_client.d.ts +5 -2
  71. package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
  72. package/dest/state_machine/dummy_p2p_client.js +9 -0
  73. package/dest/state_machine/global_variable_builder.d.ts +3 -4
  74. package/dest/state_machine/global_variable_builder.d.ts.map +1 -1
  75. package/dest/state_machine/global_variable_builder.js +0 -3
  76. package/dest/state_machine/index.d.ts +8 -6
  77. package/dest/state_machine/index.d.ts.map +1 -1
  78. package/dest/state_machine/index.js +41 -19
  79. package/dest/state_machine/mock_epoch_cache.d.ts +2 -3
  80. package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
  81. package/dest/state_machine/mock_epoch_cache.js +3 -6
  82. package/dest/state_machine/synchronizer.d.ts +10 -2
  83. package/dest/state_machine/synchronizer.d.ts.map +1 -1
  84. package/dest/state_machine/synchronizer.js +18 -5
  85. package/dest/txe_session.d.ts +43 -28
  86. package/dest/txe_session.d.ts.map +1 -1
  87. package/dest/txe_session.js +183 -47
  88. package/dest/utils/block_creation.d.ts +2 -2
  89. package/dest/utils/block_creation.d.ts.map +1 -1
  90. package/dest/utils/block_creation.js +2 -2
  91. package/dest/utils/encoding.d.ts +8 -5
  92. package/dest/utils/encoding.d.ts.map +1 -1
  93. package/dest/utils/tx_effect_creation.d.ts +1 -1
  94. package/dest/utils/tx_effect_creation.d.ts.map +1 -1
  95. package/dest/utils/tx_effect_creation.js +0 -1
  96. package/dest/utils/txe_artifact_resolver.d.ts +37 -0
  97. package/dest/utils/txe_artifact_resolver.d.ts.map +1 -0
  98. package/dest/utils/txe_artifact_resolver.js +161 -0
  99. package/dest/utils/txe_public_contract_data_source.d.ts +1 -1
  100. package/dest/utils/txe_public_contract_data_source.d.ts.map +1 -1
  101. package/dest/utils/txe_public_contract_data_source.js +7 -4
  102. package/dest/worker.bundle.js +1 -1
  103. package/package.json +18 -17
  104. package/src/bin/check_txe_oracle_version.ts +11 -17
  105. package/src/bin/oracle_test_server.ts +51 -0
  106. package/src/constants.ts +6 -2
  107. package/src/dispatcher_pool.ts +4 -3
  108. package/src/index.ts +21 -198
  109. package/src/oracle/interfaces.ts +35 -9
  110. package/src/oracle/tagging_secret_strategy.ts +25 -0
  111. package/src/oracle/test-resolver/default_fixtures.ts +271 -0
  112. package/src/oracle/test-resolver/index.ts +44 -0
  113. package/src/oracle/test-resolver/resolver.ts +245 -0
  114. package/src/oracle/txe_oracle_public_context.ts +36 -4
  115. package/src/oracle/txe_oracle_registry.ts +556 -0
  116. package/src/oracle/txe_oracle_top_level_context.ts +249 -66
  117. package/src/{txe_oracle_version.ts → oracle/txe_oracle_version.ts} +4 -4
  118. package/src/rpc_translator.ts +850 -1065
  119. package/src/state_machine/archiver.ts +9 -3
  120. package/src/state_machine/dummy_p2p_client.ts +13 -0
  121. package/src/state_machine/global_variable_builder.ts +2 -16
  122. package/src/state_machine/index.ts +50 -34
  123. package/src/state_machine/mock_epoch_cache.ts +4 -8
  124. package/src/state_machine/synchronizer.ts +26 -5
  125. package/src/txe_session.ts +325 -56
  126. package/src/utils/block_creation.ts +2 -1
  127. package/src/utils/tx_effect_creation.ts +0 -2
  128. package/src/utils/txe_artifact_resolver.ts +217 -0
  129. package/src/utils/txe_public_contract_data_source.ts +6 -4
  130. package/dest/ContractClassRegistry-KKNT527R.js +0 -3
  131. package/dest/ContractClassRegistry-KKNT527R.js.map +0 -7
  132. package/dest/ContractInstanceRegistry-GSKBNL3Q.js +0 -3
  133. package/dest/ContractInstanceRegistry-GSKBNL3Q.js.map +0 -7
  134. package/dest/FeeJuice-GUJ5O6GB.js +0 -3
  135. package/dest/FeeJuice-GUJ5O6GB.js.map +0 -7
  136. package/dest/MultiCallEntrypoint-ZQPCKVKL.js +0 -3
  137. package/dest/MultiCallEntrypoint-ZQPCKVKL.js.map +0 -7
  138. package/dest/SchnorrAccount-QIXE5DXA.js +0 -3
  139. package/dest/SchnorrAccount-QIXE5DXA.js.map +0 -7
  140. package/dest/chunk-BJVAAXNA.js +0 -3
  141. package/dest/chunk-PPJTNNUG.js +0 -265
  142. package/dest/chunk-PPJTNNUG.js.map +0 -7
  143. package/dest/txe_oracle_version.d.ts.map +0 -1
  144. /package/dest/{chunk-BJVAAXNA.js.map → chunk-32UHX7YY.js.map} +0 -0
@@ -7,25 +7,33 @@ import { openEphemeralStore } from '@aztec/kv-store/lmdb-v2';
7
7
  import {
8
8
  AddressStore,
9
9
  AnchorBlockStore,
10
+ AnchoredContractData,
10
11
  CapsuleService,
11
12
  CapsuleStore,
12
13
  ContractStore,
14
+ FactService,
15
+ FactStore,
13
16
  JobCoordinator,
14
17
  NoteService,
15
18
  NoteStore,
16
19
  PrivateEventStore,
17
20
  RecipientTaggingStore,
18
- SenderAddressBookStore,
19
21
  SenderTaggingStore,
22
+ TaggingSecretSourcesStore,
23
+ composeHooks,
20
24
  } from '@aztec/pxe/server';
21
25
  import {
22
26
  ExecutionNoteCache,
23
27
  ExecutionTaggingIndexCache,
24
28
  HashedValuesCache,
29
+ type IMiscOracle,
25
30
  type IPrivateExecutionOracle,
26
31
  type IUtilityExecutionOracle,
27
- Oracle,
32
+ LEGACY_ORACLE_REGISTRY,
33
+ Option,
34
+ TransientArrayService,
28
35
  UtilityExecutionOracle,
36
+ buildACIRCallback,
29
37
  } from '@aztec/pxe/simulator';
30
38
  import {
31
39
  ExecutionError,
@@ -36,7 +44,7 @@ import {
36
44
  toACVMWitness,
37
45
  } from '@aztec/simulator/client';
38
46
  import { STANDARD_AUTH_REGISTRY_ADDRESS } from '@aztec/standard-contracts/auth-registry/constants';
39
- import { FunctionCall, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
47
+ import { EventSelector, FunctionCall, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
40
48
  import type { AuthWitness } from '@aztec/stdlib/auth-witness';
41
49
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
42
50
  import type { GasSettings } from '@aztec/stdlib/gas';
@@ -49,17 +57,23 @@ import { z } from 'zod';
49
57
 
50
58
  import { DEFAULT_ADDRESS, MAX_OFFCHAIN_EFFECTS_PER_TXE_QUERY, MAX_OFFCHAIN_EFFECT_LEN } from './constants.js';
51
59
  import type { IAvmExecutionOracle, ITxeExecutionOracle } from './oracle/interfaces.js';
60
+ import {
61
+ type TXETaggingSecretStrategies,
62
+ makeResolveTaggingSecretStrategyHook,
63
+ } from './oracle/tagging_secret_strategy.js';
52
64
  import { TXEOraclePublicContext } from './oracle/txe_oracle_public_context.js';
53
- import { TXEOracleTopLevelContext } from './oracle/txe_oracle_top_level_context.js';
65
+ import { callTxeLegacyHandler } from './oracle/txe_oracle_registry.js';
66
+ import { TXEOracleTopLevelContext, authorizeAllUtilityCallsHook } from './oracle/txe_oracle_top_level_context.js';
67
+ import { TXE_ORACLE_VERSION_MAJOR, TXE_ORACLE_VERSION_MINOR } from './oracle/txe_oracle_version.js';
54
68
  import { TXEPrivateExecutionOracle } from './oracle/txe_private_execution_oracle.js';
55
- import { RPCTranslator } from './rpc_translator.js';
69
+ import { RPCTranslator, UnavailableOracleError } from './rpc_translator.js';
56
70
  import { TXEArchiver } from './state_machine/archiver.js';
57
71
  import { TXEStateMachine } from './state_machine/index.js';
58
- import { TXE_ORACLE_VERSION_MAJOR, TXE_ORACLE_VERSION_MINOR } from './txe_oracle_version.js';
59
72
  import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlock } from './utils/block_creation.js';
60
73
  import type { ForeignCallArgs, ForeignCallResult } from './utils/encoding.js';
61
74
  import { makeTxEffect } from './utils/tx_effect_creation.js';
62
75
  import { TXEAccountStore } from './utils/txe_account_store.js';
76
+ import type { TXEArtifactResolver } from './utils/txe_artifact_resolver.js';
63
77
 
64
78
  /**
65
79
  * A TXE Session can be in one of four states, which change as the test progresses and different oracles are called.
@@ -116,22 +130,53 @@ export interface TXESessionStateHandler {
116
130
  setTxeOracleVersion(major: number, minor: number): void;
117
131
 
118
132
  enterTopLevelState(): Promise<void>;
119
- enterPublicState(contractAddress?: AztecAddress): Promise<void>;
133
+ enterPublicState(contractAddress: Option<AztecAddress>): Promise<void>;
120
134
  enterPrivateState(
121
- contractAddress: AztecAddress | undefined,
122
- anchorBlockNumber: BlockNumber | undefined,
135
+ contractAddress: Option<AztecAddress>,
136
+ anchorBlockNumber: Option<BlockNumber>,
123
137
  gasSettings: GasSettings,
124
138
  ): Promise<PrivateContextInputs>;
125
- enterUtilityState(contractAddress?: AztecAddress): Promise<void>;
139
+ enterUtilityState(contractAddress: Option<AztecAddress>): Promise<void>;
140
+
141
+ /**
142
+ * Executes a top-level private call: runs the private function, drains its offchain effects into the session buffer,
143
+ * commits the job, and (for non-static calls) tags the result with the mined tx hash.
144
+ */
145
+ executePrivateCall(
146
+ from: Option<AztecAddress>,
147
+ targetContractAddress: AztecAddress,
148
+ functionSelector: FunctionSelector,
149
+ args: Fr[],
150
+ argsHash: Fr,
151
+ isStaticCall: boolean,
152
+ additionalScopes: AztecAddress[],
153
+ authorizedUtilityCallTargets: AztecAddress[],
154
+ gasSettings: GasSettings,
155
+ ): Promise<Fr[]>;
126
156
 
127
- // TODO(F-335): Exposing the job info is abstraction breakage - drop the following 2 functions.
128
- cycleJob(): Promise<string>;
129
- getCurrentJob(): string;
157
+ /** Executes a top-level utility function and commits the job. */
158
+ executeUtilityFunction(
159
+ from: Option<AztecAddress>,
160
+ targetContractAddress: AztecAddress,
161
+ functionSelector: FunctionSelector,
162
+ args: Fr[],
163
+ authorizedUtilityCallTargets: AztecAddress[],
164
+ ): Promise<Fr[]>;
130
165
 
131
166
  /**
132
- * Runs an executor-style top-level call (private/public call, utility execution) with last-call tracking.
167
+ * Executes a top-level public call, commits the job, and (for non-static calls) tags the result with the mined tx
168
+ * hash.
133
169
  */
134
- withTopLevelCallTracking<T>(work: () => Promise<{ result: T; txHash?: Fr }>): Promise<T>;
170
+ executePublicCall(
171
+ from: Option<AztecAddress>,
172
+ targetContractAddress: AztecAddress,
173
+ calldata: Fr[],
174
+ isStaticCall: boolean,
175
+ gasSettings: GasSettings,
176
+ ): Promise<Fr[]>;
177
+
178
+ /** Syncs the target contract and returns the private events it emitted matching the given selector and scope. */
179
+ getPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress): Promise<Fr[][]>;
135
180
 
136
181
  /**
137
182
  * Captures a raw offchain effect payload for consumption from test environment. Called by the `emit_offchain_effect`
@@ -195,6 +240,8 @@ function emptyLastCallState(): LastCallState {
195
240
  export class TXESession implements TXESessionStateHandler {
196
241
  private state: SessionState = { name: 'TOP_LEVEL' };
197
242
  private authwits: Map<string, AuthWitness> = new Map();
243
+ private taggingSecretStrategies: TXETaggingSecretStrategies = new Map();
244
+ private authorizeAllUtilityCallTargets = false;
198
245
  private lastCallInfo: LastCallState = emptyLastCallState();
199
246
  private txeOracleVersion: { major: number; minor: number } | undefined;
200
247
 
@@ -205,6 +252,7 @@ export class TXESession implements TXESessionStateHandler {
205
252
  private sessionStore: AztecAsyncKVStore,
206
253
  private stateMachine: TXEStateMachine,
207
254
  private oracleHandler:
255
+ | IMiscOracle
208
256
  | IUtilityExecutionOracle
209
257
  | IPrivateExecutionOracle
210
258
  | IAvmExecutionOracle
@@ -216,25 +264,37 @@ export class TXESession implements TXESessionStateHandler {
216
264
  private accountStore: TXEAccountStore,
217
265
  private senderTaggingStore: SenderTaggingStore,
218
266
  private recipientTaggingStore: RecipientTaggingStore,
219
- private senderAddressBookStore: SenderAddressBookStore,
267
+ private taggingSecretSourcesStore: TaggingSecretSourcesStore,
220
268
  private capsuleStore: CapsuleStore,
269
+ private factStore: FactStore,
221
270
  private privateEventStore: PrivateEventStore,
222
271
  private jobCoordinator: JobCoordinator,
223
272
  private currentJobId: string,
224
273
  private chainId: Fr,
225
274
  private version: Fr,
226
275
  private nextBlockTimestamp: bigint,
276
+ private readonly artifactResolver: TXEArtifactResolver,
277
+ private readonly rootPath: string,
278
+ private readonly packageName: string,
227
279
  ) {}
228
280
 
229
281
  /**
230
- * Closes the per-session `txe-session` LMDB and the `NativeWorldStateService` .
231
- * Called via IPC when the dispatcher detects the end of a test. Idempotent.
282
+ * Tears down the per-session AVM simulator (process pool + CDB server), the `NativeWorldStateService`,
283
+ * and the `txe-session` LMDB. Called via IPC when the dispatcher detects the end of a test. Idempotent.
232
284
  */
233
285
  async dispose(): Promise<void> {
234
286
  if (this.disposed) {
235
287
  return;
236
288
  }
237
289
  this.disposed = true;
290
+ // Dispose the AVM pool before the world state: it kills the bb-avm-sim processes so they release their
291
+ // connection to the WSDB server, letting it shut down cleanly. Skipping this leaks a bb-avm-sim process
292
+ // (and keeps its WSDB alive) per session.
293
+ try {
294
+ await this.stateMachine.synchronizer.closeIpc();
295
+ } catch (err) {
296
+ this.logger.warn(`Error closing AVM simulator during session dispose`, err);
297
+ }
238
298
  try {
239
299
  await this.stateMachine.synchronizer.nativeWorldStateService.close();
240
300
  } catch (err) {
@@ -247,7 +307,12 @@ export class TXESession implements TXESessionStateHandler {
247
307
  }
248
308
  }
249
309
 
250
- static async init(contractStore: ContractStore) {
310
+ static async init(
311
+ contractStore: ContractStore,
312
+ artifactResolver: TXEArtifactResolver,
313
+ rootPath: string,
314
+ packageName: string,
315
+ ) {
251
316
  // Size LMDB's reader slots to the libuv pool (capped to 2 in bin/index.ts via
252
317
  // HARDWARE_CONCURRENCY): each native LMDB read needs a libuv worker thread to run, so any
253
318
  // slot beyond the pool size would sit idle while still consuming a semaphore + reader-table
@@ -259,14 +324,16 @@ export class TXESession implements TXESessionStateHandler {
259
324
  const noteStore = new NoteStore(store);
260
325
  const senderTaggingStore = new SenderTaggingStore(store);
261
326
  const recipientTaggingStore = new RecipientTaggingStore(store);
262
- const senderAddressBookStore = new SenderAddressBookStore(store);
327
+ const taggingSecretSourcesStore = new TaggingSecretSourcesStore(store);
263
328
  const capsuleStore = new CapsuleStore(store);
329
+ const factStore = new FactStore(store);
264
330
  const keyStore = new KeyStore(store);
265
331
  const accountStore = new TXEAccountStore(store);
266
332
 
267
333
  const jobCoordinator = new JobCoordinator(store);
268
334
  jobCoordinator.registerStores([
269
335
  capsuleStore,
336
+ factStore,
270
337
  senderTaggingStore,
271
338
  recipientTaggingStore,
272
339
  privateEventStore,
@@ -294,13 +361,19 @@ export class TXESession implements TXESessionStateHandler {
294
361
  accountStore,
295
362
  senderTaggingStore,
296
363
  recipientTaggingStore,
297
- senderAddressBookStore,
364
+ taggingSecretSourcesStore,
298
365
  capsuleStore,
366
+ factStore,
299
367
  privateEventStore,
300
368
  nextBlockTimestamp,
301
369
  version,
302
370
  chainId,
303
371
  new Map(),
372
+ new Map(),
373
+ false, // authorizeAllUtilityCallTargets
374
+ artifactResolver,
375
+ rootPath,
376
+ packageName,
304
377
  );
305
378
 
306
379
  await topLevelOracleHandler.mineDeploymentNullifiers([STANDARD_AUTH_REGISTRY_ADDRESS]);
@@ -317,14 +390,18 @@ export class TXESession implements TXESessionStateHandler {
317
390
  accountStore,
318
391
  senderTaggingStore,
319
392
  recipientTaggingStore,
320
- senderAddressBookStore,
393
+ taggingSecretSourcesStore,
321
394
  capsuleStore,
395
+ factStore,
322
396
  privateEventStore,
323
397
  jobCoordinator,
324
398
  initialJobId,
325
399
  version,
326
400
  chainId,
327
401
  nextBlockTimestamp,
402
+ artifactResolver,
403
+ rootPath,
404
+ packageName,
328
405
  );
329
406
  }
330
407
 
@@ -336,6 +413,18 @@ export class TXESession implements TXESessionStateHandler {
336
413
  */
337
414
  processFunction(functionName: TXEOracleFunctionName, inputs: ForeignCallArgs): Promise<ForeignCallResult> {
338
415
  try {
416
+ // Oracles retired into the PXE legacy registry have no translator method; dispatch them through the same
417
+ // buildACIRCallback legacy path that contract execution uses, keeping TXE's two oracle paths in sync.
418
+ // Use an own-property check: `in` would match inherited `Object.prototype` keys (e.g. `constructor`), routing
419
+ // them into the legacy path instead of letting them fall through to the unknown-oracle error.
420
+ if (Object.hasOwn(LEGACY_ORACLE_REGISTRY, functionName)) {
421
+ return callTxeLegacyHandler(
422
+ functionName,
423
+ inputs,
424
+ this.oracleHandler as Parameters<typeof buildACIRCallback>[0],
425
+ );
426
+ }
427
+
339
428
  const translator = new RPCTranslator(this, this.oracleHandler) as any;
340
429
  // We perform a runtime validation to check that the function name corresponds to a real oracle handler.
341
430
  const validatedFunctionName = z
@@ -380,12 +469,8 @@ export class TXESession implements TXESessionStateHandler {
380
469
  }
381
470
  }
382
471
 
383
- getCurrentJob(): string {
384
- return this.currentJobId;
385
- }
386
-
387
472
  /** Commits the current job and begins a new one. Returns the new job ID. */
388
- async cycleJob(): Promise<string> {
473
+ private async cycleJob(): Promise<string> {
389
474
  await this.jobCoordinator.commitJob(this.currentJobId);
390
475
  this.currentJobId = this.jobCoordinator.beginJob();
391
476
  return this.currentJobId;
@@ -415,7 +500,7 @@ export class TXESession implements TXESessionStateHandler {
415
500
  this.lastCallInfo.anchorBlockTimestamp = anchorBlockTimestamp;
416
501
  }
417
502
 
418
- async withTopLevelCallTracking<T>(work: () => Promise<{ result: T; txHash?: Fr }>): Promise<T> {
503
+ private async withTopLevelCallTracking<T>(work: () => Promise<{ result: T; txHash?: Fr }>): Promise<T> {
419
504
  this.resetLastCall();
420
505
  // Capture the anchor *before* `work` runs: private/public executor calls mine a new block as a
421
506
  // side effect, and that block's timestamp should not be attributed to this call's anchor.
@@ -445,6 +530,119 @@ export class TXESession implements TXESessionStateHandler {
445
530
  return { txHash, anchorBlockTimestamp };
446
531
  }
447
532
 
533
+ async executePrivateCall(
534
+ from: Option<AztecAddress>,
535
+ targetContractAddress: AztecAddress,
536
+ functionSelector: FunctionSelector,
537
+ args: Fr[],
538
+ argsHash: Fr,
539
+ isStaticCall: boolean,
540
+ additionalScopes: AztecAddress[],
541
+ authorizedUtilityCallTargets: AztecAddress[],
542
+ gasSettings: GasSettings,
543
+ ): Promise<Fr[]> {
544
+ const handler = this.handlerAsTxe();
545
+ return await this.withTopLevelCallTracking(async () => {
546
+ const { returnValues, offchainEffects } = await handler.privateCallNewFlow(
547
+ from?.value,
548
+ targetContractAddress,
549
+ functionSelector,
550
+ args,
551
+ argsHash,
552
+ isStaticCall,
553
+ additionalScopes,
554
+ this.currentJobId,
555
+ authorizedUtilityCallTargets,
556
+ gasSettings,
557
+ );
558
+
559
+ // Private execution collects offchain effects inside PXE's PrivateExecutionOracle rather than round-tripping
560
+ // them through `aztec_utl_emitOffchainEffect`, so the session buffer is empty at this point. Drain the effects
561
+ // from the execution tree into the session buffer so the next `env.offchain_messages()` call in the test sees
562
+ // them.
563
+ for (const data of offchainEffects) {
564
+ this.recordOffchainEffect(data);
565
+ }
566
+
567
+ await this.cycleJob();
568
+
569
+ if (isStaticCall) {
570
+ // Static calls revert their checkpoint and mine no block, so there is no tx hash to tag offchain effects
571
+ // with. Querying `getLastTxEffects()` here would return an unrelated predecessor tx.
572
+ return { result: returnValues };
573
+ }
574
+ const { txHash } = await handler.getLastTxEffects();
575
+ return { result: returnValues, txHash: txHash.hash };
576
+ });
577
+ }
578
+
579
+ async executeUtilityFunction(
580
+ from: Option<AztecAddress>,
581
+ targetContractAddress: AztecAddress,
582
+ functionSelector: FunctionSelector,
583
+ args: Fr[],
584
+ authorizedUtilityCallTargets: AztecAddress[],
585
+ ): Promise<Fr[]> {
586
+ const handler = this.handlerAsTxe();
587
+ return await this.withTopLevelCallTracking(async () => {
588
+ const returnValues = await handler.executeUtilityFunction(
589
+ from?.value,
590
+ targetContractAddress,
591
+ functionSelector,
592
+ args,
593
+ this.currentJobId,
594
+ authorizedUtilityCallTargets,
595
+ );
596
+
597
+ await this.cycleJob();
598
+
599
+ return { result: returnValues };
600
+ });
601
+ }
602
+
603
+ async executePublicCall(
604
+ from: Option<AztecAddress>,
605
+ targetContractAddress: AztecAddress,
606
+ calldata: Fr[],
607
+ isStaticCall: boolean,
608
+ gasSettings: GasSettings,
609
+ ): Promise<Fr[]> {
610
+ const handler = this.handlerAsTxe();
611
+ return await this.withTopLevelCallTracking(async () => {
612
+ const returnValues = await handler.publicCallNewFlow(
613
+ from?.value,
614
+ targetContractAddress,
615
+ calldata,
616
+ isStaticCall,
617
+ gasSettings,
618
+ );
619
+
620
+ await this.cycleJob();
621
+
622
+ if (isStaticCall) {
623
+ // See the equivalent branch in `executePrivateCall`.
624
+ return { result: returnValues };
625
+ }
626
+ const { txHash } = await handler.getLastTxEffects();
627
+ return { result: returnValues, txHash: txHash.hash };
628
+ });
629
+ }
630
+
631
+ async getPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress): Promise<Fr[][]> {
632
+ const handler = this.handlerAsTxe();
633
+ await handler.syncContractNonOracleMethod(contractAddress, scope, this.currentJobId);
634
+ // Cycle the job to commit the stores after the contract sync.
635
+ await this.cycleJob();
636
+ return handler.getPrivateEvents(selector, contractAddress, scope);
637
+ }
638
+
639
+ private handlerAsTxe(): ITxeExecutionOracle {
640
+ if (!('isTxe' in this.oracleHandler)) {
641
+ throw new UnavailableOracleError('Txe');
642
+ }
643
+ return this.oracleHandler;
644
+ }
645
+
448
646
  setTxeOracleVersion(major: number, minor: number): void {
449
647
  if (major !== TXE_ORACLE_VERSION_MAJOR) {
450
648
  const hint =
@@ -494,13 +692,19 @@ export class TXESession implements TXESessionStateHandler {
494
692
  this.accountStore,
495
693
  this.senderTaggingStore,
496
694
  this.recipientTaggingStore,
497
- this.senderAddressBookStore,
695
+ this.taggingSecretSourcesStore,
498
696
  this.capsuleStore,
697
+ this.factStore,
499
698
  this.privateEventStore,
500
699
  this.nextBlockTimestamp,
501
700
  this.version,
502
701
  this.chainId,
503
702
  this.authwits,
703
+ this.taggingSecretStrategies,
704
+ this.authorizeAllUtilityCallTargets,
705
+ this.artifactResolver,
706
+ this.rootPath,
707
+ this.packageName,
504
708
  );
505
709
 
506
710
  this.state = { name: 'TOP_LEVEL' };
@@ -508,10 +712,12 @@ export class TXESession implements TXESessionStateHandler {
508
712
  }
509
713
 
510
714
  async enterPrivateState(
511
- contractAddress: AztecAddress = DEFAULT_ADDRESS,
512
- anchorBlockNumber: BlockNumber | undefined,
715
+ contractAddressOpt: Option<AztecAddress>,
716
+ anchorBlockNumberOpt: Option<BlockNumber>,
513
717
  gasSettings: GasSettings,
514
718
  ): Promise<PrivateContextInputs> {
719
+ const contractAddress = contractAddressOpt?.value ?? DEFAULT_ADDRESS;
720
+ const anchorBlockNumber = anchorBlockNumberOpt?.value;
515
721
  this.exitTopLevelState();
516
722
  this.resetLastCall();
517
723
 
@@ -539,9 +745,16 @@ export class TXESession implements TXESessionStateHandler {
539
745
  const taggingIndexCache = new ExecutionTaggingIndexCache();
540
746
 
541
747
  const utilityExecutor = this.utilityExecutorForContractSync(anchorBlock);
748
+ const transientArrayService = new TransientArrayService();
749
+ const anchoredContractData = new AnchoredContractData(
750
+ this.contractStore,
751
+ this.stateMachine.contractClassService,
752
+ anchorBlock!,
753
+ );
542
754
  this.oracleHandler = new TXEPrivateExecutionOracle({
543
755
  argsHash: Fr.ZERO,
544
756
  txContext: new TxContext(this.chainId, this.version, gasSettings),
757
+ txRequestSalt: Fr.ZERO,
545
758
  callContext: new CallContext(AztecAddress.ZERO, contractAddress, FunctionSelector.empty(), false),
546
759
  anchorBlockHeader: anchorBlock!,
547
760
  utilityExecutor,
@@ -550,22 +763,25 @@ export class TXESession implements TXESessionStateHandler {
550
763
  executionCache: new HashedValuesCache(),
551
764
  noteCache,
552
765
  taggingIndexCache,
553
- contractStore: this.contractStore,
766
+ anchoredContractData,
554
767
  noteStore: this.noteStore,
555
768
  keyStore: this.keyStore,
556
769
  addressStore: this.addressStore,
557
770
  aztecNode: this.stateMachine.node,
558
771
  senderTaggingStore: this.senderTaggingStore,
559
772
  recipientTaggingStore: this.recipientTaggingStore,
560
- senderAddressBookStore: this.senderAddressBookStore,
773
+ taggingSecretSourcesStore: this.taggingSecretSourcesStore,
561
774
  capsuleService: new CapsuleService(this.capsuleStore, await this.keyStore.getAccounts()),
775
+ factService: new FactService(this.factStore, await this.keyStore.getAccounts()),
562
776
  privateEventStore: this.privateEventStore,
563
777
  contractSyncService: this.stateMachine.contractSyncService,
564
778
  l2TipsStore: this.stateMachine.l2TipsProvider,
565
779
  jobId: this.currentJobId,
566
780
  scopes: await this.keyStore.getAccounts(),
567
- messageContextService: this.stateMachine.messageContextService,
781
+ txResolver: this.stateMachine.txResolver,
568
782
  simulator: new WASMSimulator(),
783
+ hooks: this.buildExecutionHooks(),
784
+ transientArrayService,
569
785
  });
570
786
 
571
787
  // We store the note and tagging index caches fed into the PrivateExecutionOracle (along with some other auxiliary
@@ -583,7 +799,8 @@ export class TXESession implements TXESessionStateHandler {
583
799
  return (this.oracleHandler as TXEPrivateExecutionOracle).getPrivateContextInputs();
584
800
  }
585
801
 
586
- async enterPublicState(contractAddress?: AztecAddress) {
802
+ async enterPublicState(contractAddressOpt: Option<AztecAddress>) {
803
+ const contractAddress = contractAddressOpt?.value ?? DEFAULT_ADDRESS;
587
804
  this.exitTopLevelState();
588
805
  this.resetLastCall();
589
806
 
@@ -598,10 +815,11 @@ export class TXESession implements TXESessionStateHandler {
598
815
  });
599
816
 
600
817
  this.oracleHandler = new TXEOraclePublicContext(
601
- contractAddress ?? DEFAULT_ADDRESS,
818
+ contractAddress,
602
819
  await this.stateMachine.synchronizer.nativeWorldStateService.fork(),
603
820
  getSingleTxBlockRequestHash(globalVariables.blockNumber),
604
821
  globalVariables,
822
+ this.contractStore,
605
823
  );
606
824
 
607
825
  this.state = { name: 'PUBLIC' };
@@ -611,7 +829,8 @@ export class TXESession implements TXESessionStateHandler {
611
829
  this.setLastCallContext(Fr.ZERO, latestHeader.globalVariables.timestamp);
612
830
  }
613
831
 
614
- async enterUtilityState(contractAddress: AztecAddress = DEFAULT_ADDRESS) {
832
+ async enterUtilityState(contractAddressOpt: Option<AztecAddress>) {
833
+ const contractAddress = contractAddressOpt?.value ?? DEFAULT_ADDRESS;
615
834
  this.exitTopLevelState();
616
835
  this.resetLastCall();
617
836
 
@@ -630,26 +849,40 @@ export class TXESession implements TXESessionStateHandler {
630
849
  ).syncNoteNullifiers(contractAddress, await this.keyStore.getAccounts());
631
850
 
632
851
  this.oracleHandler = new UtilityExecutionOracle({
633
- contractAddress,
852
+ callContext: CallContext.from({
853
+ msgSender: AztecAddress.NULL_MSG_SENDER,
854
+ contractAddress,
855
+ // No specific function is being executed in this inlined utility context, hence the empty selector.
856
+ functionSelector: FunctionSelector.empty(),
857
+ isStaticCall: true,
858
+ }),
634
859
  authWitnesses: [],
635
860
  capsules: [],
636
861
  anchorBlockHeader,
637
- contractStore: this.contractStore,
862
+ anchoredContractData: new AnchoredContractData(
863
+ this.contractStore,
864
+ this.stateMachine.contractClassService,
865
+ anchorBlockHeader,
866
+ ),
638
867
  noteStore: this.noteStore,
639
868
  keyStore: this.keyStore,
640
869
  addressStore: this.addressStore,
641
870
  aztecNode: this.stateMachine.node,
642
871
  recipientTaggingStore: this.recipientTaggingStore,
643
- senderAddressBookStore: this.senderAddressBookStore,
872
+ taggingSecretSourcesStore: this.taggingSecretSourcesStore,
644
873
  capsuleService: new CapsuleService(this.capsuleStore, await this.keyStore.getAccounts()),
874
+ factService: new FactService(this.factStore, await this.keyStore.getAccounts()),
645
875
  privateEventStore: this.privateEventStore,
646
- messageContextService: this.stateMachine.messageContextService,
876
+ txResolver: this.stateMachine.txResolver,
647
877
  contractSyncService: this.stateMachine.contractSyncService,
648
878
  l2TipsStore: this.stateMachine.l2TipsProvider,
649
879
  jobId: this.currentJobId,
650
880
  scopes: await this.keyStore.getAccounts(),
651
881
  simulator: new WASMSimulator(),
652
882
  utilityExecutor: this.utilityExecutorForContractSync(anchorBlockHeader),
883
+ hooks: this.buildExecutionHooks(),
884
+ // Execution-tree root (top-level utility run): own store; nested frames inherit it.
885
+ transientArrayService: new TransientArrayService(),
653
886
  });
654
887
 
655
888
  this.state = { name: 'UTILITY' };
@@ -665,15 +898,23 @@ export class TXESession implements TXESessionStateHandler {
665
898
  }
666
899
 
667
900
  // Note that while all public and private contexts do is build a single block that we then process when exiting
668
- // those, the top level context performs a large number of actions not captured in the following 'close' call. Among
669
- // others, it will create empty blocks (via `advanceBlocksBy` and `deploy`), create blocks with transactions via
670
- // `privateCallNewFlow` and `publicCallNewFlow`, add accounts to PXE via `addAccount`, etc. This is a
671
- // slight inconsistency in the working model of this class, but is not too bad.
672
- // TODO: it's quite unfortunate that we need to capture the authwits created to later pass them again when the top
673
- // level context is re-created. This is because authwits create a temporary utility context that'd otherwise reset
674
- // the authwits if not persisted, so we'd not be able to pass more than one per execution.
675
- // Ideally authwits would be passed alongside a contract call instead of pre-seeded.
676
- [this.nextBlockTimestamp, this.authwits] = (this.oracleHandler as TXEOracleTopLevelContext).close();
901
+ // them, the top level context does most of its work as it goes: it creates empty blocks (via `advanceBlocksBy`
902
+ // and `deploy`), creates blocks with transactions (via `privateCallNewFlow` and `publicCallNewFlow`), adds
903
+ // accounts to PXE (via `addAccount`), etc. This is a slight inconsistency in the working model of this class, but
904
+ // is not too bad. The `close` call below therefore only hands back the session-scoped values that a test
905
+ // sets directly at the top level, outside any contract execution (e.g. via `advanceTimestampBy`,
906
+ // `addAuthWitness`, `setTaggingSecretStrategies`). The oracle handler is discarded on every state transition,
907
+ // so the session must seed these values into the contexts it creates later.
908
+
909
+ // TODO: persisting authwits this way is quite unfortunate: they create a temporary utility context that would
910
+ // otherwise reset them, so we'd not be able to pass more than one per execution. Ideally authwits would be passed
911
+ // alongside a contract call instead of pre-seeded.
912
+ ({
913
+ nextBlockTimestamp: this.nextBlockTimestamp,
914
+ authwits: this.authwits,
915
+ taggingSecretStrategies: this.taggingSecretStrategies,
916
+ authorizeAllUtilityCallTargets: this.authorizeAllUtilityCallTargets,
917
+ } = (this.oracleHandler as TXEOracleTopLevelContext).close());
677
918
  }
678
919
 
679
920
  private async exitPrivateState() {
@@ -722,7 +963,18 @@ export class TXESession implements TXESessionStateHandler {
722
963
 
723
964
  private utilityExecutorForContractSync(anchorBlock: any) {
724
965
  return async (call: FunctionCall, scopes: AztecAddress[]) => {
725
- const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
966
+ const anchoredContractData = new AnchoredContractData(
967
+ this.contractStore,
968
+ this.stateMachine.contractClassService,
969
+ anchorBlock!,
970
+ );
971
+ const entryPointArtifact = await anchoredContractData.getFunctionArtifactWithDebugMetadata(
972
+ call.to,
973
+ call.selector,
974
+ );
975
+ if (!entryPointArtifact) {
976
+ throw new Error(`Cannot run function ${call.selector} on ${call.to}: the contract is not registered.`);
977
+ }
726
978
  if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
727
979
  throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
728
980
  }
@@ -730,29 +982,38 @@ export class TXESession implements TXESessionStateHandler {
730
982
  try {
731
983
  const simulator = new WASMSimulator();
732
984
  const oracle = new UtilityExecutionOracle({
733
- contractAddress: call.to,
985
+ callContext: CallContext.from({
986
+ msgSender: AztecAddress.NULL_MSG_SENDER,
987
+ contractAddress: call.to,
988
+ functionSelector: call.selector,
989
+ isStaticCall: true,
990
+ }),
734
991
  authWitnesses: [],
735
992
  capsules: [],
736
993
  anchorBlockHeader: anchorBlock!,
737
- contractStore: this.contractStore,
994
+ anchoredContractData,
738
995
  noteStore: this.noteStore,
739
996
  keyStore: this.keyStore,
740
997
  addressStore: this.addressStore,
741
998
  aztecNode: this.stateMachine.node,
742
999
  recipientTaggingStore: this.recipientTaggingStore,
743
- senderAddressBookStore: this.senderAddressBookStore,
1000
+ taggingSecretSourcesStore: this.taggingSecretSourcesStore,
744
1001
  capsuleService: new CapsuleService(this.capsuleStore, scopes),
1002
+ factService: new FactService(this.factStore, scopes),
745
1003
  privateEventStore: this.privateEventStore,
746
- messageContextService: this.stateMachine.messageContextService,
1004
+ txResolver: this.stateMachine.txResolver,
747
1005
  contractSyncService: this.stateMachine.contractSyncService,
748
1006
  l2TipsStore: this.stateMachine.l2TipsProvider,
749
1007
  jobId: this.currentJobId,
750
1008
  scopes,
751
1009
  simulator,
752
1010
  utilityExecutor: this.utilityExecutorForContractSync(anchorBlock),
1011
+ hooks: this.buildExecutionHooks(),
1012
+ // Top-level utility entrypoint: gets a fresh store. Nested frames inherit it via UtilityExecutionOracle.
1013
+ transientArrayService: new TransientArrayService(),
753
1014
  });
754
1015
  await simulator
755
- .executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
1016
+ .executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, buildACIRCallback(oracle))
756
1017
  .catch((err: Error) => {
757
1018
  err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
758
1019
  throw new ExecutionError(
@@ -770,4 +1031,12 @@ export class TXESession implements TXESessionStateHandler {
770
1031
  }
771
1032
  };
772
1033
  }
1034
+
1035
+ /** Execution hooks for the oracles this session builds. Every oracle construction site must use this. */
1036
+ private buildExecutionHooks() {
1037
+ return composeHooks({
1038
+ resolveTaggingSecretStrategy: makeResolveTaggingSecretStrategyHook(this.taggingSecretStrategies),
1039
+ authorizeUtilityCall: this.authorizeAllUtilityCallTargets ? authorizeAllUtilityCallsHook : undefined,
1040
+ });
1041
+ }
773
1042
  }