From b635be475f6040cdd85b9dfbc2172905e0323bc8 Mon Sep 17 00:00:00 2001 From: Terry <644052732@qq.com> Date: Thu, 16 May 2024 20:02:27 +0800 Subject: [PATCH 1/4] feat: extend eigen rpc, add get_batch_proof, get_block_by_number --- src/batch_proposer/mod.rs | 23 ++++++++++++++++++-- src/commands/run.rs | 13 +++++++++-- src/custom_reth/eigen.rs | 45 +++++++++++++++++++++++++++++++++++---- src/custom_reth/mod.rs | 3 +++ src/db/mod.rs | 38 +++++++++++++++++++++++++++++++++ src/operator.rs | 14 +++++------- src/prover/provider.rs | 12 +---------- src/settlement/worker.rs | 21 ++++++++++++++++-- 8 files changed, 139 insertions(+), 30 deletions(-) diff --git a/src/batch_proposer/mod.rs b/src/batch_proposer/mod.rs index 3289af4..b82faa3 100644 --- a/src/batch_proposer/mod.rs +++ b/src/batch_proposer/mod.rs @@ -1,5 +1,5 @@ -use crate::db::keys; use crate::db::Database; +use crate::db::{keys, prefix, Status}; use anyhow::{anyhow, bail, Result}; use ethers_providers::{Http, Middleware, Provider}; use std::sync::Arc; @@ -75,7 +75,26 @@ impl L2Watcher { .map_err(|e| anyhow!("{:?}", e)) .map(|number| { log::info!("L2Watcher fetched block({})", number); - db.put(keys::KEY_LAST_SEQUENCE_FINALITY_BLOCK_NUMBER.to_vec(), number.as_u64().to_be_bytes().to_vec()) + + let last_fetched_block = match db.get(keys::KEY_LAST_SEQUENCE_FINALITY_BLOCK_NUMBER) { + None => { + db.put(keys::KEY_LAST_SEQUENCE_FINALITY_BLOCK_NUMBER.to_vec(), number.as_u64().to_be_bytes().to_vec()); + 0 + } + Some(block_number_bytes) => { + u64::from_be_bytes(block_number_bytes.try_into().unwrap()) + } + }; + + db.put(keys::KEY_LAST_SEQUENCE_FINALITY_BLOCK_NUMBER.to_vec(), number.as_u64().to_be_bytes().to_vec()); + for number in last_fetched_block+1..number.as_u64()+1 { + // update block status to sequenced + let status_key = format!("{}{}", std::str::from_utf8(prefix::PREFIX_BLOCK_STATUS).unwrap(), number); + let status = Status::Sequenced; + let encoded_status = serde_json::to_vec(&status).unwrap(); + db.put(status_key.as_bytes().to_vec(), encoded_status); + + } }) }, _ = stop_rx.recv() => { diff --git a/src/commands/run.rs b/src/commands/run.rs index c3be2f2..2e088c5 100644 --- a/src/commands/run.rs +++ b/src/commands/run.rs @@ -1,6 +1,7 @@ use std::fmt; +use std::sync::Arc; -use anyhow::Result; +use anyhow::{anyhow, Result}; use tokio::select; use tokio::signal::unix::{signal, SignalKind}; use tokio::sync::mpsc; @@ -211,15 +212,21 @@ impl RunCmd { reth_stop_tx.send(()).await.unwrap(); }); + // initialize the database + let rollup_db = + lfs::open_db(db_config).map_err(|e| anyhow!("Failed to open db: {:?}", e))?; + let arc_rollup_db = Arc::new(rollup_db); + let (reth_started_signal_tx, reth_started_signal_rx) = mpsc::channel::<()>(1); let a = aggregator_addr.clone(); + let operator_rollup_db = arc_rollup_db.clone(); tokio::spawn(async move { // Run the operator Operator::run( &GLOBAL_ENV.l2addr, &GLOBAL_ENV.prover_addr, settlement_spec.clone(), - db_config.clone(), + operator_rollup_db, a.as_str(), stop_rx, reth_started_signal_rx, @@ -231,11 +238,13 @@ impl RunCmd { let rpc_args = self.reth_cmd.rpc.clone(); let dev_args = self.reth_cmd.dev; let data_dir = self.reth_cmd.datadir.clone(); + let reth_rollup_db = arc_rollup_db.clone(); // Launch the custom reth custom_reth::launch_custom_node( reth_stop_rx, reth_started_signal_tx, + reth_rollup_db, chain_spec, rpc_args, data_dir, diff --git a/src/custom_reth/eigen.rs b/src/custom_reth/eigen.rs index 25b4b00..3495096 100644 --- a/src/custom_reth/eigen.rs +++ b/src/custom_reth/eigen.rs @@ -1,10 +1,13 @@ +use std::sync::Arc; // Reth block related imports use reth_primitives::{Block, B256}; use reth_provider::BlockReaderIdExt; // Rpc related imports +use crate::db::{prefix, BlockExt, Database as RollupDatabase, ProofResult, Status}; use jsonrpsee::proc_macros::rpc; -use reth_rpc::eth::error::EthResult; +use reth_interfaces::RethError; +use reth_rpc::eth::error::{EthApiError, EthResult}; /// trait interface for a custom rpc namespace: `EigenRpc` /// @@ -15,14 +18,17 @@ pub trait EigenRpcExtApi { #[method(name = "customMethod")] fn custom_methhod(&self) -> EthResult>; #[method(name = "getBlockByNumber")] - fn get_block_by_number(&self, block_no: u64) -> EthResult>; + fn get_block_by_number(&self, block_no: u64) -> EthResult>; #[method(name = "traceTransaction")] fn trace_transaction(&self, hash: B256) -> EthResult>; + #[method(name = "getBatchProof")] + fn get_batch_proof(&self, block_no: u64) -> EthResult>; } /// The type that implements `EigenRpc` rpc namespace trait pub struct EigenRpcExt { pub provider: Provider, + pub rollup_db: Arc>, } impl EigenRpcExtApiServer for EigenRpcExt @@ -39,9 +45,24 @@ where } // TODO: override the eth_get_block_by_hash to check if the block has been confirmed by L1 - fn get_block_by_number(&self, block_no: u64) -> EthResult> { + fn get_block_by_number(&self, block_no: u64) -> EthResult> { let block = self.provider.block_by_number(block_no)?; - Ok(block) + if let Some(block) = block { + let status_key = format!( + "{}{}", + std::str::from_utf8(prefix::PREFIX_BLOCK_STATUS) + .map_err(|e| EthApiError::Internal(RethError::Custom(e.to_string())))?, + block_no + ); + let status = match self.rollup_db.get(status_key.as_bytes()) { + Some(status_bytes) => serde_json::from_slice(&status_bytes) + .map_err(|e| EthApiError::Internal(RethError::Custom(e.to_string())))?, + None => Status::Pending, + }; + Ok(Some(BlockExt { block, status })) + } else { + Ok(None) + } } // TODO return the pre and post data for zkvm @@ -50,4 +71,20 @@ where //let traces = self.provider.trace Ok(Some(())) } + + fn get_batch_proof(&self, block_no: u64) -> EthResult> { + let next_proof_key = format!( + "{}{}", + std::str::from_utf8(prefix::PREFIX_BATCH_PROOF) + .map_err(|e| EthApiError::Internal(RethError::Custom(e.to_string())))?, + block_no + ); + if let Some(proof_bytes) = self.rollup_db.get(next_proof_key.as_bytes()) { + let proof: ProofResult = serde_json::from_slice(&proof_bytes) + .map_err(|e| EthApiError::Internal(RethError::Custom(e.to_string())))?; + Ok(Some(proof)) + } else { + Ok(None) + } + } } diff --git a/src/custom_reth/mod.rs b/src/custom_reth/mod.rs index 6454ed3..7caf6e2 100644 --- a/src/custom_reth/mod.rs +++ b/src/custom_reth/mod.rs @@ -47,6 +47,7 @@ use thiserror::Error; use crate::custom_reth::eigen::EigenRpcExt; use crate::custom_reth::eigen::EigenRpcExtApiServer; +use crate::db::Database as RollupDatabase; use anyhow::{anyhow, Result}; use jsonrpsee::tracing; use reth_blockchain_tree::{ @@ -341,6 +342,7 @@ where pub async fn launch_custom_node( mut stop_rx: tokio::sync::mpsc::Receiver<()>, reth_started_signal_channel: tokio::sync::mpsc::Sender<()>, + rollup_db: Arc>, spec: Arc, rpc_args: RpcServerArgs, data_dir: MaybePlatformPath, @@ -395,6 +397,7 @@ pub async fn launch_custom_node( // create EigenRpcExt Instance let custom_rpc = EigenRpcExt { provider: provider.clone(), + rollup_db: rollup_db.clone(), }; // add EigenRpcExt to RPC modules diff --git a/src/db/mod.rs b/src/db/mod.rs index 65c5c4a..5b4ca6f 100644 --- a/src/db/mod.rs +++ b/src/db/mod.rs @@ -1,6 +1,10 @@ // TODO: Fix me #![allow(dead_code)] +use jsonrpsee::core::Serialize; +use reth_primitives::Block; +use serde::Deserialize; + mod data_availability_db; pub(crate) mod lfs; @@ -36,4 +40,38 @@ pub(crate) mod keys { pub(crate) mod prefix { pub const PREFIX_BATCH_PROOF: &[u8] = b"BATCH_PROOF_"; + pub const PREFIX_BLOCK_STATUS: &[u8] = b"BLOCK_STATUS_"; +} + +/// A custom struct that extends the standard `reth::Block` struct with a `status` field. +/// This additional field represents the status of the block within the rollup process. +#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)] +pub struct BlockExt { + pub block: Block, + pub status: Status, +} + +#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)] +pub enum Status { + /// the tx is pending + Pending, + /// confirmed by sequencer + Sequenced, + /// packing the block into a batch + Batching, + /// confirmed by DA + /// TODO: we skip the DA for now, should support it in the future + Submitted, + /// confirmed by settlement + Finalized, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct ProofResult { + // TODO: refactor to batch + pub block_number: u64, + pub proof: String, + pub public_input: String, + pub pre_state_root: [u8; 32], + pub post_state_root: [u8; 32], } diff --git a/src/operator.rs b/src/operator.rs index c5064b8..ab1cead 100644 --- a/src/operator.rs +++ b/src/operator.rs @@ -8,7 +8,7 @@ use anyhow::{anyhow, Result}; // use ethers_core::types::{Bytes, H160, U256}; use ethers_providers::{Http, Provider}; // use serde::Serialize; -use crate::db::lfs; +use crate::db::Database; use std::sync::Arc; use tokio::sync::mpsc; use tokio::sync::mpsc::Receiver; @@ -22,7 +22,7 @@ impl Operator { l2addr: &str, prover_addr: &str, settlement_spec: NetworkSpec, - db_config: lfs::DBConfig, + rollup_db: Arc>, aggregator_addr: &str, mut stop_rx: Receiver<()>, mut reth_started_signal_rx: Receiver<()>, @@ -31,10 +31,6 @@ impl Operator { // initialize the prover let prover = ProverChannel::new(prover_addr, aggregator_addr); - // initialize the database - let db = lfs::open_db(db_config).map_err(|e| anyhow!("Failed to open db: {:?}", e))?; - let arc_db = Arc::new(db); - // initialize the settlement layer let settlement_provider = init_settlement_provider(settlement_spec) .map_err(|e| anyhow!("Failed to init settlement: {:?}", e))?; @@ -51,14 +47,14 @@ impl Operator { log::info!("Initializing reth Provider with address: {}", l2addr); let l2provider = Provider::::try_from(l2addr) .map_err(|e| anyhow!("Failed to init l2 provider: {:?}", e))?; - let mut l2watcher = L2Watcher::new(arc_db.clone(), l2provider); + let mut l2watcher = L2Watcher::new(rollup_db.clone(), l2provider); // start all components of the eigen-zeth full node // start the L2Watcher l2watcher.start().await.unwrap(); // start the verify worker - let arc_db_for_verify_worker = arc_db.clone(); + let arc_db_for_verify_worker = rollup_db.clone(); let (verify_stop_tx, verify_stop_rx) = mpsc::channel::<()>(1); tokio::spawn(async move { Settler::verify_worker( @@ -70,7 +66,7 @@ impl Operator { }); // start the proof worker - let arc_db_for_proof_worker = arc_db.clone(); + let arc_db_for_proof_worker = rollup_db.clone(); let (proof_stop_tx, proof_stop_rx) = mpsc::channel::<()>(1); tokio::spawn(async move { Settler::proof_worker(arc_db_for_proof_worker, prover, proof_stop_rx).await diff --git a/src/prover/provider.rs b/src/prover/provider.rs index 045564d..f1b5208 100644 --- a/src/prover/provider.rs +++ b/src/prover/provider.rs @@ -6,6 +6,7 @@ //! 3) If the task is finished, update the status into proof database, hence the extended RPC module will fetch this and return it to SDK. use crate::config::env::GLOBAL_ENV; +use crate::db::ProofResult; use crate::prover::provider::prover_service::prover_request::RequestType; use crate::prover::provider::prover_service::prover_response::ResponseType; use crate::prover::provider::prover_service::prover_service_client::ProverServiceClient; @@ -14,7 +15,6 @@ use crate::prover::provider::prover_service::{ ProverRequest, }; use anyhow::{anyhow, bail, Result}; -use serde::{Deserialize, Serialize}; use std::fmt; use std::time::Duration; use tokio::sync::mpsc; @@ -63,16 +63,6 @@ pub enum ExecuteResult { Failed(ErrMsg), } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct ProofResult { - // TODO: refactor to batch - pub block_number: u64, - pub proof: String, - pub public_input: String, - pub pre_state_root: [u8; 32], - pub post_state_root: [u8; 32], -} - /// ProveStep ... #[derive(Debug)] enum ProveStep { diff --git a/src/settlement/worker.rs b/src/settlement/worker.rs index ead0c46..966383e 100644 --- a/src/settlement/worker.rs +++ b/src/settlement/worker.rs @@ -1,5 +1,4 @@ -use crate::db::{keys, prefix, Database}; -use crate::prover::provider::ProofResult; +use crate::db::{keys, prefix, Database, ProofResult, Status}; use crate::prover::ProverChannel; use crate::settlement::Settlement; use anyhow::Result; @@ -57,7 +56,13 @@ impl Settler { match (next_batch, current_batch){ (None, None) => { // insert the first block + // packing the first block db.put(keys::KEY_NEXT_BATCH.to_vec(), 1_u64.to_be_bytes().to_vec()); + // update the block status to Batching + let status_key = format!("{}{}", std::str::from_utf8(prefix::PREFIX_BLOCK_STATUS).unwrap(), 1); + let status = Status::Batching; + let encoded_status = serde_json::to_vec(&status).unwrap(); + db.put(status_key.as_bytes().to_vec(), encoded_status); }, (Some(no), None) => { let block_no = u64::from_be_bytes(no.try_into().unwrap()); @@ -84,7 +89,13 @@ impl Settler { // update the next batch number, trigger the next prove task let block_no_next = block_no + 1; + // packing the next block db.put(keys::KEY_NEXT_BATCH.to_vec(), block_no_next.to_be_bytes().to_vec()); + // update the block status to Batching + let status_key = format!("{}{}", std::str::from_utf8(prefix::PREFIX_BLOCK_STATUS).unwrap(), block_no_next); + let status = Status::Batching; + let encoded_status = serde_json::to_vec(&status).unwrap(); + db.put(status_key.as_bytes().to_vec(), encoded_status); } _ = stop_rx.recv() => { @@ -167,6 +178,12 @@ impl Settler { Ok(_) => { log::info!("verify proof success, block({})", proof_data.block_number); db.put(keys::KEY_LAST_VERIFIED_BLOCK_NUMBER.to_vec(), proof_data.block_number.to_be_bytes().to_vec()); + + // verify success, update the block status to Finalized + let status_key = format!("{}{}", std::str::from_utf8(prefix::PREFIX_BLOCK_STATUS).unwrap(), proof_data.block_number); + let status = Status::Finalized; + let encoded_status = serde_json::to_vec(&status).unwrap(); + db.put(status_key.as_bytes().to_vec(), encoded_status); } Err(e) => { log::error!("verify proof failed, block({}), err: {:?}",proof_data.block_number, e); From 7f811e12e4839b9868bdd60cffcb9c8532573fbe Mon Sep 17 00:00:00 2001 From: Terry <644052732@qq.com> Date: Thu, 16 May 2024 23:20:44 +0800 Subject: [PATCH 2/4] fix: update the first block status --- src/settlement/worker.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/settlement/worker.rs b/src/settlement/worker.rs index 966383e..b1a7bf9 100644 --- a/src/settlement/worker.rs +++ b/src/settlement/worker.rs @@ -37,6 +37,11 @@ impl Settler { let next_batch = match db.get(keys::KEY_NEXT_BATCH) { None => { db.put(keys::KEY_NEXT_BATCH.to_vec(), 1_u64.to_be_bytes().to_vec()); + // update the block status to Batching + let status_key = format!("{}{}", std::str::from_utf8(prefix::PREFIX_BLOCK_STATUS).unwrap(), 1); + let status = Status::Batching; + let encoded_status = serde_json::to_vec(&status).unwrap(); + db.put(status_key.as_bytes().to_vec(), encoded_status); 1 } Some(block_number_bytes) => { From 8b90b6b0a5e8f476f7c10f1abfacd2a6f79c43eb Mon Sep 17 00:00:00 2001 From: Terry <644052732@qq.com> Date: Fri, 17 May 2024 16:21:33 +0800 Subject: [PATCH 3/4] docs: update README --- README.md | 4 ++++ src/prover/provider.rs | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3d0f45f..ff38e73 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,8 @@ PROVER_ADDR=http://localhost:50061 cargo run -r -- run --database mdbx --log-lev curl -H "Content-Type: application/json" -X POST --data '{"jsonrpc":"2.0","method":"eigenrpc_customMethod","params":[],"id": 10}' 127.0.0.1:8546 curl -H "Content-Type: application/json" -X POST --data '{"jsonrpc":"2.0","method":"eigenrpc_getBlockByNumber","params":[0],"id": 10}' 127.0.0.1:8546 + +curl -H "Content-Type: application/json" -X POST --data '{"jsonrpc":"2.0","method":"eigenrpc_getBatchProof","params":[0],"id": 10}' 127.0.0.1:8546 ``` You can also use [cast](https://github.com/foundry-rs/foundry/releases). @@ -30,4 +32,6 @@ You can also use [cast](https://github.com/foundry-rs/foundry/releases). cast rpc --rpc-url http://localhost:8546 eigenrpc_customMethod cast rpc --rpc-url http://localhost:8546 eigenrpc_getBlockByNumber 0 + +cast rpc --rpc-url http://localhost:8546 eigenrpc_getBatchProof 0 ``` diff --git a/src/prover/provider.rs b/src/prover/provider.rs index f1b5208..b0ce2d8 100644 --- a/src/prover/provider.rs +++ b/src/prover/provider.rs @@ -19,6 +19,7 @@ use std::fmt; use std::time::Duration; use tokio::sync::mpsc; use tokio::sync::mpsc::{Receiver, Sender}; +use tokio::time; use tokio_stream::wrappers::ReceiverStream; pub mod prover_service { @@ -145,7 +146,8 @@ impl ProverChannel { Err(e) => { // stop with the error // TODO: relaunch the endpoint - log::error!("ProverEndpoint error: {:?}", e); + log::error!("ProverEndpoint stopped with error, try again later, err: {:?}", e); + time::sleep(Duration::from_secs(10)).await; } } } From d3b4d17d9e67a5da7d6782aaaf5121378b250338 Mon Sep 17 00:00:00 2001 From: Terry <644052732@qq.com> Date: Fri, 17 May 2024 16:57:49 +0800 Subject: [PATCH 4/4] refactor: update eigen api: getBatchProof, state root [u8; 32] -> 0x + hexadecimal string --- src/custom_reth/eigen.rs | 37 ++++++++++++++++++++++++++++++++----- src/db/mod.rs | 9 --------- src/prover/provider.rs | 5 ++++- 3 files changed, 36 insertions(+), 15 deletions(-) diff --git a/src/custom_reth/eigen.rs b/src/custom_reth/eigen.rs index 3495096..ba52b1c 100644 --- a/src/custom_reth/eigen.rs +++ b/src/custom_reth/eigen.rs @@ -1,13 +1,15 @@ +use jsonrpsee::core::Serialize; use std::sync::Arc; // Reth block related imports use reth_primitives::{Block, B256}; use reth_provider::BlockReaderIdExt; // Rpc related imports -use crate::db::{prefix, BlockExt, Database as RollupDatabase, ProofResult, Status}; +use crate::db::{prefix, Database as RollupDatabase, ProofResult, Status}; use jsonrpsee::proc_macros::rpc; use reth_interfaces::RethError; use reth_rpc::eth::error::{EthApiError, EthResult}; +use serde::Deserialize; /// trait interface for a custom rpc namespace: `EigenRpc` /// @@ -22,7 +24,7 @@ pub trait EigenRpcExtApi { #[method(name = "traceTransaction")] fn trace_transaction(&self, hash: B256) -> EthResult>; #[method(name = "getBatchProof")] - fn get_batch_proof(&self, block_no: u64) -> EthResult>; + fn get_batch_proof(&self, block_no: u64) -> EthResult>; } /// The type that implements `EigenRpc` rpc namespace trait @@ -44,7 +46,6 @@ where Ok(block) } - // TODO: override the eth_get_block_by_hash to check if the block has been confirmed by L1 fn get_block_by_number(&self, block_no: u64) -> EthResult> { let block = self.provider.block_by_number(block_no)?; if let Some(block) = block { @@ -72,7 +73,7 @@ where Ok(Some(())) } - fn get_batch_proof(&self, block_no: u64) -> EthResult> { + fn get_batch_proof(&self, block_no: u64) -> EthResult> { let next_proof_key = format!( "{}{}", std::str::from_utf8(prefix::PREFIX_BATCH_PROOF) @@ -82,9 +83,35 @@ where if let Some(proof_bytes) = self.rollup_db.get(next_proof_key.as_bytes()) { let proof: ProofResult = serde_json::from_slice(&proof_bytes) .map_err(|e| EthApiError::Internal(RethError::Custom(e.to_string())))?; - Ok(Some(proof)) + let proof_info = BatchProofInfo { + block_number: proof.block_number, + proof: proof.proof, + public_input: proof.public_input, + pre_state_root: format!("0x{}", hex::encode(proof.pre_state_root)), + post_state_root: format!("0x{}", hex::encode(proof.post_state_root)), + }; + Ok(Some(proof_info)) } else { Ok(None) } } } + +/// A custom struct that extends the standard `reth::Block` struct with a `status` field. +/// This additional field represents the status of the block within the rollup process. +#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)] +pub struct BlockExt { + pub block: Block, + pub status: Status, +} + +#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)] +pub struct BatchProofInfo { + pub block_number: u64, + pub proof: String, + pub public_input: String, + // 0x + hex([u8; 32]) + pub pre_state_root: String, + // 0x + hex([u8; 32]) + pub post_state_root: String, +} diff --git a/src/db/mod.rs b/src/db/mod.rs index 5b4ca6f..3a57073 100644 --- a/src/db/mod.rs +++ b/src/db/mod.rs @@ -2,7 +2,6 @@ #![allow(dead_code)] use jsonrpsee::core::Serialize; -use reth_primitives::Block; use serde::Deserialize; mod data_availability_db; @@ -43,14 +42,6 @@ pub(crate) mod prefix { pub const PREFIX_BLOCK_STATUS: &[u8] = b"BLOCK_STATUS_"; } -/// A custom struct that extends the standard `reth::Block` struct with a `status` field. -/// This additional field represents the status of the block within the rollup process. -#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)] -pub struct BlockExt { - pub block: Block, - pub status: Status, -} - #[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)] pub enum Status { /// the tx is pending diff --git a/src/prover/provider.rs b/src/prover/provider.rs index b0ce2d8..27b2862 100644 --- a/src/prover/provider.rs +++ b/src/prover/provider.rs @@ -146,7 +146,10 @@ impl ProverChannel { Err(e) => { // stop with the error // TODO: relaunch the endpoint - log::error!("ProverEndpoint stopped with error, try again later, err: {:?}", e); + log::error!( + "ProverEndpoint stopped with error, try again later, err: {:?}", + e + ); time::sleep(Duration::from_secs(10)).await; } }