@aztec/sequencer-client 0.26.3 → 0.26.6

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 (85) hide show
  1. package/dest/block_builder/solo_block_builder.d.ts +5 -4
  2. package/dest/block_builder/solo_block_builder.d.ts.map +1 -1
  3. package/dest/block_builder/solo_block_builder.js +82 -34
  4. package/dest/client/sequencer-client.d.ts.map +1 -1
  5. package/dest/client/sequencer-client.js +29 -3
  6. package/dest/config.d.ts.map +1 -1
  7. package/dest/config.js +4 -2
  8. package/dest/index.d.ts +9 -7
  9. package/dest/index.d.ts.map +1 -1
  10. package/dest/index.js +9 -8
  11. package/dest/publisher/l1-publisher.js +5 -5
  12. package/dest/publisher/viem-tx-sender.js +2 -2
  13. package/dest/sequencer/abstract_phase_manager.d.ts +12 -15
  14. package/dest/sequencer/abstract_phase_manager.d.ts.map +1 -1
  15. package/dest/sequencer/abstract_phase_manager.js +32 -24
  16. package/dest/sequencer/app_logic_phase_manager.d.ts +1 -6
  17. package/dest/sequencer/app_logic_phase_manager.d.ts.map +1 -1
  18. package/dest/sequencer/app_logic_phase_manager.js +11 -8
  19. package/dest/sequencer/hints_builder.d.ts +13 -0
  20. package/dest/sequencer/hints_builder.d.ts.map +1 -0
  21. package/dest/sequencer/hints_builder.js +21 -0
  22. package/dest/sequencer/index.d.ts +1 -1
  23. package/dest/sequencer/index.d.ts.map +1 -1
  24. package/dest/sequencer/index.js +2 -2
  25. package/dest/sequencer/phase_manager_factory.d.ts.map +1 -1
  26. package/dest/sequencer/phase_manager_factory.js +5 -1
  27. package/dest/sequencer/processed_tx.d.ts +37 -2
  28. package/dest/sequencer/processed_tx.d.ts.map +1 -1
  29. package/dest/sequencer/processed_tx.js +67 -9
  30. package/dest/sequencer/public_processor.d.ts +3 -1
  31. package/dest/sequencer/public_processor.d.ts.map +1 -1
  32. package/dest/sequencer/public_processor.js +18 -11
  33. package/dest/sequencer/sequencer.d.ts.map +1 -1
  34. package/dest/sequencer/sequencer.js +3 -4
  35. package/dest/sequencer/setup_phase_manager.d.ts +1 -6
  36. package/dest/sequencer/setup_phase_manager.d.ts.map +1 -1
  37. package/dest/sequencer/setup_phase_manager.js +3 -5
  38. package/dest/sequencer/tail_phase_manager.d.ts +28 -0
  39. package/dest/sequencer/tail_phase_manager.d.ts.map +1 -0
  40. package/dest/sequencer/tail_phase_manager.js +32 -0
  41. package/dest/sequencer/teardown_phase_manager.d.ts +1 -6
  42. package/dest/sequencer/teardown_phase_manager.d.ts.map +1 -1
  43. package/dest/sequencer/teardown_phase_manager.js +3 -4
  44. package/dest/simulator/acvm_native.d.ts +20 -0
  45. package/dest/simulator/acvm_native.d.ts.map +1 -0
  46. package/dest/simulator/acvm_native.js +96 -0
  47. package/dest/simulator/acvm_wasm.d.ts +7 -0
  48. package/dest/simulator/acvm_wasm.d.ts.map +1 -0
  49. package/dest/simulator/acvm_wasm.js +23 -0
  50. package/dest/simulator/index.d.ts +8 -1
  51. package/dest/simulator/index.d.ts.map +1 -1
  52. package/dest/simulator/index.js +2 -2
  53. package/dest/simulator/public_kernel.d.ts +11 -1
  54. package/dest/simulator/public_kernel.d.ts.map +1 -1
  55. package/dest/simulator/public_kernel.js +34 -6
  56. package/dest/simulator/rollup.d.ts +4 -0
  57. package/dest/simulator/rollup.d.ts.map +1 -1
  58. package/dest/simulator/rollup.js +16 -20
  59. package/dest/simulator/simulation_provider.d.ts +9 -0
  60. package/dest/simulator/simulation_provider.d.ts.map +1 -0
  61. package/dest/simulator/simulation_provider.js +2 -0
  62. package/package.json +15 -13
  63. package/src/block_builder/solo_block_builder.ts +115 -82
  64. package/src/client/sequencer-client.ts +37 -2
  65. package/src/config.ts +4 -0
  66. package/src/index.ts +9 -7
  67. package/src/publisher/l1-publisher.ts +4 -4
  68. package/src/publisher/viem-tx-sender.ts +1 -1
  69. package/src/sequencer/abstract_phase_manager.ts +58 -48
  70. package/src/sequencer/app_logic_phase_manager.ts +12 -22
  71. package/src/sequencer/hints_builder.ts +56 -0
  72. package/src/sequencer/index.ts +1 -1
  73. package/src/sequencer/phase_manager_factory.ts +12 -0
  74. package/src/sequencer/processed_tx.ts +147 -17
  75. package/src/sequencer/public_processor.ts +28 -14
  76. package/src/sequencer/sequencer.ts +2 -3
  77. package/src/sequencer/setup_phase_manager.ts +5 -19
  78. package/src/sequencer/tail_phase_manager.ts +49 -0
  79. package/src/sequencer/teardown_phase_manager.ts +5 -18
  80. package/src/simulator/acvm_native.ts +112 -0
  81. package/src/simulator/acvm_wasm.ts +31 -0
  82. package/src/simulator/index.ts +8 -0
  83. package/src/simulator/public_kernel.ts +62 -8
  84. package/src/simulator/rollup.ts +31 -19
  85. package/src/simulator/simulation_provider.ts +10 -0
@@ -180,7 +180,6 @@ export class Sequencer {
180
180
  this.log.info(`Building block ${newBlockNumber} with ${validTxs.length} transactions`);
181
181
  this.state = SequencerState.CREATING_BLOCK;
182
182
 
183
- // Process txs and drop the ones that fail processing
184
183
  // We create a fresh processor each time to reset any cached state (eg storage writes)
185
184
  const processor = await this.publicProcessorFactory.create(historicalHeader, newGlobalVariables);
186
185
  const [publicProcessorDuration, [processedTxs, failedTxs]] = await elapsed(() => processor.process(validTxs));
@@ -255,12 +254,12 @@ export class Sequencer {
255
254
  return;
256
255
  }
257
256
 
258
- const blockCalldataHash = block.body.getCalldataHash();
257
+ const txsEffectsHash = block.body.getTxsEffectsHash();
259
258
  this.log.info(`Publishing ${newContracts.length} contracts in block ${block.number}`);
260
259
 
261
260
  const publishedContractData = await this.publisher.processNewContractData(
262
261
  block.number,
263
- blockCalldataHash,
262
+ txsEffectsHash,
264
263
  newContracts,
265
264
  );
266
265
 
@@ -27,34 +27,20 @@ export class SetupPhaseManager extends AbstractPhaseManager {
27
27
  super(db, publicExecutor, publicKernel, publicProver, globalVariables, historicalHeader, phase);
28
28
  }
29
29
 
30
- // this is a no-op for now
31
- async handle(
30
+ override async handle(
32
31
  tx: Tx,
33
32
  previousPublicKernelOutput: PublicKernelCircuitPublicInputs,
34
33
  previousPublicKernelProof: Proof,
35
- ): Promise<{
36
- /**
37
- * the output of the public kernel circuit for this phase
38
- */
39
- publicKernelOutput: PublicKernelCircuitPublicInputs;
40
- /**
41
- * the proof of the public kernel circuit for this phase
42
- */
43
- publicKernelProof: Proof;
44
- }> {
34
+ ) {
45
35
  this.log(`Processing tx ${tx.getTxHash()}`);
46
- this.log(`Executing enqueued public calls for tx ${tx.getTxHash()}`);
47
- const [publicKernelOutput, publicKernelProof, newUnencryptedFunctionLogs] = await this.processEnqueuedPublicCalls(
48
- tx,
49
- previousPublicKernelOutput,
50
- previousPublicKernelProof,
51
- );
36
+ const [publicKernelOutput, publicKernelProof, newUnencryptedFunctionLogs, revertReason] =
37
+ await this.processEnqueuedPublicCalls(tx, previousPublicKernelOutput, previousPublicKernelProof);
52
38
  tx.unencryptedLogs.addFunctionLogs(newUnencryptedFunctionLogs);
53
39
 
54
40
  // commit the state updates from this transaction
55
41
  await this.publicStateDB.commit();
56
42
 
57
- return { publicKernelOutput, publicKernelProof };
43
+ return { publicKernelOutput, publicKernelProof, revertReason };
58
44
  }
59
45
 
60
46
  async rollback(tx: Tx, err: unknown): Promise<FailedTx> {
@@ -0,0 +1,49 @@
1
+ import { Tx } from '@aztec/circuit-types';
2
+ import { GlobalVariables, Header, Proof, PublicKernelCircuitPublicInputs } from '@aztec/circuits.js';
3
+ import { PublicExecutor, PublicStateDB } from '@aztec/simulator';
4
+ import { MerkleTreeOperations } from '@aztec/world-state';
5
+
6
+ import { PublicProver } from '../prover/index.js';
7
+ import { PublicKernelCircuitSimulator } from '../simulator/index.js';
8
+ import { ContractsDataSourcePublicDB } from '../simulator/public_executor.js';
9
+ import { AbstractPhaseManager, PublicKernelPhase } from './abstract_phase_manager.js';
10
+ import { FailedTx } from './processed_tx.js';
11
+
12
+ export class TailPhaseManager extends AbstractPhaseManager {
13
+ constructor(
14
+ protected db: MerkleTreeOperations,
15
+ protected publicExecutor: PublicExecutor,
16
+ protected publicKernel: PublicKernelCircuitSimulator,
17
+ protected publicProver: PublicProver,
18
+ protected globalVariables: GlobalVariables,
19
+ protected historicalHeader: Header,
20
+ protected publicContractsDB: ContractsDataSourcePublicDB,
21
+ protected publicStateDB: PublicStateDB,
22
+ public readonly phase: PublicKernelPhase = PublicKernelPhase.TAIL,
23
+ ) {
24
+ super(db, publicExecutor, publicKernel, publicProver, globalVariables, historicalHeader, phase);
25
+ }
26
+
27
+ async handle(tx: Tx, previousPublicKernelOutput: PublicKernelCircuitPublicInputs, previousPublicKernelProof: Proof) {
28
+ this.log(`Processing tx ${tx.getTxHash()}`);
29
+ this.log(`Executing tail circuit for tx ${tx.getTxHash()}`);
30
+ const [publicKernelOutput, publicKernelProof] = await this.runKernelCircuit(
31
+ previousPublicKernelOutput,
32
+ previousPublicKernelProof,
33
+ );
34
+
35
+ // commit the state updates from this transaction
36
+ await this.publicStateDB.commit();
37
+
38
+ return { publicKernelOutput, publicKernelProof, revertReason: undefined };
39
+ }
40
+
41
+ async rollback(tx: Tx, err: unknown): Promise<FailedTx> {
42
+ this.log.warn(`Error processing tx ${tx.getTxHash()}: ${err}`);
43
+ await this.publicStateDB.rollback();
44
+ return {
45
+ tx,
46
+ error: err instanceof Error ? err : new Error('Unknown error'),
47
+ };
48
+ }
49
+ }
@@ -27,33 +27,20 @@ export class TeardownPhaseManager extends AbstractPhaseManager {
27
27
  super(db, publicExecutor, publicKernel, publicProver, globalVariables, historicalHeader, phase);
28
28
  }
29
29
 
30
- async handle(
30
+ override async handle(
31
31
  tx: Tx,
32
32
  previousPublicKernelOutput: PublicKernelCircuitPublicInputs,
33
33
  previousPublicKernelProof: Proof,
34
- ): Promise<{
35
- /**
36
- * the output of the public kernel circuit for this phase
37
- */
38
- publicKernelOutput: PublicKernelCircuitPublicInputs;
39
- /**
40
- * the proof of the public kernel circuit for this phase
41
- */
42
- publicKernelProof: Proof;
43
- }> {
34
+ ) {
44
35
  this.log(`Processing tx ${tx.getTxHash()}`);
45
- this.log(`Executing enqueued public calls for tx ${tx.getTxHash()}`);
46
- const [publicKernelOutput, publicKernelProof, newUnencryptedFunctionLogs] = await this.processEnqueuedPublicCalls(
47
- tx,
48
- previousPublicKernelOutput,
49
- previousPublicKernelProof,
50
- );
36
+ const [publicKernelOutput, publicKernelProof, newUnencryptedFunctionLogs, revertReason] =
37
+ await this.processEnqueuedPublicCalls(tx, previousPublicKernelOutput, previousPublicKernelProof);
51
38
  tx.unencryptedLogs.addFunctionLogs(newUnencryptedFunctionLogs);
52
39
 
53
40
  // commit the state updates from this transaction
54
41
  await this.publicStateDB.commit();
55
42
 
56
- return { publicKernelOutput, publicKernelProof };
43
+ return { publicKernelOutput, publicKernelProof, revertReason };
57
44
  }
58
45
 
59
46
  async rollback(tx: Tx, err: unknown): Promise<FailedTx> {
@@ -0,0 +1,112 @@
1
+ import { randomBytes } from '@aztec/foundation/crypto';
2
+ import { NoirCompiledCircuit } from '@aztec/types/noir';
3
+
4
+ import { WitnessMap } from '@noir-lang/types';
5
+ import * as proc from 'child_process';
6
+ import fs from 'fs/promises';
7
+
8
+ import { SimulationProvider } from './simulation_provider.js';
9
+
10
+ /**
11
+ * Parses a TOML format witness map string into a Map structure
12
+ * @param outputString - The witness map in TOML format
13
+ * @returns The parsed witness map
14
+ */
15
+ function parseIntoWitnessMap(outputString: string) {
16
+ const lines = outputString.split('\n');
17
+ return new Map<number, string>(
18
+ lines
19
+ .filter((line: string) => line.length)
20
+ .map((line: string) => {
21
+ const pair = line.replaceAll(' ', '').split('=');
22
+ return [Number(pair[0]), pair[1].replaceAll('"', '')];
23
+ }),
24
+ );
25
+ }
26
+
27
+ /**
28
+ *
29
+ * @param inputWitness - The circuit's input witness
30
+ * @param bytecode - The circuit buytecode
31
+ * @param workingDirectory - A directory to use for temporary files by the ACVM
32
+ * @param pathToAcvm - The path to the ACVm binary
33
+ * @returns The completed partial witness outputted from the circuit
34
+ */
35
+ export async function executeNativeCircuit(
36
+ inputWitness: WitnessMap,
37
+ bytecode: Buffer,
38
+ workingDirectory: string,
39
+ pathToAcvm: string,
40
+ ) {
41
+ const bytecodeFilename = 'bytecode';
42
+ const witnessFilename = 'input_witness.toml';
43
+
44
+ // convert the witness map to TOML format
45
+ let witnessMap = '';
46
+ inputWitness.forEach((value: string, key: number) => {
47
+ witnessMap = witnessMap.concat(`${key} = '${value}'\n`);
48
+ });
49
+
50
+ // In case the directory is still around from some time previously, remove it
51
+ await fs.rm(workingDirectory, { recursive: true, force: true });
52
+ // Create the new working directory
53
+ await fs.mkdir(workingDirectory, { recursive: true });
54
+ // Write the bytecode and input witness to the working directory
55
+ await fs.writeFile(`${workingDirectory}/${bytecodeFilename}`, bytecode);
56
+ await fs.writeFile(`${workingDirectory}/${witnessFilename}`, witnessMap);
57
+
58
+ // Execute the ACVM using the given args
59
+ const args = [
60
+ `execute`,
61
+ `--working-directory`,
62
+ `${workingDirectory}`,
63
+ `--bytecode`,
64
+ `${bytecodeFilename}`,
65
+ `--input-witness`,
66
+ `${witnessFilename}`,
67
+ `--print`,
68
+ ];
69
+ const processPromise = new Promise<string>((resolve, reject) => {
70
+ let outputWitness = Buffer.alloc(0);
71
+ let errorBuffer = Buffer.alloc(0);
72
+ const acvm = proc.spawn(pathToAcvm, args);
73
+ acvm.stdout.on('data', data => {
74
+ outputWitness = Buffer.concat([outputWitness, data]);
75
+ });
76
+ acvm.stderr.on('data', data => {
77
+ errorBuffer = Buffer.concat([errorBuffer, data]);
78
+ });
79
+ acvm.on('close', code => {
80
+ if (code === 0) {
81
+ resolve(outputWitness.toString('utf-8'));
82
+ } else {
83
+ reject(errorBuffer.toString('utf-8'));
84
+ }
85
+ });
86
+ });
87
+
88
+ try {
89
+ const output = await processPromise;
90
+ return parseIntoWitnessMap(output);
91
+ } finally {
92
+ // Clean up the working directory before we leave
93
+ await fs.rm(workingDirectory, { recursive: true, force: true });
94
+ }
95
+ }
96
+
97
+ export class NativeACVMSimulator implements SimulationProvider {
98
+ constructor(private workingDirectory: string, private pathToAcvm: string) {}
99
+ async simulateCircuit(input: WitnessMap, compiledCircuit: NoirCompiledCircuit): Promise<WitnessMap> {
100
+ // Execute the circuit on those initial witness values
101
+
102
+ // Decode the bytecode from base64 since the acvm does not know about base64 encoding
103
+ const decodedBytecode = Buffer.from(compiledCircuit.bytecode, 'base64');
104
+
105
+ // Provide a unique working directory so we don't get clashes with parallel executions
106
+ const directory = `${this.workingDirectory}/${randomBytes(32).toString('hex')}`;
107
+ // Execute the circuit
108
+ const _witnessMap = await executeNativeCircuit(input, decodedBytecode, directory, this.pathToAcvm);
109
+
110
+ return _witnessMap;
111
+ }
112
+ }
@@ -0,0 +1,31 @@
1
+ import { NoirCompiledCircuit } from '@aztec/types/noir';
2
+
3
+ import { WasmBlackBoxFunctionSolver, createBlackBoxSolver, executeCircuitWithBlackBoxSolver } from '@noir-lang/acvm_js';
4
+ import { WitnessMap } from '@noir-lang/types';
5
+
6
+ import { SimulationProvider } from './simulation_provider.js';
7
+
8
+ let solver: Promise<WasmBlackBoxFunctionSolver>;
9
+
10
+ const getSolver = (): Promise<WasmBlackBoxFunctionSolver> => {
11
+ if (!solver) {
12
+ solver = createBlackBoxSolver();
13
+ }
14
+ return solver;
15
+ };
16
+
17
+ export class WASMSimulator implements SimulationProvider {
18
+ async simulateCircuit(input: WitnessMap, compiledCircuit: NoirCompiledCircuit): Promise<WitnessMap> {
19
+ // Execute the circuit on those initial witness values
20
+ //
21
+ // Decode the bytecode from base64 since the acvm does not know about base64 encoding
22
+ const decodedBytecode = Buffer.from(compiledCircuit.bytecode, 'base64');
23
+ //
24
+ // Execute the circuit
25
+ const _witnessMap = await executeCircuitWithBlackBoxSolver(await getSolver(), decodedBytecode, input, () => {
26
+ throw Error('unexpected oracle during execution');
27
+ });
28
+
29
+ return _witnessMap;
30
+ }
31
+ }
@@ -4,6 +4,7 @@ import {
4
4
  MergeRollupInputs,
5
5
  PublicKernelCircuitPrivateInputs,
6
6
  PublicKernelCircuitPublicInputs,
7
+ PublicKernelTailCircuitPrivateInputs,
7
8
  RootRollupInputs,
8
9
  RootRollupPublicInputs,
9
10
  } from '@aztec/circuits.js';
@@ -54,4 +55,11 @@ export interface PublicKernelCircuitSimulator {
54
55
  * @returns The public inputs as outputs of the simulation.
55
56
  */
56
57
  publicKernelCircuitTeardown(inputs: PublicKernelCircuitPrivateInputs): Promise<PublicKernelCircuitPublicInputs>;
58
+ /**
59
+ * Simulates the public kernel tail circuit from its inputs.
60
+ * @param inputs - Inputs to the circuit.
61
+ * @returns The public inputs as outputs of the simulation.
62
+ */
63
+ publicKernelCircuitTail(inputs: PublicKernelTailCircuitPrivateInputs): Promise<PublicKernelCircuitPublicInputs>;
57
64
  }
65
+ export * from './acvm_wasm.js';
@@ -1,14 +1,28 @@
1
1
  import { CircuitSimulationStats } from '@aztec/circuit-types/stats';
2
- import { PublicKernelCircuitPrivateInputs, PublicKernelCircuitPublicInputs } from '@aztec/circuits.js';
2
+ import {
3
+ PublicKernelCircuitPrivateInputs,
4
+ PublicKernelCircuitPublicInputs,
5
+ PublicKernelTailCircuitPrivateInputs,
6
+ } from '@aztec/circuits.js';
3
7
  import { createDebugLogger } from '@aztec/foundation/log';
4
8
  import { elapsed } from '@aztec/foundation/timer';
5
9
  import {
6
- executePublicKernelAppLogic,
7
- executePublicKernelSetup,
8
- executePublicKernelTeardown,
10
+ PublicKernelAppLogicArtifact,
11
+ PublicKernelSetupArtifact,
12
+ PublicKernelTailArtifact,
13
+ PublicKernelTeardownArtifact,
14
+ convertPublicInnerRollupInputsToWitnessMap,
15
+ convertPublicInnerRollupOutputFromWitnessMap,
16
+ convertPublicSetupRollupInputsToWitnessMap,
17
+ convertPublicSetupRollupOutputFromWitnessMap,
18
+ convertPublicTailInputsToWitnessMap,
19
+ convertPublicTailOutputFromWitnessMap,
20
+ convertPublicTeardownRollupInputsToWitnessMap,
21
+ convertPublicTeardownRollupOutputFromWitnessMap,
9
22
  } from '@aztec/noir-protocol-circuits-types';
10
23
 
11
- import { PublicKernelCircuitSimulator } from './index.js';
24
+ import { PublicKernelCircuitSimulator, WASMSimulator } from './index.js';
25
+ import { SimulationProvider } from './simulation_provider.js';
12
26
 
13
27
  /**
14
28
  * Implements the PublicKernelCircuitSimulator.
@@ -16,6 +30,11 @@ import { PublicKernelCircuitSimulator } from './index.js';
16
30
  export class RealPublicKernelCircuitSimulator implements PublicKernelCircuitSimulator {
17
31
  private log = createDebugLogger('aztec:public-kernel-simulator');
18
32
 
33
+ // Some circuits are so small it is faster to use WASM
34
+ private wasmSimulator: WASMSimulator = new WASMSimulator();
35
+
36
+ constructor(private simulator: SimulationProvider) {}
37
+
19
38
  /**
20
39
  * Simulates the public kernel setup circuit from its inputs.
21
40
  * @param input - Inputs to the circuit.
@@ -27,7 +46,11 @@ export class RealPublicKernelCircuitSimulator implements PublicKernelCircuitSimu
27
46
  if (!input.previousKernel.publicInputs.needsSetup) {
28
47
  throw new Error(`Expected previous kernel inputs to need setup`);
29
48
  }
30
- const [duration, result] = await elapsed(() => executePublicKernelSetup(input));
49
+ const inputWitness = convertPublicSetupRollupInputsToWitnessMap(input);
50
+ const [duration, witness] = await elapsed(() =>
51
+ this.wasmSimulator.simulateCircuit(inputWitness, PublicKernelSetupArtifact),
52
+ );
53
+ const result = convertPublicSetupRollupOutputFromWitnessMap(witness);
31
54
  this.log(`Simulated public kernel setup circuit`, {
32
55
  eventName: 'circuit-simulation',
33
56
  circuitName: 'public-kernel-setup',
@@ -49,7 +72,11 @@ export class RealPublicKernelCircuitSimulator implements PublicKernelCircuitSimu
49
72
  if (!input.previousKernel.publicInputs.needsAppLogic) {
50
73
  throw new Error(`Expected previous kernel inputs to need app logic`);
51
74
  }
52
- const [duration, result] = await elapsed(() => executePublicKernelAppLogic(input));
75
+ const inputWitness = convertPublicInnerRollupInputsToWitnessMap(input);
76
+ const [duration, witness] = await elapsed(() =>
77
+ this.wasmSimulator.simulateCircuit(inputWitness, PublicKernelAppLogicArtifact),
78
+ );
79
+ const result = convertPublicInnerRollupOutputFromWitnessMap(witness);
53
80
  this.log(`Simulated public kernel app logic circuit`, {
54
81
  eventName: 'circuit-simulation',
55
82
  circuitName: 'public-kernel-app-logic',
@@ -71,7 +98,11 @@ export class RealPublicKernelCircuitSimulator implements PublicKernelCircuitSimu
71
98
  if (!input.previousKernel.publicInputs.needsTeardown) {
72
99
  throw new Error(`Expected previous kernel inputs to need teardown`);
73
100
  }
74
- const [duration, result] = await elapsed(() => executePublicKernelTeardown(input));
101
+ const inputWitness = convertPublicTeardownRollupInputsToWitnessMap(input);
102
+ const [duration, witness] = await elapsed(() =>
103
+ this.wasmSimulator.simulateCircuit(inputWitness, PublicKernelTeardownArtifact),
104
+ );
105
+ const result = convertPublicTeardownRollupOutputFromWitnessMap(witness);
75
106
  this.log(`Simulated public kernel teardown circuit`, {
76
107
  eventName: 'circuit-simulation',
77
108
  circuitName: 'public-kernel-teardown',
@@ -81,4 +112,27 @@ export class RealPublicKernelCircuitSimulator implements PublicKernelCircuitSimu
81
112
  } satisfies CircuitSimulationStats);
82
113
  return result;
83
114
  }
115
+
116
+ /**
117
+ * Simulates the public kernel tail circuit from its inputs.
118
+ * @param input - Inputs to the circuit.
119
+ * @returns The public inputs as outputs of the simulation.
120
+ */
121
+ public async publicKernelCircuitTail(
122
+ input: PublicKernelTailCircuitPrivateInputs,
123
+ ): Promise<PublicKernelCircuitPublicInputs> {
124
+ const inputWitness = convertPublicTailInputsToWitnessMap(input);
125
+ const [duration, witness] = await elapsed(() =>
126
+ this.wasmSimulator.simulateCircuit(inputWitness, PublicKernelTailArtifact),
127
+ );
128
+ const result = convertPublicTailOutputFromWitnessMap(witness);
129
+ this.log(`Simulated public kernel tail circuit`, {
130
+ eventName: 'circuit-simulation',
131
+ circuitName: 'public-kernel-tail',
132
+ duration,
133
+ inputSize: input.toBuffer().length,
134
+ outputSize: result.toBuffer().length,
135
+ } satisfies CircuitSimulationStats);
136
+ return result;
137
+ }
84
138
  }
@@ -8,9 +8,20 @@ import {
8
8
  } from '@aztec/circuits.js';
9
9
  import { createDebugLogger } from '@aztec/foundation/log';
10
10
  import { elapsed } from '@aztec/foundation/timer';
11
- import { executeBaseRollup, executeMergeRollup, executeRootRollup } from '@aztec/noir-protocol-circuits-types';
11
+ import {
12
+ BaseRollupArtifact,
13
+ MergeRollupArtifact,
14
+ RootRollupArtifact,
15
+ convertBaseRollupInputsToWitnessMap,
16
+ convertBaseRollupOutputsFromWitnessMap,
17
+ convertMergeRollupInputsToWitnessMap,
18
+ convertMergeRollupOutputsFromWitnessMap,
19
+ convertRootRollupInputsToWitnessMap,
20
+ convertRootRollupOutputsFromWitnessMap,
21
+ } from '@aztec/noir-protocol-circuits-types';
12
22
 
13
- import { RollupSimulator } from './index.js';
23
+ import { RollupSimulator, WASMSimulator } from './index.js';
24
+ import { SimulationProvider } from './simulation_provider.js';
14
25
 
15
26
  /**
16
27
  * Implements the rollup circuit simulator.
@@ -18,21 +29,22 @@ import { RollupSimulator } from './index.js';
18
29
  export class RealRollupCircuitSimulator implements RollupSimulator {
19
30
  private log = createDebugLogger('aztec:rollup-simulator');
20
31
 
32
+ // Some circuits are so small it is faster to use WASM
33
+ private wasmSimulator: WASMSimulator = new WASMSimulator();
34
+
35
+ constructor(private simulationProvider: SimulationProvider) {}
36
+
21
37
  /**
22
38
  * Simulates the base rollup circuit from its inputs.
23
39
  * @param input - Inputs to the circuit.
24
40
  * @returns The public inputs as outputs of the simulation.
25
41
  */
26
42
  public async baseRollupCircuit(input: BaseRollupInputs): Promise<BaseOrMergeRollupPublicInputs> {
27
- const [duration, result] = await elapsed(() => executeBaseRollup(input));
43
+ const witnessMap = convertBaseRollupInputsToWitnessMap(input);
28
44
 
29
- this.log(`Simulated base rollup circuit`, {
30
- eventName: 'circuit-simulation',
31
- circuitName: 'base-rollup',
32
- duration,
33
- inputSize: input.toBuffer().length,
34
- outputSize: result.toBuffer().length,
35
- } satisfies CircuitSimulationStats);
45
+ const witness = await this.simulationProvider.simulateCircuit(witnessMap, BaseRollupArtifact);
46
+
47
+ const result = convertBaseRollupOutputsFromWitnessMap(witness);
36
48
 
37
49
  return Promise.resolve(result);
38
50
  }
@@ -42,15 +54,11 @@ export class RealRollupCircuitSimulator implements RollupSimulator {
42
54
  * @returns The public inputs as outputs of the simulation.
43
55
  */
44
56
  public async mergeRollupCircuit(input: MergeRollupInputs): Promise<BaseOrMergeRollupPublicInputs> {
45
- const [duration, result] = await elapsed(() => executeMergeRollup(input));
57
+ const witnessMap = convertMergeRollupInputsToWitnessMap(input);
46
58
 
47
- this.log(`Simulated merge rollup circuit`, {
48
- eventName: 'circuit-simulation',
49
- circuitName: 'merge-rollup',
50
- duration,
51
- inputSize: input.toBuffer().length,
52
- outputSize: result.toBuffer().length,
53
- } satisfies CircuitSimulationStats);
59
+ const witness = await this.wasmSimulator.simulateCircuit(witnessMap, MergeRollupArtifact);
60
+
61
+ const result = convertMergeRollupOutputsFromWitnessMap(witness);
54
62
 
55
63
  return result;
56
64
  }
@@ -61,7 +69,11 @@ export class RealRollupCircuitSimulator implements RollupSimulator {
61
69
  * @returns The public inputs as outputs of the simulation.
62
70
  */
63
71
  public async rootRollupCircuit(input: RootRollupInputs): Promise<RootRollupPublicInputs> {
64
- const [duration, result] = await elapsed(() => executeRootRollup(input));
72
+ const witnessMap = convertRootRollupInputsToWitnessMap(input);
73
+
74
+ const [duration, witness] = await elapsed(() => this.wasmSimulator.simulateCircuit(witnessMap, RootRollupArtifact));
75
+
76
+ const result = convertRootRollupOutputsFromWitnessMap(witness);
65
77
 
66
78
  this.log(`Simulated root rollup circuit`, {
67
79
  eventName: 'circuit-simulation',
@@ -0,0 +1,10 @@
1
+ import { NoirCompiledCircuit } from '@aztec/types/noir';
2
+
3
+ import { WitnessMap } from '@noir-lang/types';
4
+
5
+ /**
6
+ * Low level simulation interface
7
+ */
8
+ export interface SimulationProvider {
9
+ simulateCircuit(input: WitnessMap, compiledCircuit: NoirCompiledCircuit): Promise<WitnessMap>;
10
+ }