diff --git a/src/cli/serve.rs b/src/cli/serve.rs index f8e5a06..c8091d4 100644 --- a/src/cli/serve.rs +++ b/src/cli/serve.rs @@ -52,6 +52,8 @@ use crate::{ utilities::{try_raise_fd_limit, value_parsers}, }; +const SPV_RESET_TIP_OFFSET: u32 = 1200; + #[derive(Parser)] pub struct Args { #[clap(flatten)] @@ -206,6 +208,34 @@ impl Args { let (spv_client, spv_update) = storage.generate_spv_client_and_spv_update(spv_tip_height, limit, flags)?; + let tx_hash = + self.reorg_spv_cells(&spv_service, input, spv_client, spv_update)?; + + prev_tx_hash = Some(tx_hash); + } + SpvOperation::Reset(input) => { + let flags = input.info.get_flags()?; + if BitcoinChainType::Testnet != flags.into() { + let msg = "failed to reorg since no common parent between SPV instance and storage"; + return Err(Error::other(msg)); + } + + log::info!( + "stale length: {:?}, clients count: {:?}", + input.stale.len(), + input.info.clients_count + ); + log::info!("Try to reset SPV instance"); + + let spv_tip_height = + input.curr.client.headers_mmr_root.max_height - SPV_RESET_TIP_OFFSET; + + let (spv_client, spv_update) = storage.generate_spv_client_and_spv_update( + spv_tip_height, + self.spv_headers_update_limit, + flags, + )?; + let tx_hash = self.reorg_spv_cells(&spv_service, input, spv_client, spv_update)?; diff --git a/src/components/spv_service.rs b/src/components/spv_service.rs index 607da98..7d6f798 100644 --- a/src/components/spv_service.rs +++ b/src/components/spv_service.rs @@ -36,6 +36,7 @@ pub struct SpvReorgInput { pub enum SpvOperation { Update(SpvUpdateInput), Reorg(SpvReorgInput), + Reset(SpvReorgInput), } impl SpvService { @@ -65,7 +66,12 @@ impl SpvService { let stg_header_root_curr = packed_stg_header_root_curr.unpack(); log::warn!("[storage] header#{spv_height_curr}; mmr-root {stg_header_root_curr}"); let input = self.prepare_reorg_input(ins)?; - return Ok(SpvOperation::Reorg(input)); + if input.info.clients_count as usize == input.stale.len() { + log::warn!("[onchain] all SPV clients are stale, resetting"); + return Ok(SpvOperation::Reset(input)); + } else { + return Ok(SpvOperation::Reorg(input)); + } } let next_tip_client_id = ins.info.next_tip_client_id(); @@ -130,8 +136,13 @@ impl SpvService { stale.push(cell.clone()); info.info.tip_client_id = info.prev_tip_client_id(); } - let msg = "failed to reorg since no common parent between SPV instance and storage"; - Err(Error::other(msg)) + log::warn!("failed to reorg since no common parent between SPV instance and storage"); + let input = SpvReorgInput { + info: info.clone(), + curr: clients.get(&info.info.tip_client_id).unwrap().clone(), + stale, + }; + Ok(input) } pub(crate) fn sync_storage(&self, batch_size: u32) -> Result {