@aztec/txe 0.0.1-commit.03f7ef2 → 0.0.1-commit.04852196a

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 (74) hide show
  1. package/dest/constants.d.ts +3 -0
  2. package/dest/constants.d.ts.map +1 -0
  3. package/dest/constants.js +2 -0
  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 +33 -31
  13. package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
  14. package/dest/oracle/txe_oracle_top_level_context.js +179 -92
  15. package/dest/rpc_translator.d.ts +87 -81
  16. package/dest/rpc_translator.d.ts.map +1 -1
  17. package/dest/rpc_translator.js +291 -173
  18. package/dest/state_machine/archiver.d.ts +20 -67
  19. package/dest/state_machine/archiver.d.ts.map +1 -1
  20. package/dest/state_machine/archiver.js +59 -178
  21. package/dest/state_machine/dummy_p2p_client.d.ts +20 -15
  22. package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
  23. package/dest/state_machine/dummy_p2p_client.js +39 -24
  24. package/dest/state_machine/global_variable_builder.d.ts +2 -2
  25. package/dest/state_machine/global_variable_builder.d.ts.map +1 -1
  26. package/dest/state_machine/global_variable_builder.js +1 -1
  27. package/dest/state_machine/index.d.ts +6 -6
  28. package/dest/state_machine/index.d.ts.map +1 -1
  29. package/dest/state_machine/index.js +37 -14
  30. package/dest/state_machine/mock_epoch_cache.d.ts +9 -6
  31. package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
  32. package/dest/state_machine/mock_epoch_cache.js +14 -7
  33. package/dest/state_machine/synchronizer.d.ts +3 -3
  34. package/dest/state_machine/synchronizer.d.ts.map +1 -1
  35. package/dest/txe_session.d.ts +22 -16
  36. package/dest/txe_session.d.ts.map +1 -1
  37. package/dest/txe_session.js +153 -56
  38. package/dest/util/encoding.d.ts +17 -17
  39. package/dest/util/txe_account_store.d.ts +10 -0
  40. package/dest/util/txe_account_store.d.ts.map +1 -0
  41. package/dest/util/{txe_account_data_provider.js → txe_account_store.js} +1 -1
  42. package/dest/util/txe_public_contract_data_source.d.ts +5 -6
  43. package/dest/util/txe_public_contract_data_source.d.ts.map +1 -1
  44. package/dest/util/txe_public_contract_data_source.js +12 -29
  45. package/dest/utils/block_creation.d.ts +4 -4
  46. package/dest/utils/block_creation.d.ts.map +1 -1
  47. package/dest/utils/block_creation.js +18 -5
  48. package/dest/utils/tx_effect_creation.d.ts +2 -3
  49. package/dest/utils/tx_effect_creation.d.ts.map +1 -1
  50. package/dest/utils/tx_effect_creation.js +3 -6
  51. package/package.json +16 -16
  52. package/src/constants.ts +3 -0
  53. package/src/index.ts +89 -52
  54. package/src/oracle/interfaces.ts +32 -31
  55. package/src/oracle/txe_oracle_public_context.ts +16 -18
  56. package/src/oracle/txe_oracle_top_level_context.ts +217 -133
  57. package/src/rpc_translator.ts +309 -185
  58. package/src/state_machine/archiver.ts +54 -220
  59. package/src/state_machine/dummy_p2p_client.ts +55 -32
  60. package/src/state_machine/global_variable_builder.ts +1 -1
  61. package/src/state_machine/index.ts +50 -12
  62. package/src/state_machine/mock_epoch_cache.ts +15 -11
  63. package/src/state_machine/synchronizer.ts +2 -2
  64. package/src/txe_session.ts +207 -120
  65. package/src/util/{txe_account_data_provider.ts → txe_account_store.ts} +1 -1
  66. package/src/util/txe_public_contract_data_source.ts +16 -42
  67. package/src/utils/block_creation.ts +19 -16
  68. package/src/utils/tx_effect_creation.ts +3 -11
  69. package/dest/util/txe_account_data_provider.d.ts +0 -10
  70. package/dest/util/txe_account_data_provider.d.ts.map +0 -1
  71. package/dest/util/txe_contract_data_provider.d.ts +0 -12
  72. package/dest/util/txe_contract_data_provider.d.ts.map +0 -1
  73. package/dest/util/txe_contract_data_provider.js +0 -22
  74. package/src/util/txe_contract_data_provider.ts +0 -36
@@ -12,14 +12,17 @@ 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
- AddressDataProvider,
17
- CapsuleDataProvider,
18
- NoteDataProvider,
17
+ AddressStore,
18
+ CapsuleStore,
19
+ type ContractStore,
20
+ NoteStore,
19
21
  ORACLE_VERSION,
20
- PrivateEventDataProvider,
21
- RecipientTaggingDataProvider,
22
- SenderTaggingDataProvider,
22
+ PrivateEventStore,
23
+ RecipientTaggingStore,
24
+ SenderAddressBookStore,
25
+ SenderTaggingStore,
23
26
  enrichPublicSimulationError,
24
27
  } from '@aztec/pxe/server';
25
28
  import {
@@ -48,7 +51,7 @@ import {
48
51
  PublicContractsDB,
49
52
  PublicProcessor,
50
53
  } from '@aztec/simulator/server';
51
- import { type ContractArtifact, EventSelector, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
54
+ import { type ContractArtifact, EventSelector, FunctionCall, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
52
55
  import { AuthWitness } from '@aztec/stdlib/auth-witness';
53
56
  import { PublicSimulatorConfig } from '@aztec/stdlib/avm';
54
57
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
@@ -79,10 +82,9 @@ import {
79
82
  import type { UInt64 } from '@aztec/stdlib/types';
80
83
  import { ForkCheckpoint } from '@aztec/world-state';
81
84
 
85
+ import { DEFAULT_ADDRESS } from '../constants.js';
82
86
  import type { TXEStateMachine } from '../state_machine/index.js';
83
- import { DEFAULT_ADDRESS } from '../txe_session.js';
84
- import type { TXEAccountDataProvider } from '../util/txe_account_data_provider.js';
85
- import type { TXEContractDataProvider } from '../util/txe_contract_data_provider.js';
87
+ import type { TXEAccountStore } from '../util/txe_account_store.js';
86
88
  import { TXEPublicContractDataSource } from '../util/txe_public_contract_data_source.js';
87
89
  import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlock } from '../utils/block_creation.js';
88
90
  import type { ITxeExecutionOracle } from './interfaces.js';
@@ -95,15 +97,16 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
95
97
 
96
98
  constructor(
97
99
  private stateMachine: TXEStateMachine,
98
- private contractDataProvider: TXEContractDataProvider,
99
- private noteDataProvider: NoteDataProvider,
100
+ private contractStore: ContractStore,
101
+ private noteStore: NoteStore,
100
102
  private keyStore: KeyStore,
101
- private addressDataProvider: AddressDataProvider,
102
- private accountDataProvider: TXEAccountDataProvider,
103
- private senderTaggingDataProvider: SenderTaggingDataProvider,
104
- private recipientTaggingDataProvider: RecipientTaggingDataProvider,
105
- private capsuleDataProvider: CapsuleDataProvider,
106
- private privateEventDataProvider: PrivateEventDataProvider,
103
+ private addressStore: AddressStore,
104
+ private accountStore: TXEAccountStore,
105
+ private senderTaggingStore: SenderTaggingStore,
106
+ private recipientTaggingStore: RecipientTaggingStore,
107
+ private senderAddressBookStore: SenderAddressBookStore,
108
+ private capsuleStore: CapsuleStore,
109
+ private privateEventStore: PrivateEventStore,
107
110
  private nextBlockTimestamp: bigint,
108
111
  private version: Fr,
109
112
  private chainId: Fr,
@@ -113,7 +116,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
113
116
  this.logger.debug('Entering Top Level Context');
114
117
  }
115
118
 
116
- utilityAssertCompatibleOracleVersion(version: number): void {
119
+ assertCompatibleOracleVersion(version: number): void {
117
120
  if (version !== ORACLE_VERSION) {
118
121
  throw new Error(
119
122
  `Incompatible oracle version. TXE is using version '${ORACLE_VERSION}', but got a request for '${version}'.`,
@@ -123,38 +126,40 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
123
126
 
124
127
  // This is typically only invoked in private contexts, but it is convenient to also have it in top-level for testing
125
128
  // setup.
126
- utilityGetRandomField(): Fr {
129
+ getRandomField(): Fr {
127
130
  return Fr.random();
128
131
  }
129
132
 
130
133
  // We instruct users to debug contracts via this oracle, so it makes sense that they'd expect it to also work in tests
131
- utilityDebugLog(level: number, message: string, fields: Fr[]): void {
134
+ log(level: number, message: string, fields: Fr[]): Promise<void> {
132
135
  if (!LogLevels[level]) {
133
- throw new Error(`Invalid debug log level: ${level}`);
136
+ throw new Error(`Invalid log level: ${level}`);
134
137
  }
135
138
  const levelName = LogLevels[level];
136
139
 
137
140
  this.logger[levelName](`${applyStringFormatting(message, fields)}`, { module: `${this.logger.module}:debug_log` });
141
+ return Promise.resolve();
138
142
  }
139
143
 
140
- txeGetDefaultAddress(): AztecAddress {
144
+ getDefaultAddress(): AztecAddress {
141
145
  return DEFAULT_ADDRESS;
142
146
  }
143
147
 
144
- async txeGetNextBlockNumber(): Promise<BlockNumber> {
148
+ async getNextBlockNumber(): Promise<BlockNumber> {
145
149
  return BlockNumber((await this.getLastBlockNumber()) + 1);
146
150
  }
147
151
 
148
- txeGetNextBlockTimestamp(): Promise<bigint> {
152
+ getNextBlockTimestamp(): Promise<bigint> {
149
153
  return Promise.resolve(this.nextBlockTimestamp);
150
154
  }
151
155
 
152
- async txeGetLastBlockTimestamp() {
156
+ async getLastBlockTimestamp() {
153
157
  return (await this.stateMachine.node.getBlockHeader('latest'))!.globalVariables.timestamp;
154
158
  }
155
159
 
156
- async txeGetLastTxEffects() {
157
- 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);
158
163
 
159
164
  if (block!.body.txEffects.length != 1) {
160
165
  // Note that calls like env.mine() will result in blocks with no transactions, hitting this
@@ -166,9 +171,28 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
166
171
  return { txHash: txEffects.txHash, noteHashes: txEffects.noteHashes, nullifiers: txEffects.nullifiers };
167
172
  }
168
173
 
169
- 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) {
170
194
  return (
171
- await this.privateEventDataProvider.getPrivateEvents(selector, {
195
+ await this.privateEventStore.getPrivateEvents(selector, {
172
196
  contractAddress,
173
197
  scopes: [scope],
174
198
  fromBlock: 0,
@@ -177,7 +201,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
177
201
  ).map(e => e.packedEvent);
178
202
  }
179
203
 
180
- async txeAdvanceBlocksBy(blocks: number) {
204
+ async advanceBlocksBy(blocks: number) {
181
205
  this.logger.debug(`time traveling ${blocks} blocks`);
182
206
 
183
207
  for (let i = 0; i < blocks; i++) {
@@ -185,12 +209,12 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
185
209
  }
186
210
  }
187
211
 
188
- txeAdvanceTimestampBy(duration: UInt64) {
212
+ advanceTimestampBy(duration: UInt64) {
189
213
  this.logger.debug(`time traveling ${duration} seconds`);
190
214
  this.nextBlockTimestamp += duration;
191
215
  }
192
216
 
193
- async txeDeploy(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
217
+ async deploy(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
194
218
  // Emit deployment nullifier
195
219
  await this.mineBlock({
196
220
  nullifiers: [
@@ -202,41 +226,41 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
202
226
  });
203
227
 
204
228
  if (!secret.equals(Fr.ZERO)) {
205
- await this.txeAddAccount(artifact, instance, secret);
229
+ await this.addAccount(artifact, instance, secret);
206
230
  } else {
207
- await this.contractDataProvider.addContractInstance(instance);
208
- await this.contractDataProvider.addContractArtifact(instance.currentContractClassId, artifact);
231
+ await this.contractStore.addContractInstance(instance);
232
+ await this.contractStore.addContractArtifact(artifact);
209
233
  this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
210
234
  }
211
235
  }
212
236
 
213
- async txeAddAccount(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
237
+ async addAccount(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
214
238
  const partialAddress = await computePartialAddress(instance);
215
239
 
216
240
  this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
217
- await this.contractDataProvider.addContractInstance(instance);
218
- await this.contractDataProvider.addContractArtifact(instance.currentContractClassId, artifact);
241
+ await this.contractStore.addContractInstance(instance);
242
+ await this.contractStore.addContractArtifact(artifact);
219
243
 
220
244
  const completeAddress = await this.keyStore.addAccount(secret, partialAddress);
221
- await this.accountDataProvider.setAccount(completeAddress.address, completeAddress);
222
- await this.addressDataProvider.addCompleteAddress(completeAddress);
245
+ await this.accountStore.setAccount(completeAddress.address, completeAddress);
246
+ await this.addressStore.addCompleteAddress(completeAddress);
223
247
  this.logger.debug(`Created account ${completeAddress.address}`);
224
248
 
225
249
  return completeAddress;
226
250
  }
227
251
 
228
- async txeCreateAccount(secret: Fr) {
252
+ async createAccount(secret: Fr) {
229
253
  // This is a foot gun !
230
254
  const completeAddress = await this.keyStore.addAccount(secret, secret);
231
- await this.accountDataProvider.setAccount(completeAddress.address, completeAddress);
232
- await this.addressDataProvider.addCompleteAddress(completeAddress);
255
+ await this.accountStore.setAccount(completeAddress.address, completeAddress);
256
+ await this.addressStore.addCompleteAddress(completeAddress);
233
257
  this.logger.debug(`Created account ${completeAddress.address}`);
234
258
 
235
259
  return completeAddress;
236
260
  }
237
261
 
238
- async txeAddAuthWitness(address: AztecAddress, messageHash: Fr) {
239
- const account = await this.accountDataProvider.getAccount(address);
262
+ async addAuthWitness(address: AztecAddress, messageHash: Fr) {
263
+ const account = await this.accountStore.getAccount(address);
240
264
  const privateKey = await this.keyStore.getMasterSecretKey(account.publicKeys.masterIncomingViewingPublicKey);
241
265
 
242
266
  const schnorr = new Schnorr();
@@ -248,7 +272,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
248
272
  }
249
273
 
250
274
  async mineBlock(options: { nullifiers?: Fr[] } = {}) {
251
- const blockNumber = await this.txeGetNextBlockNumber();
275
+ const blockNumber = await this.getNextBlockNumber();
252
276
 
253
277
  const txEffect = TxEffect.empty();
254
278
  txEffect.nullifiers = [getSingleTxBlockRequestHash(blockNumber), ...(options.nullifiers ?? [])];
@@ -272,19 +296,20 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
272
296
  await this.stateMachine.handleL2Block(block);
273
297
  }
274
298
 
275
- async txePrivateCallNewFlow(
299
+ async privateCallNewFlow(
276
300
  from: AztecAddress,
277
301
  targetContractAddress: AztecAddress = AztecAddress.zero(),
278
302
  functionSelector: FunctionSelector = FunctionSelector.empty(),
279
303
  args: Fr[],
280
304
  argsHash: Fr = Fr.zero(),
281
305
  isStaticCall: boolean = false,
306
+ jobId: string,
282
307
  ) {
283
308
  this.logger.verbose(
284
- `Executing external function ${await this.contractDataProvider.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`,
309
+ `Executing external function ${await this.contractStore.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`,
285
310
  );
286
311
 
287
- const artifact = await this.contractDataProvider.getFunctionArtifact(targetContractAddress, functionSelector);
312
+ const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
288
313
  if (!artifact) {
289
314
  const message = functionSelector.equals(await FunctionSelector.fromSignature('verify_private_authwit(Field)'))
290
315
  ? 'Found no account contract artifact for a private authwit check - use `create_contract_account` instead of `create_light_account` for authwit support.'
@@ -292,60 +317,77 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
292
317
  throw new Error(message);
293
318
  }
294
319
 
295
- const blockNumber = await this.txeGetNextBlockNumber();
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
+
324
+ // Sync notes before executing private function to discover notes from previous transactions
325
+ const utilityExecutor = async (call: FunctionCall, execScopes: AccessScopes) => {
326
+ await this.executeUtilityCall(call, execScopes, jobId);
327
+ };
328
+
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
+ );
338
+
339
+ const blockNumber = await this.getNextBlockNumber();
296
340
 
297
341
  const callContext = new CallContext(from, targetContractAddress, functionSelector, isStaticCall);
298
342
 
299
343
  const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
300
-
301
344
  const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
302
-
303
345
  const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
304
346
 
305
347
  const txContext = new TxContext(this.chainId, this.version, gasSettings);
306
348
 
307
- const blockHeader = await this.stateMachine.anchorBlockDataProvider.getBlockHeader();
308
-
309
349
  const protocolNullifier = await computeProtocolNullifier(getSingleTxBlockRequestHash(blockNumber));
310
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);
311
356
  const taggingIndexCache = new ExecutionTaggingIndexCache();
312
357
 
313
358
  const simulator = new WASMSimulator();
314
359
 
315
- const privateExecutionOracle = new PrivateExecutionOracle(
360
+ const privateExecutionOracle = new PrivateExecutionOracle({
316
361
  argsHash,
317
362
  txContext,
318
363
  callContext,
319
- /** Header of a block whose state is used during private execution (not the block the transaction is included in). */
320
- blockHeader,
321
- /** List of transient auth witnesses to be used during this simulation */
322
- Array.from(this.authwits.values()),
323
- /** List of transient auth witnesses to be used during this simulation */
324
- [],
325
- HashedValuesCache.create([new HashedValues(args, argsHash)]),
364
+ anchorBlockHeader: blockHeader,
365
+ utilityExecutor,
366
+ authWitnesses: Array.from(this.authwits.values()),
367
+ capsules: [],
368
+ executionCache: HashedValuesCache.create([new HashedValues(args, argsHash)]),
326
369
  noteCache,
327
370
  taggingIndexCache,
328
- this.contractDataProvider,
329
- this.noteDataProvider,
330
- this.keyStore,
331
- this.addressDataProvider,
332
- this.stateMachine.node,
333
- this.stateMachine.anchorBlockDataProvider,
334
- this.senderTaggingDataProvider,
335
- this.recipientTaggingDataProvider,
336
- this.capsuleDataProvider,
337
- this.privateEventDataProvider,
338
- 0,
339
- 1,
340
- undefined, // log
341
- undefined, // scopes
342
- /**
343
- * In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
344
- * contract would perform, including setting senderForTags.
345
- */
346
- 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,
347
389
  simulator,
348
- );
390
+ });
349
391
 
350
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.
351
393
  let result: PrivateExecutionResult;
@@ -367,24 +409,27 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
367
409
  );
368
410
  const publicFunctionsCalldata = await Promise.all(
369
411
  publicCallRequests.map(async r => {
370
- const calldata = await privateExecutionOracle.privateLoadFromExecutionCache(r.calldataHash);
412
+ const calldata = await privateExecutionOracle.loadFromExecutionCache(r.calldataHash);
371
413
  return new HashedValues(calldata, r.calldataHash);
372
414
  }),
373
415
  );
374
416
 
375
- // TXE's top level context does not track side effect counters, and as such, minRevertibleSideEffectCounter is always 0.
376
- // This has the unfortunate consequence of always producing revertible nullifiers, which means we
377
- // must set the firstNullifierHint to Fr.ZERO so the txRequestHash is always used as nonce generator
378
- result = new PrivateExecutionResult(executionResult, Fr.ZERO, publicFunctionsCalldata);
417
+ noteCache.finish();
418
+ const nonceGenerator = noteCache.getNonceGenerator();
419
+ result = new PrivateExecutionResult(executionResult, nonceGenerator, publicFunctionsCalldata);
379
420
  } catch (err) {
380
421
  throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during private execution'));
381
422
  }
382
423
 
383
- // According to the protocol rules, the nonce generator for the note hashes
384
- // can either be the first nullifier in the tx or the hash of the initial tx request
385
- // if there are none.
386
- const nonceGenerator = result.firstNullifier.equals(Fr.ZERO) ? protocolNullifier : result.firstNullifier;
387
- const { publicInputs } = await generateSimulatedProvingResult(result, nonceGenerator, this.contractDataProvider);
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
+ );
388
433
 
389
434
  const globals = makeGlobalVariables();
390
435
  globals.blockNumber = blockNumber;
@@ -395,7 +440,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
395
440
 
396
441
  const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
397
442
 
398
- const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(blockNumber, this.contractDataProvider));
443
+ const bindings = this.logger.getBindings();
444
+ const contractsDB = new PublicContractsDB(
445
+ new TXEPublicContractDataSource(blockNumber, this.contractStore),
446
+ bindings,
447
+ );
399
448
  const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
400
449
  const config = PublicSimulatorConfig.from({
401
450
  skipFeeEnforcement: true,
@@ -408,8 +457,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
408
457
  globals,
409
458
  guardedMerkleTrees,
410
459
  contractsDB,
411
- new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config),
460
+ new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings),
412
461
  new TestDateProvider(),
462
+ undefined,
463
+ createLogger('simulator:public-processor', bindings),
413
464
  );
414
465
 
415
466
  const tx = await Tx.create({
@@ -434,7 +485,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
434
485
  } else if (!processedTx.revertCode.isOK()) {
435
486
  if (processedTx.revertReason) {
436
487
  try {
437
- await enrichPublicSimulationError(processedTx.revertReason, this.contractDataProvider, this.logger);
488
+ await enrichPublicSimulationError(processedTx.revertReason, this.contractStore, this.logger);
438
489
  // eslint-disable-next-line no-empty
439
490
  } catch {}
440
491
  throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
@@ -472,17 +523,17 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
472
523
  return executionResult.returnValues ?? [];
473
524
  }
474
525
 
475
- async txePublicCallNewFlow(
526
+ async publicCallNewFlow(
476
527
  from: AztecAddress,
477
528
  targetContractAddress: AztecAddress,
478
529
  calldata: Fr[],
479
530
  isStaticCall: boolean,
480
531
  ) {
481
532
  this.logger.verbose(
482
- `Executing public function ${await this.contractDataProvider.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`,
533
+ `Executing public function ${await this.contractStore.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`,
483
534
  );
484
535
 
485
- const blockNumber = await this.txeGetNextBlockNumber();
536
+ const blockNumber = await this.getNextBlockNumber();
486
537
 
487
538
  const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
488
539
 
@@ -492,7 +543,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
492
543
 
493
544
  const txContext = new TxContext(this.chainId, this.version, gasSettings);
494
545
 
495
- const anchorBlockHeader = await this.stateMachine.anchorBlockDataProvider.getBlockHeader();
546
+ const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
496
547
 
497
548
  const calldataHash = await computeCalldataHash(calldata);
498
549
  const calldataHashedValues = new HashedValues(calldata, calldataHash);
@@ -506,7 +557,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
506
557
 
507
558
  const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
508
559
 
509
- const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(blockNumber, this.contractDataProvider));
560
+ const bindings2 = this.logger.getBindings();
561
+ const contractsDB = new PublicContractsDB(
562
+ new TXEPublicContractDataSource(blockNumber, this.contractStore),
563
+ bindings2,
564
+ );
510
565
  const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
511
566
  const config = PublicSimulatorConfig.from({
512
567
  skipFeeEnforcement: true,
@@ -515,8 +570,16 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
515
570
  collectStatistics: false,
516
571
  collectCallMetadata: true,
517
572
  });
518
- const simulator = new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config);
519
- 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
+ );
520
583
 
521
584
  // We're simulating a scenario in which private execution immediately enqueues a public call and halts. The private
522
585
  // kernel init would in this case inject a nullifier with the transaction request hash as a non-revertible
@@ -547,7 +610,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
547
610
  constantData,
548
611
  /*gasUsed=*/ new Gas(0, 0),
549
612
  /*feePayer=*/ AztecAddress.zero(),
550
- /*includeByTimestamp=*/ 0n,
613
+ /*expirationTimestamp=*/ 0n,
551
614
  inputsForPublic,
552
615
  undefined,
553
616
  );
@@ -574,7 +637,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
574
637
  } else if (!processedTx.revertCode.isOK()) {
575
638
  if (processedTx.revertReason) {
576
639
  try {
577
- await enrichPublicSimulationError(processedTx.revertReason, this.contractDataProvider, this.logger);
640
+ await enrichPublicSimulationError(processedTx.revertReason, this.contractStore, this.logger);
578
641
  // eslint-disable-next-line no-empty
579
642
  } catch {}
580
643
  throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
@@ -615,26 +678,46 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
615
678
  return returnValues ?? [];
616
679
  }
617
680
 
618
- async txeSimulateUtilityFunction(
681
+ async executeUtilityFunction(
619
682
  targetContractAddress: AztecAddress,
620
683
  functionSelector: FunctionSelector,
621
684
  args: Fr[],
685
+ jobId: string,
622
686
  ) {
623
- const artifact = await this.contractDataProvider.getFunctionArtifact(targetContractAddress, functionSelector);
687
+ const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
624
688
  if (!artifact) {
625
689
  throw new Error(`Cannot call ${functionSelector} as there is no artifact found at ${targetContractAddress}.`);
626
690
  }
627
691
 
628
- const call = {
692
+ // Sync notes before executing utility function to discover notes from previous transactions
693
+ const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
694
+ await this.stateMachine.contractSyncService.ensureContractSynced(
695
+ targetContractAddress,
696
+ functionSelector,
697
+ async (call, execScopes) => {
698
+ await this.executeUtilityCall(call, execScopes, jobId);
699
+ },
700
+ blockHeader,
701
+ jobId,
702
+ 'ALL_SCOPES',
703
+ );
704
+
705
+ const call = FunctionCall.from({
629
706
  name: artifact.name,
630
- selector: functionSelector,
631
707
  to: targetContractAddress,
632
- };
708
+ selector: functionSelector,
709
+ type: FunctionType.UTILITY,
710
+ hideMsgSender: false,
711
+ isStatic: false,
712
+ args,
713
+ returnTypes: [],
714
+ });
633
715
 
634
- const entryPointArtifact = await this.contractDataProvider.getFunctionArtifactWithDebugMetadata(
635
- call.to,
636
- call.selector,
637
- );
716
+ return this.executeUtilityCall(call, 'ALL_SCOPES', jobId);
717
+ }
718
+
719
+ private async executeUtilityCall(call: FunctionCall, scopes: AccessScopes, jobId: string): Promise<Fr[]> {
720
+ const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
638
721
  if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
639
722
  throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
640
723
  }
@@ -645,25 +728,26 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
645
728
  });
646
729
 
647
730
  try {
648
- const anchorBlockHeader = await this.stateMachine.anchorBlockDataProvider.getBlockHeader();
649
- const oracle = new UtilityExecutionOracle(
650
- call.to,
651
- [],
652
- [],
731
+ const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
732
+ const oracle = new UtilityExecutionOracle({
733
+ contractAddress: call.to,
734
+ authWitnesses: [],
735
+ capsules: [],
653
736
  anchorBlockHeader,
654
- this.contractDataProvider,
655
- this.noteDataProvider,
656
- this.keyStore,
657
- this.addressDataProvider,
658
- this.stateMachine.node,
659
- this.stateMachine.anchorBlockDataProvider,
660
- this.senderTaggingDataProvider,
661
- this.recipientTaggingDataProvider,
662
- this.capsuleDataProvider,
663
- this.privateEventDataProvider,
664
- );
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
+ });
665
749
  const acirExecutionResult = await new WASMSimulator()
666
- .executeUserCircuit(toACVMWitness(0, args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
750
+ .executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
667
751
  .catch((err: Error) => {
668
752
  err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
669
753
  throw new ExecutionError(
@@ -677,10 +761,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
677
761
  );
678
762
  });
679
763
 
680
- this.logger.verbose(`Utility simulation for ${call.to}.${call.selector} completed`);
764
+ this.logger.verbose(`Utility execution for ${call.to}.${call.selector} completed`);
681
765
  return witnessMapToFields(acirExecutionResult.returnWitness);
682
766
  } catch (err) {
683
- 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'));
684
768
  }
685
769
  }
686
770