@aztec/txe 3.0.0-rc.5 → 4.0.0-nightly.20260107

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 (66) 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 +4 -2
  8. package/dest/oracle/interfaces.d.ts.map +1 -1
  9. package/dest/oracle/txe_oracle_public_context.d.ts +2 -2
  10. package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
  11. package/dest/oracle/txe_oracle_public_context.js +3 -5
  12. package/dest/oracle/txe_oracle_top_level_context.d.ts +18 -10
  13. package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
  14. package/dest/oracle/txe_oracle_top_level_context.js +83 -52
  15. package/dest/rpc_translator.d.ts +9 -3
  16. package/dest/rpc_translator.d.ts.map +1 -1
  17. package/dest/rpc_translator.js +33 -3
  18. package/dest/state_machine/archiver.d.ts +19 -7
  19. package/dest/state_machine/archiver.d.ts.map +1 -1
  20. package/dest/state_machine/archiver.js +93 -15
  21. package/dest/state_machine/dummy_p2p_client.d.ts +1 -1
  22. package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
  23. package/dest/state_machine/dummy_p2p_client.js +3 -1
  24. package/dest/state_machine/global_variable_builder.d.ts +3 -2
  25. package/dest/state_machine/global_variable_builder.d.ts.map +1 -1
  26. package/dest/state_machine/global_variable_builder.js +12 -0
  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 +13 -19
  30. package/dest/txe_session.d.ts +15 -9
  31. package/dest/txe_session.d.ts.map +1 -1
  32. package/dest/txe_session.js +72 -42
  33. package/dest/util/encoding.d.ts +601 -2
  34. package/dest/util/encoding.d.ts.map +1 -1
  35. package/dest/util/txe_account_store.d.ts +10 -0
  36. package/dest/util/txe_account_store.d.ts.map +1 -0
  37. package/dest/util/{txe_account_data_provider.js → txe_account_store.js} +1 -1
  38. package/dest/util/txe_contract_store.d.ts +12 -0
  39. package/dest/util/txe_contract_store.d.ts.map +1 -0
  40. package/dest/util/{txe_contract_data_provider.js → txe_contract_store.js} +3 -3
  41. package/dest/util/txe_public_contract_data_source.d.ts +4 -4
  42. package/dest/util/txe_public_contract_data_source.d.ts.map +1 -1
  43. package/dest/util/txe_public_contract_data_source.js +10 -10
  44. package/dest/utils/block_creation.d.ts +16 -2
  45. package/dest/utils/block_creation.d.ts.map +1 -1
  46. package/dest/utils/block_creation.js +22 -1
  47. package/package.json +15 -15
  48. package/src/constants.ts +3 -0
  49. package/src/index.ts +15 -12
  50. package/src/oracle/interfaces.ts +3 -1
  51. package/src/oracle/txe_oracle_public_context.ts +3 -8
  52. package/src/oracle/txe_oracle_top_level_context.ts +125 -76
  53. package/src/rpc_translator.ts +45 -3
  54. package/src/state_machine/archiver.ts +119 -21
  55. package/src/state_machine/dummy_p2p_client.ts +3 -1
  56. package/src/state_machine/global_variable_builder.ts +18 -1
  57. package/src/state_machine/index.ts +18 -17
  58. package/src/txe_session.ts +157 -69
  59. package/src/util/{txe_account_data_provider.ts → txe_account_store.ts} +1 -1
  60. package/src/util/{txe_contract_data_provider.ts → txe_contract_store.ts} +3 -3
  61. package/src/util/txe_public_contract_data_source.ts +9 -9
  62. package/src/utils/block_creation.ts +31 -1
  63. package/dest/util/txe_account_data_provider.d.ts +0 -10
  64. package/dest/util/txe_account_data_provider.d.ts.map +0 -1
  65. package/dest/util/txe_contract_data_provider.d.ts +0 -12
  66. package/dest/util/txe_contract_data_provider.d.ts.map +0 -1
@@ -13,9 +13,14 @@ import { LogLevels, type Logger, applyStringFormatting, createLogger } from '@az
13
13
  import { TestDateProvider } from '@aztec/foundation/timer';
14
14
  import type { KeyStore } from '@aztec/key-store';
15
15
  import {
16
- AddressDataProvider,
16
+ AddressStore,
17
+ CapsuleStore,
18
+ NoteStore,
17
19
  ORACLE_VERSION,
18
- PXEOracleInterface,
20
+ PrivateEventStore,
21
+ RecipientTaggingStore,
22
+ SenderAddressBookStore,
23
+ SenderTaggingStore,
19
24
  enrichPublicSimulationError,
20
25
  } from '@aztec/pxe/server';
21
26
  import {
@@ -44,11 +49,10 @@ import {
44
49
  PublicContractsDB,
45
50
  PublicProcessor,
46
51
  } from '@aztec/simulator/server';
47
- import { type ContractArtifact, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
52
+ import { type ContractArtifact, EventSelector, FunctionCall, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
48
53
  import { AuthWitness } from '@aztec/stdlib/auth-witness';
49
54
  import { PublicSimulatorConfig } from '@aztec/stdlib/avm';
50
55
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
51
- import { Body, L2Block } from '@aztec/stdlib/block';
52
56
  import { type ContractInstanceWithAddress, computePartialAddress } from '@aztec/stdlib/contract';
53
57
  import { Gas, GasFees, GasSettings } from '@aztec/stdlib/gas';
54
58
  import { computeCalldataHash, computeProtocolNullifier, siloNullifier } from '@aztec/stdlib/hash';
@@ -59,7 +63,7 @@ import {
59
63
  PublicCallRequest,
60
64
  } from '@aztec/stdlib/kernel';
61
65
  import { ChonkProof } from '@aztec/stdlib/proofs';
62
- import { makeAppendOnlyTreeSnapshot, makeGlobalVariables } from '@aztec/stdlib/testing';
66
+ import { makeGlobalVariables } from '@aztec/stdlib/testing';
63
67
  import { MerkleTreeId } from '@aztec/stdlib/trees';
64
68
  import {
65
69
  CallContext,
@@ -76,15 +80,12 @@ import {
76
80
  import type { UInt64 } from '@aztec/stdlib/types';
77
81
  import { ForkCheckpoint } from '@aztec/world-state';
78
82
 
83
+ import { DEFAULT_ADDRESS } from '../constants.js';
79
84
  import type { TXEStateMachine } from '../state_machine/index.js';
80
- import type { TXEAccountDataProvider } from '../util/txe_account_data_provider.js';
81
- import type { TXEContractDataProvider } from '../util/txe_contract_data_provider.js';
85
+ import type { TXEAccountStore } from '../util/txe_account_store.js';
86
+ import type { TXEContractStore } from '../util/txe_contract_store.js';
82
87
  import { TXEPublicContractDataSource } from '../util/txe_public_contract_data_source.js';
83
- import {
84
- getSingleTxBlockRequestHash,
85
- insertTxEffectIntoWorldTrees,
86
- makeTXEBlockHeader,
87
- } from '../utils/block_creation.js';
88
+ import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlock } from '../utils/block_creation.js';
88
89
  import type { ITxeExecutionOracle } from './interfaces.js';
89
90
 
90
91
  export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracle {
@@ -95,11 +96,16 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
95
96
 
96
97
  constructor(
97
98
  private stateMachine: TXEStateMachine,
98
- private contractDataProvider: TXEContractDataProvider,
99
+ private contractStore: TXEContractStore,
100
+ private noteStore: NoteStore,
99
101
  private keyStore: KeyStore,
100
- private addressDataProvider: AddressDataProvider,
101
- private accountDataProvider: TXEAccountDataProvider,
102
- private pxeOracleInterface: PXEOracleInterface,
102
+ private addressStore: AddressStore,
103
+ private accountStore: TXEAccountStore,
104
+ private senderTaggingStore: SenderTaggingStore,
105
+ private recipientTaggingStore: RecipientTaggingStore,
106
+ private senderAddressBookStore: SenderAddressBookStore,
107
+ private capsuleStore: CapsuleStore,
108
+ private privateEventStore: PrivateEventStore,
103
109
  private nextBlockTimestamp: bigint,
104
110
  private version: Fr,
105
111
  private chainId: Fr,
@@ -133,6 +139,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
133
139
  this.logger[levelName](`${applyStringFormatting(message, fields)}`, { module: `${this.logger.module}:debug_log` });
134
140
  }
135
141
 
142
+ txeGetDefaultAddress(): AztecAddress {
143
+ return DEFAULT_ADDRESS;
144
+ }
145
+
136
146
  async txeGetNextBlockNumber(): Promise<BlockNumber> {
137
147
  return BlockNumber((await this.getLastBlockNumber()) + 1);
138
148
  }
@@ -146,7 +156,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
146
156
  }
147
157
 
148
158
  async txeGetLastTxEffects() {
149
- const block = await this.stateMachine.archiver.getBlock('latest');
159
+ const block = await this.stateMachine.archiver.getL2Block('latest');
150
160
 
151
161
  if (block!.body.txEffects.length != 1) {
152
162
  // Note that calls like env.mine() will result in blocks with no transactions, hitting this
@@ -158,6 +168,17 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
158
168
  return { txHash: txEffects.txHash, noteHashes: txEffects.noteHashes, nullifiers: txEffects.nullifiers };
159
169
  }
160
170
 
171
+ async txeGetPrivateEvents(selector: EventSelector, contractAddress: AztecAddress, scope: AztecAddress) {
172
+ return (
173
+ await this.privateEventStore.getPrivateEvents(selector, {
174
+ contractAddress,
175
+ scopes: [scope],
176
+ fromBlock: 0,
177
+ toBlock: (await this.getLastBlockNumber()) + 1,
178
+ })
179
+ ).map(e => e.packedEvent);
180
+ }
181
+
161
182
  async txeAdvanceBlocksBy(blocks: number) {
162
183
  this.logger.debug(`time traveling ${blocks} blocks`);
163
184
 
@@ -185,8 +206,8 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
185
206
  if (!secret.equals(Fr.ZERO)) {
186
207
  await this.txeAddAccount(artifact, instance, secret);
187
208
  } else {
188
- await this.contractDataProvider.addContractInstance(instance);
189
- await this.contractDataProvider.addContractArtifact(instance.currentContractClassId, artifact);
209
+ await this.contractStore.addContractInstance(instance);
210
+ await this.contractStore.addContractArtifact(instance.currentContractClassId, artifact);
190
211
  this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
191
212
  }
192
213
  }
@@ -195,29 +216,29 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
195
216
  const partialAddress = await computePartialAddress(instance);
196
217
 
197
218
  this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
198
- await this.contractDataProvider.addContractInstance(instance);
199
- await this.contractDataProvider.addContractArtifact(instance.currentContractClassId, artifact);
219
+ await this.contractStore.addContractInstance(instance);
220
+ await this.contractStore.addContractArtifact(instance.currentContractClassId, artifact);
200
221
 
201
222
  const completeAddress = await this.keyStore.addAccount(secret, partialAddress);
202
- await this.accountDataProvider.setAccount(completeAddress.address, completeAddress);
203
- await this.addressDataProvider.addCompleteAddress(completeAddress);
223
+ await this.accountStore.setAccount(completeAddress.address, completeAddress);
224
+ await this.addressStore.addCompleteAddress(completeAddress);
204
225
  this.logger.debug(`Created account ${completeAddress.address}`);
205
226
 
206
227
  return completeAddress;
207
228
  }
208
229
 
209
230
  async txeCreateAccount(secret: Fr) {
210
- // This is a footgun !
231
+ // This is a foot gun !
211
232
  const completeAddress = await this.keyStore.addAccount(secret, secret);
212
- await this.accountDataProvider.setAccount(completeAddress.address, completeAddress);
213
- await this.addressDataProvider.addCompleteAddress(completeAddress);
233
+ await this.accountStore.setAccount(completeAddress.address, completeAddress);
234
+ await this.addressStore.addCompleteAddress(completeAddress);
214
235
  this.logger.debug(`Created account ${completeAddress.address}`);
215
236
 
216
237
  return completeAddress;
217
238
  }
218
239
 
219
240
  async txeAddAuthWitness(address: AztecAddress, messageHash: Fr) {
220
- const account = await this.accountDataProvider.getAccount(address);
241
+ const account = await this.accountStore.getAccount(address);
221
242
  const privateKey = await this.keyStore.getMasterSecretKey(account.publicKeys.masterIncomingViewingPublicKey);
222
243
 
223
244
  const schnorr = new Schnorr();
@@ -238,19 +259,13 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
238
259
  const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
239
260
  await insertTxEffectIntoWorldTrees(txEffect, forkedWorldTrees);
240
261
 
241
- const block = new L2Block(
242
- makeAppendOnlyTreeSnapshot(),
243
- await makeTXEBlockHeader(
244
- forkedWorldTrees,
245
- makeGlobalVariables(undefined, {
246
- blockNumber,
247
- timestamp: this.nextBlockTimestamp,
248
- version: this.version,
249
- chainId: this.chainId,
250
- }),
251
- ),
252
- new Body([txEffect]),
253
- );
262
+ const globals = makeGlobalVariables(undefined, {
263
+ blockNumber,
264
+ timestamp: this.nextBlockTimestamp,
265
+ version: this.version,
266
+ chainId: this.chainId,
267
+ });
268
+ const block = await makeTXEBlock(forkedWorldTrees, globals, [txEffect]);
254
269
 
255
270
  await forkedWorldTrees.close();
256
271
 
@@ -268,10 +283,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
268
283
  isStaticCall: boolean = false,
269
284
  ) {
270
285
  this.logger.verbose(
271
- `Executing external function ${await this.contractDataProvider.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`,
286
+ `Executing external function ${await this.contractStore.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`,
272
287
  );
273
288
 
274
- const artifact = await this.contractDataProvider.getFunctionArtifact(targetContractAddress, functionSelector);
289
+ const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
275
290
  if (!artifact) {
276
291
  const message = functionSelector.equals(await FunctionSelector.fromSignature('verify_private_authwit(Field)'))
277
292
  ? 'Found no account contract artifact for a private authwit check - use `create_contract_account` instead of `create_light_account` for authwit support.'
@@ -279,19 +294,24 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
279
294
  throw new Error(message);
280
295
  }
281
296
 
297
+ // Sync notes before executing private function to discover notes from previous transactions
298
+ const utilityExecutor = async (call: FunctionCall) => {
299
+ await this.executeUtilityCall(call);
300
+ };
301
+
302
+ await this.contractStore.syncPrivateState(targetContractAddress, functionSelector, utilityExecutor);
303
+
282
304
  const blockNumber = await this.txeGetNextBlockNumber();
283
305
 
284
306
  const callContext = new CallContext(from, targetContractAddress, functionSelector, isStaticCall);
285
307
 
286
308
  const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
287
-
288
309
  const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
289
-
290
310
  const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
291
311
 
292
312
  const txContext = new TxContext(this.chainId, this.version, gasSettings);
293
313
 
294
- const blockHeader = await this.pxeOracleInterface.getAnchorBlockHeader();
314
+ const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
295
315
 
296
316
  const protocolNullifier = await computeProtocolNullifier(getSingleTxBlockRequestHash(blockNumber));
297
317
  const noteCache = new ExecutionNoteCache(protocolNullifier);
@@ -305,6 +325,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
305
325
  callContext,
306
326
  /** Header of a block whose state is used during private execution (not the block the transaction is included in). */
307
327
  blockHeader,
328
+ utilityExecutor,
308
329
  /** List of transient auth witnesses to be used during this simulation */
309
330
  Array.from(this.authwits.values()),
310
331
  /** List of transient auth witnesses to be used during this simulation */
@@ -312,7 +333,17 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
312
333
  HashedValuesCache.create([new HashedValues(args, argsHash)]),
313
334
  noteCache,
314
335
  taggingIndexCache,
315
- this.pxeOracleInterface,
336
+ this.contractStore,
337
+ this.noteStore,
338
+ this.keyStore,
339
+ this.addressStore,
340
+ this.stateMachine.node,
341
+ this.stateMachine.anchorBlockStore,
342
+ this.senderTaggingStore,
343
+ this.recipientTaggingStore,
344
+ this.senderAddressBookStore,
345
+ this.capsuleStore,
346
+ this.privateEventStore,
316
347
  0,
317
348
  1,
318
349
  undefined, // log
@@ -362,7 +393,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
362
393
  // can either be the first nullifier in the tx or the hash of the initial tx request
363
394
  // if there are none.
364
395
  const nonceGenerator = result.firstNullifier.equals(Fr.ZERO) ? protocolNullifier : result.firstNullifier;
365
- const { publicInputs } = await generateSimulatedProvingResult(result, nonceGenerator, this.contractDataProvider);
396
+ const { publicInputs } = await generateSimulatedProvingResult(result, nonceGenerator, this.contractStore);
366
397
 
367
398
  const globals = makeGlobalVariables();
368
399
  globals.blockNumber = blockNumber;
@@ -373,7 +404,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
373
404
 
374
405
  const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
375
406
 
376
- const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(blockNumber, this.contractDataProvider));
407
+ const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(blockNumber, this.contractStore));
377
408
  const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
378
409
  const config = PublicSimulatorConfig.from({
379
410
  skipFeeEnforcement: true,
@@ -412,7 +443,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
412
443
  } else if (!processedTx.revertCode.isOK()) {
413
444
  if (processedTx.revertReason) {
414
445
  try {
415
- await enrichPublicSimulationError(processedTx.revertReason, this.contractDataProvider, this.logger);
446
+ await enrichPublicSimulationError(processedTx.revertReason, this.contractStore, this.logger);
416
447
  // eslint-disable-next-line no-empty
417
448
  } catch {}
418
449
  throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
@@ -441,13 +472,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
441
472
  const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
442
473
  await forkedWorldTrees.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
443
474
 
444
- const body = new Body([txEffect]);
445
-
446
- const l2Block = new L2Block(
447
- makeAppendOnlyTreeSnapshot(),
448
- await makeTXEBlockHeader(forkedWorldTrees, globals),
449
- body,
450
- );
475
+ const l2Block = await makeTXEBlock(forkedWorldTrees, globals, [txEffect]);
451
476
 
452
477
  await this.stateMachine.handleL2Block(l2Block);
453
478
 
@@ -463,7 +488,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
463
488
  isStaticCall: boolean,
464
489
  ) {
465
490
  this.logger.verbose(
466
- `Executing public function ${await this.contractDataProvider.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`,
491
+ `Executing public function ${await this.contractStore.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`,
467
492
  );
468
493
 
469
494
  const blockNumber = await this.txeGetNextBlockNumber();
@@ -476,7 +501,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
476
501
 
477
502
  const txContext = new TxContext(this.chainId, this.version, gasSettings);
478
503
 
479
- const anchorBlockHeader = await this.pxeOracleInterface.getAnchorBlockHeader();
504
+ const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
480
505
 
481
506
  const calldataHash = await computeCalldataHash(calldata);
482
507
  const calldataHashedValues = new HashedValues(calldata, calldataHash);
@@ -490,7 +515,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
490
515
 
491
516
  const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
492
517
 
493
- const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(blockNumber, this.contractDataProvider));
518
+ const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(blockNumber, this.contractStore));
494
519
  const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
495
520
  const config = PublicSimulatorConfig.from({
496
521
  skipFeeEnforcement: true,
@@ -558,7 +583,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
558
583
  } else if (!processedTx.revertCode.isOK()) {
559
584
  if (processedTx.revertReason) {
560
585
  try {
561
- await enrichPublicSimulationError(processedTx.revertReason, this.contractDataProvider, this.logger);
586
+ await enrichPublicSimulationError(processedTx.revertReason, this.contractStore, this.logger);
562
587
  // eslint-disable-next-line no-empty
563
588
  } catch {}
564
589
  throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
@@ -590,13 +615,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
590
615
  const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
591
616
  await forkedWorldTrees.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
592
617
 
593
- const body = new Body([txEffect]);
594
-
595
- const l2Block = new L2Block(
596
- makeAppendOnlyTreeSnapshot(),
597
- await makeTXEBlockHeader(forkedWorldTrees, globals),
598
- body,
599
- );
618
+ const l2Block = await makeTXEBlock(forkedWorldTrees, globals, [txEffect]);
600
619
 
601
620
  await this.stateMachine.handleL2Block(l2Block);
602
621
 
@@ -610,18 +629,32 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
610
629
  functionSelector: FunctionSelector,
611
630
  args: Fr[],
612
631
  ) {
613
- const artifact = await this.contractDataProvider.getFunctionArtifact(targetContractAddress, functionSelector);
632
+ const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
614
633
  if (!artifact) {
615
634
  throw new Error(`Cannot call ${functionSelector} as there is no artifact found at ${targetContractAddress}.`);
616
635
  }
617
636
 
618
- const call = {
619
- name: artifact.name,
620
- selector: functionSelector,
621
- to: targetContractAddress,
622
- };
637
+ // Sync notes before executing utility function to discover notes from previous transactions
638
+ await this.contractStore.syncPrivateState(targetContractAddress, functionSelector, async call => {
639
+ await this.executeUtilityCall(call);
640
+ });
623
641
 
624
- const entryPointArtifact = await this.pxeOracleInterface.getFunctionArtifact(call.to, call.selector);
642
+ const call = new FunctionCall(
643
+ artifact.name,
644
+ targetContractAddress,
645
+ functionSelector,
646
+ FunctionType.UTILITY,
647
+ false,
648
+ false,
649
+ args,
650
+ [],
651
+ );
652
+
653
+ return this.executeUtilityCall(call);
654
+ }
655
+
656
+ private async executeUtilityCall(call: FunctionCall): Promise<Fr[]> {
657
+ const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
625
658
  if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
626
659
  throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
627
660
  }
@@ -632,9 +665,25 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
632
665
  });
633
666
 
634
667
  try {
635
- const oracle = new UtilityExecutionOracle(call.to, [], [], this.pxeOracleInterface);
668
+ const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
669
+ const oracle = new UtilityExecutionOracle(
670
+ call.to,
671
+ [],
672
+ [],
673
+ anchorBlockHeader,
674
+ this.contractStore,
675
+ this.noteStore,
676
+ this.keyStore,
677
+ this.addressStore,
678
+ this.stateMachine.node,
679
+ this.stateMachine.anchorBlockStore,
680
+ this.recipientTaggingStore,
681
+ this.senderAddressBookStore,
682
+ this.capsuleStore,
683
+ this.privateEventStore,
684
+ );
636
685
  const acirExecutionResult = await new WASMSimulator()
637
- .executeUserCircuit(toACVMWitness(0, args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
686
+ .executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
638
687
  .catch((err: Error) => {
639
688
  err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
640
689
  throw new ExecutionError(
@@ -8,7 +8,7 @@ import {
8
8
  type IUtilityExecutionOracle,
9
9
  packAsRetrievedNote,
10
10
  } from '@aztec/pxe/simulator';
11
- import { type ContractArtifact, FunctionSelector, NoteSelector } from '@aztec/stdlib/abi';
11
+ import { type ContractArtifact, EventSelector, FunctionSelector, NoteSelector } from '@aztec/stdlib/abi';
12
12
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
13
13
  import { MerkleTreeId } from '@aztec/stdlib/trees';
14
14
 
@@ -30,6 +30,9 @@ import {
30
30
  toSingle,
31
31
  } from './util/encoding.js';
32
32
 
33
+ const MAX_EVENT_LEN = 12; // This is MAX_MESSAGE_CONTENT_LEN - PRIVATE_EVENT_RESERVED_FIELDS
34
+ const MAX_PRIVATE_EVENTS_PER_TXE_QUERY = 5;
35
+
33
36
  export class UnavailableOracleError extends Error {
34
37
  constructor(oracleName: string) {
35
38
  super(`${oracleName} oracles not available with the current handler`);
@@ -156,6 +159,12 @@ export class RPCTranslator {
156
159
 
157
160
  // TXE-specific oracles
158
161
 
162
+ txeGetDefaultAddress() {
163
+ const defaultAddress = this.handlerAsTxe().txeGetDefaultAddress();
164
+
165
+ return toForeignCallResult([toSingle(defaultAddress)]);
166
+ }
167
+
159
168
  async txeGetNextBlockNumber() {
160
169
  const nextBlockNumber = await this.handlerAsTxe().txeGetNextBlockNumber();
161
170
 
@@ -267,6 +276,39 @@ export class RPCTranslator {
267
276
  ]);
268
277
  }
269
278
 
279
+ async txeGetPrivateEvents(
280
+ foreignSelector: ForeignCallSingle,
281
+ foreignContractAddress: ForeignCallSingle,
282
+ foreignScope: ForeignCallSingle,
283
+ ) {
284
+ const selector = EventSelector.fromField(fromSingle(foreignSelector));
285
+ const contractAddress = addressFromSingle(foreignContractAddress);
286
+ const scope = addressFromSingle(foreignScope);
287
+
288
+ const events = await this.handlerAsTxe().txeGetPrivateEvents(selector, contractAddress, scope);
289
+
290
+ if (events.length > MAX_PRIVATE_EVENTS_PER_TXE_QUERY) {
291
+ throw new Error(`Array of length ${events.length} larger than maxLen ${MAX_PRIVATE_EVENTS_PER_TXE_QUERY}`);
292
+ }
293
+
294
+ if (events.some(e => e.length > MAX_EVENT_LEN)) {
295
+ throw new Error(`Some private event has length larger than maxLen ${MAX_EVENT_LEN}`);
296
+ }
297
+
298
+ // This is a workaround as Noir does not currently let us return nested structs with arrays. We instead return a raw
299
+ // multidimensional array in get_private_events_oracle and create the BoundedVecs here.
300
+ const rawArrayStorage = events
301
+ .map(e => e.concat(Array(MAX_EVENT_LEN - e.length).fill(new Fr(0))))
302
+ .concat(Array(MAX_PRIVATE_EVENTS_PER_TXE_QUERY - events.length).fill(Array(MAX_EVENT_LEN).fill(new Fr(0))))
303
+ .flat();
304
+ const eventLengths = events
305
+ .map(e => new Fr(e.length))
306
+ .concat(Array(MAX_PRIVATE_EVENTS_PER_TXE_QUERY - events.length).fill(new Fr(0)));
307
+ const queryLength = new Fr(events.length);
308
+
309
+ return toForeignCallResult([toArray(rawArrayStorage), toArray(eventLengths), toSingle(queryLength)]);
310
+ }
311
+
270
312
  privateStoreInExecutionCache(foreignValues: ForeignCallArray, foreignHash: ForeignCallSingle) {
271
313
  const values = fromArray(foreignValues);
272
314
  const hash = fromSingle(foreignHash);
@@ -580,8 +622,8 @@ export class RPCTranslator {
580
622
  return toForeignCallResult([toSingle(new Fr(isRevertible))]);
581
623
  }
582
624
 
583
- async utilityGetUtilityContext() {
584
- const context = await this.handlerAsUtility().utilityGetUtilityContext();
625
+ utilityGetUtilityContext() {
626
+ const context = this.handlerAsUtility().utilityGetUtilityContext();
585
627
 
586
628
  return toForeignCallResult(context.toNoirRepresentation());
587
629
  }