@aztec/txe 0.0.1-commit.e558bd1c → 0.0.1-commit.e5a3663dd

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 (60) hide show
  1. package/dest/index.d.ts +1 -1
  2. package/dest/index.d.ts.map +1 -1
  3. package/dest/index.js +88 -54
  4. package/dest/oracle/interfaces.d.ts +34 -28
  5. package/dest/oracle/interfaces.d.ts.map +1 -1
  6. package/dest/oracle/txe_oracle_public_context.d.ts +13 -13
  7. package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
  8. package/dest/oracle/txe_oracle_public_context.js +12 -12
  9. package/dest/oracle/txe_oracle_top_level_context.d.ts +31 -23
  10. package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
  11. package/dest/oracle/txe_oracle_top_level_context.js +159 -66
  12. package/dest/rpc_translator.d.ts +129 -83
  13. package/dest/rpc_translator.d.ts.map +1 -1
  14. package/dest/rpc_translator.js +479 -165
  15. package/dest/state_machine/archiver.d.ts +3 -3
  16. package/dest/state_machine/archiver.d.ts.map +1 -1
  17. package/dest/state_machine/archiver.js +12 -12
  18. package/dest/state_machine/dummy_p2p_client.d.ts +16 -12
  19. package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
  20. package/dest/state_machine/dummy_p2p_client.js +28 -16
  21. package/dest/state_machine/global_variable_builder.d.ts +9 -4
  22. package/dest/state_machine/global_variable_builder.d.ts.map +1 -1
  23. package/dest/state_machine/global_variable_builder.js +9 -3
  24. package/dest/state_machine/index.d.ts +4 -2
  25. package/dest/state_machine/index.d.ts.map +1 -1
  26. package/dest/state_machine/index.js +8 -4
  27. package/dest/state_machine/mock_epoch_cache.d.ts +20 -3
  28. package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
  29. package/dest/state_machine/mock_epoch_cache.js +39 -2
  30. package/dest/state_machine/synchronizer.d.ts +5 -5
  31. package/dest/state_machine/synchronizer.d.ts.map +1 -1
  32. package/dest/state_machine/synchronizer.js +3 -3
  33. package/dest/txe_session.d.ts +54 -6
  34. package/dest/txe_session.d.ts.map +1 -1
  35. package/dest/txe_session.js +152 -27
  36. package/dest/util/encoding.d.ts +71 -1
  37. package/dest/util/encoding.d.ts.map +1 -1
  38. package/dest/util/encoding.js +4 -0
  39. package/dest/util/txe_public_contract_data_source.d.ts +2 -3
  40. package/dest/util/txe_public_contract_data_source.d.ts.map +1 -1
  41. package/dest/util/txe_public_contract_data_source.js +6 -25
  42. package/package.json +15 -15
  43. package/src/index.ts +89 -52
  44. package/src/oracle/interfaces.ts +35 -32
  45. package/src/oracle/txe_oracle_public_context.ts +12 -12
  46. package/src/oracle/txe_oracle_top_level_context.ts +168 -117
  47. package/src/rpc_translator.ts +571 -196
  48. package/src/state_machine/archiver.ts +9 -9
  49. package/src/state_machine/dummy_p2p_client.ts +39 -22
  50. package/src/state_machine/global_variable_builder.ts +18 -3
  51. package/src/state_machine/index.ts +10 -2
  52. package/src/state_machine/mock_epoch_cache.ts +51 -3
  53. package/src/state_machine/synchronizer.ts +4 -4
  54. package/src/txe_session.ts +216 -76
  55. package/src/util/encoding.ts +5 -0
  56. package/src/util/txe_public_contract_data_source.ts +10 -38
  57. package/dest/util/txe_contract_store.d.ts +0 -12
  58. package/dest/util/txe_contract_store.d.ts.map +0 -1
  59. package/dest/util/txe_contract_store.js +0 -22
  60. package/src/util/txe_contract_store.ts +0 -36
@@ -1,9 +1,7 @@
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_PROCESSABLE_DA_GAS_PER_CHECKPOINT,
4
+ MAX_PROCESSABLE_L2_GAS,
7
5
  NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
8
6
  } from '@aztec/constants';
9
7
  import { BlockNumber } from '@aztec/foundation/branded-types';
@@ -14,9 +12,11 @@ import { TestDateProvider } from '@aztec/foundation/timer';
14
12
  import type { KeyStore } from '@aztec/key-store';
15
13
  import {
16
14
  AddressStore,
15
+ CapsuleService,
17
16
  CapsuleStore,
17
+ type ContractStore,
18
18
  NoteStore,
19
- ORACLE_VERSION,
19
+ ORACLE_VERSION_MAJOR,
20
20
  PrivateEventStore,
21
21
  RecipientTaggingStore,
22
22
  SenderAddressBookStore,
@@ -54,7 +54,13 @@ import { AuthWitness } from '@aztec/stdlib/auth-witness';
54
54
  import { PublicSimulatorConfig } from '@aztec/stdlib/avm';
55
55
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
56
56
  import { type ContractInstanceWithAddress, computePartialAddress } from '@aztec/stdlib/contract';
57
- import { Gas, GasFees, GasSettings } from '@aztec/stdlib/gas';
57
+ import {
58
+ FALLBACK_TEARDOWN_DA_GAS_LIMIT,
59
+ FALLBACK_TEARDOWN_L2_GAS_LIMIT,
60
+ Gas,
61
+ GasFees,
62
+ GasSettings,
63
+ } from '@aztec/stdlib/gas';
58
64
  import { computeCalldataHash, computeProtocolNullifier, siloNullifier } from '@aztec/stdlib/hash';
59
65
  import {
60
66
  PartialPrivateTailPublicInputsForPublic,
@@ -83,7 +89,6 @@ import { ForkCheckpoint } from '@aztec/world-state';
83
89
  import { DEFAULT_ADDRESS } from '../constants.js';
84
90
  import type { TXEStateMachine } from '../state_machine/index.js';
85
91
  import type { TXEAccountStore } from '../util/txe_account_store.js';
86
- import type { TXEContractStore } from '../util/txe_contract_store.js';
87
92
  import { TXEPublicContractDataSource } from '../util/txe_public_contract_data_source.js';
88
93
  import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlock } from '../utils/block_creation.js';
89
94
  import type { ITxeExecutionOracle } from './interfaces.js';
@@ -96,7 +101,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
96
101
 
97
102
  constructor(
98
103
  private stateMachine: TXEStateMachine,
99
- private contractStore: TXEContractStore,
104
+ private contractStore: ContractStore,
100
105
  private noteStore: NoteStore,
101
106
  private keyStore: KeyStore,
102
107
  private addressStore: AddressStore,
@@ -106,7 +111,6 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
106
111
  private senderAddressBookStore: SenderAddressBookStore,
107
112
  private capsuleStore: CapsuleStore,
108
113
  private privateEventStore: PrivateEventStore,
109
- private jobId: string,
110
114
  private nextBlockTimestamp: bigint,
111
115
  private version: Fr,
112
116
  private chainId: Fr,
@@ -116,47 +120,60 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
116
120
  this.logger.debug('Entering Top Level Context');
117
121
  }
118
122
 
119
- utilityAssertCompatibleOracleVersion(version: number): void {
120
- if (version !== ORACLE_VERSION) {
123
+ private contractOracleVersion: { major: number; minor: number } | undefined;
124
+
125
+ assertCompatibleOracleVersion(major: number, minor: number): void {
126
+ if (major !== ORACLE_VERSION_MAJOR) {
127
+ const hint =
128
+ major > ORACLE_VERSION_MAJOR
129
+ ? '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.'
130
+ : '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
131
  throw new Error(
122
- `Incompatible oracle version. TXE is using version '${ORACLE_VERSION}', but got a request for '${version}'.`,
132
+ `Incompatible aztec cli version: ${hint} See https://docs.aztec.network/errors/8 (expected oracle major version ${ORACLE_VERSION_MAJOR}, got ${major})`,
123
133
  );
124
134
  }
135
+ this.contractOracleVersion = { major, minor };
136
+ }
137
+
138
+ // Prefixed with "nonOracleFunction" as it is not used as an oracle handler.
139
+ nonOracleFunctionGetContractOracleVersion(): { major: number; minor: number } | undefined {
140
+ return this.contractOracleVersion;
125
141
  }
126
142
 
127
143
  // This is typically only invoked in private contexts, but it is convenient to also have it in top-level for testing
128
144
  // setup.
129
- utilityGetRandomField(): Fr {
145
+ getRandomField(): Fr {
130
146
  return Fr.random();
131
147
  }
132
148
 
133
149
  // We instruct users to debug contracts via this oracle, so it makes sense that they'd expect it to also work in tests
134
- utilityDebugLog(level: number, message: string, fields: Fr[]): void {
150
+ log(level: number, message: string, fields: Fr[]): Promise<void> {
135
151
  if (!LogLevels[level]) {
136
- throw new Error(`Invalid debug log level: ${level}`);
152
+ throw new Error(`Invalid log level: ${level}`);
137
153
  }
138
154
  const levelName = LogLevels[level];
139
155
 
140
156
  this.logger[levelName](`${applyStringFormatting(message, fields)}`, { module: `${this.logger.module}:debug_log` });
157
+ return Promise.resolve();
141
158
  }
142
159
 
143
- txeGetDefaultAddress(): AztecAddress {
160
+ getDefaultAddress(): AztecAddress {
144
161
  return DEFAULT_ADDRESS;
145
162
  }
146
163
 
147
- async txeGetNextBlockNumber(): Promise<BlockNumber> {
164
+ async getNextBlockNumber(): Promise<BlockNumber> {
148
165
  return BlockNumber((await this.getLastBlockNumber()) + 1);
149
166
  }
150
167
 
151
- txeGetNextBlockTimestamp(): Promise<bigint> {
168
+ getNextBlockTimestamp(): Promise<bigint> {
152
169
  return Promise.resolve(this.nextBlockTimestamp);
153
170
  }
154
171
 
155
- async txeGetLastBlockTimestamp() {
172
+ async getLastBlockTimestamp() {
156
173
  return (await this.stateMachine.node.getBlockHeader('latest'))!.globalVariables.timestamp;
157
174
  }
158
175
 
159
- async txeGetLastTxEffects() {
176
+ async getLastTxEffects() {
160
177
  const latestBlockNumber = await this.stateMachine.archiver.getBlockNumber();
161
178
  const block = await this.stateMachine.archiver.getBlock(latestBlockNumber);
162
179
 
@@ -167,10 +184,34 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
167
184
 
168
185
  const txEffects = block!.body.txEffects[0];
169
186
 
170
- return { txHash: txEffects.txHash, noteHashes: txEffects.noteHashes, nullifiers: txEffects.nullifiers };
187
+ return {
188
+ txHash: txEffects.txHash,
189
+ noteHashes: txEffects.noteHashes,
190
+ nullifiers: txEffects.nullifiers,
191
+ privateLogs: txEffects.privateLogs,
192
+ };
193
+ }
194
+
195
+ async syncContractNonOracleMethod(contractAddress: AztecAddress, scope: AztecAddress, jobId: string) {
196
+ if (contractAddress.equals(DEFAULT_ADDRESS)) {
197
+ this.logger.debug(`Skipping sync in getPrivateEvents because the events correspond to the default address.`);
198
+ return;
199
+ }
200
+
201
+ const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
202
+ await this.stateMachine.contractSyncService.ensureContractSynced(
203
+ contractAddress,
204
+ null,
205
+ async (call, execScopes) => {
206
+ await this.executeUtilityCall(call, execScopes, jobId);
207
+ },
208
+ blockHeader,
209
+ jobId,
210
+ [scope],
211
+ );
171
212
  }
172
213
 
173
- async txeGetPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress) {
214
+ async getPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress) {
174
215
  return (
175
216
  await this.privateEventStore.getPrivateEvents(selector, {
176
217
  contractAddress,
@@ -181,7 +222,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
181
222
  ).map(e => e.packedEvent);
182
223
  }
183
224
 
184
- async txeAdvanceBlocksBy(blocks: number) {
225
+ async advanceBlocksBy(blocks: number) {
185
226
  this.logger.debug(`time traveling ${blocks} blocks`);
186
227
 
187
228
  for (let i = 0; i < blocks; i++) {
@@ -189,12 +230,12 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
189
230
  }
190
231
  }
191
232
 
192
- txeAdvanceTimestampBy(duration: UInt64) {
233
+ advanceTimestampBy(duration: UInt64) {
193
234
  this.logger.debug(`time traveling ${duration} seconds`);
194
235
  this.nextBlockTimestamp += duration;
195
236
  }
196
237
 
197
- async txeDeploy(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
238
+ async deploy(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
198
239
  // Emit deployment nullifier
199
240
  await this.mineBlock({
200
241
  nullifiers: [
@@ -206,20 +247,20 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
206
247
  });
207
248
 
208
249
  if (!secret.equals(Fr.ZERO)) {
209
- await this.txeAddAccount(artifact, instance, secret);
250
+ await this.addAccount(artifact, instance, secret);
210
251
  } else {
211
252
  await this.contractStore.addContractInstance(instance);
212
- await this.contractStore.addContractArtifact(instance.currentContractClassId, artifact);
253
+ await this.contractStore.addContractArtifact(artifact);
213
254
  this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
214
255
  }
215
256
  }
216
257
 
217
- async txeAddAccount(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
258
+ async addAccount(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
218
259
  const partialAddress = await computePartialAddress(instance);
219
260
 
220
261
  this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
221
262
  await this.contractStore.addContractInstance(instance);
222
- await this.contractStore.addContractArtifact(instance.currentContractClassId, artifact);
263
+ await this.contractStore.addContractArtifact(artifact);
223
264
 
224
265
  const completeAddress = await this.keyStore.addAccount(secret, partialAddress);
225
266
  await this.accountStore.setAccount(completeAddress.address, completeAddress);
@@ -229,7 +270,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
229
270
  return completeAddress;
230
271
  }
231
272
 
232
- async txeCreateAccount(secret: Fr) {
273
+ async createAccount(secret: Fr) {
233
274
  // This is a foot gun !
234
275
  const completeAddress = await this.keyStore.addAccount(secret, secret);
235
276
  await this.accountStore.setAccount(completeAddress.address, completeAddress);
@@ -239,7 +280,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
239
280
  return completeAddress;
240
281
  }
241
282
 
242
- async txeAddAuthWitness(address: AztecAddress, messageHash: Fr) {
283
+ async addAuthWitness(address: AztecAddress, messageHash: Fr) {
243
284
  const account = await this.accountStore.getAccount(address);
244
285
  const privateKey = await this.keyStore.getMasterSecretKey(account.publicKeys.masterIncomingViewingPublicKey);
245
286
 
@@ -252,7 +293,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
252
293
  }
253
294
 
254
295
  async mineBlock(options: { nullifiers?: Fr[] } = {}) {
255
- const blockNumber = await this.txeGetNextBlockNumber();
296
+ const blockNumber = await this.getNextBlockNumber();
256
297
 
257
298
  const txEffect = TxEffect.empty();
258
299
  txEffect.nullifiers = [getSingleTxBlockRequestHash(blockNumber), ...(options.nullifiers ?? [])];
@@ -276,13 +317,14 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
276
317
  await this.stateMachine.handleL2Block(block);
277
318
  }
278
319
 
279
- async txePrivateCallNewFlow(
320
+ async privateCallNewFlow(
280
321
  from: AztecAddress,
281
322
  targetContractAddress: AztecAddress = AztecAddress.zero(),
282
323
  functionSelector: FunctionSelector = FunctionSelector.empty(),
283
324
  args: Fr[],
284
325
  argsHash: Fr = Fr.zero(),
285
326
  isStaticCall: boolean = false,
327
+ jobId: string,
286
328
  ) {
287
329
  this.logger.verbose(
288
330
  `Executing external function ${await this.contractStore.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`,
@@ -296,14 +338,13 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
296
338
  throw new Error(message);
297
339
  }
298
340
 
299
- // When `from` is the zero address (used when creating a new contract account for example),
300
- // we disable scope filtering by setting effectiveScopes to undefined. This allows these operations
301
- // to proceed without requiring keys registered for the zero address.
302
- const effectiveScopes = from.isZero() ? undefined : [from];
341
+ // When `from` is the zero address (e.g. when deploying a new account contract), we return an
342
+ // empty scope list which acts as deny-all: no notes are visible and no keys are accessible.
343
+ const effectiveScopes = from.isZero() ? [] : [from];
303
344
 
304
345
  // Sync notes before executing private function to discover notes from previous transactions
305
- const utilityExecutor = async (call: FunctionCall) => {
306
- await this.executeUtilityCall(call, effectiveScopes);
346
+ const utilityExecutor = async (call: FunctionCall, execScopes: AztecAddress[]) => {
347
+ await this.executeUtilityCall(call, execScopes, jobId);
307
348
  };
308
349
 
309
350
  const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
@@ -312,15 +353,16 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
312
353
  functionSelector,
313
354
  utilityExecutor,
314
355
  blockHeader,
315
- this.jobId,
356
+ jobId,
357
+ effectiveScopes,
316
358
  );
317
359
 
318
- const blockNumber = await this.txeGetNextBlockNumber();
360
+ const blockNumber = await this.getNextBlockNumber();
319
361
 
320
362
  const callContext = new CallContext(from, targetContractAddress, functionSelector, isStaticCall);
321
363
 
322
- const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
323
- const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
364
+ const gasLimits = new Gas(MAX_PROCESSABLE_DA_GAS_PER_CHECKPOINT, MAX_PROCESSABLE_L2_GAS);
365
+ const teardownGasLimits = new Gas(FALLBACK_TEARDOWN_DA_GAS_LIMIT, FALLBACK_TEARDOWN_L2_GAS_LIMIT);
324
366
  const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
325
367
 
326
368
  const txContext = new TxContext(this.chainId, this.version, gasSettings);
@@ -336,43 +378,39 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
336
378
 
337
379
  const simulator = new WASMSimulator();
338
380
 
339
- const privateExecutionOracle = new PrivateExecutionOracle(
381
+ const privateExecutionOracle = new PrivateExecutionOracle({
340
382
  argsHash,
341
383
  txContext,
342
384
  callContext,
343
- /** Header of a block whose state is used during private execution (not the block the transaction is included in). */
344
- blockHeader,
385
+ anchorBlockHeader: blockHeader,
345
386
  utilityExecutor,
346
- /** List of transient auth witnesses to be used during this simulation */
347
- Array.from(this.authwits.values()),
348
- /** List of transient auth witnesses to be used during this simulation */
349
- [],
350
- HashedValuesCache.create([new HashedValues(args, argsHash)]),
387
+ authWitnesses: Array.from(this.authwits.values()),
388
+ capsules: [],
389
+ executionCache: HashedValuesCache.create([new HashedValues(args, argsHash)]),
351
390
  noteCache,
352
391
  taggingIndexCache,
353
- this.contractStore,
354
- this.noteStore,
355
- this.keyStore,
356
- this.addressStore,
357
- this.stateMachine.node,
358
- this.senderTaggingStore,
359
- this.recipientTaggingStore,
360
- this.senderAddressBookStore,
361
- this.capsuleStore,
362
- this.privateEventStore,
363
- this.stateMachine.contractSyncService,
364
- this.jobId,
365
- 0, // totalPublicArgsCount
366
- minRevertibleSideEffectCounter, // (start) sideEffectCounter
367
- undefined, // log
368
- effectiveScopes, // scopes
369
- /**
370
- * In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
371
- * contract would perform, including setting senderForTags.
372
- */
373
- from,
392
+ contractStore: this.contractStore,
393
+ noteStore: this.noteStore,
394
+ keyStore: this.keyStore,
395
+ addressStore: this.addressStore,
396
+ aztecNode: this.stateMachine.node,
397
+ senderTaggingStore: this.senderTaggingStore,
398
+ recipientTaggingStore: this.recipientTaggingStore,
399
+ senderAddressBookStore: this.senderAddressBookStore,
400
+ capsuleService: new CapsuleService(this.capsuleStore, effectiveScopes),
401
+ privateEventStore: this.privateEventStore,
402
+ contractSyncService: this.stateMachine.contractSyncService,
403
+ jobId,
404
+ totalPublicCalldataCount: 0,
405
+ sideEffectCounter: minRevertibleSideEffectCounter,
406
+ scopes: effectiveScopes,
407
+ // In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
408
+ // contract would perform, including setting senderForTags.
409
+ senderForTags: from,
374
410
  simulator,
375
- );
411
+ messageContextService: this.stateMachine.messageContextService,
412
+ l2TipsStore: this.stateMachine.node,
413
+ });
376
414
 
377
415
  // 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.
378
416
  let result: PrivateExecutionResult;
@@ -394,7 +432,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
394
432
  );
395
433
  const publicFunctionsCalldata = await Promise.all(
396
434
  publicCallRequests.map(async r => {
397
- const calldata = await privateExecutionOracle.privateLoadFromExecutionCache(r.calldataHash);
435
+ const calldata = await privateExecutionOracle.getHashPreimage(r.calldataHash);
398
436
  return new HashedValues(calldata, r.calldataHash);
399
437
  }),
400
438
  );
@@ -411,7 +449,8 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
411
449
  // We pass the non-zero minRevertibleSideEffectCounter to make sure the side effects are split correctly.
412
450
  const { publicInputs } = await generateSimulatedProvingResult(
413
451
  result,
414
- this.contractStore,
452
+ (addr, sel) => this.contractStore.getDebugFunctionName(addr, sel),
453
+ this.stateMachine.node,
415
454
  minRevertibleSideEffectCounter,
416
455
  );
417
456
 
@@ -478,11 +517,17 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
478
517
  }
479
518
  }
480
519
 
520
+ // Walk the nested private-call tree and collect every offchain effect the transaction emitted.
521
+ // PXE stores these on each `PrivateCallExecutionResult` and they never reach TXE via the
522
+ // `aztec_utl_emitOffchainEffect` foreign-call path (that path only fires at the top-level), so
523
+ // we pull them out here and the RPC wrapper will hand them to `TXESession` for buffering.
524
+ const offchainEffects = collectNested([executionResult], r => r.offchainEffects.map(e => e.data));
525
+
481
526
  if (isStaticCall) {
482
527
  await checkpoint!.revert();
483
528
 
484
529
  await forkedWorldTrees.close();
485
- return executionResult.returnValues ?? [];
530
+ return { returnValues: executionResult.returnValues ?? [], offchainEffects };
486
531
  }
487
532
 
488
533
  const txEffect = TxEffect.empty();
@@ -504,10 +549,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
504
549
 
505
550
  await forkedWorldTrees.close();
506
551
 
507
- return executionResult.returnValues ?? [];
552
+ return { returnValues: executionResult.returnValues ?? [], offchainEffects };
508
553
  }
509
554
 
510
- async txePublicCallNewFlow(
555
+ async publicCallNewFlow(
511
556
  from: AztecAddress,
512
557
  targetContractAddress: AztecAddress,
513
558
  calldata: Fr[],
@@ -517,11 +562,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
517
562
  `Executing public function ${await this.contractStore.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`,
518
563
  );
519
564
 
520
- const blockNumber = await this.txeGetNextBlockNumber();
565
+ const blockNumber = await this.getNextBlockNumber();
521
566
 
522
- const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
567
+ const gasLimits = new Gas(MAX_PROCESSABLE_DA_GAS_PER_CHECKPOINT, MAX_PROCESSABLE_L2_GAS);
523
568
 
524
- const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
569
+ const teardownGasLimits = new Gas(FALLBACK_TEARDOWN_DA_GAS_LIMIT, FALLBACK_TEARDOWN_L2_GAS_LIMIT);
525
570
 
526
571
  const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
527
572
 
@@ -594,7 +639,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
594
639
  constantData,
595
640
  /*gasUsed=*/ new Gas(0, 0),
596
641
  /*feePayer=*/ AztecAddress.zero(),
597
- /*includeByTimestamp=*/ 0n,
642
+ /*expirationTimestamp=*/ 0n,
598
643
  inputsForPublic,
599
644
  undefined,
600
645
  );
@@ -662,10 +707,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
662
707
  return returnValues ?? [];
663
708
  }
664
709
 
665
- async txeSimulateUtilityFunction(
710
+ async executeUtilityFunction(
666
711
  targetContractAddress: AztecAddress,
667
712
  functionSelector: FunctionSelector,
668
713
  args: Fr[],
714
+ jobId: string,
669
715
  ) {
670
716
  const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
671
717
  if (!artifact) {
@@ -677,28 +723,29 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
677
723
  await this.stateMachine.contractSyncService.ensureContractSynced(
678
724
  targetContractAddress,
679
725
  functionSelector,
680
- async call => {
681
- await this.executeUtilityCall(call);
726
+ async (call, execScopes) => {
727
+ await this.executeUtilityCall(call, execScopes, jobId);
682
728
  },
683
729
  blockHeader,
684
- this.jobId,
730
+ jobId,
731
+ await this.keyStore.getAccounts(),
685
732
  );
686
733
 
687
- const call = new FunctionCall(
688
- artifact.name,
689
- targetContractAddress,
690
- functionSelector,
691
- FunctionType.UTILITY,
692
- false,
693
- false,
734
+ const call = FunctionCall.from({
735
+ name: artifact.name,
736
+ to: targetContractAddress,
737
+ selector: functionSelector,
738
+ type: FunctionType.UTILITY,
739
+ hideMsgSender: false,
740
+ isStatic: false,
694
741
  args,
695
- [],
696
- );
742
+ returnTypes: [],
743
+ });
697
744
 
698
- return this.executeUtilityCall(call);
745
+ return this.executeUtilityCall(call, await this.keyStore.getAccounts(), jobId);
699
746
  }
700
747
 
701
- private async executeUtilityCall(call: FunctionCall, scopes?: AztecAddress[]): Promise<Fr[]> {
748
+ private async executeUtilityCall(call: FunctionCall, scopes: AztecAddress[], jobId: string): Promise<Fr[]> {
702
749
  const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
703
750
  if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
704
751
  throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
@@ -711,25 +758,29 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
711
758
 
712
759
  try {
713
760
  const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
714
- const oracle = new UtilityExecutionOracle(
715
- call.to,
716
- [],
717
- [],
761
+ const simulator = new WASMSimulator();
762
+ const oracle = new UtilityExecutionOracle({
763
+ contractAddress: call.to,
764
+ authWitnesses: [],
765
+ capsules: [],
718
766
  anchorBlockHeader,
719
- this.contractStore,
720
- this.noteStore,
721
- this.keyStore,
722
- this.addressStore,
723
- this.stateMachine.node,
724
- this.recipientTaggingStore,
725
- this.senderAddressBookStore,
726
- this.capsuleStore,
727
- this.privateEventStore,
728
- this.jobId,
729
- undefined, // log
730
- scopes, // scopes - used to filter notes by account
731
- );
732
- const acirExecutionResult = await new WASMSimulator()
767
+ contractStore: this.contractStore,
768
+ noteStore: this.noteStore,
769
+ keyStore: this.keyStore,
770
+ addressStore: this.addressStore,
771
+ aztecNode: this.stateMachine.node,
772
+ recipientTaggingStore: this.recipientTaggingStore,
773
+ senderAddressBookStore: this.senderAddressBookStore,
774
+ capsuleService: new CapsuleService(this.capsuleStore, scopes),
775
+ privateEventStore: this.privateEventStore,
776
+ messageContextService: this.stateMachine.messageContextService,
777
+ contractSyncService: this.stateMachine.contractSyncService,
778
+ l2TipsStore: this.stateMachine.node,
779
+ jobId,
780
+ scopes,
781
+ simulator,
782
+ });
783
+ const acirExecutionResult = await simulator
733
784
  .executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
734
785
  .catch((err: Error) => {
735
786
  err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
@@ -744,10 +795,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
744
795
  );
745
796
  });
746
797
 
747
- this.logger.verbose(`Utility simulation for ${call.to}.${call.selector} completed`);
798
+ this.logger.verbose(`Utility execution for ${call.to}.${call.selector} completed`);
748
799
  return witnessMapToFields(acirExecutionResult.returnWitness);
749
800
  } catch (err) {
750
- throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility simulation'));
801
+ throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility execution'));
751
802
  }
752
803
  }
753
804