@aztec/txe 0.0.1-commit.7d4e6cd → 0.0.1-commit.7ffbba4

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