Skip to content

Commit 9cf3cc4

Browse files
committed
fix: do not exit process on sync failure
1 parent 20769e2 commit 9cf3cc4

File tree

6 files changed

+54
-16
lines changed

6 files changed

+54
-16
lines changed

core/src/client/api.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use helios_common::{
1515
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
1616
pub trait HeliosApi<N: NetworkSpec>: Send + Sync + 'static {
1717
// node management
18-
async fn wait_synced(&self);
18+
async fn wait_synced(&self) -> Result<()>;
1919
async fn shutdown(&self);
2020
// state fetch
2121
async fn get_balance(&self, address: Address, block_id: BlockId) -> Result<U256>;

core/src/client/node.rs

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use std::marker::PhantomData;
22
use std::sync::Arc;
3-
use std::time::Duration;
43

54
use alloy::consensus::BlockHeader;
65
use alloy::eips::{BlockId, BlockNumberOrTag};
@@ -27,7 +26,7 @@ use helios_common::{
2726
use crate::consensus::Consensus;
2827
use crate::errors::ClientError;
2928
use crate::execution::filter_state::{FilterState, FilterType};
30-
use crate::time::{interval, SystemTime, UNIX_EPOCH};
29+
use crate::time::{SystemTime, UNIX_EPOCH};
3130

3231
use super::api::HeliosApi;
3332

@@ -169,14 +168,8 @@ impl<N: NetworkSpec, C: Consensus<N::BlockResponse>, E: ExecutionProvider<N>> He
169168
}
170169
}
171170

172-
async fn wait_synced(&self) {
173-
let mut interval = interval(Duration::from_millis(100));
174-
loop {
175-
interval.tick().await;
176-
if let Ok(SyncStatus::None) = self.syncing().await {
177-
break;
178-
}
179-
}
171+
async fn wait_synced(&self) -> Result<()> {
172+
self.consensus.wait_synced().await
180173
}
181174

182175
async fn call(&self, tx: &N::TransactionRequest, block_id: BlockId) -> Result<Bytes> {

core/src/consensus.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
use alloy::network::{primitives::HeaderResponse, BlockResponse, TransactionResponse};
2+
use async_trait::async_trait;
23
use eyre::Result;
34
use serde::Serialize;
45
use tokio::sync::{mpsc, watch};
56

7+
#[async_trait]
68
pub trait Consensus<
79
B: BlockResponse<Transaction: TransactionResponse, Header: HeaderResponse> + Serialize,
810
>: Sync + Send + 'static
@@ -12,4 +14,5 @@ pub trait Consensus<
1214
fn expected_highest_block(&self) -> u64;
1315
fn chain_id(&self) -> u64;
1416
fn shutdown(&self) -> Result<()>;
17+
async fn wait_synced(&self) -> Result<()>;
1518
}

ethereum/src/consensus.rs

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use std::marker::PhantomData;
2-
use std::process;
32
use std::sync::Arc;
43

54
use alloy::consensus::proofs::{calculate_transaction_root, calculate_withdrawals_root};
@@ -20,7 +19,7 @@ use url::Url;
2019
use tokio::sync::mpsc::channel;
2120
use tokio::sync::mpsc::Receiver;
2221
use tokio::sync::mpsc::Sender;
23-
use tokio::sync::watch;
22+
use tokio::sync::{watch, Mutex};
2423

2524
use helios_consensus_core::{
2625
apply_bootstrap, apply_finality_update, apply_update, calc_sync_period,
@@ -40,10 +39,18 @@ use crate::constants::MAX_REQUEST_LIGHT_CLIENT_UPDATES;
4039
use crate::database::Database;
4140
use crate::rpc::ConsensusRpc;
4241

42+
#[derive(Debug, Clone)]
43+
pub enum ConsensusSyncStatus {
44+
Syncing,
45+
Synced,
46+
Error(String),
47+
}
48+
4349
pub struct ConsensusClient<S: ConsensusSpec, R: ConsensusRpc<S>, DB: Database> {
4450
pub block_recv: Option<Receiver<Block<Transaction>>>,
4551
pub finalized_block_recv: Option<watch::Receiver<Option<Block<Transaction>>>>,
4652
pub checkpoint_recv: watch::Receiver<Option<B256>>,
53+
sync_status_recv: Mutex<watch::Receiver<ConsensusSyncStatus>>,
4754
shutdown_send: watch::Sender<bool>,
4855
genesis_time: u64,
4956
config: Arc<Config>,
@@ -62,6 +69,7 @@ pub struct Inner<S: ConsensusSpec, R: ConsensusRpc<S>> {
6269
phantom: PhantomData<S>,
6370
}
6471

72+
#[async_trait::async_trait]
6573
impl<S: ConsensusSpec, R: ConsensusRpc<S>, DB: Database> Consensus<Block>
6674
for ConsensusClient<S, R, DB>
6775
{
@@ -85,13 +93,30 @@ impl<S: ConsensusSpec, R: ConsensusRpc<S>, DB: Database> Consensus<Block>
8593
self.shutdown_send.send(true)?;
8694
Ok(())
8795
}
96+
97+
async fn wait_synced(&self) -> Result<()> {
98+
let mut sync_status_recv = self.sync_status_recv.lock().await;
99+
100+
loop {
101+
let status = sync_status_recv.borrow().clone();
102+
match status {
103+
ConsensusSyncStatus::Synced => return Ok(()),
104+
ConsensusSyncStatus::Error(err) => return Err(eyre!("sync failed: {}", err)),
105+
ConsensusSyncStatus::Syncing => {
106+
// Wait for status to change
107+
sync_status_recv.changed().await?;
108+
}
109+
}
110+
}
111+
}
88112
}
89113

90114
impl<S: ConsensusSpec, R: ConsensusRpc<S>, DB: Database> ConsensusClient<S, R, DB> {
91115
pub fn new(rpc: &Url, config: Arc<Config>) -> Result<ConsensusClient<S, R, DB>> {
92116
let (block_send, block_recv) = channel(256);
93117
let (finalized_block_send, finalized_block_recv) = watch::channel(None);
94118
let (checkpoint_send, checkpoint_recv) = watch::channel(None);
119+
let (sync_status_send, sync_status_recv) = watch::channel(ConsensusSyncStatus::Syncing);
95120
let (shutdown_send, shutdown_recv) = watch::channel(false);
96121

97122
let config_clone = config.clone();
@@ -125,20 +150,24 @@ impl<S: ConsensusSpec, R: ConsensusRpc<S>, DB: Database> ConsensusClient<S, R, D
125150
let res = sync_all_fallbacks(&mut inner, config.chain.chain_id).await;
126151
if let Err(err) = res {
127152
error!(target: "helios::consensus", err = %err, "sync failed");
128-
process::exit(1);
153+
_ = sync_status_send.send(ConsensusSyncStatus::Error(err.to_string()));
154+
return;
129155
}
130156
} else if let Some(fallback) = &config.fallback {
131157
let res = sync_fallback(&mut inner, fallback).await;
132158
if let Err(err) = res {
133159
error!(target: "helios::consensus", err = %err, "sync failed");
134-
process::exit(1);
160+
_ = sync_status_send.send(ConsensusSyncStatus::Error(err.to_string()));
161+
return;
135162
}
136163
} else {
137164
error!(target: "helios::consensus", err = %err, "sync failed");
138-
process::exit(1);
165+
_ = sync_status_send.send(ConsensusSyncStatus::Error(err.to_string()));
166+
return;
139167
}
140168
}
141169

170+
_ = sync_status_send.send(ConsensusSyncStatus::Synced);
142171
_ = inner.send_blocks().await;
143172

144173
let start = Instant::now() + inner.duration_until_next_update().to_std().unwrap();
@@ -180,6 +209,7 @@ impl<S: ConsensusSpec, R: ConsensusRpc<S>, DB: Database> ConsensusClient<S, R, D
180209
block_recv: Some(block_recv),
181210
finalized_block_recv: Some(finalized_block_recv),
182211
checkpoint_recv,
212+
sync_status_recv: Mutex::new(sync_status_recv),
183213
shutdown_send,
184214
genesis_time,
185215
config: config_clone,

linea/src/consensus.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ impl ConsensusClient {
7171
}
7272
}
7373

74+
#[async_trait::async_trait]
7475
impl Consensus<Block<Transaction>> for ConsensusClient {
7576
fn chain_id(&self) -> u64 {
7677
self.chain_id
@@ -91,6 +92,11 @@ impl Consensus<Block<Transaction>> for ConsensusClient {
9192
fn expected_highest_block(&self) -> u64 {
9293
u64::MAX
9394
}
95+
96+
async fn wait_synced(&self) -> eyre::Result<()> {
97+
// Linea consensus doesn't have a sync process, so immediately return Ok
98+
Ok(())
99+
}
94100
}
95101

96102
#[allow(dead_code)]

opstack/src/consensus.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ impl ConsensusClient {
8787
}
8888
}
8989

90+
#[async_trait::async_trait]
9091
impl Consensus<Block<Transaction>> for ConsensusClient {
9192
fn chain_id(&self) -> u64 {
9293
self.chain_id
@@ -107,6 +108,11 @@ impl Consensus<Block<Transaction>> for ConsensusClient {
107108
fn expected_highest_block(&self) -> u64 {
108109
u64::MAX
109110
}
111+
112+
async fn wait_synced(&self) -> eyre::Result<()> {
113+
// OpStack consensus doesn't have a sync process, so immediately return Ok
114+
Ok(())
115+
}
110116
}
111117

112118
#[allow(dead_code)]

0 commit comments

Comments
 (0)