@aztec/txe 0.0.1-commit.f2ce05ee → 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 (176) 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 +73 -157
  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 +69 -30
  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 +38 -14
  61. package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
  62. package/dest/oracle/txe_oracle_public_context.js +61 -13
  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 +69 -29
  67. package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
  68. package/dest/oracle/txe_oracle_top_level_context.js +332 -109
  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 +901 -624
  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 +28 -15
  87. package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
  88. package/dest/state_machine/dummy_p2p_client.js +54 -18
  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 -16
  102. package/dest/txe_session.d.ts.map +1 -1
  103. package/dest/txe_session.js +365 -55
  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/utils/txe_public_contract_data_source.js +51 -0
  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 -190
  135. package/src/msgpackr_fr_extension.ts +23 -0
  136. package/src/oracle/interfaces.ts +75 -35
  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 +74 -12
  142. package/src/oracle/txe_oracle_registry.ts +556 -0
  143. package/src/oracle/txe_oracle_top_level_context.ts +421 -160
  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 +1116 -1006
  148. package/src/state_machine/archiver.ts +41 -20
  149. package/src/state_machine/dummy_p2p_client.ts +80 -30
  150. package/src/state_machine/global_variable_builder.ts +12 -11
  151. package/src/state_machine/index.ts +63 -27
  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 +601 -115
  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/utils/txe_public_contract_data_source.ts +60 -0
  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_contract_store.d.ts +0 -12
  166. package/dest/util/txe_contract_store.d.ts.map +0 -1
  167. package/dest/util/txe_contract_store.js +0 -22
  168. package/dest/util/txe_public_contract_data_source.d.ts +0 -21
  169. package/dest/util/txe_public_contract_data_source.d.ts.map +0 -1
  170. package/dest/util/txe_public_contract_data_source.js +0 -67
  171. package/src/util/txe_contract_store.ts +0 -36
  172. package/src/util/txe_public_contract_data_source.ts +0 -86
  173. /package/dest/{util → utils}/expected_failure_error.js +0 -0
  174. /package/dest/{util → utils}/txe_account_store.js +0 -0
  175. /package/src/{util → utils}/expected_failure_error.ts +0 -0
  176. /package/src/{util → utils}/txe_account_store.ts +0 -0
@@ -1,36 +1,45 @@
1
1
  import {
2
2
  CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS,
3
- DEFAULT_DA_GAS_LIMIT,
4
- DEFAULT_L2_GAS_LIMIT,
5
- DEFAULT_TEARDOWN_DA_GAS_LIMIT,
6
- DEFAULT_TEARDOWN_L2_GAS_LIMIT,
3
+ MAX_PRIVATE_LOGS_PER_TX,
7
4
  NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
8
5
  } from '@aztec/constants';
9
6
  import { BlockNumber } from '@aztec/foundation/branded-types';
10
7
  import { Schnorr } from '@aztec/foundation/crypto/schnorr';
11
8
  import { Fr } from '@aztec/foundation/curves/bn254';
9
+ import type { EthAddress } from '@aztec/foundation/eth-address';
12
10
  import { LogLevels, type Logger, applyStringFormatting, createLogger } from '@aztec/foundation/log';
13
11
  import { TestDateProvider } from '@aztec/foundation/timer';
14
12
  import type { KeyStore } from '@aztec/key-store';
15
13
  import {
16
14
  AddressStore,
15
+ AnchoredContractData,
16
+ CapsuleService,
17
17
  CapsuleStore,
18
+ type ContractStore,
19
+ type ExecutionHooks,
20
+ FactService,
21
+ FactStore,
18
22
  NoteStore,
19
- ORACLE_VERSION,
23
+ ORACLE_VERSION_MAJOR,
20
24
  PrivateEventStore,
21
25
  RecipientTaggingStore,
22
- SenderAddressBookStore,
23
26
  SenderTaggingStore,
27
+ TaggingSecretSourcesStore,
28
+ type TaggingSecretStrategy,
29
+ composeHooks,
24
30
  enrichPublicSimulationError,
25
31
  } from '@aztec/pxe/server';
26
32
  import {
33
+ CONTRACT_INSTANCE,
27
34
  ExecutionNoteCache,
28
35
  ExecutionTaggingIndexCache,
29
36
  HashedValuesCache,
30
37
  type IMiscOracle,
31
- Oracle,
38
+ type Option,
32
39
  PrivateExecutionOracle,
40
+ TransientArrayService,
33
41
  UtilityExecutionOracle,
42
+ buildACIRCallback,
34
43
  executePrivateFunction,
35
44
  generateSimulatedProvingResult,
36
45
  } from '@aztec/pxe/simulator';
@@ -62,6 +71,10 @@ import {
62
71
  PrivateToPublicAccumulatedData,
63
72
  PublicCallRequest,
64
73
  } from '@aztec/stdlib/kernel';
74
+ import { deriveKeys, hashPublicKey } from '@aztec/stdlib/keys';
75
+ import type { PrivateLog } from '@aztec/stdlib/logs';
76
+ import { AppTaggingSecretKind } from '@aztec/stdlib/logs';
77
+ import { L1Actor, L1ToL2Message, L2Actor } from '@aztec/stdlib/messaging';
65
78
  import { ChonkProof } from '@aztec/stdlib/proofs';
66
79
  import { makeGlobalVariables } from '@aztec/stdlib/testing';
67
80
  import { MerkleTreeId } from '@aztec/stdlib/trees';
@@ -78,15 +91,16 @@ import {
78
91
  collectNested,
79
92
  } from '@aztec/stdlib/tx';
80
93
  import type { UInt64 } from '@aztec/stdlib/types';
81
- import { ForkCheckpoint } from '@aztec/world-state';
94
+ import { ForkCheckpoint } from '@aztec/world-state/native';
82
95
 
83
- import { DEFAULT_ADDRESS } from '../constants.js';
96
+ import { DEFAULT_ADDRESS, MAX_PRIVATE_EVENTS_PER_TXE_QUERY, MAX_PRIVATE_EVENT_LEN } from '../constants.js';
84
97
  import type { TXEStateMachine } from '../state_machine/index.js';
85
- import type { TXEAccountStore } from '../util/txe_account_store.js';
86
- import type { TXEContractStore } from '../util/txe_contract_store.js';
87
- import { TXEPublicContractDataSource } from '../util/txe_public_contract_data_source.js';
88
98
  import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlock } from '../utils/block_creation.js';
99
+ import type { TXEAccountStore } from '../utils/txe_account_store.js';
100
+ import type { TXEArtifactResolver } from '../utils/txe_artifact_resolver.js';
101
+ import { TXEPublicContractDataSource } from '../utils/txe_public_contract_data_source.js';
89
102
  import type { ITxeExecutionOracle } from './interfaces.js';
103
+ import { type TXETaggingSecretStrategies, makeResolveTaggingSecretStrategyHook } from './tagging_secret_strategy.js';
90
104
 
91
105
  export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracle {
92
106
  isMisc = true as const;
@@ -96,44 +110,61 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
96
110
 
97
111
  constructor(
98
112
  private stateMachine: TXEStateMachine,
99
- private contractStore: TXEContractStore,
113
+ private contractStore: ContractStore,
100
114
  private noteStore: NoteStore,
101
115
  private keyStore: KeyStore,
102
116
  private addressStore: AddressStore,
103
117
  private accountStore: TXEAccountStore,
104
118
  private senderTaggingStore: SenderTaggingStore,
105
119
  private recipientTaggingStore: RecipientTaggingStore,
106
- private senderAddressBookStore: SenderAddressBookStore,
120
+ private taggingSecretSourcesStore: TaggingSecretSourcesStore,
107
121
  private capsuleStore: CapsuleStore,
122
+ private factStore: FactStore,
108
123
  private privateEventStore: PrivateEventStore,
109
- private jobId: string,
110
124
  private nextBlockTimestamp: bigint,
111
125
  private version: Fr,
112
126
  private chainId: Fr,
113
127
  private authwits: Map<string, AuthWitness>,
128
+ private taggingSecretStrategies: TXETaggingSecretStrategies,
129
+ private authorizeAllUtilityCallTargets: boolean,
130
+ private readonly artifactResolver: TXEArtifactResolver,
131
+ private readonly rootPath: string,
132
+ private readonly packageName: string,
114
133
  ) {
115
134
  this.logger = createLogger('txe:top_level_context');
116
135
  this.logger.debug('Entering Top Level Context');
117
136
  }
118
137
 
119
- utilityAssertCompatibleOracleVersion(version: number): void {
120
- if (version !== ORACLE_VERSION) {
138
+ private contractOracleVersion: { major: number; minor: number } | undefined;
139
+
140
+ assertCompatibleOracleVersion(major: number, minor: number): void {
141
+ if (major !== ORACLE_VERSION_MAJOR) {
142
+ const hint =
143
+ major > ORACLE_VERSION_MAJOR
144
+ ? 'The contract was compiled with a newer version of Aztec.nr than this aztec cli version supports. Upgrade your aztec cli version to a compatible version.'
145
+ : 'The contract was compiled with an older version of Aztec.nr than this aztec cli version supports. Recompile the contract with a compatible version of Aztec.nr.';
121
146
  throw new Error(
122
- `Incompatible oracle version. TXE is using version '${ORACLE_VERSION}', but got a request for '${version}'.`,
147
+ `Incompatible aztec cli version: ${hint} See https://docs.aztec.network/errors/8 (expected oracle major version ${ORACLE_VERSION_MAJOR}, got ${major})`,
123
148
  );
124
149
  }
150
+ this.contractOracleVersion = { major, minor };
151
+ }
152
+
153
+ // Prefixed with "nonOracleFunction" as it is not used as an oracle handler.
154
+ nonOracleFunctionGetContractOracleVersion(): { major: number; minor: number } | undefined {
155
+ return this.contractOracleVersion;
125
156
  }
126
157
 
127
158
  // This is typically only invoked in private contexts, but it is convenient to also have it in top-level for testing
128
159
  // setup.
129
- utilityGetRandomField(): Fr {
160
+ getRandomField(): Fr {
130
161
  return Fr.random();
131
162
  }
132
163
 
133
164
  // We instruct users to debug contracts via this oracle, so it makes sense that they'd expect it to also work in tests
134
- utilityDebugLog(level: number, message: string, fields: Fr[]): Promise<void> {
165
+ log(level: number, message: string, _fieldsSize: number, fields: Fr[]): Promise<void> {
135
166
  if (!LogLevels[level]) {
136
- throw new Error(`Invalid debug log level: ${level}`);
167
+ throw new Error(`Invalid log level: ${level}`);
137
168
  }
138
169
  const levelName = LogLevels[level];
139
170
 
@@ -141,25 +172,25 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
141
172
  return Promise.resolve();
142
173
  }
143
174
 
144
- txeGetDefaultAddress(): AztecAddress {
175
+ getDefaultAddress(): AztecAddress {
145
176
  return DEFAULT_ADDRESS;
146
177
  }
147
178
 
148
- async txeGetNextBlockNumber(): Promise<BlockNumber> {
179
+ async getNextBlockNumber(): Promise<BlockNumber> {
149
180
  return BlockNumber((await this.getLastBlockNumber()) + 1);
150
181
  }
151
182
 
152
- txeGetNextBlockTimestamp(): Promise<bigint> {
183
+ getNextBlockTimestamp(): Promise<bigint> {
153
184
  return Promise.resolve(this.nextBlockTimestamp);
154
185
  }
155
186
 
156
- async txeGetLastBlockTimestamp() {
157
- return (await this.stateMachine.node.getBlockHeader('latest'))!.globalVariables.timestamp;
187
+ async getLastBlockTimestamp() {
188
+ return (await this.stateMachine.node.getBlockData('latest'))!.header.globalVariables.timestamp;
158
189
  }
159
190
 
160
- async txeGetLastTxEffects() {
191
+ async getLastTxEffects(): Promise<{ txHash: TxHash; noteHashes: Fr[]; nullifiers: Fr[]; privateLogs: PrivateLog[] }> {
161
192
  const latestBlockNumber = await this.stateMachine.archiver.getBlockNumber();
162
- const block = await this.stateMachine.archiver.getBlock(latestBlockNumber);
193
+ const block = await this.stateMachine.archiver.getBlock({ number: latestBlockNumber });
163
194
 
164
195
  if (block!.body.txEffects.length != 1) {
165
196
  // Note that calls like env.mine() will result in blocks with no transactions, hitting this
@@ -168,11 +199,40 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
168
199
 
169
200
  const txEffects = block!.body.txEffects[0];
170
201
 
171
- return { txHash: txEffects.txHash, noteHashes: txEffects.noteHashes, nullifiers: txEffects.nullifiers };
202
+ const privateLogs = txEffects.privateLogs;
203
+ if (privateLogs.length > MAX_PRIVATE_LOGS_PER_TX) {
204
+ throw new Error(`${privateLogs.length} private logs exceed max ${MAX_PRIVATE_LOGS_PER_TX}`);
205
+ }
206
+
207
+ return {
208
+ txHash: txEffects.txHash,
209
+ noteHashes: txEffects.noteHashes,
210
+ nullifiers: txEffects.nullifiers,
211
+ privateLogs,
212
+ };
172
213
  }
173
214
 
174
- async txeGetPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress) {
175
- return (
215
+ async syncContractNonOracleMethod(contractAddress: AztecAddress, scope: AztecAddress, jobId: string) {
216
+ if (contractAddress.equals(DEFAULT_ADDRESS)) {
217
+ this.logger.debug(`Skipping sync in getPrivateEvents because the events correspond to the default address.`);
218
+ return;
219
+ }
220
+
221
+ const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
222
+ await this.stateMachine.contractSyncService.ensureContractSynced(
223
+ contractAddress,
224
+ null,
225
+ async (call, execScopes) => {
226
+ await this.executeUtilityCall(call, { scopes: execScopes, jobId });
227
+ },
228
+ blockHeader,
229
+ jobId,
230
+ [scope],
231
+ );
232
+ }
233
+
234
+ async getPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress) {
235
+ const events = (
176
236
  await this.privateEventStore.getPrivateEvents(selector, {
177
237
  contractAddress,
178
238
  scopes: [scope],
@@ -180,9 +240,18 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
180
240
  toBlock: (await this.getLastBlockNumber()) + 1,
181
241
  })
182
242
  ).map(e => e.packedEvent);
243
+
244
+ if (events.length > MAX_PRIVATE_EVENTS_PER_TXE_QUERY) {
245
+ throw new Error(`Array of length ${events.length} larger than maxLen ${MAX_PRIVATE_EVENTS_PER_TXE_QUERY}`);
246
+ }
247
+ if (events.some(e => e.length > MAX_PRIVATE_EVENT_LEN)) {
248
+ throw new Error(`Some private event has length larger than maxLen ${MAX_PRIVATE_EVENT_LEN}`);
249
+ }
250
+
251
+ return events;
183
252
  }
184
253
 
185
- async txeAdvanceBlocksBy(blocks: number) {
254
+ async advanceBlocksBy(blocks: number) {
186
255
  this.logger.debug(`time traveling ${blocks} blocks`);
187
256
 
188
257
  for (let i = 0; i < blocks; i++) {
@@ -190,39 +259,76 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
190
259
  }
191
260
  }
192
261
 
193
- txeAdvanceTimestampBy(duration: UInt64) {
262
+ advanceTimestampBy(duration: UInt64) {
194
263
  this.logger.debug(`time traveling ${duration} seconds`);
195
264
  this.nextBlockTimestamp += duration;
196
265
  }
197
266
 
198
- async txeDeploy(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
267
+ private deploymentNullifier(address: AztecAddress): Promise<Fr> {
268
+ return siloNullifier(AztecAddress.fromNumberUnsafe(CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS), address.toField());
269
+ }
270
+
271
+ async deploy(
272
+ contractPath: string,
273
+ initializer: string,
274
+ args: Fr[],
275
+ secret: Fr,
276
+ salt: Fr,
277
+ deployer: AztecAddress,
278
+ ): Promise<Fr[]> {
279
+ const { artifact, instance } = await this.artifactResolver.resolveDeployArtifact({
280
+ rootPath: this.rootPath,
281
+ packageName: this.packageName,
282
+ contractPath,
283
+ initializer,
284
+ args,
285
+ secret,
286
+ salt,
287
+ deployer,
288
+ });
289
+
199
290
  // Emit deployment nullifier
200
291
  await this.mineBlock({
201
- nullifiers: [
202
- await siloNullifier(
203
- AztecAddress.fromNumber(CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS),
204
- instance.address.toField(),
205
- ),
206
- ],
292
+ nullifiers: [await this.deploymentNullifier(instance.address)],
207
293
  });
208
294
 
209
295
  if (!secret.equals(Fr.ZERO)) {
210
- await this.txeAddAccount(artifact, instance, secret);
296
+ await this.registerContractAndAddAccount(artifact, instance, secret);
211
297
  } else {
212
298
  await this.contractStore.addContractInstance(instance);
213
- await this.contractStore.addContractArtifact(instance.currentContractClassId, artifact);
299
+ await this.contractStore.addContractArtifact(artifact);
214
300
  this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
215
301
  }
302
+
303
+ return CONTRACT_INSTANCE.serialization!.fn(instance).flat();
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
+ });
216
313
  }
217
314
 
218
- async txeAddAccount(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
+ ) {
219
325
  const partialAddress = await computePartialAddress(instance);
220
326
 
221
327
  this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
222
328
  await this.contractStore.addContractInstance(instance);
223
- await this.contractStore.addContractArtifact(instance.currentContractClassId, artifact);
329
+ await this.contractStore.addContractArtifact(artifact);
224
330
 
225
- const completeAddress = await this.keyStore.addAccount(secret, partialAddress);
331
+ const completeAddress = await this.keyStore.addAccount(await deriveKeys(secret), partialAddress);
226
332
  await this.accountStore.setAccount(completeAddress.address, completeAddress);
227
333
  await this.addressStore.addCompleteAddress(completeAddress);
228
334
  this.logger.debug(`Created account ${completeAddress.address}`);
@@ -230,9 +336,8 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
230
336
  return completeAddress;
231
337
  }
232
338
 
233
- async txeCreateAccount(secret: Fr) {
234
- // This is a foot gun !
235
- 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);
236
341
  await this.accountStore.setAccount(completeAddress.address, completeAddress);
237
342
  await this.addressStore.addCompleteAddress(completeAddress);
238
343
  this.logger.debug(`Created account ${completeAddress.address}`);
@@ -240,27 +345,67 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
240
345
  return completeAddress;
241
346
  }
242
347
 
243
- async txeAddAuthWitness(address: AztecAddress, messageHash: Fr) {
348
+ async addAuthWitness(address: AztecAddress, messageHash: Fr) {
244
349
  const account = await this.accountStore.getAccount(address);
245
- 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);
246
352
 
247
353
  const schnorr = new Schnorr();
248
- const signature = await schnorr.constructSignature(messageHash.toBuffer(), privateKey);
354
+ const signature = await schnorr.constructSignature(messageHash, privateKey);
249
355
 
250
- const authWitness = new AuthWitness(messageHash, [...signature.toBuffer()]);
356
+ const authWitness = new AuthWitness(messageHash, signature.toLimbFields());
251
357
 
252
358
  this.authwits.set(authWitness.requestHash.toString(), authWitness);
253
359
  }
254
360
 
255
- async mineBlock(options: { nullifiers?: Fr[] } = {}) {
256
- const blockNumber = await this.txeGetNextBlockNumber();
361
+ setTaggingSecretStrategies(
362
+ unconstrainedStrategy: Option<TaggingSecretStrategy>,
363
+ constrainedStrategy: Option<TaggingSecretStrategy>,
364
+ ): void {
365
+ const apply = (mode: AppTaggingSecretKind, strategy: Option<TaggingSecretStrategy>) => {
366
+ if (strategy.isSome()) {
367
+ this.taggingSecretStrategies.set(mode, strategy.value);
368
+ } else {
369
+ this.taggingSecretStrategies.delete(mode);
370
+ }
371
+ };
372
+ apply(AppTaggingSecretKind.UNCONSTRAINED, unconstrainedStrategy);
373
+ apply(AppTaggingSecretKind.CONSTRAINED, constrainedStrategy);
374
+ }
375
+
376
+ setAuthorizeAllUtilityCallTargets(authorizeAll: boolean): void {
377
+ this.authorizeAllUtilityCallTargets = authorizeAll;
378
+ }
379
+
380
+ async sendL1ToL2Message(content: Fr, secretHash: Fr, sender: EthAddress, recipient: AztecAddress): Promise<Fr> {
381
+ // Messages are appended to the tree, so the next free slot is simply the current tree size.
382
+ const { size } = await this.stateMachine.synchronizer
383
+ .getCommitted()
384
+ .getTreeInfo(MerkleTreeId.L1_TO_L2_MESSAGE_TREE);
385
+ const leafIndex = new Fr(size);
386
+
387
+ const message = new L1ToL2Message(
388
+ new L1Actor(sender, this.chainId.toNumber()),
389
+ new L2Actor(recipient, this.version.toNumber()),
390
+ content,
391
+ secretHash,
392
+ leafIndex,
393
+ );
394
+
395
+ await this.mineBlock({ l1ToL2Messages: [message.hash()] });
396
+
397
+ return leafIndex;
398
+ }
399
+
400
+ async mineBlock(options: { nullifiers?: Fr[]; l1ToL2Messages?: Fr[] } = {}) {
401
+ const blockNumber = await this.getNextBlockNumber();
257
402
 
258
403
  const txEffect = TxEffect.empty();
259
404
  txEffect.nullifiers = [getSingleTxBlockRequestHash(blockNumber), ...(options.nullifiers ?? [])];
260
405
  txEffect.txHash = new TxHash(new Fr(blockNumber));
261
406
 
262
407
  const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
263
- await insertTxEffectIntoWorldTrees(txEffect, forkedWorldTrees);
408
+ await insertTxEffectIntoWorldTrees(txEffect, forkedWorldTrees, options.l1ToL2Messages ?? []);
264
409
 
265
410
  const globals = makeGlobalVariables(undefined, {
266
411
  blockNumber,
@@ -274,22 +419,33 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
274
419
 
275
420
  this.logger.info(`Created block ${blockNumber} with timestamp ${block.header.globalVariables.timestamp}`);
276
421
 
277
- await this.stateMachine.handleL2Block(block);
422
+ await this.stateMachine.handleL2Block(block, options.l1ToL2Messages ?? []);
278
423
  }
279
424
 
280
- async txePrivateCallNewFlow(
281
- from: AztecAddress,
425
+ async privateCallNewFlow(
426
+ from: AztecAddress | undefined,
282
427
  targetContractAddress: AztecAddress = AztecAddress.zero(),
283
428
  functionSelector: FunctionSelector = FunctionSelector.empty(),
284
429
  args: Fr[],
285
430
  argsHash: Fr = Fr.zero(),
286
431
  isStaticCall: boolean = false,
432
+ additionalScopes: AztecAddress[] = [],
433
+ jobId: string,
434
+ authorizedUtilityCallTargets: AztecAddress[],
435
+ gasSettings: GasSettings,
287
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
+
288
444
  this.logger.verbose(
289
- `Executing external function ${await this.contractStore.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`,
445
+ `Executing external function ${await anchoredContractData.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`,
290
446
  );
291
447
 
292
- const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
448
+ const artifact = await anchoredContractData.getFunctionArtifact(targetContractAddress, functionSelector);
293
449
  if (!artifact) {
294
450
  const message = functionSelector.equals(await FunctionSelector.fromSignature('verify_private_authwit(Field)'))
295
451
  ? 'Found no account contract artifact for a private authwit check - use `create_contract_account` instead of `create_light_account` for authwit support.'
@@ -297,32 +453,26 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
297
453
  throw new Error(message);
298
454
  }
299
455
 
300
- // When `from` is the zero address (used when creating a new contract account for example),
301
- // we disable scope filtering by setting effectiveScopes to undefined. This allows these operations
302
- // to proceed without requiring keys registered for the zero address.
303
- const effectiveScopes = from.isZero() ? undefined : [from];
456
+ const scopes = from === undefined ? additionalScopes : [from, ...additionalScopes];
304
457
 
305
458
  // Sync notes before executing private function to discover notes from previous transactions
306
- const utilityExecutor = async (call: FunctionCall) => {
307
- await this.executeUtilityCall(call, effectiveScopes);
459
+ const utilityExecutor = async (call: FunctionCall, execScopes: AztecAddress[]) => {
460
+ await this.executeUtilityCall(call, { scopes: execScopes, jobId });
308
461
  };
309
462
 
310
- const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
311
463
  await this.stateMachine.contractSyncService.ensureContractSynced(
312
464
  targetContractAddress,
313
465
  functionSelector,
314
466
  utilityExecutor,
315
467
  blockHeader,
316
- this.jobId,
468
+ jobId,
469
+ scopes,
317
470
  );
318
471
 
319
- const blockNumber = await this.txeGetNextBlockNumber();
472
+ const blockNumber = await this.getNextBlockNumber();
320
473
 
321
- const callContext = new CallContext(from, targetContractAddress, functionSelector, isStaticCall);
322
-
323
- const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
324
- const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
325
- 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);
326
476
 
327
477
  const txContext = new TxContext(this.chainId, this.version, gasSettings);
328
478
 
@@ -337,43 +487,51 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
337
487
 
338
488
  const simulator = new WASMSimulator();
339
489
 
340
- const privateExecutionOracle = new PrivateExecutionOracle(
490
+ const transientArrayService = new TransientArrayService();
491
+ const privateExecutionOracle = new PrivateExecutionOracle({
341
492
  argsHash,
342
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,
343
496
  callContext,
344
- /** Header of a block whose state is used during private execution (not the block the transaction is included in). */
345
- blockHeader,
497
+ anchorBlockHeader: blockHeader,
346
498
  utilityExecutor,
347
- /** List of transient auth witnesses to be used during this simulation */
348
- Array.from(this.authwits.values()),
349
- /** List of transient auth witnesses to be used during this simulation */
350
- [],
351
- HashedValuesCache.create([new HashedValues(args, argsHash)]),
499
+ authWitnesses: Array.from(this.authwits.values()),
500
+ capsules: [],
501
+ executionCache: HashedValuesCache.create([new HashedValues(args, argsHash)]),
352
502
  noteCache,
353
503
  taggingIndexCache,
354
- this.contractStore,
355
- this.noteStore,
356
- this.keyStore,
357
- this.addressStore,
358
- this.stateMachine.node,
359
- this.senderTaggingStore,
360
- this.recipientTaggingStore,
361
- this.senderAddressBookStore,
362
- this.capsuleStore,
363
- this.privateEventStore,
364
- this.stateMachine.contractSyncService,
365
- this.jobId,
366
- 0, // totalPublicArgsCount
367
- minRevertibleSideEffectCounter, // (start) sideEffectCounter
368
- undefined, // log
369
- effectiveScopes, // scopes
370
- /**
371
- * In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
372
- * contract would perform, including setting senderForTags.
373
- */
374
- from,
504
+ anchoredContractData,
505
+ noteStore: this.noteStore,
506
+ keyStore: this.keyStore,
507
+ addressStore: this.addressStore,
508
+ aztecNode: this.stateMachine.node,
509
+ senderTaggingStore: this.senderTaggingStore,
510
+ recipientTaggingStore: this.recipientTaggingStore,
511
+ taggingSecretSourcesStore: this.taggingSecretSourcesStore,
512
+ capsuleService: new CapsuleService(this.capsuleStore, scopes),
513
+ factService: new FactService(this.factStore, scopes),
514
+ privateEventStore: this.privateEventStore,
515
+ contractSyncService: this.stateMachine.contractSyncService,
516
+ jobId,
517
+ totalPublicCalldataCount: 0,
518
+ sideEffectCounter: minRevertibleSideEffectCounter,
519
+ scopes,
520
+ // In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
521
+ // contract would perform, including setting senderForTags.
522
+ senderForTags: from,
375
523
  simulator,
376
- );
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,
534
+ });
377
535
 
378
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.
379
537
  let result: PrivateExecutionResult;
@@ -395,12 +553,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
395
553
  );
396
554
  const publicFunctionsCalldata = await Promise.all(
397
555
  publicCallRequests.map(async r => {
398
- const calldata = await privateExecutionOracle.privateLoadFromExecutionCache(r.calldataHash);
556
+ const calldata = await privateExecutionOracle.getHashPreimage(r.calldataHash);
399
557
  return new HashedValues(calldata, r.calldataHash);
400
558
  }),
401
559
  );
402
560
 
403
- noteCache.finish();
404
561
  const nonceGenerator = noteCache.getNonceGenerator();
405
562
  result = new PrivateExecutionResult(executionResult, nonceGenerator, publicFunctionsCalldata);
406
563
  } catch (err) {
@@ -412,7 +569,8 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
412
569
  // We pass the non-zero minRevertibleSideEffectCounter to make sure the side effects are split correctly.
413
570
  const { publicInputs } = await generateSimulatedProvingResult(
414
571
  result,
415
- (addr, sel) => this.contractStore.getDebugFunctionName(addr, sel),
572
+ (addr, sel) => anchoredContractData.getDebugFunctionName(addr, sel),
573
+ this.stateMachine.node,
416
574
  minRevertibleSideEffectCounter,
417
575
  );
418
576
 
@@ -470,7 +628,13 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
470
628
  } else if (!processedTx.revertCode.isOK()) {
471
629
  if (processedTx.revertReason) {
472
630
  try {
473
- 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
+ );
474
638
  // eslint-disable-next-line no-empty
475
639
  } catch {}
476
640
  throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
@@ -479,11 +643,17 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
479
643
  }
480
644
  }
481
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
+
482
652
  if (isStaticCall) {
483
653
  await checkpoint!.revert();
484
654
 
485
655
  await forkedWorldTrees.close();
486
- return executionResult.returnValues ?? [];
656
+ return { returnValues: executionResult.returnValues ?? [], offchainEffects };
487
657
  }
488
658
 
489
659
  const txEffect = TxEffect.empty();
@@ -505,31 +675,31 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
505
675
 
506
676
  await forkedWorldTrees.close();
507
677
 
508
- return executionResult.returnValues ?? [];
678
+ return { returnValues: executionResult.returnValues ?? [], offchainEffects };
509
679
  }
510
680
 
511
- async txePublicCallNewFlow(
512
- from: AztecAddress,
681
+ async publicCallNewFlow(
682
+ from: AztecAddress | undefined,
513
683
  targetContractAddress: AztecAddress,
514
684
  calldata: Fr[],
515
685
  isStaticCall: boolean,
686
+ gasSettings: GasSettings,
516
687
  ) {
517
- this.logger.verbose(
518
- `Executing public function ${await this.contractStore.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`,
688
+ const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
689
+ const anchoredContractData = new AnchoredContractData(
690
+ this.contractStore,
691
+ this.stateMachine.contractClassService,
692
+ anchorBlockHeader,
519
693
  );
520
694
 
521
- const blockNumber = await this.txeGetNextBlockNumber();
522
-
523
- const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
524
-
525
- const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
695
+ this.logger.verbose(
696
+ `Executing public function ${await anchoredContractData.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`,
697
+ );
526
698
 
527
- const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
699
+ const blockNumber = await this.getNextBlockNumber();
528
700
 
529
701
  const txContext = new TxContext(this.chainId, this.version, gasSettings);
530
702
 
531
- const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
532
-
533
703
  const calldataHash = await computeCalldataHash(calldata);
534
704
  const calldataHashedValues = new HashedValues(calldata, calldataHash);
535
705
 
@@ -577,7 +747,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
577
747
  // may require producing reverts.
578
748
  const revertibleAccumulatedData = PrivateToPublicAccumulatedData.empty();
579
749
  revertibleAccumulatedData.publicCallRequests[0] = new PublicCallRequest(
580
- from,
750
+ from ?? AztecAddress.NULL_MSG_SENDER,
581
751
  targetContractAddress,
582
752
  isStaticCall,
583
753
  calldataHash,
@@ -595,7 +765,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
595
765
  constantData,
596
766
  /*gasUsed=*/ new Gas(0, 0),
597
767
  /*feePayer=*/ AztecAddress.zero(),
598
- /*includeByTimestamp=*/ 0n,
768
+ /*expirationTimestamp=*/ 0n,
599
769
  inputsForPublic,
600
770
  undefined,
601
771
  );
@@ -622,7 +792,13 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
622
792
  } else if (!processedTx.revertCode.isOK()) {
623
793
  if (processedTx.revertReason) {
624
794
  try {
625
- 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
+ );
626
802
  // eslint-disable-next-line no-empty
627
803
  } catch {}
628
804
  throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
@@ -663,26 +839,36 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
663
839
  return returnValues ?? [];
664
840
  }
665
841
 
666
- async txeSimulateUtilityFunction(
842
+ async executeUtilityFunction(
843
+ from: AztecAddress | undefined,
667
844
  targetContractAddress: AztecAddress,
668
845
  functionSelector: FunctionSelector,
669
846
  args: Fr[],
847
+ jobId: string,
848
+ authorizedUtilityCallTargets: AztecAddress[],
670
849
  ) {
671
- 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);
672
858
  if (!artifact) {
673
859
  throw new Error(`Cannot call ${functionSelector} as there is no artifact found at ${targetContractAddress}.`);
674
860
  }
675
861
 
676
862
  // Sync notes before executing utility function to discover notes from previous transactions
677
- const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
678
863
  await this.stateMachine.contractSyncService.ensureContractSynced(
679
864
  targetContractAddress,
680
865
  functionSelector,
681
- async call => {
682
- await this.executeUtilityCall(call);
866
+ async (call, execScopes) => {
867
+ await this.executeUtilityCall(call, { scopes: execScopes, jobId });
683
868
  },
684
869
  blockHeader,
685
- this.jobId,
870
+ jobId,
871
+ await this.keyStore.getAccounts(),
686
872
  );
687
873
 
688
874
  const call = FunctionCall.from({
@@ -696,11 +882,34 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
696
882
  returnTypes: [],
697
883
  });
698
884
 
699
- return this.executeUtilityCall(call);
885
+ return this.executeUtilityCall(call, {
886
+ from,
887
+ scopes: await this.keyStore.getAccounts(),
888
+ jobId,
889
+ authorizedUtilityCallTargets,
890
+ });
700
891
  }
701
892
 
702
- private async executeUtilityCall(call: FunctionCall, scopes?: AztecAddress[]): Promise<Fr[]> {
703
- 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
+ }
704
913
  if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
705
914
  throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
706
915
  }
@@ -711,27 +920,45 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
711
920
  });
712
921
 
713
922
  try {
714
- const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
715
- const oracle = new UtilityExecutionOracle(
716
- call.to,
717
- [],
718
- [],
923
+ const simulator = new WASMSimulator();
924
+ const utilityExecutor = async (syncCall: FunctionCall, execScopes: AztecAddress[]) => {
925
+ await this.executeUtilityCall(syncCall, { scopes: execScopes, jobId, authorizedUtilityCallTargets });
926
+ };
927
+ const oracle = new UtilityExecutionOracle({
928
+ callContext: CallContext.from({
929
+ msgSender: from,
930
+ contractAddress: call.to,
931
+ functionSelector: call.selector,
932
+ isStaticCall: true,
933
+ }),
934
+ authWitnesses: [],
935
+ capsules: [],
719
936
  anchorBlockHeader,
720
- this.contractStore,
721
- this.noteStore,
722
- this.keyStore,
723
- this.addressStore,
724
- this.stateMachine.node,
725
- this.recipientTaggingStore,
726
- this.senderAddressBookStore,
727
- this.capsuleStore,
728
- this.privateEventStore,
729
- this.jobId,
730
- undefined, // log
731
- scopes, // scopes - used to filter notes by account
732
- );
733
- const acirExecutionResult = await new WASMSimulator()
734
- .executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
937
+ anchoredContractData,
938
+ noteStore: this.noteStore,
939
+ keyStore: this.keyStore,
940
+ addressStore: this.addressStore,
941
+ aztecNode: this.stateMachine.node,
942
+ recipientTaggingStore: this.recipientTaggingStore,
943
+ taggingSecretSourcesStore: this.taggingSecretSourcesStore,
944
+ capsuleService: new CapsuleService(this.capsuleStore, scopes),
945
+ factService: new FactService(this.factStore, scopes),
946
+ privateEventStore: this.privateEventStore,
947
+ txResolver: this.stateMachine.txResolver,
948
+ contractSyncService: this.stateMachine.contractSyncService,
949
+ l2TipsStore: this.stateMachine.l2TipsProvider,
950
+ jobId,
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(),
959
+ });
960
+ const acirExecutionResult = await simulator
961
+ .executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, buildACIRCallback(oracle))
735
962
  .catch((err: Error) => {
736
963
  err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
737
964
  throw new ExecutionError(
@@ -745,20 +972,54 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
745
972
  );
746
973
  });
747
974
 
748
- this.logger.verbose(`Utility simulation for ${call.to}.${call.selector} completed`);
975
+ this.logger.verbose(`Utility execution for ${call.to}.${call.selector} completed`);
749
976
  return witnessMapToFields(acirExecutionResult.returnWitness);
750
977
  } catch (err) {
751
- throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility simulation'));
978
+ throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility execution'));
752
979
  }
753
980
  }
754
981
 
755
- close(): [bigint, Map<string, AuthWitness>] {
982
+ close(): {
983
+ nextBlockTimestamp: bigint;
984
+ authwits: Map<string, AuthWitness>;
985
+ taggingSecretStrategies: TXETaggingSecretStrategies;
986
+ authorizeAllUtilityCallTargets: boolean;
987
+ } {
756
988
  this.logger.debug('Exiting Top Level Context');
757
- return [this.nextBlockTimestamp, this.authwits];
989
+ return {
990
+ nextBlockTimestamp: this.nextBlockTimestamp,
991
+ authwits: this.authwits,
992
+ taggingSecretStrategies: this.taggingSecretStrategies,
993
+ authorizeAllUtilityCallTargets: this.authorizeAllUtilityCallTargets,
994
+ };
758
995
  }
759
996
 
760
997
  private async getLastBlockNumber(): Promise<BlockNumber> {
761
- const header = await this.stateMachine.node.getBlockHeader('latest');
762
- 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
+ });
763
1016
  }
764
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 });