@aztec/txe 0.0.1-commit.f504929 → 0.0.1-commit.f5a9928

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 (170) hide show
  1. package/dest/AuthRegistry-56AMRLSQ.js +3 -0
  2. package/dest/AuthRegistry-56AMRLSQ.js.map +7 -0
  3. package/dest/ContractClassRegistry-CRN27URB.js +3 -0
  4. package/dest/ContractClassRegistry-CRN27URB.js.map +7 -0
  5. package/dest/ContractInstanceRegistry-GRGL26IC.js +3 -0
  6. package/dest/ContractInstanceRegistry-GRGL26IC.js.map +7 -0
  7. package/dest/FeeJuice-J23RVHLW.js +3 -0
  8. package/dest/FeeJuice-J23RVHLW.js.map +7 -0
  9. package/dest/HandshakeRegistry-5.0.1-PEFCLEGP.js +3 -0
  10. package/dest/HandshakeRegistry-5.0.1-PEFCLEGP.js.map +7 -0
  11. package/dest/HandshakeRegistry-GNFACTEE.js +3 -0
  12. package/dest/HandshakeRegistry-GNFACTEE.js.map +7 -0
  13. package/dest/MultiCallEntrypoint-MIDICLQB.js +3 -0
  14. package/dest/MultiCallEntrypoint-MIDICLQB.js.map +7 -0
  15. package/dest/SchnorrAccount-ZRENHSMV.js +3 -0
  16. package/dest/SchnorrAccount-ZRENHSMV.js.map +7 -0
  17. package/dest/SchnorrInitializerlessAccount-L56LOFSV.js +3 -0
  18. package/dest/SchnorrInitializerlessAccount-L56LOFSV.js.map +7 -0
  19. package/dest/bin/check_txe_oracle_version.d.ts +2 -0
  20. package/dest/bin/check_txe_oracle_version.d.ts.map +1 -0
  21. package/dest/bin/check_txe_oracle_version.js +53 -0
  22. package/dest/bin/index.js +3 -30
  23. package/dest/bin/index.js.map +7 -0
  24. package/dest/bin/oracle_test_server.d.ts +3 -0
  25. package/dest/bin/oracle_test_server.d.ts.map +1 -0
  26. package/dest/bin/oracle_test_server.js +41 -0
  27. package/dest/chunk-BJVAAXNA.js +3 -0
  28. package/dest/chunk-BJVAAXNA.js.map +7 -0
  29. package/dest/chunk-C2WBKKGS.js +266 -0
  30. package/dest/chunk-C2WBKKGS.js.map +7 -0
  31. package/dest/chunk-OFS2CI6U.js +304 -0
  32. package/dest/chunk-OFS2CI6U.js.map +7 -0
  33. package/dest/constants.d.ts +5 -1
  34. package/dest/constants.d.ts.map +1 -1
  35. package/dest/constants.js +9 -1
  36. package/dest/dispatcher_pool.d.ts +67 -0
  37. package/dest/dispatcher_pool.d.ts.map +1 -0
  38. package/dest/dispatcher_pool.js +286 -0
  39. package/dest/index.d.ts +51 -7
  40. package/dest/index.d.ts.map +1 -1
  41. package/dest/index.js +72 -190
  42. package/dest/metafile.json +40416 -0
  43. package/dest/msgpackr_fr_extension.d.ts +2 -0
  44. package/dest/msgpackr_fr_extension.d.ts.map +1 -0
  45. package/dest/msgpackr_fr_extension.js +21 -0
  46. package/dest/oracle/interfaces.d.ts +47 -9
  47. package/dest/oracle/interfaces.d.ts.map +1 -1
  48. package/dest/oracle/tagging_secret_strategy.d.ts +12 -0
  49. package/dest/oracle/tagging_secret_strategy.d.ts.map +1 -0
  50. package/dest/oracle/tagging_secret_strategy.js +12 -0
  51. package/dest/oracle/test-resolver/default_fixtures.d.ts +16 -0
  52. package/dest/oracle/test-resolver/default_fixtures.d.ts.map +1 -0
  53. package/dest/oracle/test-resolver/default_fixtures.js +200 -0
  54. package/dest/oracle/test-resolver/index.d.ts +9 -0
  55. package/dest/oracle/test-resolver/index.d.ts.map +1 -0
  56. package/dest/oracle/test-resolver/index.js +32 -0
  57. package/dest/oracle/test-resolver/resolver.d.ts +48 -0
  58. package/dest/oracle/test-resolver/resolver.d.ts.map +1 -0
  59. package/dest/oracle/test-resolver/resolver.js +181 -0
  60. package/dest/oracle/txe_oracle_public_context.d.ts +26 -2
  61. package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
  62. package/dest/oracle/txe_oracle_public_context.js +49 -1
  63. package/dest/oracle/txe_oracle_registry.d.ts +172 -0
  64. package/dest/oracle/txe_oracle_registry.d.ts.map +1 -0
  65. package/dest/oracle/txe_oracle_registry.js +767 -0
  66. package/dest/oracle/txe_oracle_top_level_context.d.ts +58 -17
  67. package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
  68. package/dest/oracle/txe_oracle_top_level_context.js +259 -88
  69. package/dest/oracle/txe_oracle_version.d.ts +17 -0
  70. package/dest/oracle/txe_oracle_version.d.ts.map +1 -0
  71. package/dest/oracle/txe_oracle_version.js +14 -0
  72. package/dest/oracle/txe_private_execution_oracle.d.ts +17 -0
  73. package/dest/oracle/txe_private_execution_oracle.d.ts.map +1 -0
  74. package/dest/oracle/txe_private_execution_oracle.js +15 -0
  75. package/dest/rpc_server.d.ts +14 -0
  76. package/dest/rpc_server.d.ts.map +1 -0
  77. package/dest/rpc_server.js +78 -0
  78. package/dest/rpc_translator.d.ts +115 -228
  79. package/dest/rpc_translator.d.ts.map +1 -1
  80. package/dest/rpc_translator.js +791 -607
  81. package/dest/server.bundle.js +3 -0
  82. package/dest/server.bundle.js.map +7 -0
  83. package/dest/state_machine/archiver.d.ts +6 -5
  84. package/dest/state_machine/archiver.d.ts.map +1 -1
  85. package/dest/state_machine/archiver.js +28 -20
  86. package/dest/state_machine/dummy_p2p_client.d.ts +18 -8
  87. package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
  88. package/dest/state_machine/dummy_p2p_client.js +31 -4
  89. package/dest/state_machine/global_variable_builder.d.ts +10 -6
  90. package/dest/state_machine/global_variable_builder.d.ts.map +1 -1
  91. package/dest/state_machine/global_variable_builder.js +8 -5
  92. package/dest/state_machine/index.d.ts +11 -5
  93. package/dest/state_machine/index.d.ts.map +1 -1
  94. package/dest/state_machine/index.js +50 -10
  95. package/dest/state_machine/mock_epoch_cache.d.ts +16 -3
  96. package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
  97. package/dest/state_machine/mock_epoch_cache.js +29 -2
  98. package/dest/state_machine/synchronizer.d.ts +9 -6
  99. package/dest/state_machine/synchronizer.d.ts.map +1 -1
  100. package/dest/state_machine/synchronizer.js +10 -6
  101. package/dest/txe_session.d.ts +90 -19
  102. package/dest/txe_session.d.ts.map +1 -1
  103. package/dest/txe_session.js +315 -61
  104. package/dest/utils/block_creation.d.ts +2 -2
  105. package/dest/utils/block_creation.d.ts.map +1 -1
  106. package/dest/utils/block_creation.js +2 -2
  107. package/dest/utils/encoding.d.ts +192 -0
  108. package/dest/utils/encoding.d.ts.map +1 -0
  109. package/dest/{util → utils}/encoding.js +7 -2
  110. package/dest/{util → utils}/expected_failure_error.d.ts +1 -1
  111. package/dest/utils/expected_failure_error.d.ts.map +1 -0
  112. package/dest/utils/tx_effect_creation.d.ts +1 -1
  113. package/dest/utils/tx_effect_creation.d.ts.map +1 -1
  114. package/dest/utils/tx_effect_creation.js +0 -1
  115. package/dest/{util → utils}/txe_account_store.d.ts +1 -1
  116. package/dest/utils/txe_account_store.d.ts.map +1 -0
  117. package/dest/utils/txe_artifact_resolver.d.ts +37 -0
  118. package/dest/utils/txe_artifact_resolver.d.ts.map +1 -0
  119. package/dest/utils/txe_artifact_resolver.js +161 -0
  120. package/dest/utils/txe_public_contract_data_source.d.ts +20 -0
  121. package/dest/utils/txe_public_contract_data_source.d.ts.map +1 -0
  122. package/dest/{util → utils}/txe_public_contract_data_source.js +8 -7
  123. package/dest/worker.bundle.js +3 -0
  124. package/dest/worker.bundle.js.map +7 -0
  125. package/dest/worker.d.ts +2 -0
  126. package/dest/worker.d.ts.map +1 -0
  127. package/dest/worker.js +92 -0
  128. package/package.json +38 -21
  129. package/src/bin/check_txe_oracle_version.ts +67 -0
  130. package/src/bin/index.ts +11 -2
  131. package/src/bin/oracle_test_server.ts +51 -0
  132. package/src/constants.ts +11 -1
  133. package/src/dispatcher_pool.ts +317 -0
  134. package/src/index.ts +99 -227
  135. package/src/msgpackr_fr_extension.ts +23 -0
  136. package/src/oracle/interfaces.ts +47 -8
  137. package/src/oracle/tagging_secret_strategy.ts +25 -0
  138. package/src/oracle/test-resolver/default_fixtures.ts +271 -0
  139. package/src/oracle/test-resolver/index.ts +44 -0
  140. package/src/oracle/test-resolver/resolver.ts +245 -0
  141. package/src/oracle/txe_oracle_public_context.ts +62 -0
  142. package/src/oracle/txe_oracle_registry.ts +556 -0
  143. package/src/oracle/txe_oracle_top_level_context.ts +342 -97
  144. package/src/oracle/txe_oracle_version.ts +17 -0
  145. package/src/oracle/txe_private_execution_oracle.ts +30 -0
  146. package/src/rpc_server.ts +87 -0
  147. package/src/rpc_translator.ts +882 -870
  148. package/src/state_machine/archiver.ts +41 -20
  149. package/src/state_machine/dummy_p2p_client.ts +49 -12
  150. package/src/state_machine/global_variable_builder.ts +12 -11
  151. package/src/state_machine/index.ts +63 -28
  152. package/src/state_machine/mock_epoch_cache.ts +38 -3
  153. package/src/state_machine/synchronizer.ts +13 -7
  154. package/src/txe_session.ts +552 -75
  155. package/src/utils/block_creation.ts +2 -1
  156. package/src/{util → utils}/encoding.ts +8 -2
  157. package/src/utils/tx_effect_creation.ts +0 -2
  158. package/src/utils/txe_artifact_resolver.ts +217 -0
  159. package/src/{util → utils}/txe_public_contract_data_source.ts +6 -6
  160. package/src/worker.ts +98 -0
  161. package/dest/util/encoding.d.ts +0 -720
  162. package/dest/util/encoding.d.ts.map +0 -1
  163. package/dest/util/expected_failure_error.d.ts.map +0 -1
  164. package/dest/util/txe_account_store.d.ts.map +0 -1
  165. package/dest/util/txe_public_contract_data_source.d.ts +0 -20
  166. package/dest/util/txe_public_contract_data_source.d.ts.map +0 -1
  167. /package/dest/{util → utils}/expected_failure_error.js +0 -0
  168. /package/dest/{util → utils}/txe_account_store.js +0 -0
  169. /package/src/{util → utils}/expected_failure_error.ts +0 -0
  170. /package/src/{util → utils}/txe_account_store.ts +0 -0
@@ -1,38 +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
- import type { AccessScopes } from '@aztec/pxe/client/lazy';
16
13
  import {
17
14
  AddressStore,
15
+ AnchoredContractData,
16
+ CapsuleService,
18
17
  CapsuleStore,
19
18
  type ContractStore,
19
+ type ExecutionHooks,
20
+ FactService,
21
+ FactStore,
20
22
  NoteStore,
21
- ORACLE_VERSION,
23
+ ORACLE_VERSION_MAJOR,
22
24
  PrivateEventStore,
23
25
  RecipientTaggingStore,
24
- SenderAddressBookStore,
25
26
  SenderTaggingStore,
27
+ TaggingSecretSourcesStore,
28
+ type TaggingSecretStrategy,
29
+ composeHooks,
26
30
  enrichPublicSimulationError,
27
31
  } from '@aztec/pxe/server';
28
32
  import {
33
+ CONTRACT_INSTANCE,
29
34
  ExecutionNoteCache,
30
35
  ExecutionTaggingIndexCache,
31
36
  HashedValuesCache,
32
37
  type IMiscOracle,
33
- Oracle,
38
+ type Option,
34
39
  PrivateExecutionOracle,
40
+ TransientArrayService,
35
41
  UtilityExecutionOracle,
42
+ buildACIRCallback,
36
43
  executePrivateFunction,
37
44
  generateSimulatedProvingResult,
38
45
  } from '@aztec/pxe/simulator';
@@ -64,6 +71,10 @@ import {
64
71
  PrivateToPublicAccumulatedData,
65
72
  PublicCallRequest,
66
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';
67
78
  import { ChonkProof } from '@aztec/stdlib/proofs';
68
79
  import { makeGlobalVariables } from '@aztec/stdlib/testing';
69
80
  import { MerkleTreeId } from '@aztec/stdlib/trees';
@@ -80,14 +91,16 @@ import {
80
91
  collectNested,
81
92
  } from '@aztec/stdlib/tx';
82
93
  import type { UInt64 } from '@aztec/stdlib/types';
83
- import { ForkCheckpoint } from '@aztec/world-state';
94
+ import { ForkCheckpoint } from '@aztec/world-state/native';
84
95
 
85
- import { DEFAULT_ADDRESS } from '../constants.js';
96
+ import { DEFAULT_ADDRESS, MAX_PRIVATE_EVENTS_PER_TXE_QUERY, MAX_PRIVATE_EVENT_LEN } from '../constants.js';
86
97
  import type { TXEStateMachine } from '../state_machine/index.js';
87
- import type { TXEAccountStore } from '../util/txe_account_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;
@@ -104,24 +117,42 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
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
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
- assertCompatibleOracleVersion(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
@@ -131,7 +162,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
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
- log(level: number, message: string, fields: Fr[]): Promise<void> {
165
+ log(level: number, message: string, _fieldsSize: number, fields: Fr[]): Promise<void> {
135
166
  if (!LogLevels[level]) {
136
167
  throw new Error(`Invalid log level: ${level}`);
137
168
  }
@@ -154,12 +185,12 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
154
185
  }
155
186
 
156
187
  async getLastBlockTimestamp() {
157
- return (await this.stateMachine.node.getBlockHeader('latest'))!.globalVariables.timestamp;
188
+ return (await this.stateMachine.node.getBlockData('latest'))!.header.globalVariables.timestamp;
158
189
  }
159
190
 
160
- async getLastTxEffects() {
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,7 +199,17 @@ 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
+ };
172
213
  }
173
214
 
174
215
  async syncContractNonOracleMethod(contractAddress: AztecAddress, scope: AztecAddress, jobId: string) {
@@ -182,7 +223,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
182
223
  contractAddress,
183
224
  null,
184
225
  async (call, execScopes) => {
185
- await this.executeUtilityCall(call, execScopes, jobId);
226
+ await this.executeUtilityCall(call, { scopes: execScopes, jobId });
186
227
  },
187
228
  blockHeader,
188
229
  jobId,
@@ -191,7 +232,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
191
232
  }
192
233
 
193
234
  async getPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress) {
194
- return (
235
+ const events = (
195
236
  await this.privateEventStore.getPrivateEvents(selector, {
196
237
  contractAddress,
197
238
  scopes: [scope],
@@ -199,6 +240,15 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
199
240
  toBlock: (await this.getLastBlockNumber()) + 1,
200
241
  })
201
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;
202
252
  }
203
253
 
204
254
  async advanceBlocksBy(blocks: number) {
@@ -214,34 +264,71 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
214
264
  this.nextBlockTimestamp += duration;
215
265
  }
216
266
 
217
- async deploy(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
+
218
290
  // Emit deployment nullifier
219
291
  await this.mineBlock({
220
- nullifiers: [
221
- await siloNullifier(
222
- AztecAddress.fromNumber(CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS),
223
- instance.address.toField(),
224
- ),
225
- ],
292
+ nullifiers: [await this.deploymentNullifier(instance.address)],
226
293
  });
227
294
 
228
295
  if (!secret.equals(Fr.ZERO)) {
229
- await this.addAccount(artifact, instance, secret);
296
+ await this.registerContractAndAddAccount(artifact, instance, secret);
230
297
  } else {
231
298
  await this.contractStore.addContractInstance(instance);
232
299
  await this.contractStore.addContractArtifact(artifact);
233
300
  this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
234
301
  }
302
+
303
+ return CONTRACT_INSTANCE.serialization!.fn(instance).flat();
304
+ }
305
+
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
+ });
235
313
  }
236
314
 
237
- async addAccount(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
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
+ ) {
238
325
  const partialAddress = await computePartialAddress(instance);
239
326
 
240
327
  this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
241
328
  await this.contractStore.addContractInstance(instance);
242
329
  await this.contractStore.addContractArtifact(artifact);
243
330
 
244
- const completeAddress = await this.keyStore.addAccount(secret, partialAddress);
331
+ const completeAddress = await this.keyStore.addAccount(await deriveKeys(secret), partialAddress);
245
332
  await this.accountStore.setAccount(completeAddress.address, completeAddress);
246
333
  await this.addressStore.addCompleteAddress(completeAddress);
247
334
  this.logger.debug(`Created account ${completeAddress.address}`);
@@ -249,9 +336,8 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
249
336
  return completeAddress;
250
337
  }
251
338
 
252
- async createAccount(secret: Fr) {
253
- // This is a foot gun !
254
- 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);
255
341
  await this.accountStore.setAccount(completeAddress.address, completeAddress);
256
342
  await this.addressStore.addCompleteAddress(completeAddress);
257
343
  this.logger.debug(`Created account ${completeAddress.address}`);
@@ -261,17 +347,57 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
261
347
 
262
348
  async addAuthWitness(address: AztecAddress, messageHash: Fr) {
263
349
  const account = await this.accountStore.getAccount(address);
264
- 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);
265
352
 
266
353
  const schnorr = new Schnorr();
267
- const signature = await schnorr.constructSignature(messageHash.toBuffer(), privateKey);
354
+ const signature = await schnorr.constructSignature(messageHash, privateKey);
268
355
 
269
- const authWitness = new AuthWitness(messageHash, [...signature.toBuffer()]);
356
+ const authWitness = new AuthWitness(messageHash, signature.toLimbFields());
270
357
 
271
358
  this.authwits.set(authWitness.requestHash.toString(), authWitness);
272
359
  }
273
360
 
274
- async mineBlock(options: { nullifiers?: Fr[] } = {}) {
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[] } = {}) {
275
401
  const blockNumber = await this.getNextBlockNumber();
276
402
 
277
403
  const txEffect = TxEffect.empty();
@@ -279,7 +405,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
279
405
  txEffect.txHash = new TxHash(new Fr(blockNumber));
280
406
 
281
407
  const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
282
- await insertTxEffectIntoWorldTrees(txEffect, forkedWorldTrees);
408
+ await insertTxEffectIntoWorldTrees(txEffect, forkedWorldTrees, options.l1ToL2Messages ?? []);
283
409
 
284
410
  const globals = makeGlobalVariables(undefined, {
285
411
  blockNumber,
@@ -293,23 +419,33 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
293
419
 
294
420
  this.logger.info(`Created block ${blockNumber} with timestamp ${block.header.globalVariables.timestamp}`);
295
421
 
296
- await this.stateMachine.handleL2Block(block);
422
+ await this.stateMachine.handleL2Block(block, options.l1ToL2Messages ?? []);
297
423
  }
298
424
 
299
425
  async privateCallNewFlow(
300
- from: AztecAddress,
426
+ from: AztecAddress | undefined,
301
427
  targetContractAddress: AztecAddress = AztecAddress.zero(),
302
428
  functionSelector: FunctionSelector = FunctionSelector.empty(),
303
429
  args: Fr[],
304
430
  argsHash: Fr = Fr.zero(),
305
431
  isStaticCall: boolean = false,
432
+ additionalScopes: AztecAddress[] = [],
306
433
  jobId: string,
434
+ authorizedUtilityCallTargets: AztecAddress[],
435
+ gasSettings: GasSettings,
307
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
+
308
444
  this.logger.verbose(
309
- `Executing external function ${await this.contractStore.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`,
445
+ `Executing external function ${await anchoredContractData.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`,
310
446
  );
311
447
 
312
- const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
448
+ const artifact = await anchoredContractData.getFunctionArtifact(targetContractAddress, functionSelector);
313
449
  if (!artifact) {
314
450
  const message = functionSelector.equals(await FunctionSelector.fromSignature('verify_private_authwit(Field)'))
315
451
  ? 'Found no account contract artifact for a private authwit check - use `create_contract_account` instead of `create_light_account` for authwit support.'
@@ -317,32 +453,26 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
317
453
  throw new Error(message);
318
454
  }
319
455
 
320
- // When `from` is the zero address (e.g. when deploying a new account contract), we return an
321
- // empty scope list which acts as deny-all: no notes are visible and no keys are accessible.
322
- const effectiveScopes = from.isZero() ? [] : [from];
456
+ const scopes = from === undefined ? additionalScopes : [from, ...additionalScopes];
323
457
 
324
458
  // Sync notes before executing private function to discover notes from previous transactions
325
- const utilityExecutor = async (call: FunctionCall, execScopes: AccessScopes) => {
326
- await this.executeUtilityCall(call, execScopes, jobId);
459
+ const utilityExecutor = async (call: FunctionCall, execScopes: AztecAddress[]) => {
460
+ await this.executeUtilityCall(call, { scopes: execScopes, jobId });
327
461
  };
328
462
 
329
- const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
330
463
  await this.stateMachine.contractSyncService.ensureContractSynced(
331
464
  targetContractAddress,
332
465
  functionSelector,
333
466
  utilityExecutor,
334
467
  blockHeader,
335
468
  jobId,
336
- effectiveScopes,
469
+ scopes,
337
470
  );
338
471
 
339
472
  const blockNumber = await this.getNextBlockNumber();
340
473
 
341
- const callContext = new CallContext(from, targetContractAddress, functionSelector, isStaticCall);
342
-
343
- const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
344
- const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
345
- 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);
346
476
 
347
477
  const txContext = new TxContext(this.chainId, this.version, gasSettings);
348
478
 
@@ -357,9 +487,12 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
357
487
 
358
488
  const simulator = new WASMSimulator();
359
489
 
490
+ const transientArrayService = new TransientArrayService();
360
491
  const privateExecutionOracle = new PrivateExecutionOracle({
361
492
  argsHash,
362
493
  txContext,
494
+ // The TXE does not run the init kernel's salt binding, so no tx-request salt is in scope.
495
+ txRequestSalt: Fr.ZERO,
363
496
  callContext,
364
497
  anchorBlockHeader: blockHeader,
365
498
  utilityExecutor,
@@ -368,25 +501,36 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
368
501
  executionCache: HashedValuesCache.create([new HashedValues(args, argsHash)]),
369
502
  noteCache,
370
503
  taggingIndexCache,
371
- contractStore: this.contractStore,
504
+ anchoredContractData,
372
505
  noteStore: this.noteStore,
373
506
  keyStore: this.keyStore,
374
507
  addressStore: this.addressStore,
375
508
  aztecNode: this.stateMachine.node,
376
509
  senderTaggingStore: this.senderTaggingStore,
377
510
  recipientTaggingStore: this.recipientTaggingStore,
378
- senderAddressBookStore: this.senderAddressBookStore,
379
- capsuleStore: this.capsuleStore,
511
+ taggingSecretSourcesStore: this.taggingSecretSourcesStore,
512
+ capsuleService: new CapsuleService(this.capsuleStore, scopes),
513
+ factService: new FactService(this.factStore, scopes),
380
514
  privateEventStore: this.privateEventStore,
381
515
  contractSyncService: this.stateMachine.contractSyncService,
382
516
  jobId,
383
517
  totalPublicCalldataCount: 0,
384
518
  sideEffectCounter: minRevertibleSideEffectCounter,
385
- scopes: effectiveScopes,
519
+ scopes,
386
520
  // In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
387
521
  // contract would perform, including setting senderForTags.
388
522
  senderForTags: from,
389
523
  simulator,
524
+ txResolver: this.stateMachine.txResolver,
525
+ l2TipsStore: this.stateMachine.l2TipsProvider,
526
+ hooks: composeHooks({
527
+ authorizeUtilityCall: this.buildAuthorizeUtilityCallHook(
528
+ isStaticCall ? 'private view' : 'private',
529
+ authorizedUtilityCallTargets,
530
+ ),
531
+ resolveTaggingSecretStrategy: makeResolveTaggingSecretStrategyHook(this.taggingSecretStrategies),
532
+ }),
533
+ transientArrayService,
390
534
  });
391
535
 
392
536
  // 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.
@@ -409,12 +553,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
409
553
  );
410
554
  const publicFunctionsCalldata = await Promise.all(
411
555
  publicCallRequests.map(async r => {
412
- const calldata = await privateExecutionOracle.loadFromExecutionCache(r.calldataHash);
556
+ const calldata = await privateExecutionOracle.getHashPreimage(r.calldataHash);
413
557
  return new HashedValues(calldata, r.calldataHash);
414
558
  }),
415
559
  );
416
560
 
417
- noteCache.finish();
418
561
  const nonceGenerator = noteCache.getNonceGenerator();
419
562
  result = new PrivateExecutionResult(executionResult, nonceGenerator, publicFunctionsCalldata);
420
563
  } catch (err) {
@@ -426,7 +569,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
426
569
  // We pass the non-zero minRevertibleSideEffectCounter to make sure the side effects are split correctly.
427
570
  const { publicInputs } = await generateSimulatedProvingResult(
428
571
  result,
429
- (addr, sel) => this.contractStore.getDebugFunctionName(addr, sel),
572
+ (addr, sel) => anchoredContractData.getDebugFunctionName(addr, sel),
430
573
  this.stateMachine.node,
431
574
  minRevertibleSideEffectCounter,
432
575
  );
@@ -485,7 +628,13 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
485
628
  } else if (!processedTx.revertCode.isOK()) {
486
629
  if (processedTx.revertReason) {
487
630
  try {
488
- await enrichPublicSimulationError(processedTx.revertReason, this.contractStore, this.logger);
631
+ await enrichPublicSimulationError(
632
+ processedTx.revertReason,
633
+ this.contractStore,
634
+ this.stateMachine.contractClassService,
635
+ await this.stateMachine.anchorBlockStore.getBlockHeader(),
636
+ this.logger,
637
+ );
489
638
  // eslint-disable-next-line no-empty
490
639
  } catch {}
491
640
  throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
@@ -494,11 +643,17 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
494
643
  }
495
644
  }
496
645
 
646
+ // Walk the nested private-call tree and collect every offchain effect the transaction emitted.
647
+ // PXE stores these on each `PrivateCallExecutionResult` and they never reach TXE via the
648
+ // `aztec_utl_emitOffchainEffect` foreign-call path (that path only fires at the top-level), so
649
+ // we pull them out here and the RPC wrapper will hand them to `TXESession` for buffering.
650
+ const offchainEffects = collectNested([executionResult], r => r.offchainEffects.map(e => e.data));
651
+
497
652
  if (isStaticCall) {
498
653
  await checkpoint!.revert();
499
654
 
500
655
  await forkedWorldTrees.close();
501
- return executionResult.returnValues ?? [];
656
+ return { returnValues: executionResult.returnValues ?? [], offchainEffects };
502
657
  }
503
658
 
504
659
  const txEffect = TxEffect.empty();
@@ -520,31 +675,31 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
520
675
 
521
676
  await forkedWorldTrees.close();
522
677
 
523
- return executionResult.returnValues ?? [];
678
+ return { returnValues: executionResult.returnValues ?? [], offchainEffects };
524
679
  }
525
680
 
526
681
  async publicCallNewFlow(
527
- from: AztecAddress,
682
+ from: AztecAddress | undefined,
528
683
  targetContractAddress: AztecAddress,
529
684
  calldata: Fr[],
530
685
  isStaticCall: boolean,
686
+ gasSettings: GasSettings,
531
687
  ) {
688
+ const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
689
+ const anchoredContractData = new AnchoredContractData(
690
+ this.contractStore,
691
+ this.stateMachine.contractClassService,
692
+ anchorBlockHeader,
693
+ );
694
+
532
695
  this.logger.verbose(
533
- `Executing public function ${await this.contractStore.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`,
696
+ `Executing public function ${await anchoredContractData.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`,
534
697
  );
535
698
 
536
699
  const blockNumber = await this.getNextBlockNumber();
537
700
 
538
- const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
539
-
540
- const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
541
-
542
- const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
543
-
544
701
  const txContext = new TxContext(this.chainId, this.version, gasSettings);
545
702
 
546
- const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
547
-
548
703
  const calldataHash = await computeCalldataHash(calldata);
549
704
  const calldataHashedValues = new HashedValues(calldata, calldataHash);
550
705
 
@@ -592,7 +747,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
592
747
  // may require producing reverts.
593
748
  const revertibleAccumulatedData = PrivateToPublicAccumulatedData.empty();
594
749
  revertibleAccumulatedData.publicCallRequests[0] = new PublicCallRequest(
595
- from,
750
+ from ?? AztecAddress.NULL_MSG_SENDER,
596
751
  targetContractAddress,
597
752
  isStaticCall,
598
753
  calldataHash,
@@ -637,7 +792,13 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
637
792
  } else if (!processedTx.revertCode.isOK()) {
638
793
  if (processedTx.revertReason) {
639
794
  try {
640
- await enrichPublicSimulationError(processedTx.revertReason, this.contractStore, this.logger);
795
+ await enrichPublicSimulationError(
796
+ processedTx.revertReason,
797
+ this.contractStore,
798
+ this.stateMachine.contractClassService,
799
+ anchorBlockHeader,
800
+ this.logger,
801
+ );
641
802
  // eslint-disable-next-line no-empty
642
803
  } catch {}
643
804
  throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
@@ -679,27 +840,35 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
679
840
  }
680
841
 
681
842
  async executeUtilityFunction(
843
+ from: AztecAddress | undefined,
682
844
  targetContractAddress: AztecAddress,
683
845
  functionSelector: FunctionSelector,
684
846
  args: Fr[],
685
847
  jobId: string,
848
+ authorizedUtilityCallTargets: AztecAddress[],
686
849
  ) {
687
- const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
850
+ const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
851
+ const anchoredContractData = new AnchoredContractData(
852
+ this.contractStore,
853
+ this.stateMachine.contractClassService,
854
+ blockHeader,
855
+ );
856
+
857
+ const artifact = await anchoredContractData.getFunctionArtifact(targetContractAddress, functionSelector);
688
858
  if (!artifact) {
689
859
  throw new Error(`Cannot call ${functionSelector} as there is no artifact found at ${targetContractAddress}.`);
690
860
  }
691
861
 
692
862
  // Sync notes before executing utility function to discover notes from previous transactions
693
- const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
694
863
  await this.stateMachine.contractSyncService.ensureContractSynced(
695
864
  targetContractAddress,
696
865
  functionSelector,
697
866
  async (call, execScopes) => {
698
- await this.executeUtilityCall(call, execScopes, jobId);
867
+ await this.executeUtilityCall(call, { scopes: execScopes, jobId });
699
868
  },
700
869
  blockHeader,
701
870
  jobId,
702
- 'ALL_SCOPES',
871
+ await this.keyStore.getAccounts(),
703
872
  );
704
873
 
705
874
  const call = FunctionCall.from({
@@ -713,11 +882,34 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
713
882
  returnTypes: [],
714
883
  });
715
884
 
716
- return this.executeUtilityCall(call, 'ALL_SCOPES', jobId);
885
+ return this.executeUtilityCall(call, {
886
+ from,
887
+ scopes: await this.keyStore.getAccounts(),
888
+ jobId,
889
+ authorizedUtilityCallTargets,
890
+ });
717
891
  }
718
892
 
719
- private async executeUtilityCall(call: FunctionCall, scopes: AccessScopes, jobId: string): Promise<Fr[]> {
720
- const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
893
+ private async executeUtilityCall(
894
+ call: FunctionCall,
895
+ {
896
+ from = AztecAddress.NULL_MSG_SENDER,
897
+ scopes,
898
+ jobId,
899
+ authorizedUtilityCallTargets = [],
900
+ }: { from?: AztecAddress; scopes: AztecAddress[]; jobId: string; authorizedUtilityCallTargets?: AztecAddress[] },
901
+ ): Promise<Fr[]> {
902
+ const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
903
+ const anchoredContractData = new AnchoredContractData(
904
+ this.contractStore,
905
+ this.stateMachine.contractClassService,
906
+ anchorBlockHeader,
907
+ );
908
+
909
+ const entryPointArtifact = await anchoredContractData.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
910
+ if (!entryPointArtifact) {
911
+ throw new Error(`Cannot run function ${call.selector} on ${call.to}: the contract is not registered.`);
912
+ }
721
913
  if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
722
914
  throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
723
915
  }
@@ -728,26 +920,45 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
728
920
  });
729
921
 
730
922
  try {
731
- const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
923
+ const simulator = new WASMSimulator();
924
+ const utilityExecutor = async (syncCall: FunctionCall, execScopes: AztecAddress[]) => {
925
+ await this.executeUtilityCall(syncCall, { scopes: execScopes, jobId, authorizedUtilityCallTargets });
926
+ };
732
927
  const oracle = new UtilityExecutionOracle({
733
- contractAddress: call.to,
928
+ callContext: CallContext.from({
929
+ msgSender: from,
930
+ contractAddress: call.to,
931
+ functionSelector: call.selector,
932
+ isStaticCall: true,
933
+ }),
734
934
  authWitnesses: [],
735
935
  capsules: [],
736
936
  anchorBlockHeader,
737
- contractStore: this.contractStore,
937
+ anchoredContractData,
738
938
  noteStore: this.noteStore,
739
939
  keyStore: this.keyStore,
740
940
  addressStore: this.addressStore,
741
941
  aztecNode: this.stateMachine.node,
742
942
  recipientTaggingStore: this.recipientTaggingStore,
743
- senderAddressBookStore: this.senderAddressBookStore,
744
- capsuleStore: this.capsuleStore,
943
+ taggingSecretSourcesStore: this.taggingSecretSourcesStore,
944
+ capsuleService: new CapsuleService(this.capsuleStore, scopes),
945
+ factService: new FactService(this.factStore, scopes),
745
946
  privateEventStore: this.privateEventStore,
947
+ txResolver: this.stateMachine.txResolver,
948
+ contractSyncService: this.stateMachine.contractSyncService,
949
+ l2TipsStore: this.stateMachine.l2TipsProvider,
746
950
  jobId,
747
951
  scopes,
952
+ simulator,
953
+ utilityExecutor,
954
+ hooks: composeHooks({
955
+ authorizeUtilityCall: this.buildAuthorizeUtilityCallHook('utility', authorizedUtilityCallTargets),
956
+ }),
957
+ // Execution-tree root (top-level utility run or contract sync): own store; nested frames inherit it.
958
+ transientArrayService: new TransientArrayService(),
748
959
  });
749
- const acirExecutionResult = await new WASMSimulator()
750
- .executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
960
+ const acirExecutionResult = await simulator
961
+ .executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, buildACIRCallback(oracle))
751
962
  .catch((err: Error) => {
752
963
  err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
753
964
  throw new ExecutionError(
@@ -768,13 +979,47 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
768
979
  }
769
980
  }
770
981
 
771
- close(): [bigint, Map<string, AuthWitness>] {
982
+ close(): {
983
+ nextBlockTimestamp: bigint;
984
+ authwits: Map<string, AuthWitness>;
985
+ taggingSecretStrategies: TXETaggingSecretStrategies;
986
+ authorizeAllUtilityCallTargets: boolean;
987
+ } {
772
988
  this.logger.debug('Exiting Top Level Context');
773
- return [this.nextBlockTimestamp, this.authwits];
989
+ return {
990
+ nextBlockTimestamp: this.nextBlockTimestamp,
991
+ authwits: this.authwits,
992
+ taggingSecretStrategies: this.taggingSecretStrategies,
993
+ authorizeAllUtilityCallTargets: this.authorizeAllUtilityCallTargets,
994
+ };
774
995
  }
775
996
 
776
997
  private async getLastBlockNumber(): Promise<BlockNumber> {
777
- const header = await this.stateMachine.node.getBlockHeader('latest');
778
- return header ? header.globalVariables.blockNumber : BlockNumber.ZERO;
998
+ const block = await this.stateMachine.node.getBlock('latest');
999
+ return block ? block.header.globalVariables.blockNumber : BlockNumber.ZERO;
1000
+ }
1001
+
1002
+ private buildAuthorizeUtilityCallHook(
1003
+ callerContext: 'private' | 'private view' | 'utility',
1004
+ authorizedTargets: AztecAddress[],
1005
+ ): ExecutionHooks['authorizeUtilityCall'] | undefined {
1006
+ if (this.authorizeAllUtilityCallTargets) {
1007
+ return authorizeAllUtilityCallsHook;
1008
+ }
1009
+ if (authorizedTargets.length === 0) {
1010
+ return undefined;
1011
+ }
1012
+ return req =>
1013
+ Promise.resolve({
1014
+ authorized: req.callerContext === callerContext && authorizedTargets.some(t => t.equals(req.target)),
1015
+ });
779
1016
  }
780
1017
  }
1018
+
1019
+ /**
1020
+ * An `authorizeUtilityCall` hook that authorizes every cross-contract utility call.
1021
+ *
1022
+ * Backs the `aztec_txe_setAuthorizeAllUtilityCallTargets` oracle.
1023
+ */
1024
+ export const authorizeAllUtilityCallsHook: NonNullable<ExecutionHooks['authorizeUtilityCall']> = () =>
1025
+ Promise.resolve({ authorized: true });