@aztec/txe 0.0.1-commit.2f68f620 → 0.0.1-commit.321f6a9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. package/dest/AuthRegistry-QVGDDH5X.js +3 -0
  2. package/dest/AuthRegistry-QVGDDH5X.js.map +7 -0
  3. package/dest/ContractClassRegistry-VWR3F42P.js +3 -0
  4. package/dest/ContractClassRegistry-VWR3F42P.js.map +7 -0
  5. package/dest/ContractInstanceRegistry-FHIWE33X.js +3 -0
  6. package/dest/ContractInstanceRegistry-FHIWE33X.js.map +7 -0
  7. package/dest/FeeJuice-SAOWVGG7.js +3 -0
  8. package/dest/FeeJuice-SAOWVGG7.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-NME3E45O.js +3 -0
  14. package/dest/SchnorrAccount-NME3E45O.js.map +7 -0
  15. package/dest/SchnorrInitializerlessAccount-WTGXU6SW.js +3 -0
  16. package/dest/SchnorrInitializerlessAccount-WTGXU6SW.js.map +7 -0
  17. package/dest/bin/check_txe_oracle_version.js +7 -15
  18. package/dest/bin/index.js +1 -1
  19. package/dest/bin/oracle_test_server.js +2 -2
  20. package/dest/chunk-32UHX7YY.js +3 -0
  21. package/dest/chunk-SZPMCTJK.js +260 -0
  22. package/dest/chunk-SZPMCTJK.js.map +7 -0
  23. package/dest/{chunk-W2NSX64C.js → chunk-YS3UIBVR.js} +2 -2
  24. package/dest/{chunk-W2NSX64C.js.map → chunk-YS3UIBVR.js.map} +3 -3
  25. package/dest/constants.d.ts +1 -1
  26. package/dest/constants.d.ts.map +1 -1
  27. package/dest/constants.js +1 -1
  28. package/dest/dispatcher_pool.d.ts +2 -2
  29. package/dest/dispatcher_pool.d.ts.map +1 -1
  30. package/dest/dispatcher_pool.js +5 -3
  31. package/dest/index.d.ts +2 -136
  32. package/dest/index.d.ts.map +1 -1
  33. package/dest/index.js +5 -3
  34. package/dest/metafile.json +9632 -7418
  35. package/dest/oracle/interfaces.d.ts +24 -11
  36. package/dest/oracle/interfaces.d.ts.map +1 -1
  37. package/dest/oracle/tagging_secret_strategy.d.ts +12 -0
  38. package/dest/oracle/tagging_secret_strategy.d.ts.map +1 -0
  39. package/dest/oracle/tagging_secret_strategy.js +12 -0
  40. package/dest/oracle/test-resolver/default_fixtures.d.ts +16 -0
  41. package/dest/oracle/test-resolver/default_fixtures.d.ts.map +1 -0
  42. package/dest/oracle/test-resolver/default_fixtures.js +200 -0
  43. package/dest/oracle/test-resolver/index.d.ts +1 -1
  44. package/dest/oracle/test-resolver/index.d.ts.map +1 -1
  45. package/dest/oracle/test-resolver/index.js +1 -2
  46. package/dest/oracle/test-resolver/resolver.d.ts +21 -7
  47. package/dest/oracle/test-resolver/resolver.d.ts.map +1 -1
  48. package/dest/oracle/test-resolver/resolver.js +100 -33
  49. package/dest/oracle/txe_oracle_public_context.d.ts +9 -9
  50. package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
  51. package/dest/oracle/txe_oracle_public_context.js +15 -9
  52. package/dest/oracle/txe_oracle_registry.d.ts +51 -26
  53. package/dest/oracle/txe_oracle_registry.d.ts.map +1 -1
  54. package/dest/oracle/txe_oracle_registry.js +258 -53
  55. package/dest/oracle/txe_oracle_top_level_context.d.ts +30 -9
  56. package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
  57. package/dest/oracle/txe_oracle_top_level_context.js +454 -288
  58. package/dest/oracle/txe_oracle_version.d.ts +4 -4
  59. package/dest/oracle/txe_oracle_version.js +4 -4
  60. package/dest/rpc_translator.d.ts +23 -4
  61. package/dest/rpc_translator.d.ts.map +1 -1
  62. package/dest/rpc_translator.js +167 -81
  63. package/dest/server.bundle.js +1 -1
  64. package/dest/state_machine/archiver.d.ts +1 -1
  65. package/dest/state_machine/archiver.d.ts.map +1 -1
  66. package/dest/state_machine/archiver.js +1 -2
  67. package/dest/state_machine/dummy_p2p_client.d.ts +5 -2
  68. package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
  69. package/dest/state_machine/dummy_p2p_client.js +9 -0
  70. package/dest/state_machine/global_variable_builder.d.ts +3 -4
  71. package/dest/state_machine/global_variable_builder.d.ts.map +1 -1
  72. package/dest/state_machine/global_variable_builder.js +0 -3
  73. package/dest/state_machine/index.d.ts +8 -6
  74. package/dest/state_machine/index.d.ts.map +1 -1
  75. package/dest/state_machine/index.js +41 -19
  76. package/dest/state_machine/synchronizer.d.ts +10 -2
  77. package/dest/state_machine/synchronizer.d.ts.map +1 -1
  78. package/dest/state_machine/synchronizer.js +18 -5
  79. package/dest/txe_session.d.ts +29 -20
  80. package/dest/txe_session.d.ts.map +1 -1
  81. package/dest/txe_session.js +165 -41
  82. package/dest/utils/block_creation.d.ts +2 -2
  83. package/dest/utils/block_creation.d.ts.map +1 -1
  84. package/dest/utils/block_creation.js +2 -2
  85. package/dest/utils/encoding.d.ts +4 -3
  86. package/dest/utils/encoding.d.ts.map +1 -1
  87. package/dest/utils/tx_effect_creation.d.ts +1 -1
  88. package/dest/utils/tx_effect_creation.d.ts.map +1 -1
  89. package/dest/utils/tx_effect_creation.js +0 -1
  90. package/dest/utils/txe_public_contract_data_source.d.ts +1 -1
  91. package/dest/utils/txe_public_contract_data_source.d.ts.map +1 -1
  92. package/dest/utils/txe_public_contract_data_source.js +7 -4
  93. package/dest/worker.bundle.js +1 -1
  94. package/package.json +17 -17
  95. package/src/bin/check_txe_oracle_version.ts +9 -12
  96. package/src/bin/oracle_test_server.ts +2 -2
  97. package/src/constants.ts +1 -1
  98. package/src/dispatcher_pool.ts +4 -3
  99. package/src/index.ts +6 -4
  100. package/src/oracle/interfaces.ts +26 -9
  101. package/src/oracle/tagging_secret_strategy.ts +25 -0
  102. package/src/oracle/test-resolver/default_fixtures.ts +271 -0
  103. package/src/oracle/test-resolver/index.ts +1 -2
  104. package/src/oracle/test-resolver/resolver.ts +121 -41
  105. package/src/oracle/txe_oracle_public_context.ts +16 -14
  106. package/src/oracle/txe_oracle_registry.ts +197 -42
  107. package/src/oracle/txe_oracle_top_level_context.ts +201 -66
  108. package/src/oracle/txe_oracle_version.ts +4 -4
  109. package/src/rpc_translator.ts +224 -108
  110. package/src/state_machine/archiver.ts +0 -1
  111. package/src/state_machine/dummy_p2p_client.ts +13 -0
  112. package/src/state_machine/global_variable_builder.ts +2 -16
  113. package/src/state_machine/index.ts +50 -34
  114. package/src/state_machine/synchronizer.ts +26 -5
  115. package/src/txe_session.ts +284 -45
  116. package/src/utils/block_creation.ts +2 -1
  117. package/src/utils/tx_effect_creation.ts +0 -2
  118. package/src/utils/txe_public_contract_data_source.ts +6 -4
  119. package/dest/ContractClassRegistry-PII7Q556.js +0 -3
  120. package/dest/ContractClassRegistry-PII7Q556.js.map +0 -7
  121. package/dest/ContractInstanceRegistry-3MHLGFNZ.js +0 -3
  122. package/dest/ContractInstanceRegistry-3MHLGFNZ.js.map +0 -7
  123. package/dest/FeeJuice-TQV5AQK7.js +0 -3
  124. package/dest/FeeJuice-TQV5AQK7.js.map +0 -7
  125. package/dest/MultiCallEntrypoint-SBJUIJY7.js +0 -3
  126. package/dest/MultiCallEntrypoint-SBJUIJY7.js.map +0 -7
  127. package/dest/SchnorrAccount-MQXPIZ44.js +0 -3
  128. package/dest/SchnorrAccount-MQXPIZ44.js.map +0 -7
  129. package/dest/chunk-BJVAAXNA.js +0 -3
  130. package/dest/chunk-CDITIZHX.js +0 -257
  131. package/dest/chunk-CDITIZHX.js.map +0 -7
  132. package/dest/oracle/test-resolver/fixtures.d.ts +0 -43
  133. package/dest/oracle/test-resolver/fixtures.d.ts.map +0 -1
  134. package/dest/oracle/test-resolver/fixtures.js +0 -39
  135. package/src/oracle/test-resolver/fixtures.ts +0 -84
  136. /package/dest/{chunk-BJVAAXNA.js.map → chunk-32UHX7YY.js.map} +0 -0
@@ -1,6 +1,8 @@
1
1
  import { NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/constants';
2
2
  import { BlockNumber } from '@aztec/foundation/branded-types';
3
+ import { padArrayEnd } from '@aztec/foundation/collection';
3
4
  import { Fr } from '@aztec/foundation/curves/bn254';
5
+ import { AvmSimulatorPool } from '@aztec/simulator/server';
4
6
  import type { BlockHash, L2Block } from '@aztec/stdlib/block';
5
7
  import type {
6
8
  MerkleTreeReadOperations,
@@ -15,18 +17,27 @@ export class TXESynchronizer implements WorldStateSynchronizer {
15
17
  // This works when set to 1 as well.
16
18
  private blockNumber = BlockNumber.ZERO;
17
19
 
20
+ /** AVM execution backend (simulator pool + CDB server) shared across all public simulations. */
21
+ public avmSimulator!: AvmSimulatorPool;
22
+
18
23
  constructor(public nativeWorldStateService: NativeWorldStateService) {}
19
24
 
20
25
  static async create() {
21
26
  const nativeWorldStateService = await NativeWorldStateService.ephemeral();
22
27
 
23
- return new this(nativeWorldStateService);
28
+ const synchronizer = new this(nativeWorldStateService);
29
+
30
+ synchronizer.avmSimulator = await AvmSimulatorPool.spawn({
31
+ wsdbIpcPath: nativeWorldStateService.getIpcPath(),
32
+ });
33
+
34
+ return synchronizer;
24
35
  }
25
36
 
26
- public async handleL2Block(block: L2Block) {
37
+ public async handleL2Block(block: L2Block, l1ToL2Messages: Fr[] = []) {
27
38
  await this.nativeWorldStateService.handleL2BlockAndMessages(
28
39
  block,
29
- Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero),
40
+ padArrayEnd<Fr, number>(l1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP),
30
41
  );
31
42
 
32
43
  this.blockNumber = block.header.globalVariables.blockNumber;
@@ -57,6 +68,11 @@ export class TXESynchronizer implements WorldStateSynchronizer {
57
68
  return this.nativeWorldStateService.getSnapshot(BlockNumber(blockNumber));
58
69
  }
59
70
 
71
+ /** Gets a snapshot at the given block number. The TXE has no reorgs, so the fork hash is not verified. */
72
+ public getVerifiedSnapshot(blockNumber: number, _blockHash: BlockHash): Promise<MerkleTreeReadOperations> {
73
+ return Promise.resolve(this.getSnapshot(blockNumber));
74
+ }
75
+
60
76
  /** Backups the db to the target path. */
61
77
  public backupTo(dstPath: string, compact?: boolean): Promise<Record<Exclude<SnapshotDataKeys, 'archiver'>, string>> {
62
78
  return this.nativeWorldStateService.backupTo(dstPath, compact);
@@ -70,8 +86,8 @@ export class TXESynchronizer implements WorldStateSynchronizer {
70
86
  throw new Error('TXE Synchronizer does not implement "status"');
71
87
  }
72
88
 
73
- public stop(): Promise<void> {
74
- throw new Error('TXE Synchronizer does not implement "stop"');
89
+ public async stop(): Promise<void> {
90
+ await this.closeIpc();
75
91
  }
76
92
 
77
93
  public stopSync(): Promise<void> {
@@ -85,4 +101,9 @@ export class TXESynchronizer implements WorldStateSynchronizer {
85
101
  public clear(): Promise<void> {
86
102
  throw new Error('TXE Synchronizer does not implement "clear"');
87
103
  }
104
+
105
+ /** Clean up IPC resources. */
106
+ public async closeIpc(): Promise<void> {
107
+ await this.avmSimulator?.[Symbol.asyncDispose]();
108
+ }
88
109
  }
@@ -7,16 +7,20 @@ 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,
@@ -25,9 +29,11 @@ import {
25
29
  type IMiscOracle,
26
30
  type IPrivateExecutionOracle,
27
31
  type IUtilityExecutionOracle,
32
+ LEGACY_ORACLE_REGISTRY,
28
33
  Option,
29
- Oracle,
34
+ TransientArrayService,
30
35
  UtilityExecutionOracle,
36
+ buildACIRCallback,
31
37
  } from '@aztec/pxe/simulator';
32
38
  import {
33
39
  ExecutionError,
@@ -38,7 +44,7 @@ import {
38
44
  toACVMWitness,
39
45
  } from '@aztec/simulator/client';
40
46
  import { STANDARD_AUTH_REGISTRY_ADDRESS } from '@aztec/standard-contracts/auth-registry/constants';
41
- import { FunctionCall, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
47
+ import { EventSelector, FunctionCall, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
42
48
  import type { AuthWitness } from '@aztec/stdlib/auth-witness';
43
49
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
44
50
  import type { GasSettings } from '@aztec/stdlib/gas';
@@ -51,11 +57,16 @@ import { z } from 'zod';
51
57
 
52
58
  import { DEFAULT_ADDRESS, MAX_OFFCHAIN_EFFECTS_PER_TXE_QUERY, MAX_OFFCHAIN_EFFECT_LEN } from './constants.js';
53
59
  import type { IAvmExecutionOracle, ITxeExecutionOracle } from './oracle/interfaces.js';
60
+ import {
61
+ type TXETaggingSecretStrategies,
62
+ makeResolveTaggingSecretStrategyHook,
63
+ } from './oracle/tagging_secret_strategy.js';
54
64
  import { TXEOraclePublicContext } from './oracle/txe_oracle_public_context.js';
55
- 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';
56
67
  import { TXE_ORACLE_VERSION_MAJOR, TXE_ORACLE_VERSION_MINOR } from './oracle/txe_oracle_version.js';
57
68
  import { TXEPrivateExecutionOracle } from './oracle/txe_private_execution_oracle.js';
58
- import { RPCTranslator } from './rpc_translator.js';
69
+ import { RPCTranslator, UnavailableOracleError } from './rpc_translator.js';
59
70
  import { TXEArchiver } from './state_machine/archiver.js';
60
71
  import { TXEStateMachine } from './state_machine/index.js';
61
72
  import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlock } from './utils/block_creation.js';
@@ -127,14 +138,45 @@ export interface TXESessionStateHandler {
127
138
  ): Promise<PrivateContextInputs>;
128
139
  enterUtilityState(contractAddress: Option<AztecAddress>): Promise<void>;
129
140
 
130
- // TODO(F-335): Exposing the job info is abstraction breakage - drop the following 2 functions.
131
- cycleJob(): Promise<string>;
132
- getCurrentJob(): string;
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[]>;
156
+
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[]>;
133
165
 
134
166
  /**
135
- * 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.
136
169
  */
137
- 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[][]>;
138
180
 
139
181
  /**
140
182
  * Captures a raw offchain effect payload for consumption from test environment. Called by the `emit_offchain_effect`
@@ -198,6 +240,8 @@ function emptyLastCallState(): LastCallState {
198
240
  export class TXESession implements TXESessionStateHandler {
199
241
  private state: SessionState = { name: 'TOP_LEVEL' };
200
242
  private authwits: Map<string, AuthWitness> = new Map();
243
+ private taggingSecretStrategies: TXETaggingSecretStrategies = new Map();
244
+ private authorizeAllUtilityCallTargets = false;
201
245
  private lastCallInfo: LastCallState = emptyLastCallState();
202
246
  private txeOracleVersion: { major: number; minor: number } | undefined;
203
247
 
@@ -220,8 +264,9 @@ export class TXESession implements TXESessionStateHandler {
220
264
  private accountStore: TXEAccountStore,
221
265
  private senderTaggingStore: SenderTaggingStore,
222
266
  private recipientTaggingStore: RecipientTaggingStore,
223
- private senderAddressBookStore: SenderAddressBookStore,
267
+ private taggingSecretSourcesStore: TaggingSecretSourcesStore,
224
268
  private capsuleStore: CapsuleStore,
269
+ private factStore: FactStore,
225
270
  private privateEventStore: PrivateEventStore,
226
271
  private jobCoordinator: JobCoordinator,
227
272
  private currentJobId: string,
@@ -234,14 +279,22 @@ export class TXESession implements TXESessionStateHandler {
234
279
  ) {}
235
280
 
236
281
  /**
237
- * Closes the per-session `txe-session` LMDB and the `NativeWorldStateService` .
238
- * 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.
239
284
  */
240
285
  async dispose(): Promise<void> {
241
286
  if (this.disposed) {
242
287
  return;
243
288
  }
244
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
+ }
245
298
  try {
246
299
  await this.stateMachine.synchronizer.nativeWorldStateService.close();
247
300
  } catch (err) {
@@ -271,14 +324,16 @@ export class TXESession implements TXESessionStateHandler {
271
324
  const noteStore = new NoteStore(store);
272
325
  const senderTaggingStore = new SenderTaggingStore(store);
273
326
  const recipientTaggingStore = new RecipientTaggingStore(store);
274
- const senderAddressBookStore = new SenderAddressBookStore(store);
327
+ const taggingSecretSourcesStore = new TaggingSecretSourcesStore(store);
275
328
  const capsuleStore = new CapsuleStore(store);
329
+ const factStore = new FactStore(store);
276
330
  const keyStore = new KeyStore(store);
277
331
  const accountStore = new TXEAccountStore(store);
278
332
 
279
333
  const jobCoordinator = new JobCoordinator(store);
280
334
  jobCoordinator.registerStores([
281
335
  capsuleStore,
336
+ factStore,
282
337
  senderTaggingStore,
283
338
  recipientTaggingStore,
284
339
  privateEventStore,
@@ -306,13 +361,16 @@ export class TXESession implements TXESessionStateHandler {
306
361
  accountStore,
307
362
  senderTaggingStore,
308
363
  recipientTaggingStore,
309
- senderAddressBookStore,
364
+ taggingSecretSourcesStore,
310
365
  capsuleStore,
366
+ factStore,
311
367
  privateEventStore,
312
368
  nextBlockTimestamp,
313
369
  version,
314
370
  chainId,
315
371
  new Map(),
372
+ new Map(),
373
+ false, // authorizeAllUtilityCallTargets
316
374
  artifactResolver,
317
375
  rootPath,
318
376
  packageName,
@@ -332,8 +390,9 @@ export class TXESession implements TXESessionStateHandler {
332
390
  accountStore,
333
391
  senderTaggingStore,
334
392
  recipientTaggingStore,
335
- senderAddressBookStore,
393
+ taggingSecretSourcesStore,
336
394
  capsuleStore,
395
+ factStore,
337
396
  privateEventStore,
338
397
  jobCoordinator,
339
398
  initialJobId,
@@ -354,6 +413,18 @@ export class TXESession implements TXESessionStateHandler {
354
413
  */
355
414
  processFunction(functionName: TXEOracleFunctionName, inputs: ForeignCallArgs): Promise<ForeignCallResult> {
356
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
+
357
428
  const translator = new RPCTranslator(this, this.oracleHandler) as any;
358
429
  // We perform a runtime validation to check that the function name corresponds to a real oracle handler.
359
430
  const validatedFunctionName = z
@@ -398,12 +469,8 @@ export class TXESession implements TXESessionStateHandler {
398
469
  }
399
470
  }
400
471
 
401
- getCurrentJob(): string {
402
- return this.currentJobId;
403
- }
404
-
405
472
  /** Commits the current job and begins a new one. Returns the new job ID. */
406
- async cycleJob(): Promise<string> {
473
+ private async cycleJob(): Promise<string> {
407
474
  await this.jobCoordinator.commitJob(this.currentJobId);
408
475
  this.currentJobId = this.jobCoordinator.beginJob();
409
476
  return this.currentJobId;
@@ -433,7 +500,7 @@ export class TXESession implements TXESessionStateHandler {
433
500
  this.lastCallInfo.anchorBlockTimestamp = anchorBlockTimestamp;
434
501
  }
435
502
 
436
- async withTopLevelCallTracking<T>(work: () => Promise<{ result: T; txHash?: Fr }>): Promise<T> {
503
+ private async withTopLevelCallTracking<T>(work: () => Promise<{ result: T; txHash?: Fr }>): Promise<T> {
437
504
  this.resetLastCall();
438
505
  // Capture the anchor *before* `work` runs: private/public executor calls mine a new block as a
439
506
  // side effect, and that block's timestamp should not be attributed to this call's anchor.
@@ -463,6 +530,119 @@ export class TXESession implements TXESessionStateHandler {
463
530
  return { txHash, anchorBlockTimestamp };
464
531
  }
465
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
+
466
646
  setTxeOracleVersion(major: number, minor: number): void {
467
647
  if (major !== TXE_ORACLE_VERSION_MAJOR) {
468
648
  const hint =
@@ -512,13 +692,16 @@ export class TXESession implements TXESessionStateHandler {
512
692
  this.accountStore,
513
693
  this.senderTaggingStore,
514
694
  this.recipientTaggingStore,
515
- this.senderAddressBookStore,
695
+ this.taggingSecretSourcesStore,
516
696
  this.capsuleStore,
697
+ this.factStore,
517
698
  this.privateEventStore,
518
699
  this.nextBlockTimestamp,
519
700
  this.version,
520
701
  this.chainId,
521
702
  this.authwits,
703
+ this.taggingSecretStrategies,
704
+ this.authorizeAllUtilityCallTargets,
522
705
  this.artifactResolver,
523
706
  this.rootPath,
524
707
  this.packageName,
@@ -562,9 +745,16 @@ export class TXESession implements TXESessionStateHandler {
562
745
  const taggingIndexCache = new ExecutionTaggingIndexCache();
563
746
 
564
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
+ );
565
754
  this.oracleHandler = new TXEPrivateExecutionOracle({
566
755
  argsHash: Fr.ZERO,
567
756
  txContext: new TxContext(this.chainId, this.version, gasSettings),
757
+ txRequestSalt: Fr.ZERO,
568
758
  callContext: new CallContext(AztecAddress.ZERO, contractAddress, FunctionSelector.empty(), false),
569
759
  anchorBlockHeader: anchorBlock!,
570
760
  utilityExecutor,
@@ -573,22 +763,28 @@ export class TXESession implements TXESessionStateHandler {
573
763
  executionCache: new HashedValuesCache(),
574
764
  noteCache,
575
765
  taggingIndexCache,
576
- contractStore: this.contractStore,
766
+ anchoredContractData,
577
767
  noteStore: this.noteStore,
578
768
  keyStore: this.keyStore,
579
769
  addressStore: this.addressStore,
580
770
  aztecNode: this.stateMachine.node,
581
771
  senderTaggingStore: this.senderTaggingStore,
582
772
  recipientTaggingStore: this.recipientTaggingStore,
583
- senderAddressBookStore: this.senderAddressBookStore,
773
+ taggingSecretSourcesStore: this.taggingSecretSourcesStore,
584
774
  capsuleService: new CapsuleService(this.capsuleStore, await this.keyStore.getAccounts()),
775
+ factService: new FactService(this.factStore, await this.keyStore.getAccounts()),
585
776
  privateEventStore: this.privateEventStore,
586
777
  contractSyncService: this.stateMachine.contractSyncService,
587
778
  l2TipsStore: this.stateMachine.l2TipsProvider,
588
779
  jobId: this.currentJobId,
589
780
  scopes: await this.keyStore.getAccounts(),
590
- messageContextService: this.stateMachine.messageContextService,
781
+ txResolver: this.stateMachine.txResolver,
591
782
  simulator: new WASMSimulator(),
783
+ hooks: composeHooks({
784
+ resolveTaggingSecretStrategy: makeResolveTaggingSecretStrategyHook(this.taggingSecretStrategies),
785
+ authorizeUtilityCall: this.authorizeAllUtilityCallTargets ? authorizeAllUtilityCallsHook : undefined,
786
+ }),
787
+ transientArrayService,
592
788
  });
593
789
 
594
790
  // We store the note and tagging index caches fed into the PrivateExecutionOracle (along with some other auxiliary
@@ -656,26 +852,42 @@ export class TXESession implements TXESessionStateHandler {
656
852
  ).syncNoteNullifiers(contractAddress, await this.keyStore.getAccounts());
657
853
 
658
854
  this.oracleHandler = new UtilityExecutionOracle({
659
- contractAddress,
855
+ callContext: CallContext.from({
856
+ msgSender: AztecAddress.NULL_MSG_SENDER,
857
+ contractAddress,
858
+ // No specific function is being executed in this inlined utility context, hence the empty selector.
859
+ functionSelector: FunctionSelector.empty(),
860
+ isStaticCall: true,
861
+ }),
660
862
  authWitnesses: [],
661
863
  capsules: [],
662
864
  anchorBlockHeader,
663
- contractStore: this.contractStore,
865
+ anchoredContractData: new AnchoredContractData(
866
+ this.contractStore,
867
+ this.stateMachine.contractClassService,
868
+ anchorBlockHeader,
869
+ ),
664
870
  noteStore: this.noteStore,
665
871
  keyStore: this.keyStore,
666
872
  addressStore: this.addressStore,
667
873
  aztecNode: this.stateMachine.node,
668
874
  recipientTaggingStore: this.recipientTaggingStore,
669
- senderAddressBookStore: this.senderAddressBookStore,
875
+ taggingSecretSourcesStore: this.taggingSecretSourcesStore,
670
876
  capsuleService: new CapsuleService(this.capsuleStore, await this.keyStore.getAccounts()),
877
+ factService: new FactService(this.factStore, await this.keyStore.getAccounts()),
671
878
  privateEventStore: this.privateEventStore,
672
- messageContextService: this.stateMachine.messageContextService,
879
+ txResolver: this.stateMachine.txResolver,
673
880
  contractSyncService: this.stateMachine.contractSyncService,
674
881
  l2TipsStore: this.stateMachine.l2TipsProvider,
675
882
  jobId: this.currentJobId,
676
883
  scopes: await this.keyStore.getAccounts(),
677
884
  simulator: new WASMSimulator(),
678
885
  utilityExecutor: this.utilityExecutorForContractSync(anchorBlockHeader),
886
+ hooks: composeHooks({
887
+ authorizeUtilityCall: this.authorizeAllUtilityCallTargets ? authorizeAllUtilityCallsHook : undefined,
888
+ }),
889
+ // Execution-tree root (top-level utility run): own store; nested frames inherit it.
890
+ transientArrayService: new TransientArrayService(),
679
891
  });
680
892
 
681
893
  this.state = { name: 'UTILITY' };
@@ -691,15 +903,23 @@ export class TXESession implements TXESessionStateHandler {
691
903
  }
692
904
 
693
905
  // Note that while all public and private contexts do is build a single block that we then process when exiting
694
- // those, the top level context performs a large number of actions not captured in the following 'close' call. Among
695
- // others, it will create empty blocks (via `advanceBlocksBy` and `deploy`), create blocks with transactions via
696
- // `privateCallNewFlow` and `publicCallNewFlow`, add accounts to PXE via `addAccount`, etc. This is a
697
- // slight inconsistency in the working model of this class, but is not too bad.
698
- // TODO: it's quite unfortunate that we need to capture the authwits created to later pass them again when the top
699
- // level context is re-created. This is because authwits create a temporary utility context that'd otherwise reset
700
- // the authwits if not persisted, so we'd not be able to pass more than one per execution.
701
- // Ideally authwits would be passed alongside a contract call instead of pre-seeded.
702
- [this.nextBlockTimestamp, this.authwits] = (this.oracleHandler as TXEOracleTopLevelContext).close();
906
+ // them, the top level context does most of its work as it goes: it creates empty blocks (via `advanceBlocksBy`
907
+ // and `deploy`), creates blocks with transactions (via `privateCallNewFlow` and `publicCallNewFlow`), adds
908
+ // accounts to PXE (via `addAccount`), etc. This is a slight inconsistency in the working model of this class, but
909
+ // is not too bad. The `close` call below therefore only hands back the session-scoped values that a test
910
+ // sets directly at the top level, outside any contract execution (e.g. via `advanceTimestampBy`,
911
+ // `addAuthWitness`, `setTaggingSecretStrategies`). The oracle handler is discarded on every state transition,
912
+ // so the session must seed these values into the contexts it creates later.
913
+
914
+ // TODO: persisting authwits this way is quite unfortunate: they create a temporary utility context that would
915
+ // otherwise reset them, so we'd not be able to pass more than one per execution. Ideally authwits would be passed
916
+ // alongside a contract call instead of pre-seeded.
917
+ ({
918
+ nextBlockTimestamp: this.nextBlockTimestamp,
919
+ authwits: this.authwits,
920
+ taggingSecretStrategies: this.taggingSecretStrategies,
921
+ authorizeAllUtilityCallTargets: this.authorizeAllUtilityCallTargets,
922
+ } = (this.oracleHandler as TXEOracleTopLevelContext).close());
703
923
  }
704
924
 
705
925
  private async exitPrivateState() {
@@ -748,7 +968,18 @@ export class TXESession implements TXESessionStateHandler {
748
968
 
749
969
  private utilityExecutorForContractSync(anchorBlock: any) {
750
970
  return async (call: FunctionCall, scopes: AztecAddress[]) => {
751
- const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
971
+ const anchoredContractData = new AnchoredContractData(
972
+ this.contractStore,
973
+ this.stateMachine.contractClassService,
974
+ anchorBlock!,
975
+ );
976
+ const entryPointArtifact = await anchoredContractData.getFunctionArtifactWithDebugMetadata(
977
+ call.to,
978
+ call.selector,
979
+ );
980
+ if (!entryPointArtifact) {
981
+ throw new Error(`Cannot run function ${call.selector} on ${call.to}: the contract is not registered.`);
982
+ }
752
983
  if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
753
984
  throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
754
985
  }
@@ -756,29 +987,37 @@ export class TXESession implements TXESessionStateHandler {
756
987
  try {
757
988
  const simulator = new WASMSimulator();
758
989
  const oracle = new UtilityExecutionOracle({
759
- contractAddress: call.to,
990
+ callContext: CallContext.from({
991
+ msgSender: AztecAddress.NULL_MSG_SENDER,
992
+ contractAddress: call.to,
993
+ functionSelector: call.selector,
994
+ isStaticCall: true,
995
+ }),
760
996
  authWitnesses: [],
761
997
  capsules: [],
762
998
  anchorBlockHeader: anchorBlock!,
763
- contractStore: this.contractStore,
999
+ anchoredContractData,
764
1000
  noteStore: this.noteStore,
765
1001
  keyStore: this.keyStore,
766
1002
  addressStore: this.addressStore,
767
1003
  aztecNode: this.stateMachine.node,
768
1004
  recipientTaggingStore: this.recipientTaggingStore,
769
- senderAddressBookStore: this.senderAddressBookStore,
1005
+ taggingSecretSourcesStore: this.taggingSecretSourcesStore,
770
1006
  capsuleService: new CapsuleService(this.capsuleStore, scopes),
1007
+ factService: new FactService(this.factStore, scopes),
771
1008
  privateEventStore: this.privateEventStore,
772
- messageContextService: this.stateMachine.messageContextService,
1009
+ txResolver: this.stateMachine.txResolver,
773
1010
  contractSyncService: this.stateMachine.contractSyncService,
774
1011
  l2TipsStore: this.stateMachine.l2TipsProvider,
775
1012
  jobId: this.currentJobId,
776
1013
  scopes,
777
1014
  simulator,
778
1015
  utilityExecutor: this.utilityExecutorForContractSync(anchorBlock),
1016
+ // Top-level utility entrypoint: gets a fresh store. Nested frames inherit it via UtilityExecutionOracle.
1017
+ transientArrayService: new TransientArrayService(),
779
1018
  });
780
1019
  await simulator
781
- .executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
1020
+ .executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, buildACIRCallback(oracle))
782
1021
  .catch((err: Error) => {
783
1022
  err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
784
1023
  throw new ExecutionError(
@@ -23,6 +23,7 @@ export function getSingleTxBlockRequestHash(blockNumber: BlockNumber): Fr {
23
23
  export async function insertTxEffectIntoWorldTrees(
24
24
  txEffect: TxEffect,
25
25
  worldTrees: MerkleTreeWriteOperations,
26
+ l1ToL2Messages: Fr[] = [],
26
27
  ): Promise<void> {
27
28
  await worldTrees.appendLeaves(
28
29
  MerkleTreeId.NOTE_HASH_TREE,
@@ -37,7 +38,7 @@ export async function insertTxEffectIntoWorldTrees(
37
38
 
38
39
  await worldTrees.appendLeaves(
39
40
  MerkleTreeId.L1_TO_L2_MESSAGE_TREE,
40
- padArrayEnd<Fr, number>(txEffect.l2ToL1Msgs, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP),
41
+ padArrayEnd<Fr, number>(l1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP),
41
42
  );
42
43
 
43
44
  // We do not need to add public data writes because we apply them as we go.
@@ -7,8 +7,6 @@ import { TxEffect, TxHash } from '@aztec/stdlib/tx';
7
7
  export async function makeTxEffect(noteCache: ExecutionNoteCache, txBlockNumber: BlockNumber): Promise<TxEffect> {
8
8
  const txEffect = TxEffect.empty();
9
9
 
10
- noteCache.finish();
11
-
12
10
  const nonceGenerator = noteCache.getNonceGenerator();
13
11
  txEffect.noteHashes = await Promise.all(
14
12
  noteCache