@aztec/txe 0.0.1-commit.3100065 → 0.0.1-commit.330febf

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 (87) 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-NADDSLGL.js → ContractInstanceRegistry-WLOZKTR6.js} +1 -1
  6. package/dest/{ContractInstanceRegistry-NADDSLGL.js.map → ContractInstanceRegistry-WLOZKTR6.js.map} +2 -2
  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-TGICA67H.js.map → MultiCallEntrypoint-QG5H33ZZ.js.map} +2 -2
  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 +8 -47
  18. package/dest/bin/index.js +1 -1
  19. package/dest/chunk-32UHX7YY.js +3 -0
  20. package/dest/{chunk-PDOEF22H.js → chunk-RVEPNDEP.js} +2 -2
  21. package/dest/{chunk-PDOEF22H.js.map → chunk-RVEPNDEP.js.map} +2 -2
  22. package/dest/chunk-XWIMXLKD.js +258 -0
  23. package/dest/chunk-XWIMXLKD.js.map +7 -0
  24. package/dest/constants.js +1 -1
  25. package/dest/metafile.json +2369 -3419
  26. package/dest/oracle/interfaces.d.ts +6 -2
  27. package/dest/oracle/interfaces.d.ts.map +1 -1
  28. package/dest/oracle/test-resolver/default_fixtures.d.ts +9 -2
  29. package/dest/oracle/test-resolver/default_fixtures.d.ts.map +1 -1
  30. package/dest/oracle/test-resolver/default_fixtures.js +32 -39
  31. package/dest/oracle/test-resolver/resolver.d.ts +1 -1
  32. package/dest/oracle/test-resolver/resolver.d.ts.map +1 -1
  33. package/dest/oracle/test-resolver/resolver.js +2 -2
  34. package/dest/oracle/txe_oracle_registry.d.ts +5 -3
  35. package/dest/oracle/txe_oracle_registry.d.ts.map +1 -1
  36. package/dest/oracle/txe_oracle_registry.js +45 -27
  37. package/dest/oracle/txe_oracle_top_level_context.d.ts +18 -5
  38. package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
  39. package/dest/oracle/txe_oracle_top_level_context.js +375 -272
  40. package/dest/oracle/txe_oracle_version.d.ts +5 -5
  41. package/dest/oracle/txe_oracle_version.js +5 -5
  42. package/dest/rpc_translator.d.ts +4 -1
  43. package/dest/rpc_translator.d.ts.map +1 -1
  44. package/dest/rpc_translator.js +25 -1
  45. package/dest/server.bundle.js +1 -1
  46. package/dest/state_machine/mock_epoch_cache.d.ts +2 -1
  47. package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
  48. package/dest/state_machine/mock_epoch_cache.js +3 -0
  49. package/dest/state_machine/synchronizer.d.ts +6 -1
  50. package/dest/state_machine/synchronizer.d.ts.map +1 -1
  51. package/dest/state_machine/synchronizer.js +12 -3
  52. package/dest/txe_session.d.ts +6 -3
  53. package/dest/txe_session.d.ts.map +1 -1
  54. package/dest/txe_session.js +25 -9
  55. package/dest/utils/encoding.d.ts +5 -3
  56. package/dest/utils/encoding.d.ts.map +1 -1
  57. package/dest/worker.bundle.js +1 -1
  58. package/package.json +17 -17
  59. package/src/bin/check_txe_oracle_version.ts +10 -49
  60. package/src/constants.ts +1 -1
  61. package/src/oracle/interfaces.ts +5 -1
  62. package/src/oracle/test-resolver/default_fixtures.ts +58 -69
  63. package/src/oracle/test-resolver/resolver.ts +2 -2
  64. package/src/oracle/txe_oracle_registry.ts +42 -25
  65. package/src/oracle/txe_oracle_top_level_context.ts +55 -23
  66. package/src/oracle/txe_oracle_version.ts +5 -5
  67. package/src/rpc_translator.ts +29 -1
  68. package/src/state_machine/mock_epoch_cache.ts +4 -0
  69. package/src/state_machine/synchronizer.ts +18 -3
  70. package/src/txe_session.ts +31 -9
  71. package/dest/AuthRegistry-FSRZIMX6.js +0 -3
  72. package/dest/AuthRegistry-FSRZIMX6.js.map +0 -7
  73. package/dest/ContractClassRegistry-N6NA3SFA.js +0 -3
  74. package/dest/ContractClassRegistry-N6NA3SFA.js.map +0 -7
  75. package/dest/FeeJuice-QBH5JWJV.js +0 -3
  76. package/dest/FeeJuice-QBH5JWJV.js.map +0 -7
  77. package/dest/HandshakeRegistry-KKUEU7XW.js +0 -3
  78. package/dest/HandshakeRegistry-KKUEU7XW.js.map +0 -7
  79. package/dest/MultiCallEntrypoint-TGICA67H.js +0 -3
  80. package/dest/SchnorrAccount-J5T6OKR3.js +0 -3
  81. package/dest/SchnorrAccount-J5T6OKR3.js.map +0 -7
  82. package/dest/SchnorrInitializerlessAccount-OOES6Q4F.js +0 -3
  83. package/dest/SchnorrInitializerlessAccount-OOES6Q4F.js.map +0 -7
  84. package/dest/chunk-BJVAAXNA.js +0 -3
  85. package/dest/chunk-YP4ODNMQ.js +0 -268
  86. package/dest/chunk-YP4ODNMQ.js.map +0 -7
  87. /package/dest/{chunk-BJVAAXNA.js.map → chunk-32UHX7YY.js.map} +0 -0
@@ -53,10 +53,10 @@ import {
53
53
  witnessMapToFields,
54
54
  } from '@aztec/simulator/client';
55
55
  import {
56
- CppPublicTxSimulator,
57
56
  GuardedMerkleTreeOperations,
58
57
  PublicContractsDB,
59
58
  PublicProcessor,
59
+ PublicTxSimulator,
60
60
  } from '@aztec/simulator/server';
61
61
  import { type ContractArtifact, EventSelector, FunctionCall, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
62
62
  import { AuthWitness } from '@aztec/stdlib/auth-witness';
@@ -126,6 +126,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
126
126
  private chainId: Fr,
127
127
  private authwits: Map<string, AuthWitness>,
128
128
  private taggingSecretStrategies: TXETaggingSecretStrategies,
129
+ private authorizeAllUtilityCallTargets: boolean,
129
130
  private readonly artifactResolver: TXEArtifactResolver,
130
131
  private readonly rootPath: string,
131
132
  private readonly packageName: string,
@@ -335,9 +336,8 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
335
336
  return completeAddress;
336
337
  }
337
338
 
338
- async createAccount(secret: Fr) {
339
- // This is a foot gun !
340
- const completeAddress = await this.keyStore.addAccount(await deriveKeys(secret), secret);
339
+ async createAccount(secret: Fr, partialAddress: Fr) {
340
+ const completeAddress = await this.keyStore.addAccount(await deriveKeys(secret), partialAddress);
341
341
  await this.accountStore.setAccount(completeAddress.address, completeAddress);
342
342
  await this.addressStore.addCompleteAddress(completeAddress);
343
343
  this.logger.debug(`Created account ${completeAddress.address}`);
@@ -373,6 +373,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
373
373
  apply(AppTaggingSecretKind.CONSTRAINED, constrainedStrategy);
374
374
  }
375
375
 
376
+ setAuthorizeAllUtilityCallTargets(authorizeAll: boolean): void {
377
+ this.authorizeAllUtilityCallTargets = authorizeAll;
378
+ }
379
+
376
380
  async sendL1ToL2Message(content: Fr, secretHash: Fr, sender: EthAddress, recipient: AztecAddress): Promise<Fr> {
377
381
  // Messages are appended to the tree, so the next free slot is simply the current tree size.
378
382
  const { size } = await this.stateMachine.synchronizer
@@ -487,7 +491,6 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
487
491
  const privateExecutionOracle = new PrivateExecutionOracle({
488
492
  argsHash,
489
493
  txContext,
490
- // The TXE does not run the init kernel's salt binding, so no tx-request salt is in scope.
491
494
  txRequestSalt: Fr.ZERO,
492
495
  callContext,
493
496
  anchorBlockHeader: blockHeader,
@@ -577,7 +580,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
577
580
  globals.version = this.version;
578
581
  globals.gasFees = GasFees.empty();
579
582
 
580
- const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
583
+ await using forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
581
584
 
582
585
  const bindings = this.logger.getBindings();
583
586
  const contractsDB = new PublicContractsDB(
@@ -592,11 +595,20 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
592
595
  collectStatistics: false,
593
596
  collectCallMetadata: true,
594
597
  });
598
+ // The AVM simulator reads this fork's contracts DB, scoped by fork id, for each simulation.
599
+ const forkId = forkedWorldTrees.getRevision().forkId;
595
600
  const processor = new PublicProcessor(
596
601
  globals,
597
602
  guardedMerkleTrees,
598
603
  contractsDB,
599
- new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings),
604
+ new PublicTxSimulator(
605
+ this.stateMachine.synchronizer.avmSimulator,
606
+ globals,
607
+ contractsDB,
608
+ forkId,
609
+ config,
610
+ bindings,
611
+ ),
600
612
  new TestDateProvider(),
601
613
  undefined,
602
614
  createLogger('simulator:public-processor', bindings),
@@ -647,8 +659,6 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
647
659
 
648
660
  if (isStaticCall) {
649
661
  await checkpoint!.revert();
650
-
651
- await forkedWorldTrees.close();
652
662
  return { returnValues: executionResult.returnValues ?? [], offchainEffects };
653
663
  }
654
664
 
@@ -669,8 +679,6 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
669
679
 
670
680
  await this.stateMachine.handleL2Block(l2Block);
671
681
 
672
- await forkedWorldTrees.close();
673
-
674
682
  return { returnValues: executionResult.returnValues ?? [], offchainEffects };
675
683
  }
676
684
 
@@ -706,7 +714,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
706
714
  globals.version = this.version;
707
715
  globals.gasFees = GasFees.empty();
708
716
 
709
- const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
717
+ await using forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
710
718
 
711
719
  const bindings2 = this.logger.getBindings();
712
720
  const contractsDB = new PublicContractsDB(
@@ -721,7 +729,16 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
721
729
  collectStatistics: false,
722
730
  collectCallMetadata: true,
723
731
  });
724
- const simulator = new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings2);
732
+ // The AVM simulator reads this fork's contracts DB, scoped by fork id, for each simulation.
733
+ const forkId2 = forkedWorldTrees.getRevision().forkId;
734
+ const simulator = new PublicTxSimulator(
735
+ this.stateMachine.synchronizer.avmSimulator,
736
+ globals,
737
+ contractsDB,
738
+ forkId2,
739
+ config,
740
+ bindings2,
741
+ );
725
742
  const processor = new PublicProcessor(
726
743
  globals,
727
744
  guardedMerkleTrees,
@@ -807,9 +824,6 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
807
824
 
808
825
  if (isStaticCall) {
809
826
  await checkpoint!.revert();
810
-
811
- await forkedWorldTrees.close();
812
-
813
827
  return returnValues ?? [];
814
828
  }
815
829
 
@@ -830,8 +844,6 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
830
844
 
831
845
  await this.stateMachine.handleL2Block(l2Block);
832
846
 
833
- await forkedWorldTrees.close();
834
-
835
847
  return returnValues ?? [];
836
848
  }
837
849
 
@@ -875,7 +887,6 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
875
887
  hideMsgSender: false,
876
888
  isStatic: false,
877
889
  args,
878
- returnTypes: [],
879
890
  });
880
891
 
881
892
  return this.executeUtilityCall(call, {
@@ -918,7 +929,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
918
929
  try {
919
930
  const simulator = new WASMSimulator();
920
931
  const utilityExecutor = async (syncCall: FunctionCall, execScopes: AztecAddress[]) => {
921
- await this.executeUtilityCall(syncCall, { scopes: execScopes, jobId, authorizedUtilityCallTargets });
932
+ await this.executeUtilityCall(syncCall, { scopes: execScopes, jobId });
922
933
  };
923
934
  const oracle = new UtilityExecutionOracle({
924
935
  callContext: CallContext.from({
@@ -946,10 +957,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
946
957
  jobId,
947
958
  scopes,
948
959
  simulator,
949
- utilityExecutor,
950
960
  hooks: composeHooks({
951
961
  authorizeUtilityCall: this.buildAuthorizeUtilityCallHook('utility', authorizedUtilityCallTargets),
952
962
  }),
963
+ utilityExecutor,
953
964
  // Execution-tree root (top-level utility run or contract sync): own store; nested frames inherit it.
954
965
  transientArrayService: new TransientArrayService(),
955
966
  });
@@ -975,9 +986,19 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
975
986
  }
976
987
  }
977
988
 
978
- close(): [bigint, Map<string, AuthWitness>, TXETaggingSecretStrategies] {
989
+ close(): {
990
+ nextBlockTimestamp: bigint;
991
+ authwits: Map<string, AuthWitness>;
992
+ taggingSecretStrategies: TXETaggingSecretStrategies;
993
+ authorizeAllUtilityCallTargets: boolean;
994
+ } {
979
995
  this.logger.debug('Exiting Top Level Context');
980
- return [this.nextBlockTimestamp, this.authwits, this.taggingSecretStrategies];
996
+ return {
997
+ nextBlockTimestamp: this.nextBlockTimestamp,
998
+ authwits: this.authwits,
999
+ taggingSecretStrategies: this.taggingSecretStrategies,
1000
+ authorizeAllUtilityCallTargets: this.authorizeAllUtilityCallTargets,
1001
+ };
981
1002
  }
982
1003
 
983
1004
  private async getLastBlockNumber(): Promise<BlockNumber> {
@@ -989,6 +1010,9 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
989
1010
  callerContext: 'private' | 'private view' | 'utility',
990
1011
  authorizedTargets: AztecAddress[],
991
1012
  ): ExecutionHooks['authorizeUtilityCall'] | undefined {
1013
+ if (this.authorizeAllUtilityCallTargets) {
1014
+ return authorizeAllUtilityCallsHook;
1015
+ }
992
1016
  if (authorizedTargets.length === 0) {
993
1017
  return undefined;
994
1018
  }
@@ -998,3 +1022,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
998
1022
  });
999
1023
  }
1000
1024
  }
1025
+
1026
+ /**
1027
+ * An `authorizeUtilityCall` hook that authorizes every cross-contract utility call.
1028
+ *
1029
+ * Backs the `aztec_txe_setAuthorizeAllUtilityCallTargets` oracle.
1030
+ */
1031
+ export const authorizeAllUtilityCallsHook: NonNullable<ExecutionHooks['authorizeUtilityCall']> = () =>
1032
+ Promise.resolve({ authorized: true });
@@ -3,15 +3,15 @@
3
3
  * TXE and Aztec.nr. This is separate from the contract oracle version in `pxe/src/oracle_version.ts`, which covers
4
4
  * oracles used during contract execution by PXE.
5
5
  *
6
- * The Noir counterparts are in `noir-projects/aztec-nr/aztec/src/test/helpers/txe_oracles.nr`.
6
+ * The Noir counterparts are in `noir-projects/labs/aztec-nr/aztec/src/test/helpers/txe_oracles.nr`.
7
7
  */
8
- export const TXE_ORACLE_VERSION_MAJOR = 3;
9
- export const TXE_ORACLE_VERSION_MINOR = 0;
8
+ export const TXE_ORACLE_VERSION_MAJOR = 4;
9
+ export const TXE_ORACLE_VERSION_MINOR = 1;
10
10
 
11
11
  /**
12
- * This hash is computed from the TXE oracle interfaces (IAvmExecutionOracle and ITxeExecutionOracle) and is used to
12
+ * This hash is computed from the TXE-specific entries in `TXE_ORACLE_REGISTRY` and is used to
13
13
  * detect when those interfaces change. When it does, bump:
14
14
  * - TXE_ORACLE_VERSION_MAJOR (and reset MINOR to 0) for breaking changes, or
15
15
  * - TXE_ORACLE_VERSION_MINOR for additive changes (new oracle method added).
16
16
  */
17
- export const TXE_ORACLE_INTERFACE_HASH = 'bea75bd85baebd7aa1438efb1defab496d27540bc805a8d854bb74b8d45fd859';
17
+ export const TXE_ORACLE_INTERFACE_HASH = '1a6c578d0a47cd8dd7dae07fd00abe781225a73920c596d873afcc061c0e4284';
@@ -188,7 +188,7 @@ export class RPCTranslator {
188
188
  return callTxeHandler({
189
189
  oracle: 'aztec_txe_createAccount',
190
190
  inputs,
191
- handler: ([secret]) => this.handlerAsTxe().createAccount(secret),
191
+ handler: ([secret, partialAddress]) => this.handlerAsTxe().createAccount(secret, partialAddress),
192
192
  });
193
193
  }
194
194
 
@@ -230,6 +230,15 @@ export class RPCTranslator {
230
230
  });
231
231
  }
232
232
 
233
+ // eslint-disable-next-line camelcase
234
+ aztec_txe_setAuthorizeAllUtilityCallTargets(...inputs: ForeignCallArgs) {
235
+ return callTxeHandler({
236
+ oracle: 'aztec_txe_setAuthorizeAllUtilityCallTargets',
237
+ inputs,
238
+ handler: ([authorizeAll]) => this.handlerAsTxe().setAuthorizeAllUtilityCallTargets(authorizeAll),
239
+ });
240
+ }
241
+
233
242
  // PXE oracles
234
243
 
235
244
  // eslint-disable-next-line camelcase
@@ -633,6 +642,15 @@ export class RPCTranslator {
633
642
  });
634
643
  }
635
644
 
645
+ // eslint-disable-next-line camelcase
646
+ aztec_utl_getTxEffects(...inputs: ForeignCallArgs) {
647
+ return callTxeHandler({
648
+ oracle: 'aztec_utl_getTxEffects',
649
+ inputs,
650
+ handler: ([txHashes]) => this.handlerAsUtility().getTxEffects(txHashes),
651
+ });
652
+ }
653
+
636
654
  // eslint-disable-next-line camelcase
637
655
  aztec_utl_setCapsule(...inputs: ForeignCallArgs) {
638
656
  return callTxeHandler({
@@ -894,6 +912,16 @@ export class RPCTranslator {
894
912
  });
895
913
  }
896
914
 
915
+ // eslint-disable-next-line camelcase
916
+ aztec_utl_callUtilityFunction(...inputs: ForeignCallArgs) {
917
+ return callTxeHandler({
918
+ oracle: 'aztec_utl_callUtilityFunction',
919
+ inputs,
920
+ handler: ([contractAddress, functionSelector, args]) =>
921
+ this.handlerAsUtility().callUtilityFunction(contractAddress, functionSelector, args),
922
+ });
923
+ }
924
+
897
925
  // AVM opcodes
898
926
 
899
927
  // eslint-disable-next-line camelcase
@@ -104,4 +104,8 @@ export class MockEpochCache implements EpochCacheInterface {
104
104
  getL1Constants(): L1RollupConstants {
105
105
  return EmptyL1RollupConstants;
106
106
  }
107
+
108
+ getLagInEpochsForValidatorSet(): number {
109
+ return 0;
110
+ }
107
111
  }
@@ -2,6 +2,7 @@ import { NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/constants';
2
2
  import { BlockNumber } from '@aztec/foundation/branded-types';
3
3
  import { padArrayEnd } from '@aztec/foundation/collection';
4
4
  import { Fr } from '@aztec/foundation/curves/bn254';
5
+ import { AvmSimulatorPool } from '@aztec/simulator/server';
5
6
  import type { BlockHash, L2Block } from '@aztec/stdlib/block';
6
7
  import type {
7
8
  MerkleTreeReadOperations,
@@ -16,12 +17,21 @@ export class TXESynchronizer implements WorldStateSynchronizer {
16
17
  // This works when set to 1 as well.
17
18
  private blockNumber = BlockNumber.ZERO;
18
19
 
20
+ /** AVM execution backend (simulator pool + CDB server) shared across all public simulations. */
21
+ public avmSimulator!: AvmSimulatorPool;
22
+
19
23
  constructor(public nativeWorldStateService: NativeWorldStateService) {}
20
24
 
21
25
  static async create() {
22
26
  const nativeWorldStateService = await NativeWorldStateService.ephemeral();
23
27
 
24
- 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;
25
35
  }
26
36
 
27
37
  public async handleL2Block(block: L2Block, l1ToL2Messages: Fr[] = []) {
@@ -76,8 +86,8 @@ export class TXESynchronizer implements WorldStateSynchronizer {
76
86
  throw new Error('TXE Synchronizer does not implement "status"');
77
87
  }
78
88
 
79
- public stop(): Promise<void> {
80
- throw new Error('TXE Synchronizer does not implement "stop"');
89
+ public async stop(): Promise<void> {
90
+ await this.closeIpc();
81
91
  }
82
92
 
83
93
  public stopSync(): Promise<void> {
@@ -91,4 +101,9 @@ export class TXESynchronizer implements WorldStateSynchronizer {
91
101
  public clear(): Promise<void> {
92
102
  throw new Error('TXE Synchronizer does not implement "clear"');
93
103
  }
104
+
105
+ /** Clean up IPC resources. */
106
+ public async closeIpc(): Promise<void> {
107
+ await this.avmSimulator?.[Symbol.asyncDispose]();
108
+ }
94
109
  }
@@ -63,7 +63,7 @@ import {
63
63
  } from './oracle/tagging_secret_strategy.js';
64
64
  import { TXEOraclePublicContext } from './oracle/txe_oracle_public_context.js';
65
65
  import { callTxeLegacyHandler } from './oracle/txe_oracle_registry.js';
66
- import { TXEOracleTopLevelContext } from './oracle/txe_oracle_top_level_context.js';
66
+ import { TXEOracleTopLevelContext, authorizeAllUtilityCallsHook } from './oracle/txe_oracle_top_level_context.js';
67
67
  import { TXE_ORACLE_VERSION_MAJOR, TXE_ORACLE_VERSION_MINOR } from './oracle/txe_oracle_version.js';
68
68
  import { TXEPrivateExecutionOracle } from './oracle/txe_private_execution_oracle.js';
69
69
  import { RPCTranslator, UnavailableOracleError } from './rpc_translator.js';
@@ -241,6 +241,7 @@ export class TXESession implements TXESessionStateHandler {
241
241
  private state: SessionState = { name: 'TOP_LEVEL' };
242
242
  private authwits: Map<string, AuthWitness> = new Map();
243
243
  private taggingSecretStrategies: TXETaggingSecretStrategies = new Map();
244
+ private authorizeAllUtilityCallTargets = false;
244
245
  private lastCallInfo: LastCallState = emptyLastCallState();
245
246
  private txeOracleVersion: { major: number; minor: number } | undefined;
246
247
 
@@ -278,14 +279,22 @@ export class TXESession implements TXESessionStateHandler {
278
279
  ) {}
279
280
 
280
281
  /**
281
- * Closes the per-session `txe-session` LMDB and the `NativeWorldStateService` .
282
- * 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.
283
284
  */
284
285
  async dispose(): Promise<void> {
285
286
  if (this.disposed) {
286
287
  return;
287
288
  }
288
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
+ }
289
298
  try {
290
299
  await this.stateMachine.synchronizer.nativeWorldStateService.close();
291
300
  } catch (err) {
@@ -361,6 +370,7 @@ export class TXESession implements TXESessionStateHandler {
361
370
  chainId,
362
371
  new Map(),
363
372
  new Map(),
373
+ false, // authorizeAllUtilityCallTargets
364
374
  artifactResolver,
365
375
  rootPath,
366
376
  packageName,
@@ -691,6 +701,7 @@ export class TXESession implements TXESessionStateHandler {
691
701
  this.chainId,
692
702
  this.authwits,
693
703
  this.taggingSecretStrategies,
704
+ this.authorizeAllUtilityCallTargets,
694
705
  this.artifactResolver,
695
706
  this.rootPath,
696
707
  this.packageName,
@@ -769,9 +780,7 @@ export class TXESession implements TXESessionStateHandler {
769
780
  scopes: await this.keyStore.getAccounts(),
770
781
  txResolver: this.stateMachine.txResolver,
771
782
  simulator: new WASMSimulator(),
772
- hooks: composeHooks({
773
- resolveTaggingSecretStrategy: makeResolveTaggingSecretStrategyHook(this.taggingSecretStrategies),
774
- }),
783
+ hooks: this.buildExecutionHooks(),
775
784
  transientArrayService,
776
785
  });
777
786
 
@@ -871,6 +880,7 @@ export class TXESession implements TXESessionStateHandler {
871
880
  scopes: await this.keyStore.getAccounts(),
872
881
  simulator: new WASMSimulator(),
873
882
  utilityExecutor: this.utilityExecutorForContractSync(anchorBlockHeader),
883
+ hooks: this.buildExecutionHooks(),
874
884
  // Execution-tree root (top-level utility run): own store; nested frames inherit it.
875
885
  transientArrayService: new TransientArrayService(),
876
886
  });
@@ -899,9 +909,12 @@ export class TXESession implements TXESessionStateHandler {
899
909
  // TODO: persisting authwits this way is quite unfortunate: they create a temporary utility context that would
900
910
  // otherwise reset them, so we'd not be able to pass more than one per execution. Ideally authwits would be passed
901
911
  // alongside a contract call instead of pre-seeded.
902
- [this.nextBlockTimestamp, this.authwits, this.taggingSecretStrategies] = (
903
- this.oracleHandler as TXEOracleTopLevelContext
904
- ).close();
912
+ ({
913
+ nextBlockTimestamp: this.nextBlockTimestamp,
914
+ authwits: this.authwits,
915
+ taggingSecretStrategies: this.taggingSecretStrategies,
916
+ authorizeAllUtilityCallTargets: this.authorizeAllUtilityCallTargets,
917
+ } = (this.oracleHandler as TXEOracleTopLevelContext).close());
905
918
  }
906
919
 
907
920
  private async exitPrivateState() {
@@ -995,6 +1008,7 @@ export class TXESession implements TXESessionStateHandler {
995
1008
  scopes,
996
1009
  simulator,
997
1010
  utilityExecutor: this.utilityExecutorForContractSync(anchorBlock),
1011
+ hooks: this.buildExecutionHooks(),
998
1012
  // Top-level utility entrypoint: gets a fresh store. Nested frames inherit it via UtilityExecutionOracle.
999
1013
  transientArrayService: new TransientArrayService(),
1000
1014
  });
@@ -1017,4 +1031,12 @@ export class TXESession implements TXESessionStateHandler {
1017
1031
  }
1018
1032
  };
1019
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
+ }
1020
1042
  }