anvil_zksync_l1_sidecar/
l1_executor.rs1use crate::commitment_generator::CommitmentGenerator;
2use crate::l1_sender::L1SenderHandle;
3use std::time::Duration;
4use tokio::sync::watch;
5use zksync_types::L1BatchNumber;
6
7#[derive(Debug, Clone)]
8pub struct L1Executor {
9 mode: L1ExecutorMode,
10}
11
12impl L1Executor {
13 pub fn manual() -> Self {
15 Self {
16 mode: L1ExecutorMode::Manual,
17 }
18 }
19
20 pub fn auto(
22 commitment_generator: CommitmentGenerator,
23 l1_sender_handle: L1SenderHandle,
24 ) -> Self {
25 Self {
26 mode: L1ExecutorMode::Auto(L1ExecutorModeAuto {
27 last_executed_batch: L1BatchNumber(0),
28 commitment_generator,
29 l1_sender_handle,
30 }),
31 }
32 }
33
34 pub async fn run(self, stop_receiver: &mut watch::Receiver<bool>) -> anyhow::Result<()> {
35 match self.mode {
36 L1ExecutorMode::Manual => {
37 stop_receiver.changed().await?;
38 Ok(())
39 }
40 L1ExecutorMode::Auto(executor) => executor.run(stop_receiver).await,
41 }
42 }
43}
44
45#[derive(Debug, Clone)]
46enum L1ExecutorMode {
47 Manual,
48 Auto(L1ExecutorModeAuto),
49}
50
51#[derive(Debug, Clone)]
52struct L1ExecutorModeAuto {
53 last_executed_batch: L1BatchNumber,
54 commitment_generator: CommitmentGenerator,
55 l1_sender_handle: L1SenderHandle,
56}
57
58impl L1ExecutorModeAuto {
59 async fn run(mut self, stop_receiver: &mut watch::Receiver<bool>) -> anyhow::Result<()> {
60 const POLL_INTERVAL: Duration = Duration::from_millis(100);
61
62 loop {
63 if *stop_receiver.borrow() {
64 tracing::info!("automatic L1 executor was interrupted");
65 return Ok(());
66 }
67 let next_batch = self.last_executed_batch + 1;
68 let Some(batch_with_metadata) = self
69 .commitment_generator
70 .get_or_generate_metadata(next_batch)
71 .await
72 else {
73 tracing::trace!(batch_number=%next_batch, "batch is not ready to be executed yet");
74 tokio::time::timeout(POLL_INTERVAL, stop_receiver.changed())
75 .await
76 .ok();
77 continue;
78 };
79 self.l1_sender_handle
80 .commit_sync(batch_with_metadata.clone())
81 .await?;
82 self.l1_sender_handle
83 .prove_sync(batch_with_metadata.clone())
84 .await?;
85 self.l1_sender_handle
86 .execute_sync(batch_with_metadata)
87 .await?;
88 tracing::debug!(batch_number=%next_batch, "batch has been automatically executed on L1");
89 self.last_executed_batch = next_batch;
90 }
91 }
92}