diff --git a/src/protocols/light_client/components/send_last_state.rs b/src/protocols/light_client/components/send_last_state.rs index 8f36255..032238c 100644 --- a/src/protocols/light_client/components/send_last_state.rs +++ b/src/protocols/light_client/components/send_last_state.rs @@ -1,5 +1,7 @@ -use super::super::{LastState, LightClientProtocol, Status}; +use super::super::{LastState, LightClientProtocol, Status, StatusCode}; +use ckb_constant::sync::MAX_TIP_AGE; use ckb_network::{CKBProtocolContext, PeerIndex}; +use ckb_systemtime::unix_time_as_millis; use ckb_types::{packed, prelude::*, utilities::merkle_mountain_range::VerifiableHeader}; use log::{debug, trace}; @@ -30,6 +32,7 @@ impl<'a> SendLastStateProcess<'a> { let last_header: VerifiableHeader = self.message.last_header().to_entity().into(); return_if_failed!(self.protocol.check_verifiable_header(&last_header)); + return_if_failed!(check_last_state(&last_header)); let last_state = LastState::new(last_header); @@ -72,3 +75,16 @@ impl<'a> SendLastStateProcess<'a> { Status::ok() } } + +fn check_last_state(last_header: &VerifiableHeader) -> Result<(), Status> { + let now = unix_time_as_millis(); + let timestamp = last_header.header().timestamp(); + if now.saturating_sub(timestamp) > MAX_TIP_AGE { + let errmsg = format!( + "still in initial block download with a very high probability \ + since {now} - {timestamp} > {MAX_TIP_AGE}", + ); + return Err(StatusCode::PeerIsInIBD.with_context(errmsg)); + } + Ok(()) +} diff --git a/src/protocols/status.rs b/src/protocols/status.rs index df1fd6b..5e7d275 100644 --- a/src/protocols/status.rs +++ b/src/protocols/status.rs @@ -34,6 +34,8 @@ pub enum StatusCode { InvalidLastState = 412, /// The peer state is not correct for transition. IncorrectLastState = 413, + /// The peer is still in initial block download with a very high probability. + PeerIsInIBD = 414, /// Receives a response but the peer isn't waiting for a response. PeerIsNotOnProcess = 421,