@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
@@ -1,4 +1,5 @@
1
- import { Body, ContractData, L2Block, MerkleTreeId, PublicDataWrite, TxEffect, TxL2Logs } from '@aztec/circuit-types';
1
+ import { Body, L2Block, MerkleTreeId, TxEffect } from '@aztec/circuit-types';
2
+ import { CircuitSimulationStats } from '@aztec/circuit-types/stats';
2
3
  import {
3
4
  ARCHIVE_HEIGHT,
4
5
  AppendOnlyTreeSnapshot,
@@ -6,13 +7,10 @@ import {
6
7
  BaseRollupInputs,
7
8
  CONTRACT_SUBTREE_HEIGHT,
8
9
  CONTRACT_SUBTREE_SIBLING_PATH_LENGTH,
9
- CombinedAccumulatedData,
10
10
  ConstantRollupData,
11
11
  GlobalVariables,
12
12
  L1_TO_L2_MSG_SUBTREE_HEIGHT,
13
13
  L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH,
14
- MAX_NEW_CONTRACTS_PER_TX,
15
- MAX_NEW_NOTE_HASHES_PER_TX,
16
14
  MAX_NEW_NULLIFIERS_PER_TX,
17
15
  MAX_PUBLIC_DATA_READS_PER_TX,
18
16
  MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
@@ -39,8 +37,6 @@ import {
39
37
  RollupTypes,
40
38
  RootRollupInputs,
41
39
  RootRollupPublicInputs,
42
- SideEffect,
43
- SideEffectLinkedToNoteHash,
44
40
  StateDiffHints,
45
41
  StateReference,
46
42
  VK_TREE_HEIGHT,
@@ -52,13 +48,15 @@ import { padArrayEnd } from '@aztec/foundation/collection';
52
48
  import { Fr } from '@aztec/foundation/fields';
53
49
  import { createDebugLogger } from '@aztec/foundation/log';
54
50
  import { Tuple, assertLength, toFriendlyJSON } from '@aztec/foundation/serialize';
51
+ import { elapsed } from '@aztec/foundation/timer';
55
52
  import { MerkleTreeOperations } from '@aztec/world-state';
56
53
 
57
54
  import chunk from 'lodash.chunk';
55
+ import { inspect } from 'util';
58
56
 
59
57
  import { VerificationKeys } from '../mocks/verification_keys.js';
60
58
  import { RollupProver } from '../prover/index.js';
61
- import { ProcessedTx } from '../sequencer/processed_tx.js';
59
+ import { ProcessedTx, toTxEffect } from '../sequencer/processed_tx.js';
62
60
  import { RollupSimulator } from '../simulator/index.js';
63
61
  import { BlockBuilder } from './index.js';
64
62
  import { TreeNames } from './types.js';
@@ -105,30 +103,7 @@ export class SoloBlockBuilder implements BlockBuilder {
105
103
  const [circuitsOutput, proof] = await this.runCircuits(globalVariables, txs, newL1ToL2Messages);
106
104
 
107
105
  // Collect all new nullifiers, commitments, and contracts from all txs in this block
108
- const txEffects: TxEffect[] = txs.map(
109
- tx =>
110
- new TxEffect(
111
- tx.data.combinedData.newNoteHashes.map((c: SideEffect) => c.value) as Tuple<
112
- Fr,
113
- typeof MAX_NEW_NOTE_HASHES_PER_TX
114
- >,
115
- tx.data.combinedData.newNullifiers.map((n: SideEffectLinkedToNoteHash) => n.value) as Tuple<
116
- Fr,
117
- typeof MAX_NEW_NULLIFIERS_PER_TX
118
- >,
119
- tx.data.combinedData.newL2ToL1Msgs,
120
- tx.data.combinedData.publicDataUpdateRequests.map(t => new PublicDataWrite(t.leafSlot, t.newValue)) as Tuple<
121
- PublicDataWrite,
122
- typeof MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX
123
- >,
124
- tx.data.combinedData.newContracts.map(cd => cd.hash()) as Tuple<Fr, typeof MAX_NEW_CONTRACTS_PER_TX>,
125
- tx.data.combinedData.newContracts.map(
126
- cd => new ContractData(cd.contractAddress, cd.portalContractAddress),
127
- ) as Tuple<ContractData, typeof MAX_NEW_CONTRACTS_PER_TX>,
128
- tx.encryptedLogs || new TxL2Logs([]),
129
- tx.unencryptedLogs || new TxL2Logs([]),
130
- ),
131
- );
106
+ const txEffects: TxEffect[] = txs.map(tx => toTxEffect(tx));
132
107
 
133
108
  const blockBody = new Body(padArrayEnd(newL1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP), txEffects);
134
109
 
@@ -138,11 +113,12 @@ export class SoloBlockBuilder implements BlockBuilder {
138
113
  body: blockBody,
139
114
  });
140
115
 
141
- if (!l2Block.body.getCalldataHash().equals(circuitsOutput.header.contentCommitment.txsHash)) {
116
+ if (!l2Block.body.getTxsEffectsHash().equals(circuitsOutput.header.contentCommitment.txsEffectsHash)) {
117
+ this.debug(inspect(blockBody));
142
118
  throw new Error(
143
- `Calldata hash mismatch, ${l2Block.body
144
- .getCalldataHash()
145
- .toString('hex')} == ${circuitsOutput.header.contentCommitment.txsHash.toString('hex')} `,
119
+ `Txs effects hash mismatch, ${l2Block.body
120
+ .getTxsEffectsHash()
121
+ .toString('hex')} == ${circuitsOutput.header.contentCommitment.txsEffectsHash.toString('hex')} `,
146
122
  );
147
123
  }
148
124
 
@@ -189,22 +165,66 @@ export class SoloBlockBuilder implements BlockBuilder {
189
165
  // padArrayEnd throws if the array is already full. Otherwise it pads till we reach the required size
190
166
  const newL1ToL2MessagesTuple = padArrayEnd(newL1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP);
191
167
 
192
- // Run the base rollup circuits for the txs
193
- const baseRollupOutputs: [BaseOrMergeRollupPublicInputs, Proof][] = [];
168
+ // Perform all tree insertions and retrieve snapshots for all base rollups
169
+ const baseRollupInputs: BaseRollupInputs[] = [];
170
+ const treeSnapshots: Map<MerkleTreeId, AppendOnlyTreeSnapshot>[] = [];
194
171
  for (const tx of txs) {
195
- baseRollupOutputs.push(await this.baseRollupCircuit(tx, globalVariables));
172
+ const input = await this.buildBaseRollupInput(tx, globalVariables);
173
+ baseRollupInputs.push(input);
174
+ const promises = [
175
+ MerkleTreeId.NOTE_HASH_TREE,
176
+ MerkleTreeId.CONTRACT_TREE,
177
+ MerkleTreeId.NULLIFIER_TREE,
178
+ MerkleTreeId.PUBLIC_DATA_TREE,
179
+ ].map(async (id: MerkleTreeId) => {
180
+ return { key: id, value: await this.getTreeSnapshot(id) };
181
+ });
182
+ const snapshots: Map<MerkleTreeId, AppendOnlyTreeSnapshot> = new Map(
183
+ (await Promise.all(promises)).map(obj => [obj.key, obj.value]),
184
+ );
185
+ treeSnapshots.push(snapshots);
186
+ }
187
+
188
+ // Run the base rollup circuits for the txs in parallel
189
+ const baseRollupOutputs: Promise<[BaseOrMergeRollupPublicInputs, Proof]>[] = [];
190
+ for (let i = 0; i < txs.length; i++) {
191
+ baseRollupOutputs.push(this.baseRollupCircuit(txs[i], baseRollupInputs[i], treeSnapshots[i]));
196
192
  }
197
193
 
198
194
  // Run merge rollups in layers until we have only two outputs
199
- let mergeRollupInputs: [BaseOrMergeRollupPublicInputs, Proof][] = baseRollupOutputs;
200
- let mergeRollupOutputs: [BaseOrMergeRollupPublicInputs, Proof][] = [];
195
+ // All merge circuits for each layer are simulated in parallel
196
+ const [duration, mergeInputs] = await elapsed(() => Promise.all(baseRollupOutputs));
197
+ for (let i = 0; i < mergeInputs.length; i++) {
198
+ this.debug(`Simulated base rollup circuit`, {
199
+ eventName: 'circuit-simulation',
200
+ circuitName: 'base-rollup',
201
+ duration: duration / mergeInputs.length,
202
+ inputSize: baseRollupInputs[i].toBuffer().length,
203
+ outputSize: mergeInputs[i][0].toBuffer().length,
204
+ } satisfies CircuitSimulationStats);
205
+ }
206
+ let mergeRollupInputs: [BaseOrMergeRollupPublicInputs, Proof][] = mergeInputs;
201
207
  while (mergeRollupInputs.length > 2) {
208
+ const mergeInputStructs: MergeRollupInputs[] = [];
202
209
  for (const pair of chunk(mergeRollupInputs, 2)) {
203
210
  const [r1, r2] = pair;
204
- mergeRollupOutputs.push(await this.mergeRollupCircuit(r1, r2));
211
+ mergeInputStructs.push(this.createMergeRollupInputs(r1, r2));
205
212
  }
206
- mergeRollupInputs = mergeRollupOutputs;
207
- mergeRollupOutputs = [];
213
+
214
+ const [duration, mergeOutputs] = await elapsed(() =>
215
+ Promise.all(mergeInputStructs.map(async input => await this.mergeRollupCircuit(input))),
216
+ );
217
+
218
+ for (let i = 0; i < mergeOutputs.length; i++) {
219
+ this.debug(`Simulated merge rollup circuit`, {
220
+ eventName: 'circuit-simulation',
221
+ circuitName: 'merge-rollup',
222
+ duration: duration / mergeOutputs.length,
223
+ inputSize: mergeInputStructs[i].toBuffer().length,
224
+ outputSize: mergeOutputs[i][0].toBuffer().length,
225
+ } satisfies CircuitSimulationStats);
226
+ }
227
+ mergeRollupInputs = mergeOutputs;
208
228
  }
209
229
 
210
230
  // Run the root rollup with the last two merge rollups (or base, if no merge layers)
@@ -214,26 +234,29 @@ export class SoloBlockBuilder implements BlockBuilder {
214
234
 
215
235
  protected async baseRollupCircuit(
216
236
  tx: ProcessedTx,
217
- globalVariables: GlobalVariables,
237
+ inputs: BaseRollupInputs,
238
+ treeSnapshots: Map<MerkleTreeId, AppendOnlyTreeSnapshot>,
218
239
  ): Promise<[BaseOrMergeRollupPublicInputs, Proof]> {
219
240
  this.debug(`Running base rollup for ${tx.hash}`);
220
- const rollupInput = await this.buildBaseRollupInput(tx, globalVariables);
221
- const rollupOutput = await this.simulator.baseRollupCircuit(rollupInput);
222
- await this.validatePartialState(rollupOutput.end);
223
- const proof = await this.prover.getBaseRollupProof(rollupInput, rollupOutput);
241
+ const rollupOutput = await this.simulator.baseRollupCircuit(inputs);
242
+ this.validatePartialState(rollupOutput.end, treeSnapshots);
243
+ const proof = await this.prover.getBaseRollupProof(inputs, rollupOutput);
224
244
  return [rollupOutput, proof];
225
245
  }
226
246
 
227
- protected async mergeRollupCircuit(
247
+ protected createMergeRollupInputs(
228
248
  left: [BaseOrMergeRollupPublicInputs, Proof],
229
249
  right: [BaseOrMergeRollupPublicInputs, Proof],
230
- ): Promise<[BaseOrMergeRollupPublicInputs, Proof]> {
250
+ ) {
231
251
  const vk = this.getVerificationKey(left[0].rollupType);
232
252
  const mergeInputs = new MergeRollupInputs([
233
253
  this.getPreviousRollupDataFromPublicInputs(left[0], left[1], vk),
234
254
  this.getPreviousRollupDataFromPublicInputs(right[0], right[1], vk),
235
255
  ]);
256
+ return mergeInputs;
257
+ }
236
258
 
259
+ protected async mergeRollupCircuit(mergeInputs: MergeRollupInputs): Promise<[BaseOrMergeRollupPublicInputs, Proof]> {
237
260
  this.debug(`Running merge rollup circuit`);
238
261
  const output = await this.simulator.mergeRollupCircuit(mergeInputs);
239
262
  const proof = await this.prover.getMergeRollupProof(mergeInputs, output);
@@ -279,40 +302,50 @@ export class SoloBlockBuilder implements BlockBuilder {
279
302
  return [rootOutput, rootProof];
280
303
  }
281
304
 
282
- protected async validatePartialState(partialState: PartialStateReference) {
283
- await Promise.all([
284
- this.validateSimulatedTree(
285
- await this.getTreeSnapshot(MerkleTreeId.NOTE_HASH_TREE),
286
- partialState.noteHashTree,
287
- 'NoteHashTree',
288
- ),
289
- this.validateSimulatedTree(
290
- await this.getTreeSnapshot(MerkleTreeId.NULLIFIER_TREE),
291
- partialState.nullifierTree,
292
- 'NullifierTree',
293
- ),
294
- this.validateSimulatedTree(
295
- await this.getTreeSnapshot(MerkleTreeId.CONTRACT_TREE),
296
- partialState.contractTree,
297
- 'ContractTree',
298
- ),
299
- this.validateSimulatedTree(
300
- await this.getTreeSnapshot(MerkleTreeId.PUBLIC_DATA_TREE),
301
- partialState.publicDataTree,
302
- 'PublicDataTree',
303
- ),
304
- ]);
305
+ protected validatePartialState(
306
+ partialState: PartialStateReference,
307
+ treeSnapshots: Map<MerkleTreeId, AppendOnlyTreeSnapshot>,
308
+ ) {
309
+ this.validateSimulatedTree(
310
+ treeSnapshots.get(MerkleTreeId.NOTE_HASH_TREE)!,
311
+ partialState.noteHashTree,
312
+ 'NoteHashTree',
313
+ );
314
+ this.validateSimulatedTree(
315
+ treeSnapshots.get(MerkleTreeId.NULLIFIER_TREE)!,
316
+ partialState.nullifierTree,
317
+ 'NullifierTree',
318
+ );
319
+ this.validateSimulatedTree(
320
+ treeSnapshots.get(MerkleTreeId.CONTRACT_TREE)!,
321
+ partialState.contractTree,
322
+ 'ContractTree',
323
+ );
324
+ this.validateSimulatedTree(
325
+ treeSnapshots.get(MerkleTreeId.PUBLIC_DATA_TREE)!,
326
+ partialState.publicDataTree,
327
+ 'PublicDataTree',
328
+ );
305
329
  }
306
330
 
307
331
  protected async validateState(state: StateReference) {
308
- await Promise.all([
309
- this.validateSimulatedTree(
310
- await this.getTreeSnapshot(MerkleTreeId.L1_TO_L2_MESSAGE_TREE),
311
- state.l1ToL2MessageTree,
312
- 'L1ToL2MessageTree',
313
- ),
314
- this.validatePartialState(state.partial),
315
- ]);
332
+ const promises = [
333
+ MerkleTreeId.NOTE_HASH_TREE,
334
+ MerkleTreeId.CONTRACT_TREE,
335
+ MerkleTreeId.NULLIFIER_TREE,
336
+ MerkleTreeId.PUBLIC_DATA_TREE,
337
+ ].map(async (id: MerkleTreeId) => {
338
+ return { key: id, value: await this.getTreeSnapshot(id) };
339
+ });
340
+ const snapshots: Map<MerkleTreeId, AppendOnlyTreeSnapshot> = new Map(
341
+ (await Promise.all(promises)).map(obj => [obj.key, obj.value]),
342
+ );
343
+ this.validatePartialState(state.partial, snapshots);
344
+ this.validateSimulatedTree(
345
+ await this.getTreeSnapshot(MerkleTreeId.L1_TO_L2_MESSAGE_TREE),
346
+ state.l1ToL2MessageTree,
347
+ 'L1ToL2MessageTree',
348
+ );
316
349
  }
317
350
 
318
351
  // Validate that the roots of all local trees match the output of the root circuit simulation
@@ -420,7 +453,7 @@ export class SoloBlockBuilder implements BlockBuilder {
420
453
  protected getKernelDataFor(tx: ProcessedTx): RollupKernelData {
421
454
  const inputs = new RollupKernelCircuitPublicInputs(
422
455
  tx.data.aggregationObject,
423
- CombinedAccumulatedData.recombine(tx.data.endNonRevertibleData, tx.data.end),
456
+ tx.data.combinedData,
424
457
  tx.data.constants,
425
458
  );
426
459
  return new RollupKernelData(
@@ -1,7 +1,10 @@
1
1
  import { ContractDataSource, L1ToL2MessageSource, L2BlockSource } from '@aztec/circuit-types';
2
+ import { createDebugLogger } from '@aztec/foundation/log';
2
3
  import { P2P } from '@aztec/p2p';
3
4
  import { WorldStateSynchronizer } from '@aztec/world-state';
4
5
 
6
+ import * as fs from 'fs/promises';
7
+
5
8
  import { SoloBlockBuilder } from '../block_builder/solo_block_builder.js';
6
9
  import { SequencerClientConfig } from '../config.js';
7
10
  import { getGlobalVariableBuilder } from '../global_variable_builder/index.js';
@@ -10,7 +13,32 @@ import { EmptyRollupProver } from '../prover/empty.js';
10
13
  import { getL1Publisher } from '../publisher/index.js';
11
14
  import { Sequencer, SequencerConfig } from '../sequencer/index.js';
12
15
  import { PublicProcessorFactory } from '../sequencer/public_processor.js';
16
+ import { NativeACVMSimulator } from '../simulator/acvm_native.js';
17
+ import { WASMSimulator } from '../simulator/acvm_wasm.js';
13
18
  import { RealRollupCircuitSimulator } from '../simulator/rollup.js';
19
+ import { SimulationProvider } from '../simulator/simulation_provider.js';
20
+
21
+ const logger = createDebugLogger('aztec:sequencer-client');
22
+
23
+ /**
24
+ * Factory function to create a simulation provider. Will attempt to use native binary simulation falling back to WASM if unavailable.
25
+ * @param config - The provided sequencer client configuration
26
+ * @returns The constructed simulation provider
27
+ */
28
+ async function getSimulationProvider(config: SequencerClientConfig): Promise<SimulationProvider> {
29
+ if (config.acvmBinaryPath && config.acvmWorkingDirectory) {
30
+ try {
31
+ await fs.access(config.acvmBinaryPath, fs.constants.R_OK);
32
+ await fs.mkdir(config.acvmWorkingDirectory, { recursive: true });
33
+ logger(`Using native ACVM at ${config.acvmBinaryPath}`);
34
+ return new NativeACVMSimulator(config.acvmWorkingDirectory, config.acvmBinaryPath);
35
+ } catch {
36
+ logger(`Failed to access ACVM at ${config.acvmBinaryPath}, falling back to WASM`);
37
+ }
38
+ }
39
+ logger('Using WASM ACVM simulation');
40
+ return new WASMSimulator();
41
+ }
14
42
 
15
43
  /**
16
44
  * Encapsulates the full sequencer and publisher.
@@ -40,14 +68,21 @@ export class SequencerClient {
40
68
  const globalsBuilder = getGlobalVariableBuilder(config);
41
69
  const merkleTreeDb = worldStateSynchronizer.getLatest();
42
70
 
71
+ const simulationProvider = await getSimulationProvider(config);
72
+
43
73
  const blockBuilder = new SoloBlockBuilder(
44
74
  merkleTreeDb,
45
75
  getVerificationKeys(),
46
- new RealRollupCircuitSimulator(),
76
+ new RealRollupCircuitSimulator(simulationProvider),
47
77
  new EmptyRollupProver(),
48
78
  );
49
79
 
50
- const publicProcessorFactory = new PublicProcessorFactory(merkleTreeDb, contractDataSource, l1ToL2MessageSource);
80
+ const publicProcessorFactory = new PublicProcessorFactory(
81
+ merkleTreeDb,
82
+ contractDataSource,
83
+ l1ToL2MessageSource,
84
+ simulationProvider,
85
+ );
51
86
 
52
87
  const sequencer = new Sequencer(
53
88
  publisher,
package/src/config.ts CHANGED
@@ -48,6 +48,8 @@ export function getConfigEnvVars(): SequencerClientConfig {
48
48
  OUTBOX_CONTRACT_ADDRESS,
49
49
  COINBASE,
50
50
  FEE_RECIPIENT,
51
+ ACVM_WORKING_DIRECTORY,
52
+ ACVM_BINARY_PATH,
51
53
  } = process.env;
52
54
 
53
55
  const publisherPrivateKey: Hex = SEQ_PUBLISHER_PRIVATE_KEY
@@ -82,5 +84,7 @@ export function getConfigEnvVars(): SequencerClientConfig {
82
84
  // TODO: undefined should not be allowed for the following 2 values in PROD
83
85
  coinbase: COINBASE ? EthAddress.fromString(COINBASE) : undefined,
84
86
  feeRecipient: FEE_RECIPIENT ? AztecAddress.fromString(FEE_RECIPIENT) : undefined,
87
+ acvmWorkingDirectory: ACVM_WORKING_DIRECTORY ? ACVM_WORKING_DIRECTORY : undefined,
88
+ acvmBinaryPath: ACVM_BINARY_PATH ? ACVM_BINARY_PATH : undefined,
85
89
  };
86
90
  }
package/src/index.ts CHANGED
@@ -1,15 +1,17 @@
1
- export * from './sequencer/index.js';
2
- export * from './config.js';
3
- export * from './publisher/index.js';
4
1
  export * from './client/index.js';
2
+ export * from './config.js';
5
3
  export * from './mocks/verification_keys.js';
4
+ export * from './publisher/index.js';
5
+ export * from './sequencer/index.js';
6
6
 
7
7
  // Used by the node to simulate public parts of transactions. Should these be moved to a shared library?
8
- export * from './sequencer/public_processor.js';
9
8
  export * from './global_variable_builder/index.js';
9
+ export * from './sequencer/public_processor.js';
10
10
 
11
11
  // Used by publisher test in e2e
12
- export { RealRollupCircuitSimulator } from './simulator/rollup.js';
13
- export { EmptyRollupProver } from './prover/empty.js';
14
12
  export { SoloBlockBuilder } from './block_builder/solo_block_builder.js';
15
- export { makeProcessedTx, makeEmptyProcessedTx } from './sequencer/processed_tx.js';
13
+ export { EmptyRollupProver } from './prover/empty.js';
14
+ export { makeEmptyProcessedTx, makeProcessedTx, partitionReverts } from './sequencer/processed_tx.js';
15
+ export { WASMSimulator } from './simulator/acvm_wasm.js';
16
+ export { RealRollupCircuitSimulator } from './simulator/rollup.js';
17
+ export { SimulationProvider } from './simulator/simulation_provider.js';
@@ -172,15 +172,15 @@ export class L1Publisher implements L2BlockReceiver {
172
172
  }
173
173
 
174
174
  if (receipt.status) {
175
- let txsHash;
175
+ let txsEffectsHash;
176
176
  if (receipt.logs.length === 1) {
177
- // txsHash from IAvailabilityOracle.TxsPublished event
178
- txsHash = receipt.logs[0].data;
177
+ // txsEffectsHash from IAvailabilityOracle.TxsPublished event
178
+ txsEffectsHash = receipt.logs[0].data;
179
179
  } else {
180
180
  this.log(`Expected 1 log, got ${receipt.logs.length}`);
181
181
  }
182
182
 
183
- this.log.info(`Block txs effects published, txsHash: ${txsHash}`);
183
+ this.log.info(`Block txs effects published, txsEffectsHash: ${txsEffectsHash}`);
184
184
  break;
185
185
  }
186
186
 
@@ -87,7 +87,7 @@ export class ViemTxSender implements L1PublisherTxSender {
87
87
  }
88
88
 
89
89
  checkIfTxsAreAvailable(block: L2Block): Promise<boolean> {
90
- const args = [`0x${block.body.getCalldataHash().toString('hex')}`] as const;
90
+ const args = [`0x${block.body.getTxsEffectsHash().toString('hex')}`] as const;
91
91
  return this.availabilityOracleContract.read.isAvailable(args);
92
92
  }
93
93