@aztec/txe 0.0.1-commit.9b94fc1 → 0.0.1-commit.9d2bcf6d

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