@aztec/txe 0.0.1-commit.3fd054f6 → 0.0.1-commit.431c48d

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