@aztec/txe 0.86.0 → 0.87.0

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 (37) hide show
  1. package/dest/oracle/txe_oracle.d.ts +11 -6
  2. package/dest/oracle/txe_oracle.d.ts.map +1 -1
  3. package/dest/oracle/txe_oracle.js +209 -38
  4. package/dest/state_machine/archiver.d.ts +53 -0
  5. package/dest/state_machine/archiver.d.ts.map +1 -0
  6. package/dest/state_machine/archiver.js +100 -0
  7. package/dest/state_machine/dummy_p2p_client.d.ts +48 -0
  8. package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -0
  9. package/dest/state_machine/dummy_p2p_client.js +122 -0
  10. package/dest/state_machine/global_variable_builder.d.ts +23 -0
  11. package/dest/state_machine/global_variable_builder.d.ts.map +1 -0
  12. package/dest/state_machine/global_variable_builder.js +29 -0
  13. package/dest/state_machine/index.d.ts +16 -0
  14. package/dest/state_machine/index.d.ts.map +1 -0
  15. package/dest/state_machine/index.js +48 -0
  16. package/dest/state_machine/synchronizer.d.ts +32 -0
  17. package/dest/state_machine/synchronizer.d.ts.map +1 -0
  18. package/dest/state_machine/synchronizer.js +58 -0
  19. package/dest/txe_service/txe_service.d.ts +12 -3
  20. package/dest/txe_service/txe_service.d.ts.map +1 -1
  21. package/dest/txe_service/txe_service.js +221 -37
  22. package/dest/util/encoding.d.ts +11 -4
  23. package/dest/util/encoding.d.ts.map +1 -1
  24. package/dest/util/encoding.js +38 -2
  25. package/package.json +18 -15
  26. package/src/oracle/txe_oracle.ts +387 -40
  27. package/src/state_machine/archiver.ts +132 -0
  28. package/src/state_machine/dummy_p2p_client.ts +167 -0
  29. package/src/state_machine/global_variable_builder.ts +55 -0
  30. package/src/state_machine/index.ts +71 -0
  31. package/src/state_machine/synchronizer.ts +87 -0
  32. package/src/txe_service/txe_service.ts +427 -31
  33. package/src/util/encoding.ts +51 -2
  34. package/dest/node/txe_node.d.ts +0 -320
  35. package/dest/node/txe_node.d.ts.map +0 -1
  36. package/dest/node/txe_node.js +0 -481
  37. package/src/node/txe_node.ts +0 -703
@@ -1,8 +1,15 @@
1
- import { Body, L2Block, Note } from '@aztec/aztec.js';
1
+ import { type AztecNode, Body, L2Block, Note } from '@aztec/aztec.js';
2
2
  import {
3
+ DEFAULT_GAS_LIMIT,
4
+ DEFAULT_TEARDOWN_GAS_LIMIT,
3
5
  type L1_TO_L2_MSG_TREE_HEIGHT,
6
+ MAX_CONTRACT_CLASS_LOGS_PER_TX,
7
+ MAX_ENQUEUED_CALLS_PER_TX,
8
+ MAX_L2_GAS_PER_TX_PUBLIC_PORTION,
9
+ MAX_L2_TO_L1_MSGS_PER_TX,
4
10
  MAX_NOTE_HASHES_PER_TX,
5
11
  MAX_NULLIFIERS_PER_TX,
12
+ MAX_PRIVATE_LOGS_PER_TX,
6
13
  NULLIFIER_SUBTREE_HEIGHT,
7
14
  type NULLIFIER_TREE_HEIGHT,
8
15
  NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
@@ -13,7 +20,7 @@ import { padArrayEnd } from '@aztec/foundation/collection';
13
20
  import { Aes128, Schnorr, poseidon2Hash } from '@aztec/foundation/crypto';
14
21
  import { Fr, Point } from '@aztec/foundation/fields';
15
22
  import { type Logger, applyStringFormatting } from '@aztec/foundation/log';
16
- import { Timer } from '@aztec/foundation/timer';
23
+ import { TestDateProvider, Timer } from '@aztec/foundation/timer';
17
24
  import { KeyStore } from '@aztec/key-store';
18
25
  import type { AztecAsyncKVStore } from '@aztec/kv-store';
19
26
  import type { ProtocolContract } from '@aztec/protocol-contracts';
@@ -34,8 +41,11 @@ import {
34
41
  type MessageLoadOracleInputs,
35
42
  type NoteData,
36
43
  Oracle,
44
+ PrivateExecutionOracle,
37
45
  type TypedOracle,
46
+ UtilityExecutionOracle,
38
47
  WASMSimulator,
48
+ executePrivateFunction,
39
49
  extractCallStack,
40
50
  extractPrivateCircuitPublicInputs,
41
51
  pickNotes,
@@ -46,6 +56,7 @@ import { createTxForPublicCalls } from '@aztec/simulator/public/fixtures';
46
56
  import {
47
57
  ExecutionError,
48
58
  PublicContractsDB,
59
+ PublicProcessor,
49
60
  type PublicTxResult,
50
61
  PublicTxSimulator,
51
62
  createSimulationError,
@@ -56,6 +67,7 @@ import {
56
67
  EventSelector,
57
68
  type FunctionAbi,
58
69
  FunctionSelector,
70
+ FunctionType,
59
71
  type NoteSelector,
60
72
  countArgumentsSize,
61
73
  } from '@aztec/stdlib/abi';
@@ -64,25 +76,33 @@ import { PublicDataWrite } from '@aztec/stdlib/avm';
64
76
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
65
77
  import type { ContractInstance, ContractInstanceWithAddress } from '@aztec/stdlib/contract';
66
78
  import { SimulationError } from '@aztec/stdlib/errors';
67
- import { Gas, GasFees } from '@aztec/stdlib/gas';
79
+ import { Gas, GasFees, GasSettings } from '@aztec/stdlib/gas';
68
80
  import {
69
81
  computeNoteHashNonce,
70
82
  computePublicDataTreeLeafSlot,
71
83
  computeUniqueNoteHash,
84
+ computeVarArgsHash,
72
85
  siloNoteHash,
73
86
  siloNullifier,
74
87
  } from '@aztec/stdlib/hash';
75
88
  import type { MerkleTreeReadOperations, MerkleTreeWriteOperations } from '@aztec/stdlib/interfaces/server';
76
- import { type KeyValidationRequest, PrivateContextInputs, PublicCallRequest } from '@aztec/stdlib/kernel';
77
- import { deriveKeys } from '@aztec/stdlib/keys';
78
89
  import {
79
- ContractClassLog,
80
- IndexedTaggingSecret,
81
- LogWithTxData,
82
- type PrivateLog,
83
- type PublicLog,
84
- } from '@aztec/stdlib/logs';
90
+ type KeyValidationRequest,
91
+ PartialPrivateTailPublicInputsForPublic,
92
+ PartialPrivateTailPublicInputsForRollup,
93
+ PrivateContextInputs,
94
+ PrivateKernelTailCircuitPublicInputs,
95
+ PrivateToPublicAccumulatedData,
96
+ PrivateToRollupAccumulatedData,
97
+ PublicCallRequest,
98
+ RollupValidationRequests,
99
+ ScopedLogHash,
100
+ } from '@aztec/stdlib/kernel';
101
+ import { deriveKeys } from '@aztec/stdlib/keys';
102
+ import { ContractClassLog, IndexedTaggingSecret, LogWithTxData, PrivateLog, type PublicLog } from '@aztec/stdlib/logs';
103
+ import { ScopedL2ToL1Message } from '@aztec/stdlib/messaging';
85
104
  import type { NoteStatus } from '@aztec/stdlib/note';
105
+ import { ClientIvcProof } from '@aztec/stdlib/proofs';
86
106
  import type { CircuitWitnessGenerationStats } from '@aztec/stdlib/stats';
87
107
  import {
88
108
  makeAppendOnlyTreeSnapshot,
@@ -103,13 +123,19 @@ import {
103
123
  BlockHeader,
104
124
  CallContext,
105
125
  GlobalVariables,
126
+ HashedValues,
127
+ PrivateExecutionResult,
106
128
  PublicCallRequestWithCalldata,
129
+ Tx,
130
+ TxConstantData,
131
+ TxContext,
107
132
  TxEffect,
108
133
  TxHash,
134
+ collectNested,
109
135
  } from '@aztec/stdlib/tx';
110
136
  import { ForkCheckpoint, NativeWorldStateService } from '@aztec/world-state/native';
111
137
 
112
- import { TXENode } from '../node/txe_node.js';
138
+ import { TXEStateMachine } from '../state_machine/index.js';
113
139
  import { TXEAccountDataProvider } from '../util/txe_account_data_provider.js';
114
140
  import { TXEPublicContractDataSource } from '../util/txe_public_contract_data_source.js';
115
141
 
@@ -136,11 +162,11 @@ export class TXE implements TypedOracle {
136
162
  private ROLLUP_VERSION = 1;
137
163
  private CHAIN_ID = 1;
138
164
 
139
- private node: TXENode;
165
+ private node: AztecNode;
140
166
 
141
167
  private simulationProvider = new WASMSimulator();
142
168
 
143
- private noteCache: ExecutionNoteCache;
169
+ public noteCache: ExecutionNoteCache;
144
170
 
145
171
  private authwits: Map<string, AuthWitness> = new Map();
146
172
 
@@ -159,10 +185,12 @@ export class TXE implements TypedOracle {
159
185
  private contractAddress: AztecAddress,
160
186
  private nativeWorldStateService: NativeWorldStateService,
161
187
  private baseFork: MerkleTreeWriteOperations,
188
+ private stateMachine: TXEStateMachine,
162
189
  ) {
163
190
  this.noteCache = new ExecutionNoteCache(this.getTxRequestHash());
164
191
 
165
- this.node = new TXENode(this.blockNumber, this.ROLLUP_VERSION, this.CHAIN_ID, nativeWorldStateService, baseFork);
192
+ this.node = stateMachine.node;
193
+
166
194
  // Default msg_sender (for entrypoints) is now Fr.max_value rather than 0 addr (see #7190 & #7404)
167
195
  this.msgSender = AztecAddress.fromField(Fr.MAX_FIELD_VALUE);
168
196
 
@@ -182,14 +210,16 @@ export class TXE implements TypedOracle {
182
210
 
183
211
  static async create(logger: Logger, store: AztecAsyncKVStore, protocolContracts: ProtocolContract[]) {
184
212
  const executionCache = new HashedValuesCache();
185
- const nativeWorldStateService = await NativeWorldStateService.tmp();
213
+
214
+ const stateMachine = await TXEStateMachine.create(store);
215
+ const syncDataProvider = stateMachine.syncDataProvider;
216
+ const nativeWorldStateService = stateMachine.synchronizer.nativeWorldStateService;
186
217
  const baseFork = await nativeWorldStateService.fork();
187
218
 
188
219
  const addressDataProvider = new AddressDataProvider(store);
189
220
  const privateEventDataProvider = new PrivateEventDataProvider(store);
190
221
  const contractDataProvider = new ContractDataProvider(store);
191
222
  const noteDataProvider = await NoteDataProvider.create(store);
192
- const syncDataProvider = new SyncDataProvider(store);
193
223
  const taggingDataProvider = new TaggingDataProvider(store);
194
224
  const capsuleDataProvider = new CapsuleDataProvider(store);
195
225
  const keyStore = new KeyStore(store);
@@ -217,6 +247,7 @@ export class TXE implements TypedOracle {
217
247
  await AztecAddress.random(),
218
248
  nativeWorldStateService,
219
249
  baseFork,
250
+ stateMachine,
220
251
  );
221
252
  }
222
253
 
@@ -231,11 +262,11 @@ export class TXE implements TypedOracle {
231
262
  }
232
263
 
233
264
  getChainId(): Promise<Fr> {
234
- return Promise.resolve(this.node.getChainId().then(id => new Fr(id)));
265
+ return Promise.resolve(new Fr(this.CHAIN_ID));
235
266
  }
236
267
 
237
268
  getVersion(): Promise<Fr> {
238
- return Promise.resolve(this.node.getVersion().then(v => new Fr(v)));
269
+ return Promise.resolve(new Fr(this.ROLLUP_VERSION));
239
270
  }
240
271
 
241
272
  getMsgSender() {
@@ -268,7 +299,6 @@ export class TXE implements TypedOracle {
268
299
 
269
300
  setBlockNumber(blockNumber: number) {
270
301
  this.blockNumber = blockNumber;
271
- this.node.setBlockNumber(blockNumber);
272
302
  }
273
303
 
274
304
  getContractDataProvider() {
@@ -316,8 +346,8 @@ export class TXE implements TypedOracle {
316
346
 
317
347
  const stateReference = await snap.getStateReference();
318
348
  const inputs = PrivateContextInputs.empty();
319
- inputs.txContext.chainId = new Fr(await this.node.getChainId());
320
- inputs.txContext.version = new Fr(await this.node.getVersion());
349
+ inputs.txContext.chainId = new Fr(this.CHAIN_ID);
350
+ inputs.txContext.version = new Fr(this.ROLLUP_VERSION);
321
351
  inputs.historicalHeader.globalVariables.blockNumber = new Fr(blockNumber);
322
352
  inputs.historicalHeader.state = stateReference;
323
353
  inputs.historicalHeader.lastArchive.root = Fr.fromBuffer(
@@ -381,9 +411,7 @@ export class TXE implements TypedOracle {
381
411
  addPublicLogs(logs: PublicLog[]) {
382
412
  logs.forEach(log => {
383
413
  try {
384
- // The first elt stores lengths => tag is in fields[1]
385
- const tag = log.log[1];
386
-
414
+ const tag = log.fields[0];
387
415
  this.logger.verbose(`Found tagged public log with tag ${tag.toString()} in block ${this.blockNumber}`);
388
416
  this.publicLogs.push(log);
389
417
  } catch (err) {
@@ -619,7 +647,6 @@ export class TXE implements TypedOracle {
619
647
  counter,
620
648
  );
621
649
  this.sideEffectCounter = counter + 1;
622
- return Promise.resolve();
623
650
  }
624
651
 
625
652
  async notifyNullifiedNote(innerNullifier: Fr, noteHash: Fr, counter: number) {
@@ -725,6 +752,7 @@ export class TXE implements TypedOracle {
725
752
  txEffect.noteHashes = [...uniqueNoteHashesFromPrivate, ...this.uniqueNoteHashesFromPublic];
726
753
 
727
754
  txEffect.nullifiers = [...this.siloedNullifiersFromPublic, ...this.noteCache.getAllNullifiers()];
755
+
728
756
  if (usedTxRequestHashForNonces) {
729
757
  txEffect.nullifiers.unshift(this.getTxRequestHash());
730
758
  }
@@ -732,6 +760,7 @@ export class TXE implements TypedOracle {
732
760
  txEffect.publicDataWrites = this.publicDataWrites;
733
761
  txEffect.privateLogs = this.privateLogs;
734
762
  txEffect.publicLogs = this.publicLogs;
763
+ txEffect.txHash = new TxHash(new Fr(blockNumber));
735
764
 
736
765
  const body = new Body([txEffect]);
737
766
 
@@ -771,10 +800,6 @@ export class TXE implements TypedOracle {
771
800
  }
772
801
  }
773
802
 
774
- // At this point we always have a single tx in the block so we set the tx index to 0.
775
- const txIndexInBlock = 0;
776
- await this.node.processTxEffect(blockNumber, txIndexInBlock, new TxHash(new Fr(blockNumber)), txEffect);
777
-
778
803
  const stateReference = await fork.getStateReference();
779
804
  const archiveInfo = await fork.getTreeInfo(MerkleTreeId.ARCHIVE);
780
805
  const header = new BlockHeader(
@@ -792,14 +817,7 @@ export class TXE implements TypedOracle {
792
817
 
793
818
  await fork.updateArchive(l2Block.header);
794
819
 
795
- // We've built a block with all of our state changes in a "fork".
796
- // Now emulate a "sync" to this block, by letting cpp reapply the block's
797
- // changes to the underlying unforked world state and comparing the results
798
- // against the block's state reference (which is this state reference here in the fork).
799
- // This essentially commits the state updates to the unforked state and sanity checks the roots.
800
- await this.nativeWorldStateService.handleL2BlockAndMessages(l2Block, l1ToL2Messages);
801
-
802
- await this.syncDataProvider.setHeader(header);
820
+ await this.stateMachine.handleL2Block(l2Block);
803
821
 
804
822
  this.publicDataWrites = [];
805
823
  this.privateLogs = [];
@@ -818,6 +836,61 @@ export class TXE implements TypedOracle {
818
836
  throw new Error('Method not implemented.');
819
837
  }
820
838
 
839
+ async simulateUtilityFunction(targetContractAddress: AztecAddress, functionSelector: FunctionSelector, argsHash: Fr) {
840
+ const artifact = await this.contractDataProvider.getFunctionArtifact(targetContractAddress, functionSelector);
841
+ if (!artifact) {
842
+ throw new Error(`Cannot call ${functionSelector} as there is artifact found at ${targetContractAddress}.`);
843
+ }
844
+
845
+ const call = {
846
+ name: artifact.name,
847
+ selector: functionSelector,
848
+ to: targetContractAddress,
849
+ };
850
+
851
+ const entryPointArtifact = await this.pxeOracleInterface.getFunctionArtifact(call.to, call.selector);
852
+
853
+ if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
854
+ throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
855
+ }
856
+
857
+ const oracle = new UtilityExecutionOracle(call.to, [], [], this.pxeOracleInterface, undefined, undefined);
858
+
859
+ try {
860
+ this.logger.verbose(`Executing utility function ${entryPointArtifact.name}`, {
861
+ contract: call.to,
862
+ selector: call.selector,
863
+ });
864
+
865
+ const args = await this.loadFromExecutionCache(argsHash);
866
+ const initialWitness = toACVMWitness(0, args);
867
+ const acirExecutionResult = await this.simulationProvider
868
+ .executeUserCircuit(initialWitness, entryPointArtifact, new Oracle(oracle))
869
+ .catch((err: Error) => {
870
+ err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
871
+ throw new ExecutionError(
872
+ err.message,
873
+ {
874
+ contractAddress: call.to,
875
+ functionSelector: call.selector,
876
+ },
877
+ extractCallStack(err, entryPointArtifact.debug),
878
+ { cause: err },
879
+ );
880
+ });
881
+
882
+ const returnWitness = witnessMapToFields(acirExecutionResult.returnWitness);
883
+ this.logger.verbose(`Utility simulation for ${call.to}.${call.selector} completed`);
884
+
885
+ const returnHash = await computeVarArgsHash(returnWitness);
886
+
887
+ this.storeInExecutionCache(returnWitness, returnHash);
888
+ return returnHash;
889
+ } catch (err) {
890
+ throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during private execution'));
891
+ }
892
+ }
893
+
821
894
  async callPrivateFunction(
822
895
  targetContractAddress: AztecAddress,
823
896
  functionSelector: FunctionSelector,
@@ -934,8 +1007,8 @@ export class TXE implements TypedOracle {
934
1007
  const db = this.baseFork;
935
1008
 
936
1009
  const globalVariables = GlobalVariables.empty();
937
- globalVariables.chainId = new Fr(await this.node.getChainId());
938
- globalVariables.version = new Fr(await this.node.getVersion());
1010
+ globalVariables.chainId = new Fr(this.CHAIN_ID);
1011
+ globalVariables.version = new Fr(this.ROLLUP_VERSION);
939
1012
  globalVariables.blockNumber = new Fr(this.blockNumber);
940
1013
  globalVariables.gasFees = new GasFees(1, 1);
941
1014
 
@@ -950,6 +1023,8 @@ export class TXE implements TypedOracle {
950
1023
  contractsDB,
951
1024
  globalVariables,
952
1025
  /*doMerkleOperations=*/ false,
1026
+ /*skipFeeEnforcement=*/ false,
1027
+ /*clientInitiatedSimulation=*/ true,
953
1028
  );
954
1029
 
955
1030
  const { usedTxRequestHashForNonces } = this.noteCache.finish();
@@ -1273,4 +1348,276 @@ export class TXE implements TypedOracle {
1273
1348
  txIndexInBlock,
1274
1349
  );
1275
1350
  }
1351
+
1352
+ async privateCallNewFlow(
1353
+ from: AztecAddress,
1354
+ targetContractAddress: AztecAddress = AztecAddress.zero(),
1355
+ functionSelector: FunctionSelector = FunctionSelector.empty(),
1356
+ args: Fr[],
1357
+ argsHash: Fr = Fr.zero(),
1358
+ isStaticCall: boolean = false,
1359
+ ) {
1360
+ this.logger.verbose(
1361
+ `Executing external function ${await this.getDebugFunctionName(
1362
+ targetContractAddress,
1363
+ functionSelector,
1364
+ )}@${targetContractAddress} isStaticCall=${isStaticCall}`,
1365
+ );
1366
+
1367
+ const artifact = await this.contractDataProvider.getFunctionArtifact(targetContractAddress, functionSelector);
1368
+
1369
+ if (artifact === undefined) {
1370
+ throw new Error('Function Artifact does not exist');
1371
+ }
1372
+
1373
+ const callContext = new CallContext(from, targetContractAddress, functionSelector, isStaticCall);
1374
+
1375
+ const gasLimits = new Gas(DEFAULT_GAS_LIMIT, MAX_L2_GAS_PER_TX_PUBLIC_PORTION);
1376
+
1377
+ const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_GAS_LIMIT, MAX_L2_GAS_PER_TX_PUBLIC_PORTION);
1378
+
1379
+ const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
1380
+
1381
+ const txContext = new TxContext(this.CHAIN_ID, this.ROLLUP_VERSION, gasSettings);
1382
+
1383
+ const blockHeader = await this.pxeOracleInterface.getBlockHeader();
1384
+
1385
+ const noteCache = new ExecutionNoteCache(this.getTxRequestHash());
1386
+
1387
+ const context = new PrivateExecutionOracle(
1388
+ argsHash,
1389
+ txContext,
1390
+ callContext,
1391
+ /** Header of a block whose state is used during private execution (not the block the transaction is included in). */
1392
+ blockHeader,
1393
+ /** List of transient auth witnesses to be used during this simulation */
1394
+ [],
1395
+ /** List of transient auth witnesses to be used during this simulation */
1396
+ [],
1397
+ HashedValuesCache.create(),
1398
+ noteCache,
1399
+ this.pxeOracleInterface,
1400
+ this.simulationProvider,
1401
+ 0,
1402
+ 1,
1403
+ );
1404
+
1405
+ context.storeInExecutionCache(args, argsHash);
1406
+
1407
+ // 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.
1408
+ let result;
1409
+ try {
1410
+ const executionResult = await executePrivateFunction(
1411
+ this.simulationProvider,
1412
+ context,
1413
+ artifact,
1414
+ targetContractAddress,
1415
+ functionSelector,
1416
+ );
1417
+ const { usedTxRequestHashForNonces } = noteCache.finish();
1418
+ const firstNullifierHint = usedTxRequestHashForNonces ? Fr.ZERO : noteCache.getAllNullifiers()[0];
1419
+
1420
+ const publicCallRequests = collectNested([executionResult], r => [
1421
+ ...r.publicInputs.publicCallRequests.map(r => r.inner),
1422
+ r.publicInputs.publicTeardownCallRequest,
1423
+ ]).filter(r => !r.isEmpty());
1424
+ const publicFunctionsCalldata = await Promise.all(
1425
+ publicCallRequests.map(async r => {
1426
+ const calldata = await context.loadFromExecutionCache(r.calldataHash);
1427
+ return new HashedValues(calldata, r.calldataHash);
1428
+ }),
1429
+ );
1430
+
1431
+ result = new PrivateExecutionResult(executionResult, firstNullifierHint, publicFunctionsCalldata);
1432
+ } catch (err) {
1433
+ throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during private execution'));
1434
+ }
1435
+
1436
+ const uniqueNoteHashes: Fr[] = [];
1437
+ const taggedPrivateLogs: PrivateLog[] = [];
1438
+ const nullifiers: Fr[] = result.firstNullifier.equals(Fr.ZERO)
1439
+ ? [this.getTxRequestHash()]
1440
+ : noteCache.getAllNullifiers();
1441
+ const l2ToL1Messages: ScopedL2ToL1Message[] = [];
1442
+ const contractClassLogsHashes: ScopedLogHash[] = [];
1443
+ const publicCallRequests: PublicCallRequest[] = [];
1444
+
1445
+ const nonceGenerator = nullifiers[0];
1446
+
1447
+ let publicTeardownCallRequest;
1448
+
1449
+ let noteHashIndexInTx = 0;
1450
+ const executions = [result.entrypoint];
1451
+ while (executions.length !== 0) {
1452
+ const execution = executions.shift()!;
1453
+ executions.unshift(...execution!.nestedExecutions);
1454
+
1455
+ const { contractAddress } = execution.publicInputs.callContext;
1456
+
1457
+ const noteHashesFromExecution = await Promise.all(
1458
+ execution.publicInputs.noteHashes
1459
+ .filter(noteHash => !noteHash.isEmpty())
1460
+ .map(async noteHash => {
1461
+ const nonce = await computeNoteHashNonce(nonceGenerator, noteHashIndexInTx++);
1462
+ const siloedNoteHash = await siloNoteHash(contractAddress, noteHash.value);
1463
+
1464
+ // We could defer this to the public processor, and pass this in as non-revertible.
1465
+ return computeUniqueNoteHash(nonce, siloedNoteHash);
1466
+ }),
1467
+ );
1468
+
1469
+ const privateLogsFromExecution = await Promise.all(
1470
+ execution.publicInputs.privateLogs
1471
+ .filter(privateLog => !privateLog.isEmpty())
1472
+ .map(async metadata => {
1473
+ metadata.log.fields[0] = await poseidon2Hash([contractAddress, metadata.log.fields[0]]);
1474
+
1475
+ return metadata.log;
1476
+ }),
1477
+ );
1478
+
1479
+ uniqueNoteHashes.push(...noteHashesFromExecution);
1480
+ taggedPrivateLogs.push(...privateLogsFromExecution);
1481
+ l2ToL1Messages.push(
1482
+ ...execution.publicInputs.l2ToL1Msgs
1483
+ .filter(l2ToL1Message => !l2ToL1Message.isEmpty())
1484
+ .map(message => message.scope(contractAddress)),
1485
+ );
1486
+ contractClassLogsHashes.push(
1487
+ ...execution.publicInputs.contractClassLogsHashes
1488
+ .filter(contractClassLogsHash => !contractClassLogsHash.isEmpty())
1489
+ .map(message => message.logHash.scope(contractAddress)),
1490
+ );
1491
+ publicCallRequests.push(
1492
+ ...execution.publicInputs.publicCallRequests
1493
+ .filter(publicCallRequest => !publicCallRequest.isEmpty())
1494
+ .map(callRequest => callRequest.inner),
1495
+ );
1496
+
1497
+ if (publicTeardownCallRequest !== undefined && !execution.publicInputs.publicTeardownCallRequest.isEmpty()) {
1498
+ throw new Error('Trying to set multiple teardown requests');
1499
+ }
1500
+
1501
+ publicTeardownCallRequest = execution.publicInputs.publicTeardownCallRequest.isEmpty()
1502
+ ? publicTeardownCallRequest
1503
+ : execution.publicInputs.publicTeardownCallRequest;
1504
+ }
1505
+
1506
+ const globals = makeGlobalVariables();
1507
+ globals.blockNumber = new Fr(this.blockNumber);
1508
+ globals.gasFees = GasFees.empty();
1509
+
1510
+ const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(this));
1511
+ const simulator = new PublicTxSimulator(this.baseFork, contractsDB, globals, true, true);
1512
+ const processor = new PublicProcessor(globals, this.baseFork, contractsDB, simulator, new TestDateProvider());
1513
+
1514
+ const constantData = new TxConstantData(blockHeader, txContext, Fr.zero(), Fr.zero());
1515
+
1516
+ const hasPublicCalls = result.publicFunctionCalldata.length !== 0;
1517
+ let inputsForRollup;
1518
+ let inputsForPublic;
1519
+
1520
+ // Private only
1521
+ if (result.publicFunctionCalldata.length === 0) {
1522
+ const accumulatedDataForRollup = new PrivateToRollupAccumulatedData(
1523
+ padArrayEnd(uniqueNoteHashes, Fr.ZERO, MAX_NOTE_HASHES_PER_TX),
1524
+ padArrayEnd(nullifiers, Fr.ZERO, MAX_NULLIFIERS_PER_TX),
1525
+ padArrayEnd(l2ToL1Messages, ScopedL2ToL1Message.empty(), MAX_L2_TO_L1_MSGS_PER_TX),
1526
+ padArrayEnd(taggedPrivateLogs, PrivateLog.empty(), MAX_PRIVATE_LOGS_PER_TX),
1527
+ padArrayEnd(contractClassLogsHashes, ScopedLogHash.empty(), MAX_CONTRACT_CLASS_LOGS_PER_TX),
1528
+ );
1529
+
1530
+ inputsForRollup = new PartialPrivateTailPublicInputsForRollup(accumulatedDataForRollup);
1531
+ } else {
1532
+ const accumulatedDataForPublic = new PrivateToPublicAccumulatedData(
1533
+ padArrayEnd(uniqueNoteHashes, Fr.ZERO, MAX_NOTE_HASHES_PER_TX),
1534
+ padArrayEnd(nullifiers, Fr.ZERO, MAX_NULLIFIERS_PER_TX),
1535
+ padArrayEnd(l2ToL1Messages, ScopedL2ToL1Message.empty(), MAX_L2_TO_L1_MSGS_PER_TX),
1536
+ padArrayEnd(taggedPrivateLogs, PrivateLog.empty(), MAX_PRIVATE_LOGS_PER_TX),
1537
+ padArrayEnd(contractClassLogsHashes, ScopedLogHash.empty(), MAX_CONTRACT_CLASS_LOGS_PER_TX),
1538
+ padArrayEnd(publicCallRequests, PublicCallRequest.empty(), MAX_ENQUEUED_CALLS_PER_TX),
1539
+ );
1540
+
1541
+ inputsForPublic = new PartialPrivateTailPublicInputsForPublic(
1542
+ // We are using non-revertible because we set the first nullifier to be used as a nonce generator, otherwise the tx hash is manually calculated.
1543
+ // nonrevertible
1544
+ accumulatedDataForPublic,
1545
+ // revertible
1546
+ PrivateToPublicAccumulatedData.empty(),
1547
+ publicTeardownCallRequest ?? PublicCallRequest.empty(),
1548
+ );
1549
+ }
1550
+
1551
+ const txData = new PrivateKernelTailCircuitPublicInputs(
1552
+ constantData,
1553
+ RollupValidationRequests.empty(),
1554
+ /*gasUsed=*/ new Gas(0, 0),
1555
+ /*feePayer=*/ AztecAddress.zero(),
1556
+ hasPublicCalls ? inputsForPublic : undefined,
1557
+ !hasPublicCalls ? inputsForRollup : undefined,
1558
+ );
1559
+
1560
+ const tx = new Tx(txData, ClientIvcProof.empty(), [], result.publicFunctionCalldata);
1561
+
1562
+ const results = await processor.process([tx]);
1563
+
1564
+ const processedTxs = results[0];
1565
+ const failedTxs = results[1];
1566
+
1567
+ if (failedTxs.length !== 0) {
1568
+ throw new Error('Public execution has failed');
1569
+ }
1570
+
1571
+ const fork = this.baseFork;
1572
+
1573
+ const txEffect = TxEffect.empty();
1574
+
1575
+ txEffect.noteHashes = processedTxs[0]!.txEffect.noteHashes;
1576
+ txEffect.nullifiers = processedTxs[0]!.txEffect.nullifiers;
1577
+ txEffect.privateLogs = taggedPrivateLogs;
1578
+ txEffect.publicLogs = processedTxs[0]!.txEffect.publicLogs;
1579
+ txEffect.publicDataWrites = processedTxs[0]!.txEffect.publicDataWrites;
1580
+
1581
+ txEffect.txHash = new TxHash(new Fr(this.blockNumber));
1582
+
1583
+ const body = new Body([txEffect]);
1584
+
1585
+ const l2Block = new L2Block(
1586
+ makeAppendOnlyTreeSnapshot(this.blockNumber + 1),
1587
+ makeHeader(0, this.blockNumber, this.blockNumber),
1588
+ body,
1589
+ );
1590
+
1591
+ const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
1592
+ await fork.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
1593
+
1594
+ const stateReference = await fork.getStateReference();
1595
+ const archiveInfo = await fork.getTreeInfo(MerkleTreeId.ARCHIVE);
1596
+
1597
+ const header = new BlockHeader(
1598
+ new AppendOnlyTreeSnapshot(new Fr(archiveInfo.root), Number(archiveInfo.size)),
1599
+ makeContentCommitment(),
1600
+ stateReference,
1601
+ globals,
1602
+ Fr.ZERO,
1603
+ Fr.ZERO,
1604
+ );
1605
+
1606
+ header.globalVariables.blockNumber = new Fr(this.blockNumber);
1607
+
1608
+ l2Block.header = header;
1609
+
1610
+ await fork.updateArchive(l2Block.header);
1611
+
1612
+ await this.stateMachine.handleL2Block(l2Block);
1613
+
1614
+ const txRequestHash = this.getTxRequestHash();
1615
+
1616
+ this.setBlockNumber(this.blockNumber + 1);
1617
+ return {
1618
+ endSideEffectCounter: result.entrypoint.publicInputs.endSideEffectCounter,
1619
+ returnsHash: result.entrypoint.publicInputs.returnsHash,
1620
+ txHash: txRequestHash,
1621
+ };
1622
+ }
1276
1623
  }