@aztec/txe 0.0.1-commit.d431d1c → 0.0.1-commit.d58ff9d0

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 (174) 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.d.ts +2 -0
  18. package/dest/bin/check_txe_oracle_version.d.ts.map +1 -0
  19. package/dest/bin/check_txe_oracle_version.js +53 -0
  20. package/dest/bin/index.js +3 -30
  21. package/dest/bin/index.js.map +7 -0
  22. package/dest/bin/oracle_test_server.d.ts +3 -0
  23. package/dest/bin/oracle_test_server.d.ts.map +1 -0
  24. package/dest/bin/oracle_test_server.js +41 -0
  25. package/dest/chunk-32UHX7YY.js +3 -0
  26. package/dest/chunk-32UHX7YY.js.map +7 -0
  27. package/dest/chunk-GSUKUCKV.js +260 -0
  28. package/dest/chunk-GSUKUCKV.js.map +7 -0
  29. package/dest/chunk-UP4KKUVA.js +304 -0
  30. package/dest/chunk-UP4KKUVA.js.map +7 -0
  31. package/dest/constants.d.ts +5 -1
  32. package/dest/constants.d.ts.map +1 -1
  33. package/dest/constants.js +9 -1
  34. package/dest/dispatcher_pool.d.ts +67 -0
  35. package/dest/dispatcher_pool.d.ts.map +1 -0
  36. package/dest/dispatcher_pool.js +286 -0
  37. package/dest/index.d.ts +51 -7
  38. package/dest/index.d.ts.map +1 -1
  39. package/dest/index.js +73 -157
  40. package/dest/metafile.json +38759 -0
  41. package/dest/msgpackr_fr_extension.d.ts +2 -0
  42. package/dest/msgpackr_fr_extension.d.ts.map +1 -0
  43. package/dest/msgpackr_fr_extension.js +21 -0
  44. package/dest/oracle/interfaces.d.ts +69 -30
  45. package/dest/oracle/interfaces.d.ts.map +1 -1
  46. package/dest/oracle/tagging_secret_strategy.d.ts +12 -0
  47. package/dest/oracle/tagging_secret_strategy.d.ts.map +1 -0
  48. package/dest/oracle/tagging_secret_strategy.js +12 -0
  49. package/dest/oracle/test-resolver/default_fixtures.d.ts +16 -0
  50. package/dest/oracle/test-resolver/default_fixtures.d.ts.map +1 -0
  51. package/dest/oracle/test-resolver/default_fixtures.js +200 -0
  52. package/dest/oracle/test-resolver/index.d.ts +9 -0
  53. package/dest/oracle/test-resolver/index.d.ts.map +1 -0
  54. package/dest/oracle/test-resolver/index.js +32 -0
  55. package/dest/oracle/test-resolver/resolver.d.ts +48 -0
  56. package/dest/oracle/test-resolver/resolver.d.ts.map +1 -0
  57. package/dest/oracle/test-resolver/resolver.js +181 -0
  58. package/dest/oracle/txe_oracle_public_context.d.ts +40 -16
  59. package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
  60. package/dest/oracle/txe_oracle_public_context.js +65 -17
  61. package/dest/oracle/txe_oracle_registry.d.ts +172 -0
  62. package/dest/oracle/txe_oracle_registry.d.ts.map +1 -0
  63. package/dest/oracle/txe_oracle_registry.js +767 -0
  64. package/dest/oracle/txe_oracle_top_level_context.d.ts +69 -29
  65. package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
  66. package/dest/oracle/txe_oracle_top_level_context.js +608 -277
  67. package/dest/oracle/txe_oracle_version.d.ts +17 -0
  68. package/dest/oracle/txe_oracle_version.d.ts.map +1 -0
  69. package/dest/oracle/txe_oracle_version.js +14 -0
  70. package/dest/oracle/txe_private_execution_oracle.d.ts +17 -0
  71. package/dest/oracle/txe_private_execution_oracle.d.ts.map +1 -0
  72. package/dest/oracle/txe_private_execution_oracle.js +15 -0
  73. package/dest/rpc_server.d.ts +14 -0
  74. package/dest/rpc_server.d.ts.map +1 -0
  75. package/dest/rpc_server.js +78 -0
  76. package/dest/rpc_translator.d.ts +115 -222
  77. package/dest/rpc_translator.d.ts.map +1 -1
  78. package/dest/rpc_translator.js +901 -600
  79. package/dest/server.bundle.js +3 -0
  80. package/dest/server.bundle.js.map +7 -0
  81. package/dest/state_machine/archiver.d.ts +7 -6
  82. package/dest/state_machine/archiver.d.ts.map +1 -1
  83. package/dest/state_machine/archiver.js +31 -22
  84. package/dest/state_machine/dummy_p2p_client.d.ts +29 -16
  85. package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
  86. package/dest/state_machine/dummy_p2p_client.js +53 -20
  87. package/dest/state_machine/global_variable_builder.d.ts +10 -6
  88. package/dest/state_machine/global_variable_builder.d.ts.map +1 -1
  89. package/dest/state_machine/global_variable_builder.js +8 -5
  90. package/dest/state_machine/index.d.ts +13 -7
  91. package/dest/state_machine/index.d.ts.map +1 -1
  92. package/dest/state_machine/index.js +75 -21
  93. package/dest/state_machine/mock_epoch_cache.d.ts +21 -4
  94. package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
  95. package/dest/state_machine/mock_epoch_cache.js +35 -3
  96. package/dest/state_machine/synchronizer.d.ts +14 -6
  97. package/dest/state_machine/synchronizer.d.ts.map +1 -1
  98. package/dest/state_machine/synchronizer.js +22 -9
  99. package/dest/txe_session.d.ts +90 -16
  100. package/dest/txe_session.d.ts.map +1 -1
  101. package/dest/txe_session.js +381 -59
  102. package/dest/utils/block_creation.d.ts +6 -6
  103. package/dest/utils/block_creation.d.ts.map +1 -1
  104. package/dest/utils/block_creation.js +9 -7
  105. package/dest/utils/encoding.d.ts +192 -0
  106. package/dest/utils/encoding.d.ts.map +1 -0
  107. package/dest/{util → utils}/encoding.js +7 -2
  108. package/dest/{util → utils}/expected_failure_error.d.ts +1 -1
  109. package/dest/utils/expected_failure_error.d.ts.map +1 -0
  110. package/dest/utils/tx_effect_creation.d.ts +1 -1
  111. package/dest/utils/tx_effect_creation.d.ts.map +1 -1
  112. package/dest/utils/tx_effect_creation.js +0 -1
  113. package/dest/{util → utils}/txe_account_store.d.ts +1 -1
  114. package/dest/utils/txe_account_store.d.ts.map +1 -0
  115. package/dest/utils/txe_artifact_resolver.d.ts +37 -0
  116. package/dest/utils/txe_artifact_resolver.d.ts.map +1 -0
  117. package/dest/utils/txe_artifact_resolver.js +161 -0
  118. package/dest/utils/txe_public_contract_data_source.d.ts +20 -0
  119. package/dest/utils/txe_public_contract_data_source.d.ts.map +1 -0
  120. package/dest/utils/txe_public_contract_data_source.js +51 -0
  121. package/dest/worker.bundle.js +3 -0
  122. package/dest/worker.bundle.js.map +7 -0
  123. package/dest/worker.d.ts +2 -0
  124. package/dest/worker.d.ts.map +1 -0
  125. package/dest/worker.js +92 -0
  126. package/package.json +38 -21
  127. package/src/bin/check_txe_oracle_version.ts +67 -0
  128. package/src/bin/index.ts +11 -2
  129. package/src/bin/oracle_test_server.ts +51 -0
  130. package/src/constants.ts +11 -1
  131. package/src/dispatcher_pool.ts +317 -0
  132. package/src/index.ts +99 -190
  133. package/src/msgpackr_fr_extension.ts +23 -0
  134. package/src/oracle/interfaces.ts +75 -35
  135. package/src/oracle/tagging_secret_strategy.ts +25 -0
  136. package/src/oracle/test-resolver/default_fixtures.ts +271 -0
  137. package/src/oracle/test-resolver/index.ts +44 -0
  138. package/src/oracle/test-resolver/resolver.ts +245 -0
  139. package/src/oracle/txe_oracle_public_context.ts +80 -20
  140. package/src/oracle/txe_oracle_registry.ts +556 -0
  141. package/src/oracle/txe_oracle_top_level_context.ts +486 -180
  142. package/src/oracle/txe_oracle_version.ts +17 -0
  143. package/src/oracle/txe_private_execution_oracle.ts +30 -0
  144. package/src/rpc_server.ts +87 -0
  145. package/src/rpc_translator.ts +1116 -974
  146. package/src/state_machine/archiver.ts +45 -26
  147. package/src/state_machine/dummy_p2p_client.ts +83 -32
  148. package/src/state_machine/global_variable_builder.ts +12 -11
  149. package/src/state_machine/index.ts +105 -40
  150. package/src/state_machine/mock_epoch_cache.ts +45 -4
  151. package/src/state_machine/synchronizer.ts +31 -10
  152. package/src/txe_session.ts +630 -129
  153. package/src/utils/block_creation.ts +10 -7
  154. package/src/{util → utils}/encoding.ts +8 -2
  155. package/src/utils/tx_effect_creation.ts +0 -2
  156. package/src/utils/txe_artifact_resolver.ts +217 -0
  157. package/src/utils/txe_public_contract_data_source.ts +60 -0
  158. package/src/worker.ts +98 -0
  159. package/dest/util/encoding.d.ts +0 -720
  160. package/dest/util/encoding.d.ts.map +0 -1
  161. package/dest/util/expected_failure_error.d.ts.map +0 -1
  162. package/dest/util/txe_account_store.d.ts.map +0 -1
  163. package/dest/util/txe_contract_store.d.ts +0 -12
  164. package/dest/util/txe_contract_store.d.ts.map +0 -1
  165. package/dest/util/txe_contract_store.js +0 -22
  166. package/dest/util/txe_public_contract_data_source.d.ts +0 -21
  167. package/dest/util/txe_public_contract_data_source.d.ts.map +0 -1
  168. package/dest/util/txe_public_contract_data_source.js +0 -67
  169. package/src/util/txe_contract_store.ts +0 -36
  170. package/src/util/txe_public_contract_data_source.ts +0 -86
  171. /package/dest/{util → utils}/expected_failure_error.js +0 -0
  172. /package/dest/{util → utils}/txe_account_store.js +0 -0
  173. /package/src/{util → utils}/expected_failure_error.ts +0 -0
  174. /package/src/{util → utils}/txe_account_store.ts +0 -0
@@ -1,36 +1,45 @@
1
1
  import {
2
2
  CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS,
3
- DEFAULT_DA_GAS_LIMIT,
4
- DEFAULT_L2_GAS_LIMIT,
5
- DEFAULT_TEARDOWN_DA_GAS_LIMIT,
6
- DEFAULT_TEARDOWN_L2_GAS_LIMIT,
3
+ MAX_PRIVATE_LOGS_PER_TX,
7
4
  NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
8
5
  } from '@aztec/constants';
9
6
  import { BlockNumber } from '@aztec/foundation/branded-types';
10
7
  import { Schnorr } from '@aztec/foundation/crypto/schnorr';
11
8
  import { Fr } from '@aztec/foundation/curves/bn254';
9
+ import type { EthAddress } from '@aztec/foundation/eth-address';
12
10
  import { LogLevels, type Logger, applyStringFormatting, createLogger } from '@aztec/foundation/log';
13
11
  import { TestDateProvider } from '@aztec/foundation/timer';
14
12
  import type { KeyStore } from '@aztec/key-store';
15
13
  import {
16
14
  AddressStore,
15
+ AnchoredContractData,
16
+ CapsuleService,
17
17
  CapsuleStore,
18
+ type ContractStore,
19
+ type ExecutionHooks,
20
+ FactService,
21
+ FactStore,
18
22
  NoteStore,
19
- ORACLE_VERSION,
23
+ ORACLE_VERSION_MAJOR,
20
24
  PrivateEventStore,
21
25
  RecipientTaggingStore,
22
- SenderAddressBookStore,
23
26
  SenderTaggingStore,
27
+ TaggingSecretSourcesStore,
28
+ type TaggingSecretStrategy,
29
+ composeHooks,
24
30
  enrichPublicSimulationError,
25
31
  } from '@aztec/pxe/server';
26
32
  import {
33
+ CONTRACT_INSTANCE,
27
34
  ExecutionNoteCache,
28
35
  ExecutionTaggingIndexCache,
29
36
  HashedValuesCache,
30
37
  type IMiscOracle,
31
- Oracle,
38
+ type Option,
32
39
  PrivateExecutionOracle,
40
+ TransientArrayService,
33
41
  UtilityExecutionOracle,
42
+ buildACIRCallback,
34
43
  executePrivateFunction,
35
44
  generateSimulatedProvingResult,
36
45
  } from '@aztec/pxe/simulator';
@@ -44,10 +53,10 @@ import {
44
53
  witnessMapToFields,
45
54
  } from '@aztec/simulator/client';
46
55
  import {
47
- CppPublicTxSimulator,
48
56
  GuardedMerkleTreeOperations,
49
57
  PublicContractsDB,
50
58
  PublicProcessor,
59
+ PublicTxSimulator,
51
60
  } from '@aztec/simulator/server';
52
61
  import { type ContractArtifact, EventSelector, FunctionCall, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
53
62
  import { AuthWitness } from '@aztec/stdlib/auth-witness';
@@ -62,6 +71,10 @@ import {
62
71
  PrivateToPublicAccumulatedData,
63
72
  PublicCallRequest,
64
73
  } from '@aztec/stdlib/kernel';
74
+ import { deriveKeys, hashPublicKey } from '@aztec/stdlib/keys';
75
+ import type { PrivateLog } from '@aztec/stdlib/logs';
76
+ import { AppTaggingSecretKind } from '@aztec/stdlib/logs';
77
+ import { L1Actor, L1ToL2Message, L2Actor } from '@aztec/stdlib/messaging';
65
78
  import { ChonkProof } from '@aztec/stdlib/proofs';
66
79
  import { makeGlobalVariables } from '@aztec/stdlib/testing';
67
80
  import { MerkleTreeId } from '@aztec/stdlib/trees';
@@ -78,15 +91,16 @@ import {
78
91
  collectNested,
79
92
  } from '@aztec/stdlib/tx';
80
93
  import type { UInt64 } from '@aztec/stdlib/types';
81
- import { ForkCheckpoint } from '@aztec/world-state';
94
+ import { ForkCheckpoint } from '@aztec/world-state/native';
82
95
 
83
- import { DEFAULT_ADDRESS } from '../constants.js';
96
+ import { DEFAULT_ADDRESS, MAX_PRIVATE_EVENTS_PER_TXE_QUERY, MAX_PRIVATE_EVENT_LEN } from '../constants.js';
84
97
  import type { TXEStateMachine } from '../state_machine/index.js';
85
- import type { TXEAccountStore } from '../util/txe_account_store.js';
86
- import type { TXEContractStore } from '../util/txe_contract_store.js';
87
- import { TXEPublicContractDataSource } from '../util/txe_public_contract_data_source.js';
88
98
  import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlock } from '../utils/block_creation.js';
99
+ import type { TXEAccountStore } from '../utils/txe_account_store.js';
100
+ import type { TXEArtifactResolver } from '../utils/txe_artifact_resolver.js';
101
+ import { TXEPublicContractDataSource } from '../utils/txe_public_contract_data_source.js';
89
102
  import type { ITxeExecutionOracle } from './interfaces.js';
103
+ import { type TXETaggingSecretStrategies, makeResolveTaggingSecretStrategyHook } from './tagging_secret_strategy.js';
90
104
 
91
105
  export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracle {
92
106
  isMisc = true as const;
@@ -96,69 +110,87 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
96
110
 
97
111
  constructor(
98
112
  private stateMachine: TXEStateMachine,
99
- private contractStore: TXEContractStore,
113
+ private contractStore: ContractStore,
100
114
  private noteStore: NoteStore,
101
115
  private keyStore: KeyStore,
102
116
  private addressStore: AddressStore,
103
117
  private accountStore: TXEAccountStore,
104
118
  private senderTaggingStore: SenderTaggingStore,
105
119
  private recipientTaggingStore: RecipientTaggingStore,
106
- private senderAddressBookStore: SenderAddressBookStore,
120
+ private taggingSecretSourcesStore: TaggingSecretSourcesStore,
107
121
  private capsuleStore: CapsuleStore,
122
+ private factStore: FactStore,
108
123
  private privateEventStore: PrivateEventStore,
109
- private jobId: string,
110
124
  private nextBlockTimestamp: bigint,
111
125
  private version: Fr,
112
126
  private chainId: Fr,
113
127
  private authwits: Map<string, AuthWitness>,
128
+ private taggingSecretStrategies: TXETaggingSecretStrategies,
129
+ private authorizeAllUtilityCallTargets: boolean,
130
+ private readonly artifactResolver: TXEArtifactResolver,
131
+ private readonly rootPath: string,
132
+ private readonly packageName: string,
114
133
  ) {
115
134
  this.logger = createLogger('txe:top_level_context');
116
135
  this.logger.debug('Entering Top Level Context');
117
136
  }
118
137
 
119
- utilityAssertCompatibleOracleVersion(version: number): void {
120
- if (version !== ORACLE_VERSION) {
138
+ private contractOracleVersion: { major: number; minor: number } | undefined;
139
+
140
+ assertCompatibleOracleVersion(major: number, minor: number): void {
141
+ if (major !== ORACLE_VERSION_MAJOR) {
142
+ const hint =
143
+ major > ORACLE_VERSION_MAJOR
144
+ ? 'The contract was compiled with a newer version of Aztec.nr than this aztec cli version supports. Upgrade your aztec cli version to a compatible version.'
145
+ : 'The contract was compiled with an older version of Aztec.nr than this aztec cli version supports. Recompile the contract with a compatible version of Aztec.nr.';
121
146
  throw new Error(
122
- `Incompatible oracle version. TXE is using version '${ORACLE_VERSION}', but got a request for '${version}'.`,
147
+ `Incompatible aztec cli version: ${hint} See https://docs.aztec.network/errors/8 (expected oracle major version ${ORACLE_VERSION_MAJOR}, got ${major})`,
123
148
  );
124
149
  }
150
+ this.contractOracleVersion = { major, minor };
151
+ }
152
+
153
+ // Prefixed with "nonOracleFunction" as it is not used as an oracle handler.
154
+ nonOracleFunctionGetContractOracleVersion(): { major: number; minor: number } | undefined {
155
+ return this.contractOracleVersion;
125
156
  }
126
157
 
127
158
  // This is typically only invoked in private contexts, but it is convenient to also have it in top-level for testing
128
159
  // setup.
129
- utilityGetRandomField(): Fr {
160
+ getRandomField(): Fr {
130
161
  return Fr.random();
131
162
  }
132
163
 
133
164
  // We instruct users to debug contracts via this oracle, so it makes sense that they'd expect it to also work in tests
134
- utilityDebugLog(level: number, message: string, fields: Fr[]): void {
165
+ log(level: number, message: string, _fieldsSize: number, fields: Fr[]): Promise<void> {
135
166
  if (!LogLevels[level]) {
136
- throw new Error(`Invalid debug log level: ${level}`);
167
+ throw new Error(`Invalid log level: ${level}`);
137
168
  }
138
169
  const levelName = LogLevels[level];
139
170
 
140
171
  this.logger[levelName](`${applyStringFormatting(message, fields)}`, { module: `${this.logger.module}:debug_log` });
172
+ return Promise.resolve();
141
173
  }
142
174
 
143
- txeGetDefaultAddress(): AztecAddress {
175
+ getDefaultAddress(): AztecAddress {
144
176
  return DEFAULT_ADDRESS;
145
177
  }
146
178
 
147
- async txeGetNextBlockNumber(): Promise<BlockNumber> {
179
+ async getNextBlockNumber(): Promise<BlockNumber> {
148
180
  return BlockNumber((await this.getLastBlockNumber()) + 1);
149
181
  }
150
182
 
151
- txeGetNextBlockTimestamp(): Promise<bigint> {
183
+ getNextBlockTimestamp(): Promise<bigint> {
152
184
  return Promise.resolve(this.nextBlockTimestamp);
153
185
  }
154
186
 
155
- async txeGetLastBlockTimestamp() {
156
- return (await this.stateMachine.node.getBlockHeader('latest'))!.globalVariables.timestamp;
187
+ async getLastBlockTimestamp() {
188
+ return (await this.stateMachine.node.getBlockData('latest'))!.header.globalVariables.timestamp;
157
189
  }
158
190
 
159
- async txeGetLastTxEffects() {
191
+ async getLastTxEffects(): Promise<{ txHash: TxHash; noteHashes: Fr[]; nullifiers: Fr[]; privateLogs: PrivateLog[] }> {
160
192
  const latestBlockNumber = await this.stateMachine.archiver.getBlockNumber();
161
- const block = await this.stateMachine.archiver.getBlock(latestBlockNumber);
193
+ const block = await this.stateMachine.archiver.getBlock({ number: latestBlockNumber });
162
194
 
163
195
  if (block!.body.txEffects.length != 1) {
164
196
  // Note that calls like env.mine() will result in blocks with no transactions, hitting this
@@ -167,11 +199,40 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
167
199
 
168
200
  const txEffects = block!.body.txEffects[0];
169
201
 
170
- return { txHash: txEffects.txHash, noteHashes: txEffects.noteHashes, nullifiers: txEffects.nullifiers };
202
+ const privateLogs = txEffects.privateLogs;
203
+ if (privateLogs.length > MAX_PRIVATE_LOGS_PER_TX) {
204
+ throw new Error(`${privateLogs.length} private logs exceed max ${MAX_PRIVATE_LOGS_PER_TX}`);
205
+ }
206
+
207
+ return {
208
+ txHash: txEffects.txHash,
209
+ noteHashes: txEffects.noteHashes,
210
+ nullifiers: txEffects.nullifiers,
211
+ privateLogs,
212
+ };
171
213
  }
172
214
 
173
- async txeGetPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress) {
174
- return (
215
+ async syncContractNonOracleMethod(contractAddress: AztecAddress, scope: AztecAddress, jobId: string) {
216
+ if (contractAddress.equals(DEFAULT_ADDRESS)) {
217
+ this.logger.debug(`Skipping sync in getPrivateEvents because the events correspond to the default address.`);
218
+ return;
219
+ }
220
+
221
+ const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
222
+ await this.stateMachine.contractSyncService.ensureContractSynced(
223
+ contractAddress,
224
+ null,
225
+ async (call, execScopes) => {
226
+ await this.executeUtilityCall(call, { scopes: execScopes, jobId });
227
+ },
228
+ blockHeader,
229
+ jobId,
230
+ [scope],
231
+ );
232
+ }
233
+
234
+ async getPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress) {
235
+ const events = (
175
236
  await this.privateEventStore.getPrivateEvents(selector, {
176
237
  contractAddress,
177
238
  scopes: [scope],
@@ -179,9 +240,18 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
179
240
  toBlock: (await this.getLastBlockNumber()) + 1,
180
241
  })
181
242
  ).map(e => e.packedEvent);
243
+
244
+ if (events.length > MAX_PRIVATE_EVENTS_PER_TXE_QUERY) {
245
+ throw new Error(`Array of length ${events.length} larger than maxLen ${MAX_PRIVATE_EVENTS_PER_TXE_QUERY}`);
246
+ }
247
+ if (events.some(e => e.length > MAX_PRIVATE_EVENT_LEN)) {
248
+ throw new Error(`Some private event has length larger than maxLen ${MAX_PRIVATE_EVENT_LEN}`);
249
+ }
250
+
251
+ return events;
182
252
  }
183
253
 
184
- async txeAdvanceBlocksBy(blocks: number) {
254
+ async advanceBlocksBy(blocks: number) {
185
255
  this.logger.debug(`time traveling ${blocks} blocks`);
186
256
 
187
257
  for (let i = 0; i < blocks; i++) {
@@ -189,39 +259,76 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
189
259
  }
190
260
  }
191
261
 
192
- txeAdvanceTimestampBy(duration: UInt64) {
262
+ advanceTimestampBy(duration: UInt64) {
193
263
  this.logger.debug(`time traveling ${duration} seconds`);
194
264
  this.nextBlockTimestamp += duration;
195
265
  }
196
266
 
197
- async txeDeploy(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
267
+ private deploymentNullifier(address: AztecAddress): Promise<Fr> {
268
+ return siloNullifier(AztecAddress.fromNumberUnsafe(CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS), address.toField());
269
+ }
270
+
271
+ async deploy(
272
+ contractPath: string,
273
+ initializer: string,
274
+ args: Fr[],
275
+ secret: Fr,
276
+ salt: Fr,
277
+ deployer: AztecAddress,
278
+ ): Promise<Fr[]> {
279
+ const { artifact, instance } = await this.artifactResolver.resolveDeployArtifact({
280
+ rootPath: this.rootPath,
281
+ packageName: this.packageName,
282
+ contractPath,
283
+ initializer,
284
+ args,
285
+ secret,
286
+ salt,
287
+ deployer,
288
+ });
289
+
198
290
  // Emit deployment nullifier
199
291
  await this.mineBlock({
200
- nullifiers: [
201
- await siloNullifier(
202
- AztecAddress.fromNumber(CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS),
203
- instance.address.toField(),
204
- ),
205
- ],
292
+ nullifiers: [await this.deploymentNullifier(instance.address)],
206
293
  });
207
294
 
208
295
  if (!secret.equals(Fr.ZERO)) {
209
- await this.txeAddAccount(artifact, instance, secret);
296
+ await this.registerContractAndAddAccount(artifact, instance, secret);
210
297
  } else {
211
298
  await this.contractStore.addContractInstance(instance);
212
- await this.contractStore.addContractArtifact(instance.currentContractClassId, artifact);
299
+ await this.contractStore.addContractArtifact(artifact);
213
300
  this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
214
301
  }
302
+
303
+ return CONTRACT_INSTANCE.serialization!.fn(instance).flat();
215
304
  }
216
305
 
217
- async txeAddAccount(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
306
+ /**
307
+ * Mines a single block containing only the deployment nullifiers for the contracts at the given addresses.
308
+ */
309
+ async mineDeploymentNullifiers(addresses: AztecAddress[]) {
310
+ await this.mineBlock({
311
+ nullifiers: await Promise.all(addresses.map(address => this.deploymentNullifier(address))),
312
+ });
313
+ }
314
+
315
+ async addAccount(secret: Fr) {
316
+ const { artifact, instance } = await this.artifactResolver.resolveAccountArtifact(secret);
317
+ return this.registerContractAndAddAccount(artifact, instance, secret);
318
+ }
319
+
320
+ private async registerContractAndAddAccount(
321
+ artifact: ContractArtifact,
322
+ instance: ContractInstanceWithAddress,
323
+ secret: Fr,
324
+ ) {
218
325
  const partialAddress = await computePartialAddress(instance);
219
326
 
220
327
  this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
221
328
  await this.contractStore.addContractInstance(instance);
222
- await this.contractStore.addContractArtifact(instance.currentContractClassId, artifact);
329
+ await this.contractStore.addContractArtifact(artifact);
223
330
 
224
- const completeAddress = await this.keyStore.addAccount(secret, partialAddress);
331
+ const completeAddress = await this.keyStore.addAccount(await deriveKeys(secret), partialAddress);
225
332
  await this.accountStore.setAccount(completeAddress.address, completeAddress);
226
333
  await this.addressStore.addCompleteAddress(completeAddress);
227
334
  this.logger.debug(`Created account ${completeAddress.address}`);
@@ -229,9 +336,8 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
229
336
  return completeAddress;
230
337
  }
231
338
 
232
- async txeCreateAccount(secret: Fr) {
233
- // This is a foot gun !
234
- const completeAddress = await this.keyStore.addAccount(secret, secret);
339
+ async createAccount(secret: Fr, partialAddress: Fr) {
340
+ const completeAddress = await this.keyStore.addAccount(await deriveKeys(secret), partialAddress);
235
341
  await this.accountStore.setAccount(completeAddress.address, completeAddress);
236
342
  await this.addressStore.addCompleteAddress(completeAddress);
237
343
  this.logger.debug(`Created account ${completeAddress.address}`);
@@ -239,27 +345,67 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
239
345
  return completeAddress;
240
346
  }
241
347
 
242
- async txeAddAuthWitness(address: AztecAddress, messageHash: Fr) {
348
+ async addAuthWitness(address: AztecAddress, messageHash: Fr) {
243
349
  const account = await this.accountStore.getAccount(address);
244
- const privateKey = await this.keyStore.getMasterSecretKey(account.publicKeys.masterIncomingViewingPublicKey);
350
+ const ivpkMHash = await hashPublicKey(account.publicKeys.ivpkM);
351
+ const privateKey = await this.keyStore.getMasterSecretKey(ivpkMHash);
245
352
 
246
353
  const schnorr = new Schnorr();
247
- const signature = await schnorr.constructSignature(messageHash.toBuffer(), privateKey);
354
+ const signature = await schnorr.constructSignature(messageHash, privateKey);
248
355
 
249
- const authWitness = new AuthWitness(messageHash, [...signature.toBuffer()]);
356
+ const authWitness = new AuthWitness(messageHash, signature.toLimbFields());
250
357
 
251
358
  this.authwits.set(authWitness.requestHash.toString(), authWitness);
252
359
  }
253
360
 
254
- async mineBlock(options: { nullifiers?: Fr[] } = {}) {
255
- const blockNumber = await this.txeGetNextBlockNumber();
361
+ setTaggingSecretStrategies(
362
+ unconstrainedStrategy: Option<TaggingSecretStrategy>,
363
+ constrainedStrategy: Option<TaggingSecretStrategy>,
364
+ ): void {
365
+ const apply = (mode: AppTaggingSecretKind, strategy: Option<TaggingSecretStrategy>) => {
366
+ if (strategy.isSome()) {
367
+ this.taggingSecretStrategies.set(mode, strategy.value);
368
+ } else {
369
+ this.taggingSecretStrategies.delete(mode);
370
+ }
371
+ };
372
+ apply(AppTaggingSecretKind.UNCONSTRAINED, unconstrainedStrategy);
373
+ apply(AppTaggingSecretKind.CONSTRAINED, constrainedStrategy);
374
+ }
375
+
376
+ setAuthorizeAllUtilityCallTargets(authorizeAll: boolean): void {
377
+ this.authorizeAllUtilityCallTargets = authorizeAll;
378
+ }
379
+
380
+ async sendL1ToL2Message(content: Fr, secretHash: Fr, sender: EthAddress, recipient: AztecAddress): Promise<Fr> {
381
+ // Messages are appended to the tree, so the next free slot is simply the current tree size.
382
+ const { size } = await this.stateMachine.synchronizer
383
+ .getCommitted()
384
+ .getTreeInfo(MerkleTreeId.L1_TO_L2_MESSAGE_TREE);
385
+ const leafIndex = new Fr(size);
386
+
387
+ const message = new L1ToL2Message(
388
+ new L1Actor(sender, this.chainId.toNumber()),
389
+ new L2Actor(recipient, this.version.toNumber()),
390
+ content,
391
+ secretHash,
392
+ leafIndex,
393
+ );
394
+
395
+ await this.mineBlock({ l1ToL2Messages: [message.hash()] });
396
+
397
+ return leafIndex;
398
+ }
399
+
400
+ async mineBlock(options: { nullifiers?: Fr[]; l1ToL2Messages?: Fr[] } = {}) {
401
+ const blockNumber = await this.getNextBlockNumber();
256
402
 
257
403
  const txEffect = TxEffect.empty();
258
404
  txEffect.nullifiers = [getSingleTxBlockRequestHash(blockNumber), ...(options.nullifiers ?? [])];
259
405
  txEffect.txHash = new TxHash(new Fr(blockNumber));
260
406
 
261
407
  const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
262
- await insertTxEffectIntoWorldTrees(txEffect, forkedWorldTrees);
408
+ await insertTxEffectIntoWorldTrees(txEffect, forkedWorldTrees, options.l1ToL2Messages ?? []);
263
409
 
264
410
  const globals = makeGlobalVariables(undefined, {
265
411
  blockNumber,
@@ -273,22 +419,33 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
273
419
 
274
420
  this.logger.info(`Created block ${blockNumber} with timestamp ${block.header.globalVariables.timestamp}`);
275
421
 
276
- await this.stateMachine.handleL2Block(block);
422
+ await this.stateMachine.handleL2Block(block, options.l1ToL2Messages ?? []);
277
423
  }
278
424
 
279
- async txePrivateCallNewFlow(
280
- from: AztecAddress,
425
+ async privateCallNewFlow(
426
+ from: AztecAddress | undefined,
281
427
  targetContractAddress: AztecAddress = AztecAddress.zero(),
282
428
  functionSelector: FunctionSelector = FunctionSelector.empty(),
283
429
  args: Fr[],
284
430
  argsHash: Fr = Fr.zero(),
285
431
  isStaticCall: boolean = false,
432
+ additionalScopes: AztecAddress[] = [],
433
+ jobId: string,
434
+ authorizedUtilityCallTargets: AztecAddress[],
435
+ gasSettings: GasSettings,
286
436
  ) {
437
+ const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
438
+ const anchoredContractData = new AnchoredContractData(
439
+ this.contractStore,
440
+ this.stateMachine.contractClassService,
441
+ blockHeader,
442
+ );
443
+
287
444
  this.logger.verbose(
288
- `Executing external function ${await this.contractStore.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`,
445
+ `Executing external function ${await anchoredContractData.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`,
289
446
  );
290
447
 
291
- const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
448
+ const artifact = await anchoredContractData.getFunctionArtifact(targetContractAddress, functionSelector);
292
449
  if (!artifact) {
293
450
  const message = functionSelector.equals(await FunctionSelector.fromSignature('verify_private_authwit(Field)'))
294
451
  ? 'Found no account contract artifact for a private authwit check - use `create_contract_account` instead of `create_light_account` for authwit support.'
@@ -296,25 +453,29 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
296
453
  throw new Error(message);
297
454
  }
298
455
 
456
+ const scopes = from === undefined ? additionalScopes : [from, ...additionalScopes];
457
+
299
458
  // Sync notes before executing private function to discover notes from previous transactions
300
- const utilityExecutor = async (call: FunctionCall) => {
301
- await this.executeUtilityCall(call);
459
+ const utilityExecutor = async (call: FunctionCall, execScopes: AztecAddress[]) => {
460
+ await this.executeUtilityCall(call, { scopes: execScopes, jobId });
302
461
  };
303
462
 
304
- await this.contractStore.syncPrivateState(targetContractAddress, functionSelector, utilityExecutor);
305
-
306
- const blockNumber = await this.txeGetNextBlockNumber();
463
+ await this.stateMachine.contractSyncService.ensureContractSynced(
464
+ targetContractAddress,
465
+ functionSelector,
466
+ utilityExecutor,
467
+ blockHeader,
468
+ jobId,
469
+ scopes,
470
+ );
307
471
 
308
- const callContext = new CallContext(from, targetContractAddress, functionSelector, isStaticCall);
472
+ const blockNumber = await this.getNextBlockNumber();
309
473
 
310
- const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
311
- const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
312
- const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
474
+ const msgSender = from ?? AztecAddress.NULL_MSG_SENDER;
475
+ const callContext = new CallContext(msgSender, targetContractAddress, functionSelector, isStaticCall);
313
476
 
314
477
  const txContext = new TxContext(this.chainId, this.version, gasSettings);
315
478
 
316
- const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
317
-
318
479
  const protocolNullifier = await computeProtocolNullifier(getSingleTxBlockRequestHash(blockNumber));
319
480
  const noteCache = new ExecutionNoteCache(protocolNullifier);
320
481
  // In production, the account contract sets the min revertible counter before calling the app function.
@@ -326,43 +487,50 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
326
487
 
327
488
  const simulator = new WASMSimulator();
328
489
 
329
- const privateExecutionOracle = new PrivateExecutionOracle(
490
+ const transientArrayService = new TransientArrayService();
491
+ const privateExecutionOracle = new PrivateExecutionOracle({
330
492
  argsHash,
331
493
  txContext,
494
+ txRequestSalt: Fr.ZERO,
332
495
  callContext,
333
- /** Header of a block whose state is used during private execution (not the block the transaction is included in). */
334
- blockHeader,
496
+ anchorBlockHeader: blockHeader,
335
497
  utilityExecutor,
336
- /** List of transient auth witnesses to be used during this simulation */
337
- Array.from(this.authwits.values()),
338
- /** List of transient auth witnesses to be used during this simulation */
339
- [],
340
- HashedValuesCache.create([new HashedValues(args, argsHash)]),
498
+ authWitnesses: Array.from(this.authwits.values()),
499
+ capsules: [],
500
+ executionCache: HashedValuesCache.create([new HashedValues(args, argsHash)]),
341
501
  noteCache,
342
502
  taggingIndexCache,
343
- this.contractStore,
344
- this.noteStore,
345
- this.keyStore,
346
- this.addressStore,
347
- this.stateMachine.node,
348
- this.stateMachine.anchorBlockStore,
349
- this.senderTaggingStore,
350
- this.recipientTaggingStore,
351
- this.senderAddressBookStore,
352
- this.capsuleStore,
353
- this.privateEventStore,
354
- this.jobId,
355
- 0, // totalPublicArgsCount
356
- minRevertibleSideEffectCounter, // (start) sideEffectCounter
357
- undefined, // log
358
- undefined, // scopes
359
- /**
360
- * In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
361
- * contract would perform, including setting senderForTags.
362
- */
363
- from,
503
+ anchoredContractData,
504
+ noteStore: this.noteStore,
505
+ keyStore: this.keyStore,
506
+ addressStore: this.addressStore,
507
+ aztecNode: this.stateMachine.node,
508
+ senderTaggingStore: this.senderTaggingStore,
509
+ recipientTaggingStore: this.recipientTaggingStore,
510
+ taggingSecretSourcesStore: this.taggingSecretSourcesStore,
511
+ capsuleService: new CapsuleService(this.capsuleStore, scopes),
512
+ factService: new FactService(this.factStore, scopes),
513
+ privateEventStore: this.privateEventStore,
514
+ contractSyncService: this.stateMachine.contractSyncService,
515
+ jobId,
516
+ totalPublicCalldataCount: 0,
517
+ sideEffectCounter: minRevertibleSideEffectCounter,
518
+ scopes,
519
+ // In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
520
+ // contract would perform, including setting senderForTags.
521
+ senderForTags: from,
364
522
  simulator,
365
- );
523
+ txResolver: this.stateMachine.txResolver,
524
+ l2TipsStore: this.stateMachine.l2TipsProvider,
525
+ hooks: composeHooks({
526
+ authorizeUtilityCall: this.buildAuthorizeUtilityCallHook(
527
+ isStaticCall ? 'private view' : 'private',
528
+ authorizedUtilityCallTargets,
529
+ ),
530
+ resolveTaggingSecretStrategy: makeResolveTaggingSecretStrategyHook(this.taggingSecretStrategies),
531
+ }),
532
+ transientArrayService,
533
+ });
366
534
 
367
535
  // Note: This is a slight modification of simulator.run without any of the checks. Maybe we should modify simulator.run with a boolean value to skip checks.
368
536
  let result: PrivateExecutionResult;
@@ -384,12 +552,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
384
552
  );
385
553
  const publicFunctionsCalldata = await Promise.all(
386
554
  publicCallRequests.map(async r => {
387
- const calldata = await privateExecutionOracle.privateLoadFromExecutionCache(r.calldataHash);
555
+ const calldata = await privateExecutionOracle.getHashPreimage(r.calldataHash);
388
556
  return new HashedValues(calldata, r.calldataHash);
389
557
  }),
390
558
  );
391
559
 
392
- noteCache.finish();
393
560
  const nonceGenerator = noteCache.getNonceGenerator();
394
561
  result = new PrivateExecutionResult(executionResult, nonceGenerator, publicFunctionsCalldata);
395
562
  } catch (err) {
@@ -401,7 +568,8 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
401
568
  // We pass the non-zero minRevertibleSideEffectCounter to make sure the side effects are split correctly.
402
569
  const { publicInputs } = await generateSimulatedProvingResult(
403
570
  result,
404
- this.contractStore,
571
+ (addr, sel) => anchoredContractData.getDebugFunctionName(addr, sel),
572
+ this.stateMachine.node,
405
573
  minRevertibleSideEffectCounter,
406
574
  );
407
575
 
@@ -412,9 +580,13 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
412
580
  globals.version = this.version;
413
581
  globals.gasFees = GasFees.empty();
414
582
 
415
- const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
583
+ await using forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
416
584
 
417
- const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(blockNumber, this.contractStore));
585
+ const bindings = this.logger.getBindings();
586
+ const contractsDB = new PublicContractsDB(
587
+ new TXEPublicContractDataSource(blockNumber, this.contractStore),
588
+ bindings,
589
+ );
418
590
  const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
419
591
  const config = PublicSimulatorConfig.from({
420
592
  skipFeeEnforcement: true,
@@ -423,12 +595,23 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
423
595
  collectStatistics: false,
424
596
  collectCallMetadata: true,
425
597
  });
598
+ // The AVM simulator reads this fork's contracts DB, scoped by fork id, for each simulation.
599
+ const forkId = forkedWorldTrees.getRevision().forkId;
426
600
  const processor = new PublicProcessor(
427
601
  globals,
428
602
  guardedMerkleTrees,
429
603
  contractsDB,
430
- new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config),
604
+ new PublicTxSimulator(
605
+ this.stateMachine.synchronizer.avmSimulator,
606
+ globals,
607
+ contractsDB,
608
+ forkId,
609
+ config,
610
+ bindings,
611
+ ),
431
612
  new TestDateProvider(),
613
+ undefined,
614
+ createLogger('simulator:public-processor', bindings),
432
615
  );
433
616
 
434
617
  const tx = await Tx.create({
@@ -453,7 +636,13 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
453
636
  } else if (!processedTx.revertCode.isOK()) {
454
637
  if (processedTx.revertReason) {
455
638
  try {
456
- await enrichPublicSimulationError(processedTx.revertReason, this.contractStore, this.logger);
639
+ await enrichPublicSimulationError(
640
+ processedTx.revertReason,
641
+ this.contractStore,
642
+ this.stateMachine.contractClassService,
643
+ await this.stateMachine.anchorBlockStore.getBlockHeader(),
644
+ this.logger,
645
+ );
457
646
  // eslint-disable-next-line no-empty
458
647
  } catch {}
459
648
  throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
@@ -462,11 +651,15 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
462
651
  }
463
652
  }
464
653
 
654
+ // Walk the nested private-call tree and collect every offchain effect the transaction emitted.
655
+ // PXE stores these on each `PrivateCallExecutionResult` and they never reach TXE via the
656
+ // `aztec_utl_emitOffchainEffect` foreign-call path (that path only fires at the top-level), so
657
+ // we pull them out here and the RPC wrapper will hand them to `TXESession` for buffering.
658
+ const offchainEffects = collectNested([executionResult], r => r.offchainEffects.map(e => e.data));
659
+
465
660
  if (isStaticCall) {
466
661
  await checkpoint!.revert();
467
-
468
- await forkedWorldTrees.close();
469
- return executionResult.returnValues ?? [];
662
+ return { returnValues: executionResult.returnValues ?? [], offchainEffects };
470
663
  }
471
664
 
472
665
  const txEffect = TxEffect.empty();
@@ -486,33 +679,31 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
486
679
 
487
680
  await this.stateMachine.handleL2Block(l2Block);
488
681
 
489
- await forkedWorldTrees.close();
490
-
491
- return executionResult.returnValues ?? [];
682
+ return { returnValues: executionResult.returnValues ?? [], offchainEffects };
492
683
  }
493
684
 
494
- async txePublicCallNewFlow(
495
- from: AztecAddress,
685
+ async publicCallNewFlow(
686
+ from: AztecAddress | undefined,
496
687
  targetContractAddress: AztecAddress,
497
688
  calldata: Fr[],
498
689
  isStaticCall: boolean,
690
+ gasSettings: GasSettings,
499
691
  ) {
500
- this.logger.verbose(
501
- `Executing public function ${await this.contractStore.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`,
692
+ const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
693
+ const anchoredContractData = new AnchoredContractData(
694
+ this.contractStore,
695
+ this.stateMachine.contractClassService,
696
+ anchorBlockHeader,
502
697
  );
503
698
 
504
- const blockNumber = await this.txeGetNextBlockNumber();
505
-
506
- const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
507
-
508
- const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
699
+ this.logger.verbose(
700
+ `Executing public function ${await anchoredContractData.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`,
701
+ );
509
702
 
510
- const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
703
+ const blockNumber = await this.getNextBlockNumber();
511
704
 
512
705
  const txContext = new TxContext(this.chainId, this.version, gasSettings);
513
706
 
514
- const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
515
-
516
707
  const calldataHash = await computeCalldataHash(calldata);
517
708
  const calldataHashedValues = new HashedValues(calldata, calldataHash);
518
709
 
@@ -523,9 +714,13 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
523
714
  globals.version = this.version;
524
715
  globals.gasFees = GasFees.empty();
525
716
 
526
- const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
717
+ await using forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
527
718
 
528
- const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(blockNumber, this.contractStore));
719
+ const bindings2 = this.logger.getBindings();
720
+ const contractsDB = new PublicContractsDB(
721
+ new TXEPublicContractDataSource(blockNumber, this.contractStore),
722
+ bindings2,
723
+ );
529
724
  const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
530
725
  const config = PublicSimulatorConfig.from({
531
726
  skipFeeEnforcement: true,
@@ -534,8 +729,25 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
534
729
  collectStatistics: false,
535
730
  collectCallMetadata: true,
536
731
  });
537
- const simulator = new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config);
538
- const processor = new PublicProcessor(globals, guardedMerkleTrees, contractsDB, simulator, new TestDateProvider());
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
+ );
742
+ const processor = new PublicProcessor(
743
+ globals,
744
+ guardedMerkleTrees,
745
+ contractsDB,
746
+ simulator,
747
+ new TestDateProvider(),
748
+ undefined,
749
+ createLogger('simulator:public-processor', bindings2),
750
+ );
539
751
 
540
752
  // We're simulating a scenario in which private execution immediately enqueues a public call and halts. The private
541
753
  // kernel init would in this case inject a nullifier with the transaction request hash as a non-revertible
@@ -548,7 +760,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
548
760
  // may require producing reverts.
549
761
  const revertibleAccumulatedData = PrivateToPublicAccumulatedData.empty();
550
762
  revertibleAccumulatedData.publicCallRequests[0] = new PublicCallRequest(
551
- from,
763
+ from ?? AztecAddress.NULL_MSG_SENDER,
552
764
  targetContractAddress,
553
765
  isStaticCall,
554
766
  calldataHash,
@@ -566,7 +778,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
566
778
  constantData,
567
779
  /*gasUsed=*/ new Gas(0, 0),
568
780
  /*feePayer=*/ AztecAddress.zero(),
569
- /*includeByTimestamp=*/ 0n,
781
+ /*expirationTimestamp=*/ 0n,
570
782
  inputsForPublic,
571
783
  undefined,
572
784
  );
@@ -593,7 +805,13 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
593
805
  } else if (!processedTx.revertCode.isOK()) {
594
806
  if (processedTx.revertReason) {
595
807
  try {
596
- await enrichPublicSimulationError(processedTx.revertReason, this.contractStore, this.logger);
808
+ await enrichPublicSimulationError(
809
+ processedTx.revertReason,
810
+ this.contractStore,
811
+ this.stateMachine.contractClassService,
812
+ anchorBlockHeader,
813
+ this.logger,
814
+ );
597
815
  // eslint-disable-next-line no-empty
598
816
  } catch {}
599
817
  throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
@@ -606,9 +824,6 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
606
824
 
607
825
  if (isStaticCall) {
608
826
  await checkpoint!.revert();
609
-
610
- await forkedWorldTrees.close();
611
-
612
827
  return returnValues ?? [];
613
828
  }
614
829
 
@@ -629,42 +844,80 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
629
844
 
630
845
  await this.stateMachine.handleL2Block(l2Block);
631
846
 
632
- await forkedWorldTrees.close();
633
-
634
847
  return returnValues ?? [];
635
848
  }
636
849
 
637
- async txeSimulateUtilityFunction(
850
+ async executeUtilityFunction(
851
+ from: AztecAddress | undefined,
638
852
  targetContractAddress: AztecAddress,
639
853
  functionSelector: FunctionSelector,
640
854
  args: Fr[],
855
+ jobId: string,
856
+ authorizedUtilityCallTargets: AztecAddress[],
641
857
  ) {
642
- const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
858
+ const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
859
+ const anchoredContractData = new AnchoredContractData(
860
+ this.contractStore,
861
+ this.stateMachine.contractClassService,
862
+ blockHeader,
863
+ );
864
+
865
+ const artifact = await anchoredContractData.getFunctionArtifact(targetContractAddress, functionSelector);
643
866
  if (!artifact) {
644
867
  throw new Error(`Cannot call ${functionSelector} as there is no artifact found at ${targetContractAddress}.`);
645
868
  }
646
869
 
647
870
  // Sync notes before executing utility function to discover notes from previous transactions
648
- await this.contractStore.syncPrivateState(targetContractAddress, functionSelector, async call => {
649
- await this.executeUtilityCall(call);
650
- });
651
-
652
- const call = new FunctionCall(
653
- artifact.name,
871
+ await this.stateMachine.contractSyncService.ensureContractSynced(
654
872
  targetContractAddress,
655
873
  functionSelector,
656
- FunctionType.UTILITY,
657
- false,
658
- false,
659
- args,
660
- [],
874
+ async (call, execScopes) => {
875
+ await this.executeUtilityCall(call, { scopes: execScopes, jobId });
876
+ },
877
+ blockHeader,
878
+ jobId,
879
+ await this.keyStore.getAccounts(),
661
880
  );
662
881
 
663
- return this.executeUtilityCall(call);
882
+ const call = FunctionCall.from({
883
+ name: artifact.name,
884
+ to: targetContractAddress,
885
+ selector: functionSelector,
886
+ type: FunctionType.UTILITY,
887
+ hideMsgSender: false,
888
+ isStatic: false,
889
+ args,
890
+ returnTypes: [],
891
+ });
892
+
893
+ return this.executeUtilityCall(call, {
894
+ from,
895
+ scopes: await this.keyStore.getAccounts(),
896
+ jobId,
897
+ authorizedUtilityCallTargets,
898
+ });
664
899
  }
665
900
 
666
- private async executeUtilityCall(call: FunctionCall): Promise<Fr[]> {
667
- const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
901
+ private async executeUtilityCall(
902
+ call: FunctionCall,
903
+ {
904
+ from = AztecAddress.NULL_MSG_SENDER,
905
+ scopes,
906
+ jobId,
907
+ authorizedUtilityCallTargets = [],
908
+ }: { from?: AztecAddress; scopes: AztecAddress[]; jobId: string; authorizedUtilityCallTargets?: AztecAddress[] },
909
+ ): Promise<Fr[]> {
910
+ const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
911
+ const anchoredContractData = new AnchoredContractData(
912
+ this.contractStore,
913
+ this.stateMachine.contractClassService,
914
+ anchorBlockHeader,
915
+ );
916
+
917
+ const entryPointArtifact = await anchoredContractData.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
918
+ if (!entryPointArtifact) {
919
+ throw new Error(`Cannot run function ${call.selector} on ${call.to}: the contract is not registered.`);
920
+ }
668
921
  if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
669
922
  throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
670
923
  }
@@ -675,26 +928,45 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
675
928
  });
676
929
 
677
930
  try {
678
- const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
679
- const oracle = new UtilityExecutionOracle(
680
- call.to,
681
- [],
682
- [],
931
+ const simulator = new WASMSimulator();
932
+ const utilityExecutor = async (syncCall: FunctionCall, execScopes: AztecAddress[]) => {
933
+ await this.executeUtilityCall(syncCall, { scopes: execScopes, jobId });
934
+ };
935
+ const oracle = new UtilityExecutionOracle({
936
+ callContext: CallContext.from({
937
+ msgSender: from,
938
+ contractAddress: call.to,
939
+ functionSelector: call.selector,
940
+ isStaticCall: true,
941
+ }),
942
+ authWitnesses: [],
943
+ capsules: [],
683
944
  anchorBlockHeader,
684
- this.contractStore,
685
- this.noteStore,
686
- this.keyStore,
687
- this.addressStore,
688
- this.stateMachine.node,
689
- this.stateMachine.anchorBlockStore,
690
- this.recipientTaggingStore,
691
- this.senderAddressBookStore,
692
- this.capsuleStore,
693
- this.privateEventStore,
694
- this.jobId,
695
- );
696
- const acirExecutionResult = await new WASMSimulator()
697
- .executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
945
+ anchoredContractData,
946
+ noteStore: this.noteStore,
947
+ keyStore: this.keyStore,
948
+ addressStore: this.addressStore,
949
+ aztecNode: this.stateMachine.node,
950
+ recipientTaggingStore: this.recipientTaggingStore,
951
+ taggingSecretSourcesStore: this.taggingSecretSourcesStore,
952
+ capsuleService: new CapsuleService(this.capsuleStore, scopes),
953
+ factService: new FactService(this.factStore, scopes),
954
+ privateEventStore: this.privateEventStore,
955
+ txResolver: this.stateMachine.txResolver,
956
+ contractSyncService: this.stateMachine.contractSyncService,
957
+ l2TipsStore: this.stateMachine.l2TipsProvider,
958
+ jobId,
959
+ scopes,
960
+ simulator,
961
+ hooks: composeHooks({
962
+ authorizeUtilityCall: this.buildAuthorizeUtilityCallHook('utility', authorizedUtilityCallTargets),
963
+ }),
964
+ utilityExecutor,
965
+ // Execution-tree root (top-level utility run or contract sync): own store; nested frames inherit it.
966
+ transientArrayService: new TransientArrayService(),
967
+ });
968
+ const acirExecutionResult = await simulator
969
+ .executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, buildACIRCallback(oracle))
698
970
  .catch((err: Error) => {
699
971
  err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
700
972
  throw new ExecutionError(
@@ -708,20 +980,54 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
708
980
  );
709
981
  });
710
982
 
711
- this.logger.verbose(`Utility simulation for ${call.to}.${call.selector} completed`);
983
+ this.logger.verbose(`Utility execution for ${call.to}.${call.selector} completed`);
712
984
  return witnessMapToFields(acirExecutionResult.returnWitness);
713
985
  } catch (err) {
714
- throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility simulation'));
986
+ throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility execution'));
715
987
  }
716
988
  }
717
989
 
718
- close(): [bigint, Map<string, AuthWitness>] {
990
+ close(): {
991
+ nextBlockTimestamp: bigint;
992
+ authwits: Map<string, AuthWitness>;
993
+ taggingSecretStrategies: TXETaggingSecretStrategies;
994
+ authorizeAllUtilityCallTargets: boolean;
995
+ } {
719
996
  this.logger.debug('Exiting Top Level Context');
720
- return [this.nextBlockTimestamp, this.authwits];
997
+ return {
998
+ nextBlockTimestamp: this.nextBlockTimestamp,
999
+ authwits: this.authwits,
1000
+ taggingSecretStrategies: this.taggingSecretStrategies,
1001
+ authorizeAllUtilityCallTargets: this.authorizeAllUtilityCallTargets,
1002
+ };
721
1003
  }
722
1004
 
723
1005
  private async getLastBlockNumber(): Promise<BlockNumber> {
724
- const header = await this.stateMachine.node.getBlockHeader('latest');
725
- return header ? header.globalVariables.blockNumber : BlockNumber.ZERO;
1006
+ const block = await this.stateMachine.node.getBlock('latest');
1007
+ return block ? block.header.globalVariables.blockNumber : BlockNumber.ZERO;
1008
+ }
1009
+
1010
+ private buildAuthorizeUtilityCallHook(
1011
+ callerContext: 'private' | 'private view' | 'utility',
1012
+ authorizedTargets: AztecAddress[],
1013
+ ): ExecutionHooks['authorizeUtilityCall'] | undefined {
1014
+ if (this.authorizeAllUtilityCallTargets) {
1015
+ return authorizeAllUtilityCallsHook;
1016
+ }
1017
+ if (authorizedTargets.length === 0) {
1018
+ return undefined;
1019
+ }
1020
+ return req =>
1021
+ Promise.resolve({
1022
+ authorized: req.callerContext === callerContext && authorizedTargets.some(t => t.equals(req.target)),
1023
+ });
726
1024
  }
727
1025
  }
1026
+
1027
+ /**
1028
+ * An `authorizeUtilityCall` hook that authorizes every cross-contract utility call.
1029
+ *
1030
+ * Backs the `aztec_txe_setAuthorizeAllUtilityCallTargets` oracle.
1031
+ */
1032
+ export const authorizeAllUtilityCallsHook: NonNullable<ExecutionHooks['authorizeUtilityCall']> = () =>
1033
+ Promise.resolve({ authorized: true });