@aztec/txe 0.0.1-commit.a5db02d → 0.0.1-commit.aa0c64f

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/AuthRegistry-QVGDDH5X.js +3 -0
  2. package/dest/{AuthRegistry-56AMRLSQ.js.map → AuthRegistry-QVGDDH5X.js.map} +2 -2
  3. package/dest/ContractClassRegistry-VWR3F42P.js +3 -0
  4. package/dest/ContractClassRegistry-VWR3F42P.js.map +7 -0
  5. package/dest/{ContractInstanceRegistry-NADDSLGL.js → ContractInstanceRegistry-FHIWE33X.js} +1 -1
  6. package/dest/{ContractInstanceRegistry-NADDSLGL.js.map → ContractInstanceRegistry-FHIWE33X.js.map} +2 -2
  7. package/dest/FeeJuice-SAOWVGG7.js +3 -0
  8. package/dest/FeeJuice-SAOWVGG7.js.map +7 -0
  9. package/dest/HandshakeRegistry-GY5CPEPS.js +3 -0
  10. package/dest/HandshakeRegistry-GY5CPEPS.js.map +7 -0
  11. package/dest/{MultiCallEntrypoint-MIDICLQB.js → MultiCallEntrypoint-QG5H33ZZ.js} +1 -1
  12. package/dest/{MultiCallEntrypoint-MIDICLQB.js.map → MultiCallEntrypoint-QG5H33ZZ.js.map} +2 -2
  13. package/dest/SchnorrAccount-NME3E45O.js +3 -0
  14. package/dest/SchnorrAccount-NME3E45O.js.map +7 -0
  15. package/dest/SchnorrInitializerlessAccount-WTGXU6SW.js +3 -0
  16. package/dest/SchnorrInitializerlessAccount-WTGXU6SW.js.map +7 -0
  17. package/dest/bin/check_txe_oracle_version.js +7 -15
  18. package/dest/bin/index.js +1 -1
  19. package/dest/chunk-2XE2OXLY.js +260 -0
  20. package/dest/chunk-2XE2OXLY.js.map +7 -0
  21. package/dest/chunk-32UHX7YY.js +3 -0
  22. package/dest/{chunk-RELAEYUE.js → chunk-543AD4I4.js} +2 -2
  23. package/dest/metafile.json +1451 -2657
  24. package/dest/oracle/interfaces.d.ts +2 -2
  25. package/dest/oracle/interfaces.d.ts.map +1 -1
  26. package/dest/oracle/test-resolver/default_fixtures.d.ts +9 -2
  27. package/dest/oracle/test-resolver/default_fixtures.d.ts.map +1 -1
  28. package/dest/oracle/test-resolver/default_fixtures.js +32 -39
  29. package/dest/oracle/test-resolver/resolver.d.ts +1 -1
  30. package/dest/oracle/test-resolver/resolver.d.ts.map +1 -1
  31. package/dest/oracle/test-resolver/resolver.js +2 -2
  32. package/dest/oracle/txe_oracle_registry.d.ts +3 -3
  33. package/dest/oracle/txe_oracle_registry.d.ts.map +1 -1
  34. package/dest/oracle/txe_oracle_registry.js +37 -27
  35. package/dest/oracle/txe_oracle_top_level_context.d.ts +2 -2
  36. package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
  37. package/dest/oracle/txe_oracle_top_level_context.js +352 -264
  38. package/dest/oracle/txe_oracle_version.d.ts +3 -3
  39. package/dest/oracle/txe_oracle_version.js +3 -3
  40. package/dest/rpc_translator.js +1 -1
  41. package/dest/server.bundle.js +1 -1
  42. package/dest/state_machine/synchronizer.d.ts +6 -1
  43. package/dest/state_machine/synchronizer.d.ts.map +1 -1
  44. package/dest/state_machine/synchronizer.js +12 -3
  45. package/dest/txe_session.d.ts +3 -3
  46. package/dest/txe_session.d.ts.map +1 -1
  47. package/dest/txe_session.js +10 -2
  48. package/dest/worker.bundle.js +1 -1
  49. package/package.json +17 -17
  50. package/src/bin/check_txe_oracle_version.ts +9 -12
  51. package/src/oracle/interfaces.ts +1 -1
  52. package/src/oracle/test-resolver/default_fixtures.ts +58 -69
  53. package/src/oracle/test-resolver/resolver.ts +2 -2
  54. package/src/oracle/txe_oracle_registry.ts +38 -25
  55. package/src/oracle/txe_oracle_top_level_context.ts +27 -20
  56. package/src/oracle/txe_oracle_version.ts +3 -3
  57. package/src/rpc_translator.ts +1 -1
  58. package/src/state_machine/synchronizer.ts +18 -3
  59. package/src/txe_session.ts +10 -2
  60. package/dest/AuthRegistry-56AMRLSQ.js +0 -3
  61. package/dest/ContractClassRegistry-N6NA3SFA.js +0 -3
  62. package/dest/ContractClassRegistry-N6NA3SFA.js.map +0 -7
  63. package/dest/FeeJuice-QBH5JWJV.js +0 -3
  64. package/dest/FeeJuice-QBH5JWJV.js.map +0 -7
  65. package/dest/HandshakeRegistry-D2W3AOPD.js +0 -3
  66. package/dest/HandshakeRegistry-D2W3AOPD.js.map +0 -7
  67. package/dest/SchnorrAccount-HNL7EN7Y.js +0 -3
  68. package/dest/SchnorrAccount-HNL7EN7Y.js.map +0 -7
  69. package/dest/SchnorrInitializerlessAccount-TFAFXZW6.js +0 -3
  70. package/dest/SchnorrInitializerlessAccount-TFAFXZW6.js.map +0 -7
  71. package/dest/chunk-BJVAAXNA.js +0 -3
  72. package/dest/chunk-EKHK6CRD.js +0 -268
  73. package/dest/chunk-EKHK6CRD.js.map +0 -7
  74. /package/dest/{chunk-BJVAAXNA.js.map → chunk-32UHX7YY.js.map} +0 -0
  75. /package/dest/{chunk-RELAEYUE.js.map → chunk-543AD4I4.js.map} +0 -0
@@ -1,3 +1,68 @@
1
+ function _ts_add_disposable_resource(env, value, async) {
2
+ if (value !== null && value !== void 0) {
3
+ if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
4
+ var dispose, inner;
5
+ if (async) {
6
+ if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
7
+ dispose = value[Symbol.asyncDispose];
8
+ }
9
+ if (dispose === void 0) {
10
+ if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
11
+ dispose = value[Symbol.dispose];
12
+ if (async) inner = dispose;
13
+ }
14
+ if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
15
+ if (inner) dispose = function() {
16
+ try {
17
+ inner.call(this);
18
+ } catch (e) {
19
+ return Promise.reject(e);
20
+ }
21
+ };
22
+ env.stack.push({
23
+ value: value,
24
+ dispose: dispose,
25
+ async: async
26
+ });
27
+ } else if (async) {
28
+ env.stack.push({
29
+ async: true
30
+ });
31
+ }
32
+ return value;
33
+ }
34
+ function _ts_dispose_resources(env) {
35
+ var _SuppressedError = typeof SuppressedError === "function" ? SuppressedError : function(error, suppressed, message) {
36
+ var e = new Error(message);
37
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
38
+ };
39
+ return (_ts_dispose_resources = function _ts_dispose_resources(env) {
40
+ function fail(e) {
41
+ env.error = env.hasError ? new _SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
42
+ env.hasError = true;
43
+ }
44
+ var r, s = 0;
45
+ function next() {
46
+ while(r = env.stack.pop()){
47
+ try {
48
+ if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
49
+ if (r.dispose) {
50
+ var result = r.dispose.call(r.value);
51
+ if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) {
52
+ fail(e);
53
+ return next();
54
+ });
55
+ } else s |= 1;
56
+ } catch (e) {
57
+ fail(e);
58
+ }
59
+ }
60
+ if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
61
+ if (env.hasError) throw env.error;
62
+ }
63
+ return next();
64
+ })(env);
65
+ }
1
66
  import { CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS, MAX_PRIVATE_LOGS_PER_TX, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/constants';
2
67
  import { BlockNumber } from '@aztec/foundation/branded-types';
3
68
  import { Schnorr } from '@aztec/foundation/crypto/schnorr';
@@ -7,7 +72,7 @@ import { TestDateProvider } from '@aztec/foundation/timer';
7
72
  import { AnchoredContractData, CapsuleService, FactService, ORACLE_VERSION_MAJOR, composeHooks, enrichPublicSimulationError } from '@aztec/pxe/server';
8
73
  import { CONTRACT_INSTANCE, ExecutionNoteCache, ExecutionTaggingIndexCache, HashedValuesCache, PrivateExecutionOracle, TransientArrayService, UtilityExecutionOracle, buildACIRCallback, executePrivateFunction, generateSimulatedProvingResult } from '@aztec/pxe/simulator';
9
74
  import { ExecutionError, WASMSimulator, createSimulationError, extractCallStack, resolveAssertionMessageFromError, toACVMWitness, witnessMapToFields } from '@aztec/simulator/client';
10
- import { CppPublicTxSimulator, GuardedMerkleTreeOperations, PublicContractsDB, PublicProcessor } from '@aztec/simulator/server';
75
+ import { GuardedMerkleTreeOperations, PublicContractsDB, PublicProcessor, PublicTxSimulator } from '@aztec/simulator/server';
11
76
  import { FunctionCall, FunctionSelector, FunctionType } from '@aztec/stdlib/abi';
12
77
  import { AuthWitness } from '@aztec/stdlib/auth-witness';
13
78
  import { PublicSimulatorConfig } from '@aztec/stdlib/avm';
@@ -237,9 +302,8 @@ export class TXEOracleTopLevelContext {
237
302
  this.logger.debug(`Created account ${completeAddress.address}`);
238
303
  return completeAddress;
239
304
  }
240
- async createAccount(secret) {
241
- // This is a foot gun !
242
- const completeAddress = await this.keyStore.addAccount(await deriveKeys(secret), secret);
305
+ async createAccount(secret, partialAddress) {
306
+ const completeAddress = await this.keyStore.addAccount(await deriveKeys(secret), partialAddress);
243
307
  await this.accountStore.setAccount(completeAddress.address, completeAddress);
244
308
  await this.addressStore.addCompleteAddress(completeAddress);
245
309
  this.logger.debug(`Created account ${completeAddress.address}`);
@@ -304,277 +368,302 @@ export class TXEOracleTopLevelContext {
304
368
  await this.stateMachine.handleL2Block(block, options.l1ToL2Messages ?? []);
305
369
  }
306
370
  async privateCallNewFlow(from, targetContractAddress = AztecAddress.zero(), functionSelector = FunctionSelector.empty(), args, argsHash = Fr.zero(), isStaticCall = false, additionalScopes = [], jobId, authorizedUtilityCallTargets, gasSettings) {
307
- const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
308
- const anchoredContractData = new AnchoredContractData(this.contractStore, this.stateMachine.contractClassService, blockHeader);
309
- this.logger.verbose(`Executing external function ${await anchoredContractData.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`);
310
- const artifact = await anchoredContractData.getFunctionArtifact(targetContractAddress, functionSelector);
311
- if (!artifact) {
312
- 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';
313
- throw new Error(message);
314
- }
315
- const scopes = from === undefined ? additionalScopes : [
316
- from,
317
- ...additionalScopes
318
- ];
319
- // Sync notes before executing private function to discover notes from previous transactions
320
- const utilityExecutor = async (call, execScopes)=>{
321
- await this.executeUtilityCall(call, {
322
- scopes: execScopes,
323
- jobId
324
- });
371
+ const env = {
372
+ stack: [],
373
+ error: void 0,
374
+ hasError: false
325
375
  };
326
- await this.stateMachine.contractSyncService.ensureContractSynced(targetContractAddress, functionSelector, utilityExecutor, blockHeader, jobId, scopes);
327
- const blockNumber = await this.getNextBlockNumber();
328
- const msgSender = from ?? AztecAddress.NULL_MSG_SENDER;
329
- const callContext = new CallContext(msgSender, targetContractAddress, functionSelector, isStaticCall);
330
- const txContext = new TxContext(this.chainId, this.version, gasSettings);
331
- const protocolNullifier = await computeProtocolNullifier(getSingleTxBlockRequestHash(blockNumber));
332
- const noteCache = new ExecutionNoteCache(protocolNullifier);
333
- // In production, the account contract sets the min revertible counter before calling the app function.
334
- // Since TXE bypasses the account contract, we simulate this by setting minRevertibleSideEffectCounter to 1,
335
- // marking all side effects as revertible.
336
- const minRevertibleSideEffectCounter = 1;
337
- await noteCache.setMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter);
338
- const taggingIndexCache = new ExecutionTaggingIndexCache();
339
- const simulator = new WASMSimulator();
340
- const transientArrayService = new TransientArrayService();
341
- const privateExecutionOracle = new PrivateExecutionOracle({
342
- argsHash,
343
- txContext,
344
- // The TXE does not run the init kernel's salt binding, so no tx-request salt is in scope.
345
- txRequestSalt: Fr.ZERO,
346
- callContext,
347
- anchorBlockHeader: blockHeader,
348
- utilityExecutor,
349
- authWitnesses: Array.from(this.authwits.values()),
350
- capsules: [],
351
- executionCache: HashedValuesCache.create([
352
- new HashedValues(args, argsHash)
353
- ]),
354
- noteCache,
355
- taggingIndexCache,
356
- anchoredContractData,
357
- noteStore: this.noteStore,
358
- keyStore: this.keyStore,
359
- addressStore: this.addressStore,
360
- aztecNode: this.stateMachine.node,
361
- senderTaggingStore: this.senderTaggingStore,
362
- recipientTaggingStore: this.recipientTaggingStore,
363
- taggingSecretSourcesStore: this.taggingSecretSourcesStore,
364
- capsuleService: new CapsuleService(this.capsuleStore, scopes),
365
- factService: new FactService(this.factStore, scopes),
366
- privateEventStore: this.privateEventStore,
367
- contractSyncService: this.stateMachine.contractSyncService,
368
- jobId,
369
- totalPublicCalldataCount: 0,
370
- sideEffectCounter: minRevertibleSideEffectCounter,
371
- scopes,
372
- // In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
373
- // contract would perform, including setting senderForTags.
374
- senderForTags: from,
375
- simulator,
376
- txResolver: this.stateMachine.txResolver,
377
- l2TipsStore: this.stateMachine.l2TipsProvider,
378
- hooks: composeHooks({
379
- authorizeUtilityCall: this.buildAuthorizeUtilityCallHook(isStaticCall ? 'private view' : 'private', authorizedUtilityCallTargets),
380
- resolveTaggingSecretStrategy: makeResolveTaggingSecretStrategyHook(this.taggingSecretStrategies)
381
- }),
382
- transientArrayService
383
- });
384
- // 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.
385
- let result;
386
- let executionResult;
387
376
  try {
388
- executionResult = await executePrivateFunction(simulator, privateExecutionOracle, artifact, targetContractAddress, functionSelector);
389
- const publicCallRequests = collectNested([
377
+ const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
378
+ const anchoredContractData = new AnchoredContractData(this.contractStore, this.stateMachine.contractClassService, blockHeader);
379
+ this.logger.verbose(`Executing external function ${await anchoredContractData.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`);
380
+ const artifact = await anchoredContractData.getFunctionArtifact(targetContractAddress, functionSelector);
381
+ if (!artifact) {
382
+ 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';
383
+ throw new Error(message);
384
+ }
385
+ const scopes = from === undefined ? additionalScopes : [
386
+ from,
387
+ ...additionalScopes
388
+ ];
389
+ // Sync notes before executing private function to discover notes from previous transactions
390
+ const utilityExecutor = async (call, execScopes)=>{
391
+ await this.executeUtilityCall(call, {
392
+ scopes: execScopes,
393
+ jobId
394
+ });
395
+ };
396
+ await this.stateMachine.contractSyncService.ensureContractSynced(targetContractAddress, functionSelector, utilityExecutor, blockHeader, jobId, scopes);
397
+ const blockNumber = await this.getNextBlockNumber();
398
+ const msgSender = from ?? AztecAddress.NULL_MSG_SENDER;
399
+ const callContext = new CallContext(msgSender, targetContractAddress, functionSelector, isStaticCall);
400
+ const txContext = new TxContext(this.chainId, this.version, gasSettings);
401
+ const protocolNullifier = await computeProtocolNullifier(getSingleTxBlockRequestHash(blockNumber));
402
+ const noteCache = new ExecutionNoteCache(protocolNullifier);
403
+ // In production, the account contract sets the min revertible counter before calling the app function.
404
+ // Since TXE bypasses the account contract, we simulate this by setting minRevertibleSideEffectCounter to 1,
405
+ // marking all side effects as revertible.
406
+ const minRevertibleSideEffectCounter = 1;
407
+ await noteCache.setMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter);
408
+ const taggingIndexCache = new ExecutionTaggingIndexCache();
409
+ const simulator = new WASMSimulator();
410
+ const transientArrayService = new TransientArrayService();
411
+ const privateExecutionOracle = new PrivateExecutionOracle({
412
+ argsHash,
413
+ txContext,
414
+ txRequestSalt: Fr.ZERO,
415
+ callContext,
416
+ anchorBlockHeader: blockHeader,
417
+ utilityExecutor,
418
+ authWitnesses: Array.from(this.authwits.values()),
419
+ capsules: [],
420
+ executionCache: HashedValuesCache.create([
421
+ new HashedValues(args, argsHash)
422
+ ]),
423
+ noteCache,
424
+ taggingIndexCache,
425
+ anchoredContractData,
426
+ noteStore: this.noteStore,
427
+ keyStore: this.keyStore,
428
+ addressStore: this.addressStore,
429
+ aztecNode: this.stateMachine.node,
430
+ senderTaggingStore: this.senderTaggingStore,
431
+ recipientTaggingStore: this.recipientTaggingStore,
432
+ taggingSecretSourcesStore: this.taggingSecretSourcesStore,
433
+ capsuleService: new CapsuleService(this.capsuleStore, scopes),
434
+ factService: new FactService(this.factStore, scopes),
435
+ privateEventStore: this.privateEventStore,
436
+ contractSyncService: this.stateMachine.contractSyncService,
437
+ jobId,
438
+ totalPublicCalldataCount: 0,
439
+ sideEffectCounter: minRevertibleSideEffectCounter,
440
+ scopes,
441
+ // In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
442
+ // contract would perform, including setting senderForTags.
443
+ senderForTags: from,
444
+ simulator,
445
+ txResolver: this.stateMachine.txResolver,
446
+ l2TipsStore: this.stateMachine.l2TipsProvider,
447
+ hooks: composeHooks({
448
+ authorizeUtilityCall: this.buildAuthorizeUtilityCallHook(isStaticCall ? 'private view' : 'private', authorizedUtilityCallTargets),
449
+ resolveTaggingSecretStrategy: makeResolveTaggingSecretStrategyHook(this.taggingSecretStrategies)
450
+ }),
451
+ transientArrayService
452
+ });
453
+ // 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.
454
+ let result;
455
+ let executionResult;
456
+ try {
457
+ executionResult = await executePrivateFunction(simulator, privateExecutionOracle, artifact, targetContractAddress, functionSelector);
458
+ const publicCallRequests = collectNested([
459
+ executionResult
460
+ ], (r)=>r.publicInputs.publicCallRequests.getActiveItems().map((r)=>r.inner).concat(r.publicInputs.publicTeardownCallRequest.isEmpty() ? [] : [
461
+ r.publicInputs.publicTeardownCallRequest
462
+ ]));
463
+ const publicFunctionsCalldata = await Promise.all(publicCallRequests.map(async (r)=>{
464
+ const calldata = await privateExecutionOracle.getHashPreimage(r.calldataHash);
465
+ return new HashedValues(calldata, r.calldataHash);
466
+ }));
467
+ const nonceGenerator = noteCache.getNonceGenerator();
468
+ result = new PrivateExecutionResult(executionResult, nonceGenerator, publicFunctionsCalldata);
469
+ } catch (err) {
470
+ throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during private execution'));
471
+ }
472
+ // According to the protocol rules, there must be at least one nullifier in the tx. The first nullifier is used as
473
+ // the nonce generator for the note hashes.
474
+ // We pass the non-zero minRevertibleSideEffectCounter to make sure the side effects are split correctly.
475
+ const { publicInputs } = await generateSimulatedProvingResult(result, (addr, sel)=>anchoredContractData.getDebugFunctionName(addr, sel), this.stateMachine.node, minRevertibleSideEffectCounter);
476
+ const globals = makeGlobalVariables();
477
+ globals.blockNumber = blockNumber;
478
+ globals.timestamp = this.nextBlockTimestamp;
479
+ globals.chainId = this.chainId;
480
+ globals.version = this.version;
481
+ globals.gasFees = GasFees.empty();
482
+ const forkedWorldTrees = _ts_add_disposable_resource(env, await this.stateMachine.synchronizer.nativeWorldStateService.fork(), true);
483
+ const bindings = this.logger.getBindings();
484
+ const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(blockNumber, this.contractStore), bindings);
485
+ const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
486
+ const config = PublicSimulatorConfig.from({
487
+ skipFeeEnforcement: true,
488
+ collectDebugLogs: true,
489
+ collectHints: false,
490
+ collectStatistics: false,
491
+ collectCallMetadata: true
492
+ });
493
+ // The AVM simulator reads this fork's contracts DB, scoped by fork id, for each simulation.
494
+ const forkId = forkedWorldTrees.getRevision().forkId;
495
+ const processor = new PublicProcessor(globals, guardedMerkleTrees, contractsDB, new PublicTxSimulator(this.stateMachine.synchronizer.avmSimulator, globals, contractsDB, forkId, config, bindings), new TestDateProvider(), undefined, createLogger('simulator:public-processor', bindings));
496
+ const tx = await Tx.create({
497
+ data: publicInputs,
498
+ chonkProof: ChonkProof.empty(),
499
+ contractClassLogFields: [],
500
+ publicFunctionCalldata: result.publicFunctionCalldata
501
+ });
502
+ let checkpoint;
503
+ if (isStaticCall) {
504
+ checkpoint = await ForkCheckpoint.new(forkedWorldTrees);
505
+ }
506
+ const results = await processor.process([
507
+ tx
508
+ ]);
509
+ const [processedTx] = results[0];
510
+ const failedTxs = results[1];
511
+ if (failedTxs.length !== 0) {
512
+ throw new Error(`Public execution has failed: ${failedTxs[0].error}`);
513
+ } else if (!processedTx.revertCode.isOK()) {
514
+ if (processedTx.revertReason) {
515
+ try {
516
+ await enrichPublicSimulationError(processedTx.revertReason, this.contractStore, this.stateMachine.contractClassService, await this.stateMachine.anchorBlockStore.getBlockHeader(), this.logger);
517
+ // eslint-disable-next-line no-empty
518
+ } catch {}
519
+ throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
520
+ } else {
521
+ throw new Error('Contract execution has reverted');
522
+ }
523
+ }
524
+ // Walk the nested private-call tree and collect every offchain effect the transaction emitted.
525
+ // PXE stores these on each `PrivateCallExecutionResult` and they never reach TXE via the
526
+ // `aztec_utl_emitOffchainEffect` foreign-call path (that path only fires at the top-level), so
527
+ // we pull them out here and the RPC wrapper will hand them to `TXESession` for buffering.
528
+ const offchainEffects = collectNested([
390
529
  executionResult
391
- ], (r)=>r.publicInputs.publicCallRequests.getActiveItems().map((r)=>r.inner).concat(r.publicInputs.publicTeardownCallRequest.isEmpty() ? [] : [
392
- r.publicInputs.publicTeardownCallRequest
393
- ]));
394
- const publicFunctionsCalldata = await Promise.all(publicCallRequests.map(async (r)=>{
395
- const calldata = await privateExecutionOracle.getHashPreimage(r.calldataHash);
396
- return new HashedValues(calldata, r.calldataHash);
397
- }));
398
- const nonceGenerator = noteCache.getNonceGenerator();
399
- result = new PrivateExecutionResult(executionResult, nonceGenerator, publicFunctionsCalldata);
400
- } catch (err) {
401
- throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during private execution'));
402
- }
403
- // According to the protocol rules, there must be at least one nullifier in the tx. The first nullifier is used as
404
- // the nonce generator for the note hashes.
405
- // We pass the non-zero minRevertibleSideEffectCounter to make sure the side effects are split correctly.
406
- const { publicInputs } = await generateSimulatedProvingResult(result, (addr, sel)=>anchoredContractData.getDebugFunctionName(addr, sel), this.stateMachine.node, minRevertibleSideEffectCounter);
407
- const globals = makeGlobalVariables();
408
- globals.blockNumber = blockNumber;
409
- globals.timestamp = this.nextBlockTimestamp;
410
- globals.chainId = this.chainId;
411
- globals.version = this.version;
412
- globals.gasFees = GasFees.empty();
413
- const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
414
- const bindings = this.logger.getBindings();
415
- const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(blockNumber, this.contractStore), bindings);
416
- const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
417
- const config = PublicSimulatorConfig.from({
418
- skipFeeEnforcement: true,
419
- collectDebugLogs: true,
420
- collectHints: false,
421
- collectStatistics: false,
422
- collectCallMetadata: true
423
- });
424
- const processor = new PublicProcessor(globals, guardedMerkleTrees, contractsDB, new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings), new TestDateProvider(), undefined, createLogger('simulator:public-processor', bindings));
425
- const tx = await Tx.create({
426
- data: publicInputs,
427
- chonkProof: ChonkProof.empty(),
428
- contractClassLogFields: [],
429
- publicFunctionCalldata: result.publicFunctionCalldata
430
- });
431
- let checkpoint;
432
- if (isStaticCall) {
433
- checkpoint = await ForkCheckpoint.new(forkedWorldTrees);
434
- }
435
- const results = await processor.process([
436
- tx
437
- ]);
438
- const [processedTx] = results[0];
439
- const failedTxs = results[1];
440
- if (failedTxs.length !== 0) {
441
- throw new Error(`Public execution has failed: ${failedTxs[0].error}`);
442
- } else if (!processedTx.revertCode.isOK()) {
443
- if (processedTx.revertReason) {
444
- try {
445
- await enrichPublicSimulationError(processedTx.revertReason, this.contractStore, this.stateMachine.contractClassService, await this.stateMachine.anchorBlockStore.getBlockHeader(), this.logger);
446
- // eslint-disable-next-line no-empty
447
- } catch {}
448
- throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
449
- } else {
450
- throw new Error('Contract execution has reverted');
530
+ ], (r)=>r.offchainEffects.map((e)=>e.data));
531
+ if (isStaticCall) {
532
+ await checkpoint.revert();
533
+ return {
534
+ returnValues: executionResult.returnValues ?? [],
535
+ offchainEffects
536
+ };
451
537
  }
452
- }
453
- // Walk the nested private-call tree and collect every offchain effect the transaction emitted.
454
- // PXE stores these on each `PrivateCallExecutionResult` and they never reach TXE via the
455
- // `aztec_utl_emitOffchainEffect` foreign-call path (that path only fires at the top-level), so
456
- // we pull them out here and the RPC wrapper will hand them to `TXESession` for buffering.
457
- const offchainEffects = collectNested([
458
- executionResult
459
- ], (r)=>r.offchainEffects.map((e)=>e.data));
460
- if (isStaticCall) {
461
- await checkpoint.revert();
462
- await forkedWorldTrees.close();
538
+ const txEffect = TxEffect.empty();
539
+ txEffect.noteHashes = processedTx.txEffect.noteHashes;
540
+ txEffect.nullifiers = processedTx.txEffect.nullifiers;
541
+ txEffect.privateLogs = processedTx.txEffect.privateLogs;
542
+ txEffect.publicLogs = processedTx.txEffect.publicLogs;
543
+ txEffect.publicDataWrites = processedTx.txEffect.publicDataWrites;
544
+ txEffect.txHash = new TxHash(new Fr(blockNumber));
545
+ const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
546
+ await forkedWorldTrees.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
547
+ const l2Block = await makeTXEBlock(forkedWorldTrees, globals, [
548
+ txEffect
549
+ ]);
550
+ await this.stateMachine.handleL2Block(l2Block);
463
551
  return {
464
552
  returnValues: executionResult.returnValues ?? [],
465
553
  offchainEffects
466
554
  };
555
+ } catch (e) {
556
+ env.error = e;
557
+ env.hasError = true;
558
+ } finally{
559
+ const result = _ts_dispose_resources(env);
560
+ if (result) await result;
467
561
  }
468
- const txEffect = TxEffect.empty();
469
- txEffect.noteHashes = processedTx.txEffect.noteHashes;
470
- txEffect.nullifiers = processedTx.txEffect.nullifiers;
471
- txEffect.privateLogs = processedTx.txEffect.privateLogs;
472
- txEffect.publicLogs = processedTx.txEffect.publicLogs;
473
- txEffect.publicDataWrites = processedTx.txEffect.publicDataWrites;
474
- txEffect.txHash = new TxHash(new Fr(blockNumber));
475
- const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
476
- await forkedWorldTrees.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
477
- const l2Block = await makeTXEBlock(forkedWorldTrees, globals, [
478
- txEffect
479
- ]);
480
- await this.stateMachine.handleL2Block(l2Block);
481
- await forkedWorldTrees.close();
482
- return {
483
- returnValues: executionResult.returnValues ?? [],
484
- offchainEffects
485
- };
486
562
  }
487
563
  async publicCallNewFlow(from, targetContractAddress, calldata, isStaticCall, gasSettings) {
488
- const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
489
- const anchoredContractData = new AnchoredContractData(this.contractStore, this.stateMachine.contractClassService, anchorBlockHeader);
490
- this.logger.verbose(`Executing public function ${await anchoredContractData.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`);
491
- const blockNumber = await this.getNextBlockNumber();
492
- const txContext = new TxContext(this.chainId, this.version, gasSettings);
493
- const calldataHash = await computeCalldataHash(calldata);
494
- const calldataHashedValues = new HashedValues(calldata, calldataHash);
495
- const globals = makeGlobalVariables();
496
- globals.blockNumber = blockNumber;
497
- globals.timestamp = this.nextBlockTimestamp;
498
- globals.chainId = this.chainId;
499
- globals.version = this.version;
500
- globals.gasFees = GasFees.empty();
501
- const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
502
- const bindings2 = this.logger.getBindings();
503
- const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(blockNumber, this.contractStore), bindings2);
504
- const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
505
- const config = PublicSimulatorConfig.from({
506
- skipFeeEnforcement: true,
507
- collectDebugLogs: true,
508
- collectHints: false,
509
- collectStatistics: false,
510
- collectCallMetadata: true
511
- });
512
- const simulator = new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings2);
513
- const processor = new PublicProcessor(globals, guardedMerkleTrees, contractsDB, simulator, new TestDateProvider(), undefined, createLogger('simulator:public-processor', bindings2));
514
- // We're simulating a scenario in which private execution immediately enqueues a public call and halts. The private
515
- // kernel init would in this case inject a nullifier with the transaction request hash as a non-revertible
516
- // side-effect, which the AVM then expects to exist in order to use it as the nonce generator when siloing notes as
517
- // unique.
518
- const nonRevertibleAccumulatedData = PrivateToPublicAccumulatedData.empty();
519
- nonRevertibleAccumulatedData.nullifiers[0] = getSingleTxBlockRequestHash(blockNumber);
520
- // The enqueued public call itself we make be revertible so that the public execution is itself revertible, as tests
521
- // may require producing reverts.
522
- const revertibleAccumulatedData = PrivateToPublicAccumulatedData.empty();
523
- revertibleAccumulatedData.publicCallRequests[0] = new PublicCallRequest(from ?? AztecAddress.NULL_MSG_SENDER, targetContractAddress, isStaticCall, calldataHash);
524
- const inputsForPublic = new PartialPrivateTailPublicInputsForPublic(nonRevertibleAccumulatedData, revertibleAccumulatedData, PublicCallRequest.empty());
525
- const constantData = new TxConstantData(anchorBlockHeader, txContext, Fr.zero(), Fr.zero());
526
- const txData = new PrivateKernelTailCircuitPublicInputs(constantData, /*gasUsed=*/ new Gas(0, 0), /*feePayer=*/ AztecAddress.zero(), /*expirationTimestamp=*/ 0n, inputsForPublic, undefined);
527
- const tx = await Tx.create({
528
- data: txData,
529
- chonkProof: ChonkProof.empty(),
530
- contractClassLogFields: [],
531
- publicFunctionCalldata: [
532
- calldataHashedValues
533
- ]
534
- });
535
- let checkpoint;
536
- if (isStaticCall) {
537
- checkpoint = await ForkCheckpoint.new(forkedWorldTrees);
538
- }
539
- const results = await processor.process([
540
- tx
541
- ]);
542
- const [processedTx] = results[0];
543
- const failedTxs = results[1];
544
- if (failedTxs.length !== 0) {
545
- throw new Error(`Public execution has failed: ${failedTxs[0].error}`);
546
- } else if (!processedTx.revertCode.isOK()) {
547
- if (processedTx.revertReason) {
548
- try {
549
- await enrichPublicSimulationError(processedTx.revertReason, this.contractStore, this.stateMachine.contractClassService, anchorBlockHeader, this.logger);
550
- // eslint-disable-next-line no-empty
551
- } catch {}
552
- throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
553
- } else {
554
- throw new Error('Contract execution has reverted');
564
+ const env = {
565
+ stack: [],
566
+ error: void 0,
567
+ hasError: false
568
+ };
569
+ try {
570
+ const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
571
+ const anchoredContractData = new AnchoredContractData(this.contractStore, this.stateMachine.contractClassService, anchorBlockHeader);
572
+ this.logger.verbose(`Executing public function ${await anchoredContractData.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`);
573
+ const blockNumber = await this.getNextBlockNumber();
574
+ const txContext = new TxContext(this.chainId, this.version, gasSettings);
575
+ const calldataHash = await computeCalldataHash(calldata);
576
+ const calldataHashedValues = new HashedValues(calldata, calldataHash);
577
+ const globals = makeGlobalVariables();
578
+ globals.blockNumber = blockNumber;
579
+ globals.timestamp = this.nextBlockTimestamp;
580
+ globals.chainId = this.chainId;
581
+ globals.version = this.version;
582
+ globals.gasFees = GasFees.empty();
583
+ const forkedWorldTrees = _ts_add_disposable_resource(env, await this.stateMachine.synchronizer.nativeWorldStateService.fork(), true);
584
+ const bindings2 = this.logger.getBindings();
585
+ const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(blockNumber, this.contractStore), bindings2);
586
+ const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
587
+ const config = PublicSimulatorConfig.from({
588
+ skipFeeEnforcement: true,
589
+ collectDebugLogs: true,
590
+ collectHints: false,
591
+ collectStatistics: false,
592
+ collectCallMetadata: true
593
+ });
594
+ // The AVM simulator reads this fork's contracts DB, scoped by fork id, for each simulation.
595
+ const forkId2 = forkedWorldTrees.getRevision().forkId;
596
+ const simulator = new PublicTxSimulator(this.stateMachine.synchronizer.avmSimulator, globals, contractsDB, forkId2, config, bindings2);
597
+ const processor = new PublicProcessor(globals, guardedMerkleTrees, contractsDB, simulator, new TestDateProvider(), undefined, createLogger('simulator:public-processor', bindings2));
598
+ // We're simulating a scenario in which private execution immediately enqueues a public call and halts. The private
599
+ // kernel init would in this case inject a nullifier with the transaction request hash as a non-revertible
600
+ // side-effect, which the AVM then expects to exist in order to use it as the nonce generator when siloing notes as
601
+ // unique.
602
+ const nonRevertibleAccumulatedData = PrivateToPublicAccumulatedData.empty();
603
+ nonRevertibleAccumulatedData.nullifiers[0] = getSingleTxBlockRequestHash(blockNumber);
604
+ // The enqueued public call itself we make be revertible so that the public execution is itself revertible, as tests
605
+ // may require producing reverts.
606
+ const revertibleAccumulatedData = PrivateToPublicAccumulatedData.empty();
607
+ revertibleAccumulatedData.publicCallRequests[0] = new PublicCallRequest(from ?? AztecAddress.NULL_MSG_SENDER, targetContractAddress, isStaticCall, calldataHash);
608
+ const inputsForPublic = new PartialPrivateTailPublicInputsForPublic(nonRevertibleAccumulatedData, revertibleAccumulatedData, PublicCallRequest.empty());
609
+ const constantData = new TxConstantData(anchorBlockHeader, txContext, Fr.zero(), Fr.zero());
610
+ const txData = new PrivateKernelTailCircuitPublicInputs(constantData, /*gasUsed=*/ new Gas(0, 0), /*feePayer=*/ AztecAddress.zero(), /*expirationTimestamp=*/ 0n, inputsForPublic, undefined);
611
+ const tx = await Tx.create({
612
+ data: txData,
613
+ chonkProof: ChonkProof.empty(),
614
+ contractClassLogFields: [],
615
+ publicFunctionCalldata: [
616
+ calldataHashedValues
617
+ ]
618
+ });
619
+ let checkpoint;
620
+ if (isStaticCall) {
621
+ checkpoint = await ForkCheckpoint.new(forkedWorldTrees);
555
622
  }
556
- }
557
- const returnValues = results[3][0].values;
558
- if (isStaticCall) {
559
- await checkpoint.revert();
560
- await forkedWorldTrees.close();
623
+ const results = await processor.process([
624
+ tx
625
+ ]);
626
+ const [processedTx] = results[0];
627
+ const failedTxs = results[1];
628
+ if (failedTxs.length !== 0) {
629
+ throw new Error(`Public execution has failed: ${failedTxs[0].error}`);
630
+ } else if (!processedTx.revertCode.isOK()) {
631
+ if (processedTx.revertReason) {
632
+ try {
633
+ await enrichPublicSimulationError(processedTx.revertReason, this.contractStore, this.stateMachine.contractClassService, anchorBlockHeader, this.logger);
634
+ // eslint-disable-next-line no-empty
635
+ } catch {}
636
+ throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
637
+ } else {
638
+ throw new Error('Contract execution has reverted');
639
+ }
640
+ }
641
+ const returnValues = results[3][0].values;
642
+ if (isStaticCall) {
643
+ await checkpoint.revert();
644
+ return returnValues ?? [];
645
+ }
646
+ const txEffect = TxEffect.empty();
647
+ txEffect.noteHashes = processedTx.txEffect.noteHashes;
648
+ txEffect.nullifiers = processedTx.txEffect.nullifiers;
649
+ txEffect.privateLogs = processedTx.txEffect.privateLogs;
650
+ txEffect.publicLogs = processedTx.txEffect.publicLogs;
651
+ txEffect.publicDataWrites = processedTx.txEffect.publicDataWrites;
652
+ txEffect.txHash = new TxHash(new Fr(blockNumber));
653
+ const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
654
+ await forkedWorldTrees.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
655
+ const l2Block = await makeTXEBlock(forkedWorldTrees, globals, [
656
+ txEffect
657
+ ]);
658
+ await this.stateMachine.handleL2Block(l2Block);
561
659
  return returnValues ?? [];
660
+ } catch (e) {
661
+ env.error = e;
662
+ env.hasError = true;
663
+ } finally{
664
+ const result = _ts_dispose_resources(env);
665
+ if (result) await result;
562
666
  }
563
- const txEffect = TxEffect.empty();
564
- txEffect.noteHashes = processedTx.txEffect.noteHashes;
565
- txEffect.nullifiers = processedTx.txEffect.nullifiers;
566
- txEffect.privateLogs = processedTx.txEffect.privateLogs;
567
- txEffect.publicLogs = processedTx.txEffect.publicLogs;
568
- txEffect.publicDataWrites = processedTx.txEffect.publicDataWrites;
569
- txEffect.txHash = new TxHash(new Fr(blockNumber));
570
- const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
571
- await forkedWorldTrees.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
572
- const l2Block = await makeTXEBlock(forkedWorldTrees, globals, [
573
- txEffect
574
- ]);
575
- await this.stateMachine.handleL2Block(l2Block);
576
- await forkedWorldTrees.close();
577
- return returnValues ?? [];
578
667
  }
579
668
  async executeUtilityFunction(from, targetContractAddress, functionSelector, args, jobId, authorizedUtilityCallTargets) {
580
669
  const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
@@ -626,8 +715,7 @@ export class TXEOracleTopLevelContext {
626
715
  const utilityExecutor = async (syncCall, execScopes)=>{
627
716
  await this.executeUtilityCall(syncCall, {
628
717
  scopes: execScopes,
629
- jobId,
630
- authorizedUtilityCallTargets
718
+ jobId
631
719
  });
632
720
  };
633
721
  const oracle = new UtilityExecutionOracle({
@@ -656,10 +744,10 @@ export class TXEOracleTopLevelContext {
656
744
  jobId,
657
745
  scopes,
658
746
  simulator,
659
- utilityExecutor,
660
747
  hooks: composeHooks({
661
748
  authorizeUtilityCall: this.buildAuthorizeUtilityCallHook('utility', authorizedUtilityCallTargets)
662
749
  }),
750
+ utilityExecutor,
663
751
  // Execution-tree root (top-level utility run or contract sync): own store; nested frames inherit it.
664
752
  transientArrayService: new TransientArrayService()
665
753
  });