@aztec/txe 0.0.1-commit.6d3c34e → 0.0.1-commit.7035c9bd6

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 (65) hide show
  1. package/dest/constants.d.ts +1 -2
  2. package/dest/constants.d.ts.map +1 -1
  3. package/dest/constants.js +0 -1
  4. package/dest/index.d.ts +1 -1
  5. package/dest/index.d.ts.map +1 -1
  6. package/dest/index.js +88 -54
  7. package/dest/oracle/interfaces.d.ts +29 -28
  8. package/dest/oracle/interfaces.d.ts.map +1 -1
  9. package/dest/oracle/txe_oracle_public_context.d.ts +13 -13
  10. package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
  11. package/dest/oracle/txe_oracle_public_context.js +16 -16
  12. package/dest/oracle/txe_oracle_top_level_context.d.ts +23 -22
  13. package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
  14. package/dest/oracle/txe_oracle_top_level_context.js +144 -62
  15. package/dest/rpc_translator.d.ts +92 -81
  16. package/dest/rpc_translator.d.ts.map +1 -1
  17. package/dest/rpc_translator.js +323 -176
  18. package/dest/state_machine/archiver.d.ts +20 -69
  19. package/dest/state_machine/archiver.d.ts.map +1 -1
  20. package/dest/state_machine/archiver.js +34 -178
  21. package/dest/state_machine/dummy_p2p_client.d.ts +16 -12
  22. package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
  23. package/dest/state_machine/dummy_p2p_client.js +28 -16
  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 +39 -12
  27. package/dest/state_machine/mock_epoch_cache.d.ts +24 -8
  28. package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
  29. package/dest/state_machine/mock_epoch_cache.js +43 -9
  30. package/dest/state_machine/synchronizer.d.ts +6 -6
  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 +12 -6
  34. package/dest/txe_session.d.ts.map +1 -1
  35. package/dest/txe_session.js +112 -28
  36. package/dest/util/encoding.d.ts +17 -17
  37. package/dest/util/txe_public_contract_data_source.d.ts +2 -3
  38. package/dest/util/txe_public_contract_data_source.d.ts.map +1 -1
  39. package/dest/util/txe_public_contract_data_source.js +5 -22
  40. package/dest/utils/block_creation.d.ts +4 -4
  41. package/dest/utils/block_creation.d.ts.map +1 -1
  42. package/dest/utils/block_creation.js +18 -4
  43. package/dest/utils/tx_effect_creation.d.ts +2 -3
  44. package/dest/utils/tx_effect_creation.d.ts.map +1 -1
  45. package/dest/utils/tx_effect_creation.js +3 -6
  46. package/package.json +16 -16
  47. package/src/constants.ts +0 -1
  48. package/src/index.ts +89 -52
  49. package/src/oracle/interfaces.ts +32 -31
  50. package/src/oracle/txe_oracle_public_context.ts +16 -18
  51. package/src/oracle/txe_oracle_top_level_context.ts +178 -111
  52. package/src/rpc_translator.ts +360 -202
  53. package/src/state_machine/archiver.ts +37 -234
  54. package/src/state_machine/dummy_p2p_client.ts +40 -22
  55. package/src/state_machine/index.ts +53 -11
  56. package/src/state_machine/mock_epoch_cache.ts +53 -14
  57. package/src/state_machine/synchronizer.ts +5 -5
  58. package/src/txe_session.ts +129 -88
  59. package/src/util/txe_public_contract_data_source.ts +10 -36
  60. package/src/utils/block_creation.ts +19 -16
  61. package/src/utils/tx_effect_creation.ts +3 -11
  62. package/dest/util/txe_contract_store.d.ts +0 -12
  63. package/dest/util/txe_contract_store.d.ts.map +0 -1
  64. package/dest/util/txe_contract_store.js +0 -22
  65. package/src/util/txe_contract_store.ts +0 -36
@@ -12,9 +12,12 @@ import { Fr } from '@aztec/foundation/curves/bn254';
12
12
  import { LogLevels, type Logger, applyStringFormatting, createLogger } from '@aztec/foundation/log';
13
13
  import { TestDateProvider } from '@aztec/foundation/timer';
14
14
  import type { KeyStore } from '@aztec/key-store';
15
+ import type { AccessScopes } from '@aztec/pxe/client/lazy';
15
16
  import {
16
17
  AddressStore,
17
18
  CapsuleStore,
19
+ type ContractStore,
20
+ type ContractSyncService,
18
21
  NoteStore,
19
22
  ORACLE_VERSION,
20
23
  PrivateEventStore,
@@ -80,10 +83,9 @@ import {
80
83
  import type { UInt64 } from '@aztec/stdlib/types';
81
84
  import { ForkCheckpoint } from '@aztec/world-state';
82
85
 
83
- import { DEFAULT_ADDRESS, TXE_JOB_ID } from '../constants.js';
86
+ import { DEFAULT_ADDRESS } from '../constants.js';
84
87
  import type { TXEStateMachine } from '../state_machine/index.js';
85
88
  import type { TXEAccountStore } from '../util/txe_account_store.js';
86
- import type { TXEContractStore } from '../util/txe_contract_store.js';
87
89
  import { TXEPublicContractDataSource } from '../util/txe_public_contract_data_source.js';
88
90
  import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlock } from '../utils/block_creation.js';
89
91
  import type { ITxeExecutionOracle } from './interfaces.js';
@@ -96,7 +98,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
96
98
 
97
99
  constructor(
98
100
  private stateMachine: TXEStateMachine,
99
- private contractStore: TXEContractStore,
101
+ private contractStore: ContractStore,
100
102
  private noteStore: NoteStore,
101
103
  private keyStore: KeyStore,
102
104
  private addressStore: AddressStore,
@@ -110,12 +112,13 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
110
112
  private version: Fr,
111
113
  private chainId: Fr,
112
114
  private authwits: Map<string, AuthWitness>,
115
+ private readonly contractSyncService: ContractSyncService,
113
116
  ) {
114
117
  this.logger = createLogger('txe:top_level_context');
115
118
  this.logger.debug('Entering Top Level Context');
116
119
  }
117
120
 
118
- utilityAssertCompatibleOracleVersion(version: number): void {
121
+ assertCompatibleOracleVersion(version: number): void {
119
122
  if (version !== ORACLE_VERSION) {
120
123
  throw new Error(
121
124
  `Incompatible oracle version. TXE is using version '${ORACLE_VERSION}', but got a request for '${version}'.`,
@@ -125,38 +128,40 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
125
128
 
126
129
  // This is typically only invoked in private contexts, but it is convenient to also have it in top-level for testing
127
130
  // setup.
128
- utilityGetRandomField(): Fr {
131
+ getRandomField(): Fr {
129
132
  return Fr.random();
130
133
  }
131
134
 
132
135
  // We instruct users to debug contracts via this oracle, so it makes sense that they'd expect it to also work in tests
133
- utilityDebugLog(level: number, message: string, fields: Fr[]): void {
136
+ log(level: number, message: string, fields: Fr[]): Promise<void> {
134
137
  if (!LogLevels[level]) {
135
- throw new Error(`Invalid debug log level: ${level}`);
138
+ throw new Error(`Invalid log level: ${level}`);
136
139
  }
137
140
  const levelName = LogLevels[level];
138
141
 
139
142
  this.logger[levelName](`${applyStringFormatting(message, fields)}`, { module: `${this.logger.module}:debug_log` });
143
+ return Promise.resolve();
140
144
  }
141
145
 
142
- txeGetDefaultAddress(): AztecAddress {
146
+ getDefaultAddress(): AztecAddress {
143
147
  return DEFAULT_ADDRESS;
144
148
  }
145
149
 
146
- async txeGetNextBlockNumber(): Promise<BlockNumber> {
150
+ async getNextBlockNumber(): Promise<BlockNumber> {
147
151
  return BlockNumber((await this.getLastBlockNumber()) + 1);
148
152
  }
149
153
 
150
- txeGetNextBlockTimestamp(): Promise<bigint> {
154
+ getNextBlockTimestamp(): Promise<bigint> {
151
155
  return Promise.resolve(this.nextBlockTimestamp);
152
156
  }
153
157
 
154
- async txeGetLastBlockTimestamp() {
158
+ async getLastBlockTimestamp() {
155
159
  return (await this.stateMachine.node.getBlockHeader('latest'))!.globalVariables.timestamp;
156
160
  }
157
161
 
158
- async txeGetLastTxEffects() {
159
- const block = await this.stateMachine.archiver.getL2Block('latest');
162
+ async getLastTxEffects() {
163
+ const latestBlockNumber = await this.stateMachine.archiver.getBlockNumber();
164
+ const block = await this.stateMachine.archiver.getBlock(latestBlockNumber);
160
165
 
161
166
  if (block!.body.txEffects.length != 1) {
162
167
  // Note that calls like env.mine() will result in blocks with no transactions, hitting this
@@ -168,7 +173,26 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
168
173
  return { txHash: txEffects.txHash, noteHashes: txEffects.noteHashes, nullifiers: txEffects.nullifiers };
169
174
  }
170
175
 
171
- async txeGetPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress) {
176
+ async syncContractNonOracleMethod(contractAddress: AztecAddress, scope: AztecAddress, jobId: string) {
177
+ if (contractAddress.equals(DEFAULT_ADDRESS)) {
178
+ this.logger.debug(`Skipping sync in getPrivateEvents because the events correspond to the default address.`);
179
+ return;
180
+ }
181
+
182
+ const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
183
+ await this.stateMachine.contractSyncService.ensureContractSynced(
184
+ contractAddress,
185
+ null,
186
+ async (call, execScopes) => {
187
+ await this.executeUtilityCall(call, execScopes, jobId);
188
+ },
189
+ blockHeader,
190
+ jobId,
191
+ [scope],
192
+ );
193
+ }
194
+
195
+ async getPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress) {
172
196
  return (
173
197
  await this.privateEventStore.getPrivateEvents(selector, {
174
198
  contractAddress,
@@ -179,7 +203,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
179
203
  ).map(e => e.packedEvent);
180
204
  }
181
205
 
182
- async txeAdvanceBlocksBy(blocks: number) {
206
+ async advanceBlocksBy(blocks: number) {
183
207
  this.logger.debug(`time traveling ${blocks} blocks`);
184
208
 
185
209
  for (let i = 0; i < blocks; i++) {
@@ -187,12 +211,12 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
187
211
  }
188
212
  }
189
213
 
190
- txeAdvanceTimestampBy(duration: UInt64) {
214
+ advanceTimestampBy(duration: UInt64) {
191
215
  this.logger.debug(`time traveling ${duration} seconds`);
192
216
  this.nextBlockTimestamp += duration;
193
217
  }
194
218
 
195
- async txeDeploy(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
219
+ async deploy(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
196
220
  // Emit deployment nullifier
197
221
  await this.mineBlock({
198
222
  nullifiers: [
@@ -204,20 +228,20 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
204
228
  });
205
229
 
206
230
  if (!secret.equals(Fr.ZERO)) {
207
- await this.txeAddAccount(artifact, instance, secret);
231
+ await this.addAccount(artifact, instance, secret);
208
232
  } else {
209
233
  await this.contractStore.addContractInstance(instance);
210
- await this.contractStore.addContractArtifact(instance.currentContractClassId, artifact);
234
+ await this.contractStore.addContractArtifact(artifact);
211
235
  this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
212
236
  }
213
237
  }
214
238
 
215
- async txeAddAccount(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
239
+ async addAccount(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
216
240
  const partialAddress = await computePartialAddress(instance);
217
241
 
218
242
  this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
219
243
  await this.contractStore.addContractInstance(instance);
220
- await this.contractStore.addContractArtifact(instance.currentContractClassId, artifact);
244
+ await this.contractStore.addContractArtifact(artifact);
221
245
 
222
246
  const completeAddress = await this.keyStore.addAccount(secret, partialAddress);
223
247
  await this.accountStore.setAccount(completeAddress.address, completeAddress);
@@ -227,7 +251,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
227
251
  return completeAddress;
228
252
  }
229
253
 
230
- async txeCreateAccount(secret: Fr) {
254
+ async createAccount(secret: Fr) {
231
255
  // This is a foot gun !
232
256
  const completeAddress = await this.keyStore.addAccount(secret, secret);
233
257
  await this.accountStore.setAccount(completeAddress.address, completeAddress);
@@ -237,7 +261,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
237
261
  return completeAddress;
238
262
  }
239
263
 
240
- async txeAddAuthWitness(address: AztecAddress, messageHash: Fr) {
264
+ async addAuthWitness(address: AztecAddress, messageHash: Fr) {
241
265
  const account = await this.accountStore.getAccount(address);
242
266
  const privateKey = await this.keyStore.getMasterSecretKey(account.publicKeys.masterIncomingViewingPublicKey);
243
267
 
@@ -250,7 +274,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
250
274
  }
251
275
 
252
276
  async mineBlock(options: { nullifiers?: Fr[] } = {}) {
253
- const blockNumber = await this.txeGetNextBlockNumber();
277
+ const blockNumber = await this.getNextBlockNumber();
254
278
 
255
279
  const txEffect = TxEffect.empty();
256
280
  txEffect.nullifiers = [getSingleTxBlockRequestHash(blockNumber), ...(options.nullifiers ?? [])];
@@ -274,13 +298,14 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
274
298
  await this.stateMachine.handleL2Block(block);
275
299
  }
276
300
 
277
- async txePrivateCallNewFlow(
301
+ async privateCallNewFlow(
278
302
  from: AztecAddress,
279
303
  targetContractAddress: AztecAddress = AztecAddress.zero(),
280
304
  functionSelector: FunctionSelector = FunctionSelector.empty(),
281
305
  args: Fr[],
282
306
  argsHash: Fr = Fr.zero(),
283
307
  isStaticCall: boolean = false,
308
+ jobId: string,
284
309
  ) {
285
310
  this.logger.verbose(
286
311
  `Executing external function ${await this.contractStore.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`,
@@ -294,14 +319,26 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
294
319
  throw new Error(message);
295
320
  }
296
321
 
322
+ // When `from` is the zero address (e.g. when deploying a new account contract), we return an
323
+ // empty scope list which acts as deny-all: no notes are visible and no keys are accessible.
324
+ const effectiveScopes = from.isZero() ? [] : [from];
325
+
297
326
  // Sync notes before executing private function to discover notes from previous transactions
298
- const utilityExecutor = async (call: FunctionCall) => {
299
- await this.executeUtilityCall(call);
327
+ const utilityExecutor = async (call: FunctionCall, execScopes: AccessScopes) => {
328
+ await this.executeUtilityCall(call, execScopes, jobId);
300
329
  };
301
330
 
302
- await this.contractStore.syncPrivateState(targetContractAddress, functionSelector, utilityExecutor);
331
+ const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
332
+ await this.stateMachine.contractSyncService.ensureContractSynced(
333
+ targetContractAddress,
334
+ functionSelector,
335
+ utilityExecutor,
336
+ blockHeader,
337
+ jobId,
338
+ effectiveScopes,
339
+ );
303
340
 
304
- const blockNumber = await this.txeGetNextBlockNumber();
341
+ const blockNumber = await this.getNextBlockNumber();
305
342
 
306
343
  const callContext = new CallContext(from, targetContractAddress, functionSelector, isStaticCall);
307
344
 
@@ -311,51 +348,49 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
311
348
 
312
349
  const txContext = new TxContext(this.chainId, this.version, gasSettings);
313
350
 
314
- const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
315
-
316
351
  const protocolNullifier = await computeProtocolNullifier(getSingleTxBlockRequestHash(blockNumber));
317
352
  const noteCache = new ExecutionNoteCache(protocolNullifier);
353
+ // In production, the account contract sets the min revertible counter before calling the app function.
354
+ // Since TXE bypasses the account contract, we simulate this by setting minRevertibleSideEffectCounter to 1,
355
+ // marking all side effects as revertible.
356
+ const minRevertibleSideEffectCounter = 1;
357
+ await noteCache.setMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter);
318
358
  const taggingIndexCache = new ExecutionTaggingIndexCache();
319
359
 
320
360
  const simulator = new WASMSimulator();
321
361
 
322
- const privateExecutionOracle = new PrivateExecutionOracle(
362
+ const privateExecutionOracle = new PrivateExecutionOracle({
323
363
  argsHash,
324
364
  txContext,
325
365
  callContext,
326
- /** Header of a block whose state is used during private execution (not the block the transaction is included in). */
327
- blockHeader,
366
+ anchorBlockHeader: blockHeader,
328
367
  utilityExecutor,
329
- /** List of transient auth witnesses to be used during this simulation */
330
- Array.from(this.authwits.values()),
331
- /** List of transient auth witnesses to be used during this simulation */
332
- [],
333
- HashedValuesCache.create([new HashedValues(args, argsHash)]),
368
+ authWitnesses: Array.from(this.authwits.values()),
369
+ capsules: [],
370
+ executionCache: HashedValuesCache.create([new HashedValues(args, argsHash)]),
334
371
  noteCache,
335
372
  taggingIndexCache,
336
- this.contractStore,
337
- this.noteStore,
338
- this.keyStore,
339
- this.addressStore,
340
- this.stateMachine.node,
341
- this.stateMachine.anchorBlockStore,
342
- this.senderTaggingStore,
343
- this.recipientTaggingStore,
344
- this.senderAddressBookStore,
345
- this.capsuleStore,
346
- this.privateEventStore,
347
- TXE_JOB_ID,
348
- 0,
349
- 1,
350
- undefined, // log
351
- undefined, // scopes
352
- /**
353
- * In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
354
- * contract would perform, including setting senderForTags.
355
- */
356
- from,
373
+ contractStore: this.contractStore,
374
+ noteStore: this.noteStore,
375
+ keyStore: this.keyStore,
376
+ addressStore: this.addressStore,
377
+ aztecNode: this.stateMachine.node,
378
+ senderTaggingStore: this.senderTaggingStore,
379
+ recipientTaggingStore: this.recipientTaggingStore,
380
+ senderAddressBookStore: this.senderAddressBookStore,
381
+ capsuleStore: this.capsuleStore,
382
+ privateEventStore: this.privateEventStore,
383
+ contractSyncService: this.stateMachine.contractSyncService,
384
+ jobId,
385
+ totalPublicCalldataCount: 0,
386
+ sideEffectCounter: minRevertibleSideEffectCounter,
387
+ scopes: effectiveScopes,
388
+ // In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
389
+ // contract would perform, including setting senderForTags.
390
+ senderForTags: from,
357
391
  simulator,
358
- );
392
+ messageContextService: this.stateMachine.messageContextService,
393
+ });
359
394
 
360
395
  // 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.
361
396
  let result: PrivateExecutionResult;
@@ -377,24 +412,27 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
377
412
  );
378
413
  const publicFunctionsCalldata = await Promise.all(
379
414
  publicCallRequests.map(async r => {
380
- const calldata = await privateExecutionOracle.privateLoadFromExecutionCache(r.calldataHash);
415
+ const calldata = await privateExecutionOracle.loadFromExecutionCache(r.calldataHash);
381
416
  return new HashedValues(calldata, r.calldataHash);
382
417
  }),
383
418
  );
384
419
 
385
- // TXE's top level context does not track side effect counters, and as such, minRevertibleSideEffectCounter is always 0.
386
- // This has the unfortunate consequence of always producing revertible nullifiers, which means we
387
- // must set the firstNullifierHint to Fr.ZERO so the txRequestHash is always used as nonce generator
388
- result = new PrivateExecutionResult(executionResult, Fr.ZERO, publicFunctionsCalldata);
420
+ noteCache.finish();
421
+ const nonceGenerator = noteCache.getNonceGenerator();
422
+ result = new PrivateExecutionResult(executionResult, nonceGenerator, publicFunctionsCalldata);
389
423
  } catch (err) {
390
424
  throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during private execution'));
391
425
  }
392
426
 
393
- // According to the protocol rules, the nonce generator for the note hashes
394
- // can either be the first nullifier in the tx or the hash of the initial tx request
395
- // if there are none.
396
- const nonceGenerator = result.firstNullifier.equals(Fr.ZERO) ? protocolNullifier : result.firstNullifier;
397
- const { publicInputs } = await generateSimulatedProvingResult(result, nonceGenerator, this.contractStore);
427
+ // According to the protocol rules, there must be at least one nullifier in the tx. The first nullifier is used as
428
+ // the nonce generator for the note hashes.
429
+ // We pass the non-zero minRevertibleSideEffectCounter to make sure the side effects are split correctly.
430
+ const { publicInputs } = await generateSimulatedProvingResult(
431
+ result,
432
+ (addr, sel) => this.contractStore.getDebugFunctionName(addr, sel),
433
+ this.stateMachine.node,
434
+ minRevertibleSideEffectCounter,
435
+ );
398
436
 
399
437
  const globals = makeGlobalVariables();
400
438
  globals.blockNumber = blockNumber;
@@ -405,7 +443,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
405
443
 
406
444
  const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
407
445
 
408
- const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(blockNumber, this.contractStore));
446
+ const bindings = this.logger.getBindings();
447
+ const contractsDB = new PublicContractsDB(
448
+ new TXEPublicContractDataSource(blockNumber, this.contractStore),
449
+ bindings,
450
+ );
409
451
  const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
410
452
  const config = PublicSimulatorConfig.from({
411
453
  skipFeeEnforcement: true,
@@ -418,8 +460,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
418
460
  globals,
419
461
  guardedMerkleTrees,
420
462
  contractsDB,
421
- new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config),
463
+ new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings),
422
464
  new TestDateProvider(),
465
+ undefined,
466
+ createLogger('simulator:public-processor', bindings),
423
467
  );
424
468
 
425
469
  const tx = await Tx.create({
@@ -482,7 +526,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
482
526
  return executionResult.returnValues ?? [];
483
527
  }
484
528
 
485
- async txePublicCallNewFlow(
529
+ async publicCallNewFlow(
486
530
  from: AztecAddress,
487
531
  targetContractAddress: AztecAddress,
488
532
  calldata: Fr[],
@@ -492,7 +536,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
492
536
  `Executing public function ${await this.contractStore.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`,
493
537
  );
494
538
 
495
- const blockNumber = await this.txeGetNextBlockNumber();
539
+ const blockNumber = await this.getNextBlockNumber();
496
540
 
497
541
  const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
498
542
 
@@ -516,7 +560,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
516
560
 
517
561
  const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
518
562
 
519
- const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(blockNumber, this.contractStore));
563
+ const bindings2 = this.logger.getBindings();
564
+ const contractsDB = new PublicContractsDB(
565
+ new TXEPublicContractDataSource(blockNumber, this.contractStore),
566
+ bindings2,
567
+ );
520
568
  const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
521
569
  const config = PublicSimulatorConfig.from({
522
570
  skipFeeEnforcement: true,
@@ -525,8 +573,16 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
525
573
  collectStatistics: false,
526
574
  collectCallMetadata: true,
527
575
  });
528
- const simulator = new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config);
529
- const processor = new PublicProcessor(globals, guardedMerkleTrees, contractsDB, simulator, new TestDateProvider());
576
+ const simulator = new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings2);
577
+ const processor = new PublicProcessor(
578
+ globals,
579
+ guardedMerkleTrees,
580
+ contractsDB,
581
+ simulator,
582
+ new TestDateProvider(),
583
+ undefined,
584
+ createLogger('simulator:public-processor', bindings2),
585
+ );
530
586
 
531
587
  // We're simulating a scenario in which private execution immediately enqueues a public call and halts. The private
532
588
  // kernel init would in this case inject a nullifier with the transaction request hash as a non-revertible
@@ -557,7 +613,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
557
613
  constantData,
558
614
  /*gasUsed=*/ new Gas(0, 0),
559
615
  /*feePayer=*/ AztecAddress.zero(),
560
- /*includeByTimestamp=*/ 0n,
616
+ /*expirationTimestamp=*/ 0n,
561
617
  inputsForPublic,
562
618
  undefined,
563
619
  );
@@ -625,10 +681,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
625
681
  return returnValues ?? [];
626
682
  }
627
683
 
628
- async txeSimulateUtilityFunction(
684
+ async executeUtilityFunction(
629
685
  targetContractAddress: AztecAddress,
630
686
  functionSelector: FunctionSelector,
631
687
  args: Fr[],
688
+ jobId: string,
632
689
  ) {
633
690
  const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
634
691
  if (!artifact) {
@@ -636,25 +693,33 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
636
693
  }
637
694
 
638
695
  // Sync notes before executing utility function to discover notes from previous transactions
639
- await this.contractStore.syncPrivateState(targetContractAddress, functionSelector, async call => {
640
- await this.executeUtilityCall(call);
641
- });
642
-
643
- const call = new FunctionCall(
644
- artifact.name,
696
+ const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
697
+ await this.stateMachine.contractSyncService.ensureContractSynced(
645
698
  targetContractAddress,
646
699
  functionSelector,
647
- FunctionType.UTILITY,
648
- false,
649
- false,
650
- args,
651
- [],
700
+ async (call, execScopes) => {
701
+ await this.executeUtilityCall(call, execScopes, jobId);
702
+ },
703
+ blockHeader,
704
+ jobId,
705
+ 'ALL_SCOPES',
652
706
  );
653
707
 
654
- return this.executeUtilityCall(call);
708
+ const call = FunctionCall.from({
709
+ name: artifact.name,
710
+ to: targetContractAddress,
711
+ selector: functionSelector,
712
+ type: FunctionType.UTILITY,
713
+ hideMsgSender: false,
714
+ isStatic: false,
715
+ args,
716
+ returnTypes: [],
717
+ });
718
+
719
+ return this.executeUtilityCall(call, 'ALL_SCOPES', jobId);
655
720
  }
656
721
 
657
- private async executeUtilityCall(call: FunctionCall): Promise<Fr[]> {
722
+ private async executeUtilityCall(call: FunctionCall, scopes: AccessScopes, jobId: string): Promise<Fr[]> {
658
723
  const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
659
724
  if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
660
725
  throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
@@ -667,23 +732,25 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
667
732
 
668
733
  try {
669
734
  const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
670
- const oracle = new UtilityExecutionOracle(
671
- call.to,
672
- [],
673
- [],
735
+ const oracle = new UtilityExecutionOracle({
736
+ contractAddress: call.to,
737
+ authWitnesses: [],
738
+ capsules: [],
674
739
  anchorBlockHeader,
675
- this.contractStore,
676
- this.noteStore,
677
- this.keyStore,
678
- this.addressStore,
679
- this.stateMachine.node,
680
- this.stateMachine.anchorBlockStore,
681
- this.recipientTaggingStore,
682
- this.senderAddressBookStore,
683
- this.capsuleStore,
684
- this.privateEventStore,
685
- TXE_JOB_ID,
686
- );
740
+ contractStore: this.contractStore,
741
+ noteStore: this.noteStore,
742
+ keyStore: this.keyStore,
743
+ addressStore: this.addressStore,
744
+ aztecNode: this.stateMachine.node,
745
+ recipientTaggingStore: this.recipientTaggingStore,
746
+ senderAddressBookStore: this.senderAddressBookStore,
747
+ capsuleStore: this.capsuleStore,
748
+ privateEventStore: this.privateEventStore,
749
+ messageContextService: this.stateMachine.messageContextService,
750
+ contractSyncService: this.contractSyncService,
751
+ jobId,
752
+ scopes,
753
+ });
687
754
  const acirExecutionResult = await new WASMSimulator()
688
755
  .executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
689
756
  .catch((err: Error) => {
@@ -699,10 +766,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
699
766
  );
700
767
  });
701
768
 
702
- this.logger.verbose(`Utility simulation for ${call.to}.${call.selector} completed`);
769
+ this.logger.verbose(`Utility execution for ${call.to}.${call.selector} completed`);
703
770
  return witnessMapToFields(acirExecutionResult.returnWitness);
704
771
  } catch (err) {
705
- throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility simulation'));
772
+ throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility execution'));
706
773
  }
707
774
  }
708
775