@aztec/txe 0.0.1-commit.29c6b1a3 → 0.0.1-commit.2c0ee1788

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 (64) 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 +32 -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 +30 -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 +167 -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 +485 -173
  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 +14 -12
  18. package/dest/state_machine/dummy_p2p_client.d.ts +18 -13
  19. package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
  20. package/dest/state_machine/dummy_p2p_client.js +33 -18
  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 +7 -5
  25. package/dest/state_machine/index.d.ts.map +1 -1
  26. package/dest/state_machine/index.js +20 -11
  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 +157 -29
  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/dest/utils/block_creation.d.ts +1 -1
  43. package/dest/utils/block_creation.d.ts.map +1 -1
  44. package/dest/utils/block_creation.js +3 -1
  45. package/package.json +15 -15
  46. package/src/index.ts +89 -52
  47. package/src/oracle/interfaces.ts +33 -32
  48. package/src/oracle/txe_oracle_public_context.ts +12 -12
  49. package/src/oracle/txe_oracle_top_level_context.ts +199 -118
  50. package/src/rpc_translator.ts +562 -200
  51. package/src/state_machine/archiver.ts +11 -9
  52. package/src/state_machine/dummy_p2p_client.ts +46 -24
  53. package/src/state_machine/global_variable_builder.ts +18 -3
  54. package/src/state_machine/index.ts +33 -10
  55. package/src/state_machine/mock_epoch_cache.ts +51 -3
  56. package/src/state_machine/synchronizer.ts +4 -4
  57. package/src/txe_session.ts +228 -89
  58. package/src/util/encoding.ts +5 -0
  59. package/src/util/txe_public_contract_data_source.ts +10 -38
  60. package/src/utils/block_creation.ts +3 -1
  61. package/dest/util/txe_contract_store.d.ts +0 -12
  62. package/dest/util/txe_contract_store.d.ts.map +0 -1
  63. package/dest/util/txe_contract_store.js +0 -22
  64. 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,15 +12,16 @@ 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,
23
23
  SenderTaggingStore,
24
24
  enrichPublicSimulationError,
25
- syncState,
26
25
  } from '@aztec/pxe/server';
27
26
  import {
28
27
  ExecutionNoteCache,
@@ -55,7 +54,13 @@ import { AuthWitness } from '@aztec/stdlib/auth-witness';
55
54
  import { PublicSimulatorConfig } from '@aztec/stdlib/avm';
56
55
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
57
56
  import { type ContractInstanceWithAddress, computePartialAddress } from '@aztec/stdlib/contract';
58
- 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';
59
64
  import { computeCalldataHash, computeProtocolNullifier, siloNullifier } from '@aztec/stdlib/hash';
60
65
  import {
61
66
  PartialPrivateTailPublicInputsForPublic,
@@ -84,7 +89,6 @@ import { ForkCheckpoint } from '@aztec/world-state';
84
89
  import { DEFAULT_ADDRESS } from '../constants.js';
85
90
  import type { TXEStateMachine } from '../state_machine/index.js';
86
91
  import type { TXEAccountStore } from '../util/txe_account_store.js';
87
- import type { TXEContractStore } from '../util/txe_contract_store.js';
88
92
  import { TXEPublicContractDataSource } from '../util/txe_public_contract_data_source.js';
89
93
  import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlock } from '../utils/block_creation.js';
90
94
  import type { ITxeExecutionOracle } from './interfaces.js';
@@ -97,7 +101,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
97
101
 
98
102
  constructor(
99
103
  private stateMachine: TXEStateMachine,
100
- private contractStore: TXEContractStore,
104
+ private contractStore: ContractStore,
101
105
  private noteStore: NoteStore,
102
106
  private keyStore: KeyStore,
103
107
  private addressStore: AddressStore,
@@ -107,7 +111,6 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
107
111
  private senderAddressBookStore: SenderAddressBookStore,
108
112
  private capsuleStore: CapsuleStore,
109
113
  private privateEventStore: PrivateEventStore,
110
- private jobId: string,
111
114
  private nextBlockTimestamp: bigint,
112
115
  private version: Fr,
113
116
  private chainId: Fr,
@@ -117,47 +120,60 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
117
120
  this.logger.debug('Entering Top Level Context');
118
121
  }
119
122
 
120
- utilityAssertCompatibleOracleVersion(version: number): void {
121
- 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.';
122
131
  throw new Error(
123
- `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})`,
124
133
  );
125
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;
126
141
  }
127
142
 
128
143
  // This is typically only invoked in private contexts, but it is convenient to also have it in top-level for testing
129
144
  // setup.
130
- utilityGetRandomField(): Fr {
145
+ getRandomField(): Fr {
131
146
  return Fr.random();
132
147
  }
133
148
 
134
149
  // We instruct users to debug contracts via this oracle, so it makes sense that they'd expect it to also work in tests
135
- utilityDebugLog(level: number, message: string, fields: Fr[]): void {
150
+ log(level: number, message: string, fields: Fr[]): Promise<void> {
136
151
  if (!LogLevels[level]) {
137
- throw new Error(`Invalid debug log level: ${level}`);
152
+ throw new Error(`Invalid log level: ${level}`);
138
153
  }
139
154
  const levelName = LogLevels[level];
140
155
 
141
156
  this.logger[levelName](`${applyStringFormatting(message, fields)}`, { module: `${this.logger.module}:debug_log` });
157
+ return Promise.resolve();
142
158
  }
143
159
 
144
- txeGetDefaultAddress(): AztecAddress {
160
+ getDefaultAddress(): AztecAddress {
145
161
  return DEFAULT_ADDRESS;
146
162
  }
147
163
 
148
- async txeGetNextBlockNumber(): Promise<BlockNumber> {
164
+ async getNextBlockNumber(): Promise<BlockNumber> {
149
165
  return BlockNumber((await this.getLastBlockNumber()) + 1);
150
166
  }
151
167
 
152
- txeGetNextBlockTimestamp(): Promise<bigint> {
168
+ getNextBlockTimestamp(): Promise<bigint> {
153
169
  return Promise.resolve(this.nextBlockTimestamp);
154
170
  }
155
171
 
156
- async txeGetLastBlockTimestamp() {
172
+ async getLastBlockTimestamp() {
157
173
  return (await this.stateMachine.node.getBlockHeader('latest'))!.globalVariables.timestamp;
158
174
  }
159
175
 
160
- async txeGetLastTxEffects() {
176
+ async getLastTxEffects() {
161
177
  const latestBlockNumber = await this.stateMachine.archiver.getBlockNumber();
162
178
  const block = await this.stateMachine.archiver.getBlock(latestBlockNumber);
163
179
 
@@ -171,7 +187,26 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
171
187
  return { txHash: txEffects.txHash, noteHashes: txEffects.noteHashes, nullifiers: txEffects.nullifiers };
172
188
  }
173
189
 
174
- async txeGetPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress) {
190
+ async syncContractNonOracleMethod(contractAddress: AztecAddress, scope: AztecAddress, jobId: string) {
191
+ if (contractAddress.equals(DEFAULT_ADDRESS)) {
192
+ this.logger.debug(`Skipping sync in getPrivateEvents because the events correspond to the default address.`);
193
+ return;
194
+ }
195
+
196
+ const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
197
+ await this.stateMachine.contractSyncService.ensureContractSynced(
198
+ contractAddress,
199
+ null,
200
+ async (call, execScopes) => {
201
+ await this.executeUtilityCall(call, execScopes, jobId);
202
+ },
203
+ blockHeader,
204
+ jobId,
205
+ [scope],
206
+ );
207
+ }
208
+
209
+ async getPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress) {
175
210
  return (
176
211
  await this.privateEventStore.getPrivateEvents(selector, {
177
212
  contractAddress,
@@ -182,7 +217,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
182
217
  ).map(e => e.packedEvent);
183
218
  }
184
219
 
185
- async txeAdvanceBlocksBy(blocks: number) {
220
+ async advanceBlocksBy(blocks: number) {
186
221
  this.logger.debug(`time traveling ${blocks} blocks`);
187
222
 
188
223
  for (let i = 0; i < blocks; i++) {
@@ -190,12 +225,12 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
190
225
  }
191
226
  }
192
227
 
193
- txeAdvanceTimestampBy(duration: UInt64) {
228
+ advanceTimestampBy(duration: UInt64) {
194
229
  this.logger.debug(`time traveling ${duration} seconds`);
195
230
  this.nextBlockTimestamp += duration;
196
231
  }
197
232
 
198
- async txeDeploy(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
233
+ async deploy(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
199
234
  // Emit deployment nullifier
200
235
  await this.mineBlock({
201
236
  nullifiers: [
@@ -207,20 +242,20 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
207
242
  });
208
243
 
209
244
  if (!secret.equals(Fr.ZERO)) {
210
- await this.txeAddAccount(artifact, instance, secret);
245
+ await this.addAccount(artifact, instance, secret);
211
246
  } else {
212
247
  await this.contractStore.addContractInstance(instance);
213
- await this.contractStore.addContractArtifact(instance.currentContractClassId, artifact);
248
+ await this.contractStore.addContractArtifact(artifact);
214
249
  this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
215
250
  }
216
251
  }
217
252
 
218
- async txeAddAccount(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
253
+ async addAccount(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
219
254
  const partialAddress = await computePartialAddress(instance);
220
255
 
221
256
  this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
222
257
  await this.contractStore.addContractInstance(instance);
223
- await this.contractStore.addContractArtifact(instance.currentContractClassId, artifact);
258
+ await this.contractStore.addContractArtifact(artifact);
224
259
 
225
260
  const completeAddress = await this.keyStore.addAccount(secret, partialAddress);
226
261
  await this.accountStore.setAccount(completeAddress.address, completeAddress);
@@ -230,7 +265,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
230
265
  return completeAddress;
231
266
  }
232
267
 
233
- async txeCreateAccount(secret: Fr) {
268
+ async createAccount(secret: Fr) {
234
269
  // This is a foot gun !
235
270
  const completeAddress = await this.keyStore.addAccount(secret, secret);
236
271
  await this.accountStore.setAccount(completeAddress.address, completeAddress);
@@ -240,7 +275,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
240
275
  return completeAddress;
241
276
  }
242
277
 
243
- async txeAddAuthWitness(address: AztecAddress, messageHash: Fr) {
278
+ async addAuthWitness(address: AztecAddress, messageHash: Fr) {
244
279
  const account = await this.accountStore.getAccount(address);
245
280
  const privateKey = await this.keyStore.getMasterSecretKey(account.publicKeys.masterIncomingViewingPublicKey);
246
281
 
@@ -253,7 +288,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
253
288
  }
254
289
 
255
290
  async mineBlock(options: { nullifiers?: Fr[] } = {}) {
256
- const blockNumber = await this.txeGetNextBlockNumber();
291
+ const blockNumber = await this.getNextBlockNumber();
257
292
 
258
293
  const txEffect = TxEffect.empty();
259
294
  txEffect.nullifiers = [getSingleTxBlockRequestHash(blockNumber), ...(options.nullifiers ?? [])];
@@ -277,13 +312,14 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
277
312
  await this.stateMachine.handleL2Block(block);
278
313
  }
279
314
 
280
- async txePrivateCallNewFlow(
315
+ async privateCallNewFlow(
281
316
  from: AztecAddress,
282
317
  targetContractAddress: AztecAddress = AztecAddress.zero(),
283
318
  functionSelector: FunctionSelector = FunctionSelector.empty(),
284
319
  args: Fr[],
285
320
  argsHash: Fr = Fr.zero(),
286
321
  isStaticCall: boolean = false,
322
+ jobId: string,
287
323
  ) {
288
324
  this.logger.verbose(
289
325
  `Executing external function ${await this.contractStore.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`,
@@ -297,25 +333,35 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
297
333
  throw new Error(message);
298
334
  }
299
335
 
336
+ // When `from` is the zero address (e.g. when deploying a new account contract), we return an
337
+ // empty scope list which acts as deny-all: no notes are visible and no keys are accessible.
338
+ const effectiveScopes = from.isZero() ? [] : [from];
339
+
300
340
  // Sync notes before executing private function to discover notes from previous transactions
301
- const utilityExecutor = async (call: FunctionCall) => {
302
- await this.executeUtilityCall(call);
341
+ const utilityExecutor = async (call: FunctionCall, execScopes: AztecAddress[]) => {
342
+ await this.executeUtilityCall(call, execScopes, jobId);
303
343
  };
304
344
 
305
- await syncState(targetContractAddress, this.contractStore, functionSelector, utilityExecutor);
345
+ const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
346
+ await this.stateMachine.contractSyncService.ensureContractSynced(
347
+ targetContractAddress,
348
+ functionSelector,
349
+ utilityExecutor,
350
+ blockHeader,
351
+ jobId,
352
+ effectiveScopes,
353
+ );
306
354
 
307
- const blockNumber = await this.txeGetNextBlockNumber();
355
+ const blockNumber = await this.getNextBlockNumber();
308
356
 
309
357
  const callContext = new CallContext(from, targetContractAddress, functionSelector, isStaticCall);
310
358
 
311
- const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
312
- const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
359
+ const gasLimits = new Gas(MAX_PROCESSABLE_DA_GAS_PER_CHECKPOINT, MAX_PROCESSABLE_L2_GAS);
360
+ const teardownGasLimits = new Gas(FALLBACK_TEARDOWN_DA_GAS_LIMIT, FALLBACK_TEARDOWN_L2_GAS_LIMIT);
313
361
  const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
314
362
 
315
363
  const txContext = new TxContext(this.chainId, this.version, gasSettings);
316
364
 
317
- const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
318
-
319
365
  const protocolNullifier = await computeProtocolNullifier(getSingleTxBlockRequestHash(blockNumber));
320
366
  const noteCache = new ExecutionNoteCache(protocolNullifier);
321
367
  // In production, the account contract sets the min revertible counter before calling the app function.
@@ -327,43 +373,39 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
327
373
 
328
374
  const simulator = new WASMSimulator();
329
375
 
330
- const privateExecutionOracle = new PrivateExecutionOracle(
376
+ const privateExecutionOracle = new PrivateExecutionOracle({
331
377
  argsHash,
332
378
  txContext,
333
379
  callContext,
334
- /** Header of a block whose state is used during private execution (not the block the transaction is included in). */
335
- blockHeader,
380
+ anchorBlockHeader: blockHeader,
336
381
  utilityExecutor,
337
- /** List of transient auth witnesses to be used during this simulation */
338
- Array.from(this.authwits.values()),
339
- /** List of transient auth witnesses to be used during this simulation */
340
- [],
341
- HashedValuesCache.create([new HashedValues(args, argsHash)]),
382
+ authWitnesses: Array.from(this.authwits.values()),
383
+ capsules: [],
384
+ executionCache: HashedValuesCache.create([new HashedValues(args, argsHash)]),
342
385
  noteCache,
343
386
  taggingIndexCache,
344
- this.contractStore,
345
- this.noteStore,
346
- this.keyStore,
347
- this.addressStore,
348
- this.stateMachine.node,
349
- this.stateMachine.anchorBlockStore,
350
- this.senderTaggingStore,
351
- this.recipientTaggingStore,
352
- this.senderAddressBookStore,
353
- this.capsuleStore,
354
- this.privateEventStore,
355
- this.jobId,
356
- 0, // totalPublicArgsCount
357
- minRevertibleSideEffectCounter, // (start) sideEffectCounter
358
- undefined, // log
359
- undefined, // scopes
360
- /**
361
- * In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
362
- * contract would perform, including setting senderForTags.
363
- */
364
- from,
387
+ contractStore: this.contractStore,
388
+ noteStore: this.noteStore,
389
+ keyStore: this.keyStore,
390
+ addressStore: this.addressStore,
391
+ aztecNode: this.stateMachine.node,
392
+ senderTaggingStore: this.senderTaggingStore,
393
+ recipientTaggingStore: this.recipientTaggingStore,
394
+ senderAddressBookStore: this.senderAddressBookStore,
395
+ capsuleService: new CapsuleService(this.capsuleStore, effectiveScopes),
396
+ privateEventStore: this.privateEventStore,
397
+ contractSyncService: this.stateMachine.contractSyncService,
398
+ jobId,
399
+ totalPublicCalldataCount: 0,
400
+ sideEffectCounter: minRevertibleSideEffectCounter,
401
+ scopes: effectiveScopes,
402
+ // In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
403
+ // contract would perform, including setting senderForTags.
404
+ senderForTags: from,
365
405
  simulator,
366
- );
406
+ messageContextService: this.stateMachine.messageContextService,
407
+ l2TipsStore: this.stateMachine.node,
408
+ });
367
409
 
368
410
  // 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.
369
411
  let result: PrivateExecutionResult;
@@ -385,7 +427,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
385
427
  );
386
428
  const publicFunctionsCalldata = await Promise.all(
387
429
  publicCallRequests.map(async r => {
388
- const calldata = await privateExecutionOracle.privateLoadFromExecutionCache(r.calldataHash);
430
+ const calldata = await privateExecutionOracle.getHashPreimage(r.calldataHash);
389
431
  return new HashedValues(calldata, r.calldataHash);
390
432
  }),
391
433
  );
@@ -402,7 +444,8 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
402
444
  // We pass the non-zero minRevertibleSideEffectCounter to make sure the side effects are split correctly.
403
445
  const { publicInputs } = await generateSimulatedProvingResult(
404
446
  result,
405
- this.contractStore,
447
+ (addr, sel) => this.contractStore.getDebugFunctionName(addr, sel),
448
+ this.stateMachine.node,
406
449
  minRevertibleSideEffectCounter,
407
450
  );
408
451
 
@@ -415,7 +458,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
415
458
 
416
459
  const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
417
460
 
418
- const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(blockNumber, this.contractStore));
461
+ const bindings = this.logger.getBindings();
462
+ const contractsDB = new PublicContractsDB(
463
+ new TXEPublicContractDataSource(blockNumber, this.contractStore),
464
+ bindings,
465
+ );
419
466
  const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
420
467
  const config = PublicSimulatorConfig.from({
421
468
  skipFeeEnforcement: true,
@@ -428,8 +475,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
428
475
  globals,
429
476
  guardedMerkleTrees,
430
477
  contractsDB,
431
- new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config),
478
+ new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings),
432
479
  new TestDateProvider(),
480
+ undefined,
481
+ createLogger('simulator:public-processor', bindings),
433
482
  );
434
483
 
435
484
  const tx = await Tx.create({
@@ -463,11 +512,17 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
463
512
  }
464
513
  }
465
514
 
515
+ // Walk the nested private-call tree and collect every offchain effect the transaction emitted.
516
+ // PXE stores these on each `PrivateCallExecutionResult` and they never reach TXE via the
517
+ // `aztec_utl_emitOffchainEffect` foreign-call path (that path only fires at the top-level), so
518
+ // we pull them out here and the RPC wrapper will hand them to `TXESession` for buffering.
519
+ const offchainEffects = collectNested([executionResult], r => r.offchainEffects.map(e => e.data));
520
+
466
521
  if (isStaticCall) {
467
522
  await checkpoint!.revert();
468
523
 
469
524
  await forkedWorldTrees.close();
470
- return executionResult.returnValues ?? [];
525
+ return { returnValues: executionResult.returnValues ?? [], offchainEffects };
471
526
  }
472
527
 
473
528
  const txEffect = TxEffect.empty();
@@ -489,10 +544,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
489
544
 
490
545
  await forkedWorldTrees.close();
491
546
 
492
- return executionResult.returnValues ?? [];
547
+ return { returnValues: executionResult.returnValues ?? [], offchainEffects };
493
548
  }
494
549
 
495
- async txePublicCallNewFlow(
550
+ async publicCallNewFlow(
496
551
  from: AztecAddress,
497
552
  targetContractAddress: AztecAddress,
498
553
  calldata: Fr[],
@@ -502,11 +557,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
502
557
  `Executing public function ${await this.contractStore.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`,
503
558
  );
504
559
 
505
- const blockNumber = await this.txeGetNextBlockNumber();
560
+ const blockNumber = await this.getNextBlockNumber();
506
561
 
507
- const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
562
+ const gasLimits = new Gas(MAX_PROCESSABLE_DA_GAS_PER_CHECKPOINT, MAX_PROCESSABLE_L2_GAS);
508
563
 
509
- const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
564
+ const teardownGasLimits = new Gas(FALLBACK_TEARDOWN_DA_GAS_LIMIT, FALLBACK_TEARDOWN_L2_GAS_LIMIT);
510
565
 
511
566
  const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
512
567
 
@@ -526,7 +581,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
526
581
 
527
582
  const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
528
583
 
529
- const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(blockNumber, this.contractStore));
584
+ const bindings2 = this.logger.getBindings();
585
+ const contractsDB = new PublicContractsDB(
586
+ new TXEPublicContractDataSource(blockNumber, this.contractStore),
587
+ bindings2,
588
+ );
530
589
  const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
531
590
  const config = PublicSimulatorConfig.from({
532
591
  skipFeeEnforcement: true,
@@ -535,8 +594,16 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
535
594
  collectStatistics: false,
536
595
  collectCallMetadata: true,
537
596
  });
538
- const simulator = new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config);
539
- const processor = new PublicProcessor(globals, guardedMerkleTrees, contractsDB, simulator, new TestDateProvider());
597
+ const simulator = new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings2);
598
+ const processor = new PublicProcessor(
599
+ globals,
600
+ guardedMerkleTrees,
601
+ contractsDB,
602
+ simulator,
603
+ new TestDateProvider(),
604
+ undefined,
605
+ createLogger('simulator:public-processor', bindings2),
606
+ );
540
607
 
541
608
  // We're simulating a scenario in which private execution immediately enqueues a public call and halts. The private
542
609
  // kernel init would in this case inject a nullifier with the transaction request hash as a non-revertible
@@ -567,7 +634,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
567
634
  constantData,
568
635
  /*gasUsed=*/ new Gas(0, 0),
569
636
  /*feePayer=*/ AztecAddress.zero(),
570
- /*includeByTimestamp=*/ 0n,
637
+ /*expirationTimestamp=*/ 0n,
571
638
  inputsForPublic,
572
639
  undefined,
573
640
  );
@@ -635,10 +702,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
635
702
  return returnValues ?? [];
636
703
  }
637
704
 
638
- async txeSimulateUtilityFunction(
705
+ async executeUtilityFunction(
639
706
  targetContractAddress: AztecAddress,
640
707
  functionSelector: FunctionSelector,
641
708
  args: Fr[],
709
+ jobId: string,
642
710
  ) {
643
711
  const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
644
712
  if (!artifact) {
@@ -646,25 +714,33 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
646
714
  }
647
715
 
648
716
  // Sync notes before executing utility function to discover notes from previous transactions
649
- await syncState(targetContractAddress, this.contractStore, functionSelector, async call => {
650
- await this.executeUtilityCall(call);
651
- });
652
-
653
- const call = new FunctionCall(
654
- artifact.name,
717
+ const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
718
+ await this.stateMachine.contractSyncService.ensureContractSynced(
655
719
  targetContractAddress,
656
720
  functionSelector,
657
- FunctionType.UTILITY,
658
- false,
659
- false,
660
- args,
661
- [],
721
+ async (call, execScopes) => {
722
+ await this.executeUtilityCall(call, execScopes, jobId);
723
+ },
724
+ blockHeader,
725
+ jobId,
726
+ await this.keyStore.getAccounts(),
662
727
  );
663
728
 
664
- return this.executeUtilityCall(call);
729
+ const call = FunctionCall.from({
730
+ name: artifact.name,
731
+ to: targetContractAddress,
732
+ selector: functionSelector,
733
+ type: FunctionType.UTILITY,
734
+ hideMsgSender: false,
735
+ isStatic: false,
736
+ args,
737
+ returnTypes: [],
738
+ });
739
+
740
+ return this.executeUtilityCall(call, await this.keyStore.getAccounts(), jobId);
665
741
  }
666
742
 
667
- private async executeUtilityCall(call: FunctionCall): Promise<Fr[]> {
743
+ private async executeUtilityCall(call: FunctionCall, scopes: AztecAddress[], jobId: string): Promise<Fr[]> {
668
744
  const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
669
745
  if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
670
746
  throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
@@ -677,24 +753,29 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
677
753
 
678
754
  try {
679
755
  const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
680
- const oracle = new UtilityExecutionOracle(
681
- call.to,
682
- [],
683
- [],
756
+ const simulator = new WASMSimulator();
757
+ const oracle = new UtilityExecutionOracle({
758
+ contractAddress: call.to,
759
+ authWitnesses: [],
760
+ capsules: [],
684
761
  anchorBlockHeader,
685
- this.contractStore,
686
- this.noteStore,
687
- this.keyStore,
688
- this.addressStore,
689
- this.stateMachine.node,
690
- this.stateMachine.anchorBlockStore,
691
- this.recipientTaggingStore,
692
- this.senderAddressBookStore,
693
- this.capsuleStore,
694
- this.privateEventStore,
695
- this.jobId,
696
- );
697
- const acirExecutionResult = await new WASMSimulator()
762
+ contractStore: this.contractStore,
763
+ noteStore: this.noteStore,
764
+ keyStore: this.keyStore,
765
+ addressStore: this.addressStore,
766
+ aztecNode: this.stateMachine.node,
767
+ recipientTaggingStore: this.recipientTaggingStore,
768
+ senderAddressBookStore: this.senderAddressBookStore,
769
+ capsuleService: new CapsuleService(this.capsuleStore, scopes),
770
+ privateEventStore: this.privateEventStore,
771
+ messageContextService: this.stateMachine.messageContextService,
772
+ contractSyncService: this.stateMachine.contractSyncService,
773
+ l2TipsStore: this.stateMachine.node,
774
+ jobId,
775
+ scopes,
776
+ simulator,
777
+ });
778
+ const acirExecutionResult = await simulator
698
779
  .executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
699
780
  .catch((err: Error) => {
700
781
  err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
@@ -709,10 +790,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
709
790
  );
710
791
  });
711
792
 
712
- this.logger.verbose(`Utility simulation for ${call.to}.${call.selector} completed`);
793
+ this.logger.verbose(`Utility execution for ${call.to}.${call.selector} completed`);
713
794
  return witnessMapToFields(acirExecutionResult.returnWitness);
714
795
  } catch (err) {
715
- throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility simulation'));
796
+ throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility execution'));
716
797
  }
717
798
  }
718
799