@aztec/txe 3.0.3 → 3.9.9-nightly.20260312

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 (75) 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 +85 -52
  7. package/dest/oracle/interfaces.d.ts +9 -6
  8. package/dest/oracle/interfaces.d.ts.map +1 -1
  9. package/dest/oracle/txe_oracle_public_context.d.ts +4 -4
  10. package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
  11. package/dest/oracle/txe_oracle_public_context.js +9 -11
  12. package/dest/oracle/txe_oracle_top_level_context.d.ts +21 -13
  13. package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
  14. package/dest/oracle/txe_oracle_top_level_context.js +180 -72
  15. package/dest/rpc_translator.d.ts +29 -17
  16. package/dest/rpc_translator.d.ts.map +1 -1
  17. package/dest/rpc_translator.js +124 -57
  18. package/dest/state_machine/archiver.d.ts +20 -55
  19. package/dest/state_machine/archiver.d.ts.map +1 -1
  20. package/dest/state_machine/archiver.js +67 -108
  21. package/dest/state_machine/dummy_p2p_client.d.ts +20 -15
  22. package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
  23. package/dest/state_machine/dummy_p2p_client.js +42 -25
  24. package/dest/state_machine/global_variable_builder.d.ts +4 -3
  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 +7 -7
  28. package/dest/state_machine/index.d.ts.map +1 -1
  29. package/dest/state_machine/index.js +41 -24
  30. package/dest/state_machine/mock_epoch_cache.d.ts +9 -6
  31. package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
  32. package/dest/state_machine/mock_epoch_cache.js +14 -7
  33. package/dest/state_machine/synchronizer.d.ts +3 -3
  34. package/dest/state_machine/synchronizer.d.ts.map +1 -1
  35. package/dest/txe_session.d.ts +22 -11
  36. package/dest/txe_session.d.ts.map +1 -1
  37. package/dest/txe_session.js +154 -49
  38. package/dest/util/encoding.d.ts +617 -18
  39. package/dest/util/encoding.d.ts.map +1 -1
  40. package/dest/util/txe_account_store.d.ts +10 -0
  41. package/dest/util/txe_account_store.d.ts.map +1 -0
  42. package/dest/util/{txe_account_data_provider.js → txe_account_store.js} +1 -1
  43. package/dest/util/txe_public_contract_data_source.d.ts +5 -6
  44. package/dest/util/txe_public_contract_data_source.d.ts.map +1 -1
  45. package/dest/util/txe_public_contract_data_source.js +12 -29
  46. package/dest/utils/block_creation.d.ts +18 -4
  47. package/dest/utils/block_creation.d.ts.map +1 -1
  48. package/dest/utils/block_creation.js +37 -3
  49. package/dest/utils/tx_effect_creation.d.ts +2 -3
  50. package/dest/utils/tx_effect_creation.d.ts.map +1 -1
  51. package/dest/utils/tx_effect_creation.js +3 -6
  52. package/package.json +16 -16
  53. package/src/constants.ts +3 -0
  54. package/src/index.ts +97 -60
  55. package/src/oracle/interfaces.ts +11 -4
  56. package/src/oracle/txe_oracle_public_context.ts +9 -16
  57. package/src/oracle/txe_oracle_top_level_context.ts +223 -110
  58. package/src/rpc_translator.ts +141 -58
  59. package/src/state_machine/archiver.ts +61 -129
  60. package/src/state_machine/dummy_p2p_client.ts +58 -33
  61. package/src/state_machine/global_variable_builder.ts +19 -2
  62. package/src/state_machine/index.ts +61 -22
  63. package/src/state_machine/mock_epoch_cache.ts +15 -11
  64. package/src/state_machine/synchronizer.ts +2 -2
  65. package/src/txe_session.ts +213 -94
  66. package/src/util/{txe_account_data_provider.ts → txe_account_store.ts} +1 -1
  67. package/src/util/txe_public_contract_data_source.ts +16 -42
  68. package/src/utils/block_creation.ts +47 -14
  69. package/src/utils/tx_effect_creation.ts +3 -11
  70. package/dest/util/txe_account_data_provider.d.ts +0 -10
  71. package/dest/util/txe_account_data_provider.d.ts.map +0 -1
  72. package/dest/util/txe_contract_data_provider.d.ts +0 -12
  73. package/dest/util/txe_contract_data_provider.d.ts.map +0 -1
  74. package/dest/util/txe_contract_data_provider.js +0 -22
  75. package/src/util/txe_contract_data_provider.ts +0 -36
@@ -8,29 +8,34 @@ import { ORACLE_VERSION, enrichPublicSimulationError } from '@aztec/pxe/server';
8
8
  import { ExecutionNoteCache, ExecutionTaggingIndexCache, HashedValuesCache, Oracle, PrivateExecutionOracle, UtilityExecutionOracle, executePrivateFunction, generateSimulatedProvingResult } from '@aztec/pxe/simulator';
9
9
  import { ExecutionError, WASMSimulator, createSimulationError, extractCallStack, resolveAssertionMessageFromError, toACVMWitness, witnessMapToFields } from '@aztec/simulator/client';
10
10
  import { CppPublicTxSimulator, GuardedMerkleTreeOperations, PublicContractsDB, PublicProcessor } from '@aztec/simulator/server';
11
- import { FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
11
+ import { FunctionCall, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
12
12
  import { AuthWitness } from '@aztec/stdlib/auth-witness';
13
13
  import { PublicSimulatorConfig } from '@aztec/stdlib/avm';
14
14
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
15
- import { Body, L2Block } from '@aztec/stdlib/block';
16
15
  import { computePartialAddress } from '@aztec/stdlib/contract';
17
16
  import { Gas, GasFees, GasSettings } from '@aztec/stdlib/gas';
18
17
  import { computeCalldataHash, computeProtocolNullifier, siloNullifier } from '@aztec/stdlib/hash';
19
18
  import { PartialPrivateTailPublicInputsForPublic, PrivateKernelTailCircuitPublicInputs, PrivateToPublicAccumulatedData, PublicCallRequest } from '@aztec/stdlib/kernel';
20
19
  import { ChonkProof } from '@aztec/stdlib/proofs';
21
- import { makeAppendOnlyTreeSnapshot, makeGlobalVariables } from '@aztec/stdlib/testing';
20
+ import { makeGlobalVariables } from '@aztec/stdlib/testing';
22
21
  import { MerkleTreeId } from '@aztec/stdlib/trees';
23
22
  import { CallContext, HashedValues, PrivateExecutionResult, Tx, TxConstantData, TxContext, TxEffect, TxHash, collectNested } from '@aztec/stdlib/tx';
24
23
  import { ForkCheckpoint } from '@aztec/world-state';
24
+ import { DEFAULT_ADDRESS } from '../constants.js';
25
25
  import { TXEPublicContractDataSource } from '../util/txe_public_contract_data_source.js';
26
- import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlockHeader } from '../utils/block_creation.js';
26
+ import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlock } from '../utils/block_creation.js';
27
27
  export class TXEOracleTopLevelContext {
28
28
  stateMachine;
29
- contractDataProvider;
29
+ contractStore;
30
+ noteStore;
30
31
  keyStore;
31
- addressDataProvider;
32
- accountDataProvider;
33
- pxeOracleInterface;
32
+ addressStore;
33
+ accountStore;
34
+ senderTaggingStore;
35
+ recipientTaggingStore;
36
+ senderAddressBookStore;
37
+ capsuleStore;
38
+ privateEventStore;
34
39
  nextBlockTimestamp;
35
40
  version;
36
41
  chainId;
@@ -38,13 +43,18 @@ export class TXEOracleTopLevelContext {
38
43
  isMisc;
39
44
  isTxe;
40
45
  logger;
41
- constructor(stateMachine, contractDataProvider, keyStore, addressDataProvider, accountDataProvider, pxeOracleInterface, nextBlockTimestamp, version, chainId, authwits){
46
+ constructor(stateMachine, contractStore, noteStore, keyStore, addressStore, accountStore, senderTaggingStore, recipientTaggingStore, senderAddressBookStore, capsuleStore, privateEventStore, nextBlockTimestamp, version, chainId, authwits){
42
47
  this.stateMachine = stateMachine;
43
- this.contractDataProvider = contractDataProvider;
48
+ this.contractStore = contractStore;
49
+ this.noteStore = noteStore;
44
50
  this.keyStore = keyStore;
45
- this.addressDataProvider = addressDataProvider;
46
- this.accountDataProvider = accountDataProvider;
47
- this.pxeOracleInterface = pxeOracleInterface;
51
+ this.addressStore = addressStore;
52
+ this.accountStore = accountStore;
53
+ this.senderTaggingStore = senderTaggingStore;
54
+ this.recipientTaggingStore = recipientTaggingStore;
55
+ this.senderAddressBookStore = senderAddressBookStore;
56
+ this.capsuleStore = capsuleStore;
57
+ this.privateEventStore = privateEventStore;
48
58
  this.nextBlockTimestamp = nextBlockTimestamp;
49
59
  this.version = version;
50
60
  this.chainId = chainId;
@@ -65,14 +75,18 @@ export class TXEOracleTopLevelContext {
65
75
  return Fr.random();
66
76
  }
67
77
  // We instruct users to debug contracts via this oracle, so it makes sense that they'd expect it to also work in tests
68
- utilityDebugLog(level, message, fields) {
78
+ utilityLog(level, message, fields) {
69
79
  if (!LogLevels[level]) {
70
- throw new Error(`Invalid debug log level: ${level}`);
80
+ throw new Error(`Invalid log level: ${level}`);
71
81
  }
72
82
  const levelName = LogLevels[level];
73
83
  this.logger[levelName](`${applyStringFormatting(message, fields)}`, {
74
84
  module: `${this.logger.module}:debug_log`
75
85
  });
86
+ return Promise.resolve();
87
+ }
88
+ txeGetDefaultAddress() {
89
+ return DEFAULT_ADDRESS;
76
90
  }
77
91
  async txeGetNextBlockNumber() {
78
92
  return BlockNumber(await this.getLastBlockNumber() + 1);
@@ -84,7 +98,8 @@ export class TXEOracleTopLevelContext {
84
98
  return (await this.stateMachine.node.getBlockHeader('latest')).globalVariables.timestamp;
85
99
  }
86
100
  async txeGetLastTxEffects() {
87
- const block = await this.stateMachine.archiver.getBlock('latest');
101
+ const latestBlockNumber = await this.stateMachine.archiver.getBlockNumber();
102
+ const block = await this.stateMachine.archiver.getBlock(latestBlockNumber);
88
103
  if (block.body.txEffects.length != 1) {
89
104
  // Note that calls like env.mine() will result in blocks with no transactions, hitting this
90
105
  throw new Error(`Expected a single transaction in the last block, found ${block.body.txEffects.length}`);
@@ -96,6 +111,28 @@ export class TXEOracleTopLevelContext {
96
111
  nullifiers: txEffects.nullifiers
97
112
  };
98
113
  }
114
+ async syncContractNonOracleMethod(contractAddress, scope, jobId) {
115
+ if (contractAddress.equals(DEFAULT_ADDRESS)) {
116
+ this.logger.debug(`Skipping sync in txeGetPrivateEvents because the events correspond to the default address.`);
117
+ return;
118
+ }
119
+ const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
120
+ await this.stateMachine.contractSyncService.ensureContractSynced(contractAddress, null, async (call, execScopes)=>{
121
+ await this.executeUtilityCall(call, execScopes, jobId);
122
+ }, blockHeader, jobId, [
123
+ scope
124
+ ]);
125
+ }
126
+ async txeGetPrivateEvents(selector, contractAddress, scope) {
127
+ return (await this.privateEventStore.getPrivateEvents(selector, {
128
+ contractAddress,
129
+ scopes: [
130
+ scope
131
+ ],
132
+ fromBlock: 0,
133
+ toBlock: await this.getLastBlockNumber() + 1
134
+ })).map((e)=>e.packedEvent);
135
+ }
99
136
  async txeAdvanceBlocksBy(blocks) {
100
137
  this.logger.debug(`time traveling ${blocks} blocks`);
101
138
  for(let i = 0; i < blocks; i++){
@@ -116,32 +153,32 @@ export class TXEOracleTopLevelContext {
116
153
  if (!secret.equals(Fr.ZERO)) {
117
154
  await this.txeAddAccount(artifact, instance, secret);
118
155
  } else {
119
- await this.contractDataProvider.addContractInstance(instance);
120
- await this.contractDataProvider.addContractArtifact(instance.currentContractClassId, artifact);
156
+ await this.contractStore.addContractInstance(instance);
157
+ await this.contractStore.addContractArtifact(artifact);
121
158
  this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
122
159
  }
123
160
  }
124
161
  async txeAddAccount(artifact, instance, secret) {
125
162
  const partialAddress = await computePartialAddress(instance);
126
163
  this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
127
- await this.contractDataProvider.addContractInstance(instance);
128
- await this.contractDataProvider.addContractArtifact(instance.currentContractClassId, artifact);
164
+ await this.contractStore.addContractInstance(instance);
165
+ await this.contractStore.addContractArtifact(artifact);
129
166
  const completeAddress = await this.keyStore.addAccount(secret, partialAddress);
130
- await this.accountDataProvider.setAccount(completeAddress.address, completeAddress);
131
- await this.addressDataProvider.addCompleteAddress(completeAddress);
167
+ await this.accountStore.setAccount(completeAddress.address, completeAddress);
168
+ await this.addressStore.addCompleteAddress(completeAddress);
132
169
  this.logger.debug(`Created account ${completeAddress.address}`);
133
170
  return completeAddress;
134
171
  }
135
172
  async txeCreateAccount(secret) {
136
- // This is a footgun !
173
+ // This is a foot gun !
137
174
  const completeAddress = await this.keyStore.addAccount(secret, secret);
138
- await this.accountDataProvider.setAccount(completeAddress.address, completeAddress);
139
- await this.addressDataProvider.addCompleteAddress(completeAddress);
175
+ await this.accountStore.setAccount(completeAddress.address, completeAddress);
176
+ await this.addressStore.addCompleteAddress(completeAddress);
140
177
  this.logger.debug(`Created account ${completeAddress.address}`);
141
178
  return completeAddress;
142
179
  }
143
180
  async txeAddAuthWitness(address, messageHash) {
144
- const account = await this.accountDataProvider.getAccount(address);
181
+ const account = await this.accountStore.getAccount(address);
145
182
  const privateKey = await this.keyStore.getMasterSecretKey(account.publicKeys.masterIncomingViewingPublicKey);
146
183
  const schnorr = new Schnorr();
147
184
  const signature = await schnorr.constructSignature(messageHash.toBuffer(), privateKey);
@@ -160,42 +197,85 @@ export class TXEOracleTopLevelContext {
160
197
  txEffect.txHash = new TxHash(new Fr(blockNumber));
161
198
  const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
162
199
  await insertTxEffectIntoWorldTrees(txEffect, forkedWorldTrees);
163
- const block = new L2Block(makeAppendOnlyTreeSnapshot(), await makeTXEBlockHeader(forkedWorldTrees, makeGlobalVariables(undefined, {
200
+ const globals = makeGlobalVariables(undefined, {
164
201
  blockNumber,
165
202
  timestamp: this.nextBlockTimestamp,
166
203
  version: this.version,
167
204
  chainId: this.chainId
168
- })), new Body([
205
+ });
206
+ const block = await makeTXEBlock(forkedWorldTrees, globals, [
169
207
  txEffect
170
- ]));
208
+ ]);
171
209
  await forkedWorldTrees.close();
172
210
  this.logger.info(`Created block ${blockNumber} with timestamp ${block.header.globalVariables.timestamp}`);
173
211
  await this.stateMachine.handleL2Block(block);
174
212
  }
175
- async txePrivateCallNewFlow(from, targetContractAddress = AztecAddress.zero(), functionSelector = FunctionSelector.empty(), args, argsHash = Fr.zero(), isStaticCall = false) {
176
- this.logger.verbose(`Executing external function ${await this.contractDataProvider.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`);
177
- const artifact = await this.contractDataProvider.getFunctionArtifact(targetContractAddress, functionSelector);
213
+ async txePrivateCallNewFlow(from, targetContractAddress = AztecAddress.zero(), functionSelector = FunctionSelector.empty(), args, argsHash = Fr.zero(), isStaticCall = false, jobId) {
214
+ this.logger.verbose(`Executing external function ${await this.contractStore.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`);
215
+ const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
178
216
  if (!artifact) {
179
217
  const message = functionSelector.equals(await FunctionSelector.fromSignature('verify_private_authwit(Field)')) ? 'Found no account contract artifact for a private authwit check - use `create_contract_account` instead of `create_light_account` for authwit support.' : 'Function Artifact does not exist';
180
218
  throw new Error(message);
181
219
  }
220
+ // When `from` is the zero address (e.g. when deploying a new account contract), we return an
221
+ // empty scope list which acts as deny-all: no notes are visible and no keys are accessible.
222
+ const effectiveScopes = from.isZero() ? [] : [
223
+ from
224
+ ];
225
+ // Sync notes before executing private function to discover notes from previous transactions
226
+ const utilityExecutor = async (call, execScopes)=>{
227
+ await this.executeUtilityCall(call, execScopes, jobId);
228
+ };
229
+ const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
230
+ await this.stateMachine.contractSyncService.ensureContractSynced(targetContractAddress, functionSelector, utilityExecutor, blockHeader, jobId, effectiveScopes);
182
231
  const blockNumber = await this.txeGetNextBlockNumber();
183
232
  const callContext = new CallContext(from, targetContractAddress, functionSelector, isStaticCall);
184
233
  const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
185
234
  const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
186
235
  const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
187
236
  const txContext = new TxContext(this.chainId, this.version, gasSettings);
188
- const blockHeader = await this.pxeOracleInterface.getAnchorBlockHeader();
189
237
  const protocolNullifier = await computeProtocolNullifier(getSingleTxBlockRequestHash(blockNumber));
190
238
  const noteCache = new ExecutionNoteCache(protocolNullifier);
239
+ // In production, the account contract sets the min revertible counter before calling the app function.
240
+ // Since TXE bypasses the account contract, we simulate this by setting minRevertibleSideEffectCounter to 1,
241
+ // marking all side effects as revertible.
242
+ const minRevertibleSideEffectCounter = 1;
243
+ await noteCache.setMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter);
191
244
  const taggingIndexCache = new ExecutionTaggingIndexCache();
192
245
  const simulator = new WASMSimulator();
193
- const privateExecutionOracle = new PrivateExecutionOracle(argsHash, txContext, callContext, /** Header of a block whose state is used during private execution (not the block the transaction is included in). */ blockHeader, /** List of transient auth witnesses to be used during this simulation */ Array.from(this.authwits.values()), /** List of transient auth witnesses to be used during this simulation */ [], HashedValuesCache.create([
194
- new HashedValues(args, argsHash)
195
- ]), noteCache, taggingIndexCache, this.pxeOracleInterface, 0, 1, undefined, undefined, /**
196
- * In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
197
- * contract would perform, including setting senderForTags.
198
- */ from, simulator);
246
+ const privateExecutionOracle = new PrivateExecutionOracle({
247
+ argsHash,
248
+ txContext,
249
+ callContext,
250
+ anchorBlockHeader: blockHeader,
251
+ utilityExecutor,
252
+ authWitnesses: Array.from(this.authwits.values()),
253
+ capsules: [],
254
+ executionCache: HashedValuesCache.create([
255
+ new HashedValues(args, argsHash)
256
+ ]),
257
+ noteCache,
258
+ taggingIndexCache,
259
+ contractStore: this.contractStore,
260
+ noteStore: this.noteStore,
261
+ keyStore: this.keyStore,
262
+ addressStore: this.addressStore,
263
+ aztecNode: this.stateMachine.node,
264
+ senderTaggingStore: this.senderTaggingStore,
265
+ recipientTaggingStore: this.recipientTaggingStore,
266
+ senderAddressBookStore: this.senderAddressBookStore,
267
+ capsuleStore: this.capsuleStore,
268
+ privateEventStore: this.privateEventStore,
269
+ contractSyncService: this.stateMachine.contractSyncService,
270
+ jobId,
271
+ totalPublicCalldataCount: 0,
272
+ sideEffectCounter: minRevertibleSideEffectCounter,
273
+ scopes: effectiveScopes,
274
+ // In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
275
+ // contract would perform, including setting senderForTags.
276
+ senderForTags: from,
277
+ simulator
278
+ });
199
279
  // 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.
200
280
  let result;
201
281
  let executionResult;
@@ -210,18 +290,16 @@ export class TXEOracleTopLevelContext {
210
290
  const calldata = await privateExecutionOracle.privateLoadFromExecutionCache(r.calldataHash);
211
291
  return new HashedValues(calldata, r.calldataHash);
212
292
  }));
213
- // TXE's top level context does not track side effect counters, and as such, minRevertibleSideEffectCounter is always 0.
214
- // This has the unfortunate consequence of always producing revertible nullifiers, which means we
215
- // must set the firstNullifierHint to Fr.ZERO so the txRequestHash is always used as nonce generator
216
- result = new PrivateExecutionResult(executionResult, Fr.ZERO, publicFunctionsCalldata);
293
+ noteCache.finish();
294
+ const nonceGenerator = noteCache.getNonceGenerator();
295
+ result = new PrivateExecutionResult(executionResult, nonceGenerator, publicFunctionsCalldata);
217
296
  } catch (err) {
218
297
  throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during private execution'));
219
298
  }
220
- // According to the protocol rules, the nonce generator for the note hashes
221
- // can either be the first nullifier in the tx or the hash of the initial tx request
222
- // if there are none.
223
- const nonceGenerator = result.firstNullifier.equals(Fr.ZERO) ? protocolNullifier : result.firstNullifier;
224
- const { publicInputs } = await generateSimulatedProvingResult(result, nonceGenerator, this.contractDataProvider);
299
+ // According to the protocol rules, there must be at least one nullifier in the tx. The first nullifier is used as
300
+ // the nonce generator for the note hashes.
301
+ // We pass the non-zero minRevertibleSideEffectCounter to make sure the side effects are split correctly.
302
+ const { publicInputs } = await generateSimulatedProvingResult(result, (addr, sel)=>this.contractStore.getDebugFunctionName(addr, sel), this.stateMachine.node, minRevertibleSideEffectCounter);
225
303
  const globals = makeGlobalVariables();
226
304
  globals.blockNumber = blockNumber;
227
305
  globals.timestamp = this.nextBlockTimestamp;
@@ -229,7 +307,8 @@ export class TXEOracleTopLevelContext {
229
307
  globals.version = this.version;
230
308
  globals.gasFees = GasFees.empty();
231
309
  const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
232
- const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(blockNumber, this.contractDataProvider));
310
+ const bindings = this.logger.getBindings();
311
+ const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(blockNumber, this.contractStore), bindings);
233
312
  const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
234
313
  const config = PublicSimulatorConfig.from({
235
314
  skipFeeEnforcement: true,
@@ -238,7 +317,7 @@ export class TXEOracleTopLevelContext {
238
317
  collectStatistics: false,
239
318
  collectCallMetadata: true
240
319
  });
241
- const processor = new PublicProcessor(globals, guardedMerkleTrees, contractsDB, new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config), new TestDateProvider());
320
+ const processor = new PublicProcessor(globals, guardedMerkleTrees, contractsDB, new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings), new TestDateProvider(), undefined, createLogger('simulator:public-processor', bindings));
242
321
  const tx = await Tx.create({
243
322
  data: publicInputs,
244
323
  chonkProof: ChonkProof.empty(),
@@ -259,7 +338,7 @@ export class TXEOracleTopLevelContext {
259
338
  } else if (!processedTx.revertCode.isOK()) {
260
339
  if (processedTx.revertReason) {
261
340
  try {
262
- await enrichPublicSimulationError(processedTx.revertReason, this.contractDataProvider, this.logger);
341
+ await enrichPublicSimulationError(processedTx.revertReason, this.contractStore, this.logger);
263
342
  // eslint-disable-next-line no-empty
264
343
  } catch {}
265
344
  throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
@@ -281,22 +360,21 @@ export class TXEOracleTopLevelContext {
281
360
  txEffect.txHash = new TxHash(new Fr(blockNumber));
282
361
  const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
283
362
  await forkedWorldTrees.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
284
- const body = new Body([
363
+ const l2Block = await makeTXEBlock(forkedWorldTrees, globals, [
285
364
  txEffect
286
365
  ]);
287
- const l2Block = new L2Block(makeAppendOnlyTreeSnapshot(), await makeTXEBlockHeader(forkedWorldTrees, globals), body);
288
366
  await this.stateMachine.handleL2Block(l2Block);
289
367
  await forkedWorldTrees.close();
290
368
  return executionResult.returnValues ?? [];
291
369
  }
292
370
  async txePublicCallNewFlow(from, targetContractAddress, calldata, isStaticCall) {
293
- this.logger.verbose(`Executing public function ${await this.contractDataProvider.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`);
371
+ this.logger.verbose(`Executing public function ${await this.contractStore.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`);
294
372
  const blockNumber = await this.txeGetNextBlockNumber();
295
373
  const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
296
374
  const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
297
375
  const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
298
376
  const txContext = new TxContext(this.chainId, this.version, gasSettings);
299
- const anchorBlockHeader = await this.pxeOracleInterface.getAnchorBlockHeader();
377
+ const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
300
378
  const calldataHash = await computeCalldataHash(calldata);
301
379
  const calldataHashedValues = new HashedValues(calldata, calldataHash);
302
380
  const globals = makeGlobalVariables();
@@ -306,7 +384,8 @@ export class TXEOracleTopLevelContext {
306
384
  globals.version = this.version;
307
385
  globals.gasFees = GasFees.empty();
308
386
  const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
309
- const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(blockNumber, this.contractDataProvider));
387
+ const bindings2 = this.logger.getBindings();
388
+ const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(blockNumber, this.contractStore), bindings2);
310
389
  const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
311
390
  const config = PublicSimulatorConfig.from({
312
391
  skipFeeEnforcement: true,
@@ -315,8 +394,8 @@ export class TXEOracleTopLevelContext {
315
394
  collectStatistics: false,
316
395
  collectCallMetadata: true
317
396
  });
318
- const simulator = new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config);
319
- const processor = new PublicProcessor(globals, guardedMerkleTrees, contractsDB, simulator, new TestDateProvider());
397
+ const simulator = new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings2);
398
+ const processor = new PublicProcessor(globals, guardedMerkleTrees, contractsDB, simulator, new TestDateProvider(), undefined, createLogger('simulator:public-processor', bindings2));
320
399
  // We're simulating a scenario in which private execution immediately enqueues a public call and halts. The private
321
400
  // kernel init would in this case inject a nullifier with the transaction request hash as a non-revertible
322
401
  // side-effect, which the AVM then expects to exist in order to use it as the nonce generator when siloing notes as
@@ -329,7 +408,7 @@ export class TXEOracleTopLevelContext {
329
408
  revertibleAccumulatedData.publicCallRequests[0] = new PublicCallRequest(from, targetContractAddress, isStaticCall, calldataHash);
330
409
  const inputsForPublic = new PartialPrivateTailPublicInputsForPublic(nonRevertibleAccumulatedData, revertibleAccumulatedData, PublicCallRequest.empty());
331
410
  const constantData = new TxConstantData(anchorBlockHeader, txContext, Fr.zero(), Fr.zero());
332
- const txData = new PrivateKernelTailCircuitPublicInputs(constantData, /*gasUsed=*/ new Gas(0, 0), /*feePayer=*/ AztecAddress.zero(), /*includeByTimestamp=*/ 0n, inputsForPublic, undefined);
411
+ const txData = new PrivateKernelTailCircuitPublicInputs(constantData, /*gasUsed=*/ new Gas(0, 0), /*feePayer=*/ AztecAddress.zero(), /*expirationTimestamp=*/ 0n, inputsForPublic, undefined);
333
412
  const tx = await Tx.create({
334
413
  data: txData,
335
414
  chonkProof: ChonkProof.empty(),
@@ -352,7 +431,7 @@ export class TXEOracleTopLevelContext {
352
431
  } else if (!processedTx.revertCode.isOK()) {
353
432
  if (processedTx.revertReason) {
354
433
  try {
355
- await enrichPublicSimulationError(processedTx.revertReason, this.contractDataProvider, this.logger);
434
+ await enrichPublicSimulationError(processedTx.revertReason, this.contractStore, this.logger);
356
435
  // eslint-disable-next-line no-empty
357
436
  } catch {}
358
437
  throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
@@ -375,25 +454,37 @@ export class TXEOracleTopLevelContext {
375
454
  txEffect.txHash = new TxHash(new Fr(blockNumber));
376
455
  const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
377
456
  await forkedWorldTrees.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
378
- const body = new Body([
457
+ const l2Block = await makeTXEBlock(forkedWorldTrees, globals, [
379
458
  txEffect
380
459
  ]);
381
- const l2Block = new L2Block(makeAppendOnlyTreeSnapshot(), await makeTXEBlockHeader(forkedWorldTrees, globals), body);
382
460
  await this.stateMachine.handleL2Block(l2Block);
383
461
  await forkedWorldTrees.close();
384
462
  return returnValues ?? [];
385
463
  }
386
- async txeSimulateUtilityFunction(targetContractAddress, functionSelector, args) {
387
- const artifact = await this.contractDataProvider.getFunctionArtifact(targetContractAddress, functionSelector);
464
+ async txeExecuteUtilityFunction(targetContractAddress, functionSelector, args, jobId) {
465
+ const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
388
466
  if (!artifact) {
389
467
  throw new Error(`Cannot call ${functionSelector} as there is no artifact found at ${targetContractAddress}.`);
390
468
  }
391
- const call = {
469
+ // Sync notes before executing utility function to discover notes from previous transactions
470
+ const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
471
+ await this.stateMachine.contractSyncService.ensureContractSynced(targetContractAddress, functionSelector, async (call, execScopes)=>{
472
+ await this.executeUtilityCall(call, execScopes, jobId);
473
+ }, blockHeader, jobId, 'ALL_SCOPES');
474
+ const call = FunctionCall.from({
392
475
  name: artifact.name,
476
+ to: targetContractAddress,
393
477
  selector: functionSelector,
394
- to: targetContractAddress
395
- };
396
- const entryPointArtifact = await this.pxeOracleInterface.getFunctionArtifact(call.to, call.selector);
478
+ type: FunctionType.UTILITY,
479
+ hideMsgSender: false,
480
+ isStatic: false,
481
+ args,
482
+ returnTypes: []
483
+ });
484
+ return this.executeUtilityCall(call, 'ALL_SCOPES', jobId);
485
+ }
486
+ async executeUtilityCall(call, scopes, jobId) {
487
+ const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
397
488
  if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
398
489
  throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
399
490
  }
@@ -402,8 +493,25 @@ export class TXEOracleTopLevelContext {
402
493
  selector: call.selector
403
494
  });
404
495
  try {
405
- const oracle = new UtilityExecutionOracle(call.to, [], [], this.pxeOracleInterface);
406
- const acirExecutionResult = await new WASMSimulator().executeUserCircuit(toACVMWitness(0, args), entryPointArtifact, new Oracle(oracle).toACIRCallback()).catch((err)=>{
496
+ const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
497
+ const oracle = new UtilityExecutionOracle({
498
+ contractAddress: call.to,
499
+ authWitnesses: [],
500
+ capsules: [],
501
+ anchorBlockHeader,
502
+ contractStore: this.contractStore,
503
+ noteStore: this.noteStore,
504
+ keyStore: this.keyStore,
505
+ addressStore: this.addressStore,
506
+ aztecNode: this.stateMachine.node,
507
+ recipientTaggingStore: this.recipientTaggingStore,
508
+ senderAddressBookStore: this.senderAddressBookStore,
509
+ capsuleStore: this.capsuleStore,
510
+ privateEventStore: this.privateEventStore,
511
+ jobId,
512
+ scopes
513
+ });
514
+ const acirExecutionResult = await new WASMSimulator().executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback()).catch((err)=>{
407
515
  err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
408
516
  throw new ExecutionError(err.message, {
409
517
  contractAddress: call.to,
@@ -412,10 +520,10 @@ export class TXEOracleTopLevelContext {
412
520
  cause: err
413
521
  });
414
522
  });
415
- this.logger.verbose(`Utility simulation for ${call.to}.${call.selector} completed`);
523
+ this.logger.verbose(`Utility execution for ${call.to}.${call.selector} completed`);
416
524
  return witnessMapToFields(acirExecutionResult.returnWitness);
417
525
  } catch (err) {
418
- throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility simulation'));
526
+ throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility execution'));
419
527
  }
420
528
  }
421
529
  close() {