@aztec/txe 0.0.1-commit.d1f2d6c → 0.0.1-commit.d20b825a7

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 +14 -15
  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 +164 -65
  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 +486 -175
  15. package/dest/state_machine/archiver.d.ts +4 -4
  16. package/dest/state_machine/archiver.d.ts.map +1 -1
  17. package/dest/state_machine/archiver.js +10 -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 +36 -18
  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 -28
  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 +14 -16
  49. package/src/oracle/txe_oracle_top_level_context.ts +196 -116
  50. package/src/rpc_translator.ts +563 -202
  51. package/src/state_machine/archiver.ts +10 -11
  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 +54 -18
  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 +223 -88
  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,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
 
@@ -170,7 +187,26 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
170
187
  return { txHash: txEffects.txHash, noteHashes: txEffects.noteHashes, nullifiers: txEffects.nullifiers };
171
188
  }
172
189
 
173
- 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) {
174
210
  return (
175
211
  await this.privateEventStore.getPrivateEvents(selector, {
176
212
  contractAddress,
@@ -181,7 +217,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
181
217
  ).map(e => e.packedEvent);
182
218
  }
183
219
 
184
- async txeAdvanceBlocksBy(blocks: number) {
220
+ async advanceBlocksBy(blocks: number) {
185
221
  this.logger.debug(`time traveling ${blocks} blocks`);
186
222
 
187
223
  for (let i = 0; i < blocks; i++) {
@@ -189,12 +225,12 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
189
225
  }
190
226
  }
191
227
 
192
- txeAdvanceTimestampBy(duration: UInt64) {
228
+ advanceTimestampBy(duration: UInt64) {
193
229
  this.logger.debug(`time traveling ${duration} seconds`);
194
230
  this.nextBlockTimestamp += duration;
195
231
  }
196
232
 
197
- async txeDeploy(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
233
+ async deploy(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
198
234
  // Emit deployment nullifier
199
235
  await this.mineBlock({
200
236
  nullifiers: [
@@ -206,20 +242,20 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
206
242
  });
207
243
 
208
244
  if (!secret.equals(Fr.ZERO)) {
209
- await this.txeAddAccount(artifact, instance, secret);
245
+ await this.addAccount(artifact, instance, secret);
210
246
  } else {
211
247
  await this.contractStore.addContractInstance(instance);
212
- await this.contractStore.addContractArtifact(instance.currentContractClassId, artifact);
248
+ await this.contractStore.addContractArtifact(artifact);
213
249
  this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
214
250
  }
215
251
  }
216
252
 
217
- async txeAddAccount(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
253
+ async addAccount(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
218
254
  const partialAddress = await computePartialAddress(instance);
219
255
 
220
256
  this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
221
257
  await this.contractStore.addContractInstance(instance);
222
- await this.contractStore.addContractArtifact(instance.currentContractClassId, artifact);
258
+ await this.contractStore.addContractArtifact(artifact);
223
259
 
224
260
  const completeAddress = await this.keyStore.addAccount(secret, partialAddress);
225
261
  await this.accountStore.setAccount(completeAddress.address, completeAddress);
@@ -229,7 +265,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
229
265
  return completeAddress;
230
266
  }
231
267
 
232
- async txeCreateAccount(secret: Fr) {
268
+ async createAccount(secret: Fr) {
233
269
  // This is a foot gun !
234
270
  const completeAddress = await this.keyStore.addAccount(secret, secret);
235
271
  await this.accountStore.setAccount(completeAddress.address, completeAddress);
@@ -239,7 +275,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
239
275
  return completeAddress;
240
276
  }
241
277
 
242
- async txeAddAuthWitness(address: AztecAddress, messageHash: Fr) {
278
+ async addAuthWitness(address: AztecAddress, messageHash: Fr) {
243
279
  const account = await this.accountStore.getAccount(address);
244
280
  const privateKey = await this.keyStore.getMasterSecretKey(account.publicKeys.masterIncomingViewingPublicKey);
245
281
 
@@ -252,7 +288,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
252
288
  }
253
289
 
254
290
  async mineBlock(options: { nullifiers?: Fr[] } = {}) {
255
- const blockNumber = await this.txeGetNextBlockNumber();
291
+ const blockNumber = await this.getNextBlockNumber();
256
292
 
257
293
  const txEffect = TxEffect.empty();
258
294
  txEffect.nullifiers = [getSingleTxBlockRequestHash(blockNumber), ...(options.nullifiers ?? [])];
@@ -276,13 +312,14 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
276
312
  await this.stateMachine.handleL2Block(block);
277
313
  }
278
314
 
279
- async txePrivateCallNewFlow(
315
+ async privateCallNewFlow(
280
316
  from: AztecAddress,
281
317
  targetContractAddress: AztecAddress = AztecAddress.zero(),
282
318
  functionSelector: FunctionSelector = FunctionSelector.empty(),
283
319
  args: Fr[],
284
320
  argsHash: Fr = Fr.zero(),
285
321
  isStaticCall: boolean = false,
322
+ jobId: string,
286
323
  ) {
287
324
  this.logger.verbose(
288
325
  `Executing external function ${await this.contractStore.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`,
@@ -296,25 +333,35 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
296
333
  throw new Error(message);
297
334
  }
298
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
+
299
340
  // Sync notes before executing private function to discover notes from previous transactions
300
- const utilityExecutor = async (call: FunctionCall) => {
301
- await this.executeUtilityCall(call);
341
+ const utilityExecutor = async (call: FunctionCall, execScopes: AztecAddress[]) => {
342
+ await this.executeUtilityCall(call, execScopes, jobId);
302
343
  };
303
344
 
304
- await this.contractStore.syncPrivateState(targetContractAddress, 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
+ );
305
354
 
306
- const blockNumber = await this.txeGetNextBlockNumber();
355
+ const blockNumber = await this.getNextBlockNumber();
307
356
 
308
357
  const callContext = new CallContext(from, targetContractAddress, functionSelector, isStaticCall);
309
358
 
310
- const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
311
- 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);
312
361
  const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
313
362
 
314
363
  const txContext = new TxContext(this.chainId, this.version, gasSettings);
315
364
 
316
- const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
317
-
318
365
  const protocolNullifier = await computeProtocolNullifier(getSingleTxBlockRequestHash(blockNumber));
319
366
  const noteCache = new ExecutionNoteCache(protocolNullifier);
320
367
  // In production, the account contract sets the min revertible counter before calling the app function.
@@ -326,43 +373,39 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
326
373
 
327
374
  const simulator = new WASMSimulator();
328
375
 
329
- const privateExecutionOracle = new PrivateExecutionOracle(
376
+ const privateExecutionOracle = new PrivateExecutionOracle({
330
377
  argsHash,
331
378
  txContext,
332
379
  callContext,
333
- /** Header of a block whose state is used during private execution (not the block the transaction is included in). */
334
- blockHeader,
380
+ anchorBlockHeader: blockHeader,
335
381
  utilityExecutor,
336
- /** List of transient auth witnesses to be used during this simulation */
337
- Array.from(this.authwits.values()),
338
- /** List of transient auth witnesses to be used during this simulation */
339
- [],
340
- HashedValuesCache.create([new HashedValues(args, argsHash)]),
382
+ authWitnesses: Array.from(this.authwits.values()),
383
+ capsules: [],
384
+ executionCache: HashedValuesCache.create([new HashedValues(args, argsHash)]),
341
385
  noteCache,
342
386
  taggingIndexCache,
343
- this.contractStore,
344
- this.noteStore,
345
- this.keyStore,
346
- this.addressStore,
347
- this.stateMachine.node,
348
- this.stateMachine.anchorBlockStore,
349
- this.senderTaggingStore,
350
- this.recipientTaggingStore,
351
- this.senderAddressBookStore,
352
- this.capsuleStore,
353
- this.privateEventStore,
354
- this.jobId,
355
- 0, // totalPublicArgsCount
356
- minRevertibleSideEffectCounter, // (start) sideEffectCounter
357
- undefined, // log
358
- undefined, // scopes
359
- /**
360
- * In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
361
- * contract would perform, including setting senderForTags.
362
- */
363
- 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,
364
405
  simulator,
365
- );
406
+ messageContextService: this.stateMachine.messageContextService,
407
+ l2TipsStore: this.stateMachine.node,
408
+ });
366
409
 
367
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.
368
411
  let result: PrivateExecutionResult;
@@ -384,7 +427,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
384
427
  );
385
428
  const publicFunctionsCalldata = await Promise.all(
386
429
  publicCallRequests.map(async r => {
387
- const calldata = await privateExecutionOracle.privateLoadFromExecutionCache(r.calldataHash);
430
+ const calldata = await privateExecutionOracle.getHashPreimage(r.calldataHash);
388
431
  return new HashedValues(calldata, r.calldataHash);
389
432
  }),
390
433
  );
@@ -401,7 +444,8 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
401
444
  // We pass the non-zero minRevertibleSideEffectCounter to make sure the side effects are split correctly.
402
445
  const { publicInputs } = await generateSimulatedProvingResult(
403
446
  result,
404
- this.contractStore,
447
+ (addr, sel) => this.contractStore.getDebugFunctionName(addr, sel),
448
+ this.stateMachine.node,
405
449
  minRevertibleSideEffectCounter,
406
450
  );
407
451
 
@@ -414,7 +458,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
414
458
 
415
459
  const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
416
460
 
417
- 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
+ );
418
466
  const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
419
467
  const config = PublicSimulatorConfig.from({
420
468
  skipFeeEnforcement: true,
@@ -427,8 +475,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
427
475
  globals,
428
476
  guardedMerkleTrees,
429
477
  contractsDB,
430
- new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config),
478
+ new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings),
431
479
  new TestDateProvider(),
480
+ undefined,
481
+ createLogger('simulator:public-processor', bindings),
432
482
  );
433
483
 
434
484
  const tx = await Tx.create({
@@ -462,11 +512,17 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
462
512
  }
463
513
  }
464
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
+
465
521
  if (isStaticCall) {
466
522
  await checkpoint!.revert();
467
523
 
468
524
  await forkedWorldTrees.close();
469
- return executionResult.returnValues ?? [];
525
+ return { returnValues: executionResult.returnValues ?? [], offchainEffects };
470
526
  }
471
527
 
472
528
  const txEffect = TxEffect.empty();
@@ -488,10 +544,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
488
544
 
489
545
  await forkedWorldTrees.close();
490
546
 
491
- return executionResult.returnValues ?? [];
547
+ return { returnValues: executionResult.returnValues ?? [], offchainEffects };
492
548
  }
493
549
 
494
- async txePublicCallNewFlow(
550
+ async publicCallNewFlow(
495
551
  from: AztecAddress,
496
552
  targetContractAddress: AztecAddress,
497
553
  calldata: Fr[],
@@ -501,11 +557,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
501
557
  `Executing public function ${await this.contractStore.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`,
502
558
  );
503
559
 
504
- const blockNumber = await this.txeGetNextBlockNumber();
560
+ const blockNumber = await this.getNextBlockNumber();
505
561
 
506
- 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);
507
563
 
508
- 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);
509
565
 
510
566
  const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
511
567
 
@@ -525,7 +581,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
525
581
 
526
582
  const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
527
583
 
528
- 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
+ );
529
589
  const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
530
590
  const config = PublicSimulatorConfig.from({
531
591
  skipFeeEnforcement: true,
@@ -534,8 +594,16 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
534
594
  collectStatistics: false,
535
595
  collectCallMetadata: true,
536
596
  });
537
- const simulator = new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config);
538
- 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
+ );
539
607
 
540
608
  // We're simulating a scenario in which private execution immediately enqueues a public call and halts. The private
541
609
  // kernel init would in this case inject a nullifier with the transaction request hash as a non-revertible
@@ -566,7 +634,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
566
634
  constantData,
567
635
  /*gasUsed=*/ new Gas(0, 0),
568
636
  /*feePayer=*/ AztecAddress.zero(),
569
- /*includeByTimestamp=*/ 0n,
637
+ /*expirationTimestamp=*/ 0n,
570
638
  inputsForPublic,
571
639
  undefined,
572
640
  );
@@ -634,10 +702,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
634
702
  return returnValues ?? [];
635
703
  }
636
704
 
637
- async txeSimulateUtilityFunction(
705
+ async executeUtilityFunction(
638
706
  targetContractAddress: AztecAddress,
639
707
  functionSelector: FunctionSelector,
640
708
  args: Fr[],
709
+ jobId: string,
641
710
  ) {
642
711
  const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
643
712
  if (!artifact) {
@@ -645,25 +714,33 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
645
714
  }
646
715
 
647
716
  // Sync notes before executing utility function to discover notes from previous transactions
648
- await this.contractStore.syncPrivateState(targetContractAddress, functionSelector, async call => {
649
- await this.executeUtilityCall(call);
650
- });
651
-
652
- const call = new FunctionCall(
653
- artifact.name,
717
+ const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
718
+ await this.stateMachine.contractSyncService.ensureContractSynced(
654
719
  targetContractAddress,
655
720
  functionSelector,
656
- FunctionType.UTILITY,
657
- false,
658
- false,
659
- args,
660
- [],
721
+ async (call, execScopes) => {
722
+ await this.executeUtilityCall(call, execScopes, jobId);
723
+ },
724
+ blockHeader,
725
+ jobId,
726
+ await this.keyStore.getAccounts(),
661
727
  );
662
728
 
663
- 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);
664
741
  }
665
742
 
666
- private async executeUtilityCall(call: FunctionCall): Promise<Fr[]> {
743
+ private async executeUtilityCall(call: FunctionCall, scopes: AztecAddress[], jobId: string): Promise<Fr[]> {
667
744
  const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
668
745
  if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
669
746
  throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
@@ -676,23 +753,26 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
676
753
 
677
754
  try {
678
755
  const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
679
- const oracle = new UtilityExecutionOracle(
680
- call.to,
681
- [],
682
- [],
756
+ const oracle = new UtilityExecutionOracle({
757
+ contractAddress: call.to,
758
+ authWitnesses: [],
759
+ capsules: [],
683
760
  anchorBlockHeader,
684
- this.contractStore,
685
- this.noteStore,
686
- this.keyStore,
687
- this.addressStore,
688
- this.stateMachine.node,
689
- this.stateMachine.anchorBlockStore,
690
- this.recipientTaggingStore,
691
- this.senderAddressBookStore,
692
- this.capsuleStore,
693
- this.privateEventStore,
694
- this.jobId,
695
- );
761
+ contractStore: this.contractStore,
762
+ noteStore: this.noteStore,
763
+ keyStore: this.keyStore,
764
+ addressStore: this.addressStore,
765
+ aztecNode: this.stateMachine.node,
766
+ recipientTaggingStore: this.recipientTaggingStore,
767
+ senderAddressBookStore: this.senderAddressBookStore,
768
+ capsuleService: new CapsuleService(this.capsuleStore, scopes),
769
+ privateEventStore: this.privateEventStore,
770
+ messageContextService: this.stateMachine.messageContextService,
771
+ contractSyncService: this.stateMachine.contractSyncService,
772
+ l2TipsStore: this.stateMachine.node,
773
+ jobId,
774
+ scopes,
775
+ });
696
776
  const acirExecutionResult = await new WASMSimulator()
697
777
  .executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
698
778
  .catch((err: Error) => {
@@ -708,10 +788,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
708
788
  );
709
789
  });
710
790
 
711
- this.logger.verbose(`Utility simulation for ${call.to}.${call.selector} completed`);
791
+ this.logger.verbose(`Utility execution for ${call.to}.${call.selector} completed`);
712
792
  return witnessMapToFields(acirExecutionResult.returnWitness);
713
793
  } catch (err) {
714
- throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility simulation'));
794
+ throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility execution'));
715
795
  }
716
796
  }
717
797