@aztec/txe 0.0.1-fake-c83136db25 → 0.0.2-commit.217f559981

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 (81) hide show
  1. package/dest/bin/index.d.ts +1 -1
  2. package/dest/constants.d.ts +3 -0
  3. package/dest/constants.d.ts.map +1 -0
  4. package/dest/constants.js +2 -0
  5. package/dest/index.d.ts +1 -1
  6. package/dest/index.d.ts.map +1 -1
  7. package/dest/index.js +85 -52
  8. package/dest/oracle/interfaces.d.ts +12 -9
  9. package/dest/oracle/interfaces.d.ts.map +1 -1
  10. package/dest/oracle/txe_oracle_public_context.d.ts +7 -7
  11. package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
  12. package/dest/oracle/txe_oracle_public_context.js +10 -12
  13. package/dest/oracle/txe_oracle_top_level_context.d.ts +23 -14
  14. package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
  15. package/dest/oracle/txe_oracle_top_level_context.js +194 -87
  16. package/dest/rpc_translator.d.ts +35 -20
  17. package/dest/rpc_translator.d.ts.map +1 -1
  18. package/dest/rpc_translator.js +138 -64
  19. package/dest/state_machine/archiver.d.ts +21 -51
  20. package/dest/state_machine/archiver.d.ts.map +1 -1
  21. package/dest/state_machine/archiver.js +63 -94
  22. package/dest/state_machine/dummy_p2p_client.d.ts +20 -13
  23. package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
  24. package/dest/state_machine/dummy_p2p_client.js +41 -21
  25. package/dest/state_machine/global_variable_builder.d.ts +6 -4
  26. package/dest/state_machine/global_variable_builder.d.ts.map +1 -1
  27. package/dest/state_machine/global_variable_builder.js +13 -1
  28. package/dest/state_machine/index.d.ts +7 -7
  29. package/dest/state_machine/index.d.ts.map +1 -1
  30. package/dest/state_machine/index.js +40 -23
  31. package/dest/state_machine/mock_epoch_cache.d.ts +14 -10
  32. package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
  33. package/dest/state_machine/mock_epoch_cache.js +21 -13
  34. package/dest/state_machine/synchronizer.d.ts +3 -2
  35. package/dest/state_machine/synchronizer.d.ts.map +1 -1
  36. package/dest/state_machine/synchronizer.js +5 -4
  37. package/dest/txe_session.d.ts +21 -15
  38. package/dest/txe_session.d.ts.map +1 -1
  39. package/dest/txe_session.js +154 -53
  40. package/dest/util/encoding.d.ts +615 -16
  41. package/dest/util/encoding.d.ts.map +1 -1
  42. package/dest/util/encoding.js +1 -1
  43. package/dest/util/expected_failure_error.d.ts +1 -1
  44. package/dest/util/expected_failure_error.d.ts.map +1 -1
  45. package/dest/util/txe_account_store.d.ts +10 -0
  46. package/dest/util/txe_account_store.d.ts.map +1 -0
  47. package/dest/util/{txe_account_data_provider.js → txe_account_store.js} +1 -1
  48. package/dest/util/txe_public_contract_data_source.d.ts +8 -8
  49. package/dest/util/txe_public_contract_data_source.d.ts.map +1 -1
  50. package/dest/util/txe_public_contract_data_source.js +12 -29
  51. package/dest/utils/block_creation.d.ts +21 -6
  52. package/dest/utils/block_creation.d.ts.map +1 -1
  53. package/dest/utils/block_creation.js +38 -4
  54. package/dest/utils/tx_effect_creation.d.ts +3 -3
  55. package/dest/utils/tx_effect_creation.d.ts.map +1 -1
  56. package/dest/utils/tx_effect_creation.js +4 -7
  57. package/package.json +18 -17
  58. package/src/constants.ts +3 -0
  59. package/src/index.ts +97 -60
  60. package/src/oracle/interfaces.ts +11 -8
  61. package/src/oracle/txe_oracle_public_context.ts +12 -19
  62. package/src/oracle/txe_oracle_top_level_context.ts +229 -131
  63. package/src/rpc_translator.ts +164 -68
  64. package/src/state_machine/archiver.ts +63 -117
  65. package/src/state_machine/dummy_p2p_client.ts +58 -28
  66. package/src/state_machine/global_variable_builder.ts +22 -4
  67. package/src/state_machine/index.ts +60 -21
  68. package/src/state_machine/mock_epoch_cache.ts +25 -20
  69. package/src/state_machine/synchronizer.ts +6 -5
  70. package/src/txe_session.ts +210 -101
  71. package/src/util/encoding.ts +1 -1
  72. package/src/util/{txe_account_data_provider.ts → txe_account_store.ts} +1 -1
  73. package/src/util/txe_public_contract_data_source.ts +20 -45
  74. package/src/utils/block_creation.ts +49 -14
  75. package/src/utils/tx_effect_creation.ts +5 -12
  76. package/dest/util/txe_account_data_provider.d.ts +0 -10
  77. package/dest/util/txe_account_data_provider.d.ts.map +0 -1
  78. package/dest/util/txe_contract_data_provider.d.ts +0 -12
  79. package/dest/util/txe_contract_data_provider.d.ts.map +0 -1
  80. package/dest/util/txe_contract_data_provider.js +0 -22
  81. package/src/util/txe_contract_data_provider.ts +0 -36
@@ -6,15 +6,23 @@ import {
6
6
  DEFAULT_TEARDOWN_L2_GAS_LIMIT,
7
7
  NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
8
8
  } from '@aztec/constants';
9
- import { Schnorr } from '@aztec/foundation/crypto';
10
- import { Fr } from '@aztec/foundation/fields';
9
+ import { BlockNumber } from '@aztec/foundation/branded-types';
10
+ import { Schnorr } from '@aztec/foundation/crypto/schnorr';
11
+ import { Fr } from '@aztec/foundation/curves/bn254';
11
12
  import { LogLevels, type Logger, applyStringFormatting, createLogger } from '@aztec/foundation/log';
12
13
  import { TestDateProvider } from '@aztec/foundation/timer';
13
14
  import type { KeyStore } from '@aztec/key-store';
15
+ import type { AccessScopes } from '@aztec/pxe/client/lazy';
14
16
  import {
15
- AddressDataProvider,
17
+ AddressStore,
18
+ CapsuleStore,
19
+ type ContractStore,
20
+ NoteStore,
16
21
  ORACLE_VERSION,
17
- PXEOracleInterface,
22
+ PrivateEventStore,
23
+ RecipientTaggingStore,
24
+ SenderAddressBookStore,
25
+ SenderTaggingStore,
18
26
  enrichPublicSimulationError,
19
27
  } from '@aztec/pxe/server';
20
28
  import {
@@ -38,18 +46,18 @@ import {
38
46
  witnessMapToFields,
39
47
  } from '@aztec/simulator/client';
40
48
  import {
49
+ CppPublicTxSimulator,
41
50
  GuardedMerkleTreeOperations,
42
51
  PublicContractsDB,
43
52
  PublicProcessor,
44
- PublicTxSimulator,
45
53
  } from '@aztec/simulator/server';
46
- import { type ContractArtifact, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
54
+ import { type ContractArtifact, EventSelector, FunctionCall, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
47
55
  import { AuthWitness } from '@aztec/stdlib/auth-witness';
56
+ import { PublicSimulatorConfig } from '@aztec/stdlib/avm';
48
57
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
49
- import { Body, L2Block } from '@aztec/stdlib/block';
50
58
  import { type ContractInstanceWithAddress, computePartialAddress } from '@aztec/stdlib/contract';
51
59
  import { Gas, GasFees, GasSettings } from '@aztec/stdlib/gas';
52
- import { computeCalldataHash, siloNullifier } from '@aztec/stdlib/hash';
60
+ import { computeCalldataHash, computeProtocolNullifier, siloNullifier } from '@aztec/stdlib/hash';
53
61
  import {
54
62
  PartialPrivateTailPublicInputsForPublic,
55
63
  PrivateKernelTailCircuitPublicInputs,
@@ -57,7 +65,7 @@ import {
57
65
  PublicCallRequest,
58
66
  } from '@aztec/stdlib/kernel';
59
67
  import { ChonkProof } from '@aztec/stdlib/proofs';
60
- import { makeAppendOnlyTreeSnapshot, makeGlobalVariables } from '@aztec/stdlib/testing';
68
+ import { makeGlobalVariables } from '@aztec/stdlib/testing';
61
69
  import { MerkleTreeId } from '@aztec/stdlib/trees';
62
70
  import {
63
71
  CallContext,
@@ -74,15 +82,11 @@ import {
74
82
  import type { UInt64 } from '@aztec/stdlib/types';
75
83
  import { ForkCheckpoint } from '@aztec/world-state';
76
84
 
85
+ import { DEFAULT_ADDRESS } from '../constants.js';
77
86
  import type { TXEStateMachine } from '../state_machine/index.js';
78
- import type { TXEAccountDataProvider } from '../util/txe_account_data_provider.js';
79
- import type { TXEContractDataProvider } from '../util/txe_contract_data_provider.js';
87
+ import type { TXEAccountStore } from '../util/txe_account_store.js';
80
88
  import { TXEPublicContractDataSource } from '../util/txe_public_contract_data_source.js';
81
- import {
82
- getSingleTxBlockRequestHash,
83
- insertTxEffectIntoWorldTrees,
84
- makeTXEBlockHeader,
85
- } from '../utils/block_creation.js';
89
+ import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlock } from '../utils/block_creation.js';
86
90
  import type { ITxeExecutionOracle } from './interfaces.js';
87
91
 
88
92
  export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracle {
@@ -93,11 +97,17 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
93
97
 
94
98
  constructor(
95
99
  private stateMachine: TXEStateMachine,
96
- private contractDataProvider: TXEContractDataProvider,
100
+ private contractStore: ContractStore,
101
+ private noteStore: NoteStore,
97
102
  private keyStore: KeyStore,
98
- private addressDataProvider: AddressDataProvider,
99
- private accountDataProvider: TXEAccountDataProvider,
100
- private pxeOracleInterface: PXEOracleInterface,
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,
110
+ private jobId: string,
101
111
  private nextBlockTimestamp: bigint,
102
112
  private version: Fr,
103
113
  private chainId: Fr,
@@ -122,17 +132,22 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
122
132
  }
123
133
 
124
134
  // We instruct users to debug contracts via this oracle, so it makes sense that they'd expect it to also work in tests
125
- utilityDebugLog(level: number, message: string, fields: Fr[]): void {
135
+ utilityLog(level: number, message: string, fields: Fr[]): Promise<void> {
126
136
  if (!LogLevels[level]) {
127
- throw new Error(`Invalid debug log level: ${level}`);
137
+ throw new Error(`Invalid log level: ${level}`);
128
138
  }
129
139
  const levelName = LogLevels[level];
130
140
 
131
141
  this.logger[levelName](`${applyStringFormatting(message, fields)}`, { module: `${this.logger.module}:debug_log` });
142
+ return Promise.resolve();
143
+ }
144
+
145
+ txeGetDefaultAddress(): AztecAddress {
146
+ return DEFAULT_ADDRESS;
132
147
  }
133
148
 
134
- async txeGetNextBlockNumber(): Promise<number> {
135
- return (await this.getLastBlockNumber()) + 1;
149
+ async txeGetNextBlockNumber(): Promise<BlockNumber> {
150
+ return BlockNumber((await this.getLastBlockNumber()) + 1);
136
151
  }
137
152
 
138
153
  txeGetNextBlockTimestamp(): Promise<bigint> {
@@ -144,7 +159,8 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
144
159
  }
145
160
 
146
161
  async txeGetLastTxEffects() {
147
- const block = await this.stateMachine.archiver.getBlock('latest');
162
+ const latestBlockNumber = await this.stateMachine.archiver.getBlockNumber();
163
+ const block = await this.stateMachine.archiver.getBlock(latestBlockNumber);
148
164
 
149
165
  if (block!.body.txEffects.length != 1) {
150
166
  // Note that calls like env.mine() will result in blocks with no transactions, hitting this
@@ -156,6 +172,17 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
156
172
  return { txHash: txEffects.txHash, noteHashes: txEffects.noteHashes, nullifiers: txEffects.nullifiers };
157
173
  }
158
174
 
175
+ async txeGetPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress) {
176
+ return (
177
+ await this.privateEventStore.getPrivateEvents(selector, {
178
+ contractAddress,
179
+ scopes: [scope],
180
+ fromBlock: 0,
181
+ toBlock: (await this.getLastBlockNumber()) + 1,
182
+ })
183
+ ).map(e => e.packedEvent);
184
+ }
185
+
159
186
  async txeAdvanceBlocksBy(blocks: number) {
160
187
  this.logger.debug(`time traveling ${blocks} blocks`);
161
188
 
@@ -183,8 +210,8 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
183
210
  if (!secret.equals(Fr.ZERO)) {
184
211
  await this.txeAddAccount(artifact, instance, secret);
185
212
  } else {
186
- await this.contractDataProvider.addContractInstance(instance);
187
- await this.contractDataProvider.addContractArtifact(instance.currentContractClassId, artifact);
213
+ await this.contractStore.addContractInstance(instance);
214
+ await this.contractStore.addContractArtifact(artifact);
188
215
  this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
189
216
  }
190
217
  }
@@ -193,29 +220,29 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
193
220
  const partialAddress = await computePartialAddress(instance);
194
221
 
195
222
  this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
196
- await this.contractDataProvider.addContractInstance(instance);
197
- await this.contractDataProvider.addContractArtifact(instance.currentContractClassId, artifact);
223
+ await this.contractStore.addContractInstance(instance);
224
+ await this.contractStore.addContractArtifact(artifact);
198
225
 
199
226
  const completeAddress = await this.keyStore.addAccount(secret, partialAddress);
200
- await this.accountDataProvider.setAccount(completeAddress.address, completeAddress);
201
- await this.addressDataProvider.addCompleteAddress(completeAddress);
227
+ await this.accountStore.setAccount(completeAddress.address, completeAddress);
228
+ await this.addressStore.addCompleteAddress(completeAddress);
202
229
  this.logger.debug(`Created account ${completeAddress.address}`);
203
230
 
204
231
  return completeAddress;
205
232
  }
206
233
 
207
234
  async txeCreateAccount(secret: Fr) {
208
- // This is a footgun !
235
+ // This is a foot gun !
209
236
  const completeAddress = await this.keyStore.addAccount(secret, secret);
210
- await this.accountDataProvider.setAccount(completeAddress.address, completeAddress);
211
- await this.addressDataProvider.addCompleteAddress(completeAddress);
237
+ await this.accountStore.setAccount(completeAddress.address, completeAddress);
238
+ await this.addressStore.addCompleteAddress(completeAddress);
212
239
  this.logger.debug(`Created account ${completeAddress.address}`);
213
240
 
214
241
  return completeAddress;
215
242
  }
216
243
 
217
244
  async txeAddAuthWitness(address: AztecAddress, messageHash: Fr) {
218
- const account = await this.accountDataProvider.getAccount(address);
245
+ const account = await this.accountStore.getAccount(address);
219
246
  const privateKey = await this.keyStore.getMasterSecretKey(account.publicKeys.masterIncomingViewingPublicKey);
220
247
 
221
248
  const schnorr = new Schnorr();
@@ -236,19 +263,13 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
236
263
  const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
237
264
  await insertTxEffectIntoWorldTrees(txEffect, forkedWorldTrees);
238
265
 
239
- const block = new L2Block(
240
- makeAppendOnlyTreeSnapshot(),
241
- await makeTXEBlockHeader(
242
- forkedWorldTrees,
243
- makeGlobalVariables(undefined, {
244
- blockNumber,
245
- timestamp: this.nextBlockTimestamp,
246
- version: this.version,
247
- chainId: this.chainId,
248
- }),
249
- ),
250
- new Body([txEffect]),
251
- );
266
+ const globals = makeGlobalVariables(undefined, {
267
+ blockNumber,
268
+ timestamp: this.nextBlockTimestamp,
269
+ version: this.version,
270
+ chainId: this.chainId,
271
+ });
272
+ const block = await makeTXEBlock(forkedWorldTrees, globals, [txEffect]);
252
273
 
253
274
  await forkedWorldTrees.close();
254
275
 
@@ -266,10 +287,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
266
287
  isStaticCall: boolean = false,
267
288
  ) {
268
289
  this.logger.verbose(
269
- `Executing external function ${await this.contractDataProvider.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`,
290
+ `Executing external function ${await this.contractStore.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`,
270
291
  );
271
292
 
272
- const artifact = await this.contractDataProvider.getFunctionArtifact(targetContractAddress, functionSelector);
293
+ const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
273
294
  if (!artifact) {
274
295
  const message = functionSelector.equals(await FunctionSelector.fromSignature('verify_private_authwit(Field)'))
275
296
  ? 'Found no account contract artifact for a private authwit check - use `create_contract_account` instead of `create_light_account` for authwit support.'
@@ -277,51 +298,77 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
277
298
  throw new Error(message);
278
299
  }
279
300
 
301
+ // When `from` is the zero address (e.g. when deploying a new account contract), we return an
302
+ // empty scope list which acts as deny-all: no notes are visible and no keys are accessible.
303
+ const effectiveScopes = from.isZero() ? [] : [from];
304
+
305
+ // Sync notes before executing private function to discover notes from previous transactions
306
+ const utilityExecutor = async (call: FunctionCall, execScopes: AccessScopes) => {
307
+ await this.executeUtilityCall(call, execScopes);
308
+ };
309
+
310
+ const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
311
+ await this.stateMachine.contractSyncService.ensureContractSynced(
312
+ targetContractAddress,
313
+ functionSelector,
314
+ utilityExecutor,
315
+ blockHeader,
316
+ this.jobId,
317
+ effectiveScopes,
318
+ );
319
+
280
320
  const blockNumber = await this.txeGetNextBlockNumber();
281
321
 
282
322
  const callContext = new CallContext(from, targetContractAddress, functionSelector, isStaticCall);
283
323
 
284
324
  const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
285
-
286
325
  const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
287
-
288
326
  const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
289
327
 
290
328
  const txContext = new TxContext(this.chainId, this.version, gasSettings);
291
329
 
292
- const blockHeader = await this.pxeOracleInterface.getAnchorBlockHeader();
293
-
294
- const txRequestHash = getSingleTxBlockRequestHash(blockNumber);
295
- const noteCache = new ExecutionNoteCache(txRequestHash);
330
+ const protocolNullifier = await computeProtocolNullifier(getSingleTxBlockRequestHash(blockNumber));
331
+ const noteCache = new ExecutionNoteCache(protocolNullifier);
332
+ // In production, the account contract sets the min revertible counter before calling the app function.
333
+ // Since TXE bypasses the account contract, we simulate this by setting minRevertibleSideEffectCounter to 1,
334
+ // marking all side effects as revertible.
335
+ const minRevertibleSideEffectCounter = 1;
336
+ await noteCache.setMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter);
296
337
  const taggingIndexCache = new ExecutionTaggingIndexCache();
297
338
 
298
339
  const simulator = new WASMSimulator();
299
340
 
300
- const privateExecutionOracle = new PrivateExecutionOracle(
341
+ const privateExecutionOracle = new PrivateExecutionOracle({
301
342
  argsHash,
302
343
  txContext,
303
344
  callContext,
304
- /** Header of a block whose state is used during private execution (not the block the transaction is included in). */
305
- blockHeader,
306
- /** List of transient auth witnesses to be used during this simulation */
307
- Array.from(this.authwits.values()),
308
- /** List of transient auth witnesses to be used during this simulation */
309
- [],
310
- HashedValuesCache.create([new HashedValues(args, argsHash)]),
345
+ anchorBlockHeader: blockHeader,
346
+ utilityExecutor,
347
+ authWitnesses: Array.from(this.authwits.values()),
348
+ capsules: [],
349
+ executionCache: HashedValuesCache.create([new HashedValues(args, argsHash)]),
311
350
  noteCache,
312
351
  taggingIndexCache,
313
- this.pxeOracleInterface,
314
- 0,
315
- 1,
316
- undefined, // log
317
- undefined, // scopes
318
- /**
319
- * In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
320
- * contract would perform, including setting senderForTags.
321
- */
322
- from,
352
+ contractStore: this.contractStore,
353
+ noteStore: this.noteStore,
354
+ keyStore: this.keyStore,
355
+ addressStore: this.addressStore,
356
+ aztecNode: this.stateMachine.node,
357
+ senderTaggingStore: this.senderTaggingStore,
358
+ recipientTaggingStore: this.recipientTaggingStore,
359
+ senderAddressBookStore: this.senderAddressBookStore,
360
+ capsuleStore: this.capsuleStore,
361
+ privateEventStore: this.privateEventStore,
362
+ contractSyncService: this.stateMachine.contractSyncService,
363
+ jobId: this.jobId,
364
+ totalPublicCalldataCount: 0,
365
+ sideEffectCounter: minRevertibleSideEffectCounter,
366
+ scopes: effectiveScopes,
367
+ // In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
368
+ // contract would perform, including setting senderForTags.
369
+ senderForTags: from,
323
370
  simulator,
324
- );
371
+ });
325
372
 
326
373
  // 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.
327
374
  let result: PrivateExecutionResult;
@@ -348,19 +395,22 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
348
395
  }),
349
396
  );
350
397
 
351
- // TXE's top level context does not track side effect counters, and as such, minRevertibleSideEffectCounter is always 0.
352
- // This has the unfortunate consequence of always producing revertible nullifiers, which means we
353
- // must set the firstNullifierHint to Fr.ZERO so the txRequestHash is always used as nonce generator
354
- result = new PrivateExecutionResult(executionResult, Fr.ZERO, publicFunctionsCalldata);
398
+ noteCache.finish();
399
+ const nonceGenerator = noteCache.getNonceGenerator();
400
+ result = new PrivateExecutionResult(executionResult, nonceGenerator, publicFunctionsCalldata);
355
401
  } catch (err) {
356
402
  throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during private execution'));
357
403
  }
358
404
 
359
- // According to the protocol rules, the nonce generator for the note hashes
360
- // can either be the first nullifier in the tx or the hash of the initial tx request
361
- // if there are none.
362
- const nonceGenerator = result.firstNullifier.equals(Fr.ZERO) ? txRequestHash : result.firstNullifier;
363
- const { publicInputs } = await generateSimulatedProvingResult(result, nonceGenerator, this.contractDataProvider);
405
+ // According to the protocol rules, there must be at least one nullifier in the tx. The first nullifier is used as
406
+ // the nonce generator for the note hashes.
407
+ // We pass the non-zero minRevertibleSideEffectCounter to make sure the side effects are split correctly.
408
+ const { publicInputs } = await generateSimulatedProvingResult(
409
+ result,
410
+ (addr, sel) => this.contractStore.getDebugFunctionName(addr, sel),
411
+ this.stateMachine.node,
412
+ minRevertibleSideEffectCounter,
413
+ );
364
414
 
365
415
  const globals = makeGlobalVariables();
366
416
  globals.blockNumber = blockNumber;
@@ -371,17 +421,27 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
371
421
 
372
422
  const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
373
423
 
374
- const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(blockNumber, this.contractDataProvider));
424
+ const bindings = this.logger.getBindings();
425
+ const contractsDB = new PublicContractsDB(
426
+ new TXEPublicContractDataSource(blockNumber, this.contractStore),
427
+ bindings,
428
+ );
375
429
  const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
430
+ const config = PublicSimulatorConfig.from({
431
+ skipFeeEnforcement: true,
432
+ collectDebugLogs: true,
433
+ collectHints: false,
434
+ collectStatistics: false,
435
+ collectCallMetadata: true,
436
+ });
376
437
  const processor = new PublicProcessor(
377
438
  globals,
378
439
  guardedMerkleTrees,
379
440
  contractsDB,
380
- new PublicTxSimulator(guardedMerkleTrees, contractsDB, globals, {
381
- doMerkleOperations: true,
382
- skipFeeEnforcement: true,
383
- }),
441
+ new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings),
384
442
  new TestDateProvider(),
443
+ undefined,
444
+ createLogger('simulator:public-processor', bindings),
385
445
  );
386
446
 
387
447
  const tx = await Tx.create({
@@ -406,7 +466,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
406
466
  } else if (!processedTx.revertCode.isOK()) {
407
467
  if (processedTx.revertReason) {
408
468
  try {
409
- await enrichPublicSimulationError(processedTx.revertReason, this.contractDataProvider, this.logger);
469
+ await enrichPublicSimulationError(processedTx.revertReason, this.contractStore, this.logger);
410
470
  // eslint-disable-next-line no-empty
411
471
  } catch {}
412
472
  throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
@@ -435,13 +495,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
435
495
  const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
436
496
  await forkedWorldTrees.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
437
497
 
438
- const body = new Body([txEffect]);
439
-
440
- const l2Block = new L2Block(
441
- makeAppendOnlyTreeSnapshot(),
442
- await makeTXEBlockHeader(forkedWorldTrees, globals),
443
- body,
444
- );
498
+ const l2Block = await makeTXEBlock(forkedWorldTrees, globals, [txEffect]);
445
499
 
446
500
  await this.stateMachine.handleL2Block(l2Block);
447
501
 
@@ -457,7 +511,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
457
511
  isStaticCall: boolean,
458
512
  ) {
459
513
  this.logger.verbose(
460
- `Executing public function ${await this.contractDataProvider.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`,
514
+ `Executing public function ${await this.contractStore.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`,
461
515
  );
462
516
 
463
517
  const blockNumber = await this.txeGetNextBlockNumber();
@@ -470,7 +524,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
470
524
 
471
525
  const txContext = new TxContext(this.chainId, this.version, gasSettings);
472
526
 
473
- const anchorBlockHeader = await this.pxeOracleInterface.getAnchorBlockHeader();
527
+ const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
474
528
 
475
529
  const calldataHash = await computeCalldataHash(calldata);
476
530
  const calldataHashedValues = new HashedValues(calldata, calldataHash);
@@ -484,22 +538,36 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
484
538
 
485
539
  const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
486
540
 
487
- const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(blockNumber, this.contractDataProvider));
541
+ const bindings2 = this.logger.getBindings();
542
+ const contractsDB = new PublicContractsDB(
543
+ new TXEPublicContractDataSource(blockNumber, this.contractStore),
544
+ bindings2,
545
+ );
488
546
  const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
489
- const simulator = new PublicTxSimulator(guardedMerkleTrees, contractsDB, globals, {
490
- doMerkleOperations: true,
547
+ const config = PublicSimulatorConfig.from({
491
548
  skipFeeEnforcement: true,
549
+ collectDebugLogs: true,
550
+ collectHints: false,
551
+ collectStatistics: false,
552
+ collectCallMetadata: true,
492
553
  });
493
- const processor = new PublicProcessor(globals, guardedMerkleTrees, contractsDB, simulator, new TestDateProvider());
554
+ const simulator = new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings2);
555
+ const processor = new PublicProcessor(
556
+ globals,
557
+ guardedMerkleTrees,
558
+ contractsDB,
559
+ simulator,
560
+ new TestDateProvider(),
561
+ undefined,
562
+ createLogger('simulator:public-processor', bindings2),
563
+ );
494
564
 
495
565
  // We're simulating a scenario in which private execution immediately enqueues a public call and halts. The private
496
566
  // kernel init would in this case inject a nullifier with the transaction request hash as a non-revertible
497
567
  // side-effect, which the AVM then expects to exist in order to use it as the nonce generator when siloing notes as
498
568
  // unique.
499
569
  const nonRevertibleAccumulatedData = PrivateToPublicAccumulatedData.empty();
500
- if (!isStaticCall) {
501
- nonRevertibleAccumulatedData.nullifiers[0] = getSingleTxBlockRequestHash(blockNumber);
502
- }
570
+ nonRevertibleAccumulatedData.nullifiers[0] = getSingleTxBlockRequestHash(blockNumber);
503
571
 
504
572
  // The enqueued public call itself we make be revertible so that the public execution is itself revertible, as tests
505
573
  // may require producing reverts.
@@ -523,7 +591,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
523
591
  constantData,
524
592
  /*gasUsed=*/ new Gas(0, 0),
525
593
  /*feePayer=*/ AztecAddress.zero(),
526
- /*includeByTimestamp=*/ 0n,
594
+ /*expirationTimestamp=*/ 0n,
527
595
  inputsForPublic,
528
596
  undefined,
529
597
  );
@@ -550,7 +618,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
550
618
  } else if (!processedTx.revertCode.isOK()) {
551
619
  if (processedTx.revertReason) {
552
620
  try {
553
- await enrichPublicSimulationError(processedTx.revertReason, this.contractDataProvider, this.logger);
621
+ await enrichPublicSimulationError(processedTx.revertReason, this.contractStore, this.logger);
554
622
  // eslint-disable-next-line no-empty
555
623
  } catch {}
556
624
  throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
@@ -582,13 +650,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
582
650
  const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
583
651
  await forkedWorldTrees.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
584
652
 
585
- const body = new Body([txEffect]);
586
-
587
- const l2Block = new L2Block(
588
- makeAppendOnlyTreeSnapshot(),
589
- await makeTXEBlockHeader(forkedWorldTrees, globals),
590
- body,
591
- );
653
+ const l2Block = await makeTXEBlock(forkedWorldTrees, globals, [txEffect]);
592
654
 
593
655
  await this.stateMachine.handleL2Block(l2Block);
594
656
 
@@ -597,23 +659,41 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
597
659
  return returnValues ?? [];
598
660
  }
599
661
 
600
- async txeSimulateUtilityFunction(
601
- targetContractAddress: AztecAddress,
602
- functionSelector: FunctionSelector,
603
- args: Fr[],
604
- ) {
605
- const artifact = await this.contractDataProvider.getFunctionArtifact(targetContractAddress, functionSelector);
662
+ async txeExecuteUtilityFunction(targetContractAddress: AztecAddress, functionSelector: FunctionSelector, args: Fr[]) {
663
+ const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
606
664
  if (!artifact) {
607
665
  throw new Error(`Cannot call ${functionSelector} as there is no artifact found at ${targetContractAddress}.`);
608
666
  }
609
667
 
610
- const call = {
668
+ // Sync notes before executing utility function to discover notes from previous transactions
669
+ const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
670
+ await this.stateMachine.contractSyncService.ensureContractSynced(
671
+ targetContractAddress,
672
+ functionSelector,
673
+ async (call, execScopes) => {
674
+ await this.executeUtilityCall(call, execScopes);
675
+ },
676
+ blockHeader,
677
+ this.jobId,
678
+ 'ALL_SCOPES',
679
+ );
680
+
681
+ const call = FunctionCall.from({
611
682
  name: artifact.name,
612
- selector: functionSelector,
613
683
  to: targetContractAddress,
614
- };
684
+ selector: functionSelector,
685
+ type: FunctionType.UTILITY,
686
+ hideMsgSender: false,
687
+ isStatic: false,
688
+ args,
689
+ returnTypes: [],
690
+ });
691
+
692
+ return this.executeUtilityCall(call, 'ALL_SCOPES');
693
+ }
615
694
 
616
- const entryPointArtifact = await this.pxeOracleInterface.getFunctionArtifact(call.to, call.selector);
695
+ private async executeUtilityCall(call: FunctionCall, scopes: AccessScopes): Promise<Fr[]> {
696
+ const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
617
697
  if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
618
698
  throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
619
699
  }
@@ -624,9 +704,26 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
624
704
  });
625
705
 
626
706
  try {
627
- const oracle = new UtilityExecutionOracle(call.to, [], [], this.pxeOracleInterface);
707
+ const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
708
+ const oracle = new UtilityExecutionOracle({
709
+ contractAddress: call.to,
710
+ authWitnesses: [],
711
+ capsules: [],
712
+ anchorBlockHeader,
713
+ contractStore: this.contractStore,
714
+ noteStore: this.noteStore,
715
+ keyStore: this.keyStore,
716
+ addressStore: this.addressStore,
717
+ aztecNode: this.stateMachine.node,
718
+ recipientTaggingStore: this.recipientTaggingStore,
719
+ senderAddressBookStore: this.senderAddressBookStore,
720
+ capsuleStore: this.capsuleStore,
721
+ privateEventStore: this.privateEventStore,
722
+ jobId: this.jobId,
723
+ scopes,
724
+ });
628
725
  const acirExecutionResult = await new WASMSimulator()
629
- .executeUserCircuit(toACVMWitness(0, args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
726
+ .executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
630
727
  .catch((err: Error) => {
631
728
  err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
632
729
  throw new ExecutionError(
@@ -640,10 +737,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
640
737
  );
641
738
  });
642
739
 
643
- this.logger.verbose(`Utility simulation for ${call.to}.${call.selector} completed`);
740
+ this.logger.verbose(`Utility execution for ${call.to}.${call.selector} completed`);
644
741
  return witnessMapToFields(acirExecutionResult.returnWitness);
645
742
  } catch (err) {
646
- throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility simulation'));
743
+ throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility execution'));
647
744
  }
648
745
  }
649
746
 
@@ -652,7 +749,8 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
652
749
  return [this.nextBlockTimestamp, this.authwits];
653
750
  }
654
751
 
655
- private async getLastBlockNumber(): Promise<number> {
656
- return (await this.stateMachine.node.getBlockHeader('latest'))?.globalVariables.blockNumber ?? 0;
752
+ private async getLastBlockNumber(): Promise<BlockNumber> {
753
+ const header = await this.stateMachine.node.getBlockHeader('latest');
754
+ return header ? header.globalVariables.blockNumber : BlockNumber.ZERO;
657
755
  }
658
756
  }