@aztec/txe 0.0.1-commit.a072138 → 0.0.1-commit.a5db02d

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