/// Rollback the current synced horizon state to a consistent state.
Rollback the current synced horizon state to a consistent state.
Rollback the current synced horizon state to a consistent state .
pub fn horizon_sync_rollback(&self) -> Result<(), ChainStorageError> {
        let mut db = self.db_write_access()?;
        let sync_state = match get_horizon_sync_state(&*db)? {
            Some(state) => state,
            None => {
                debug!(target: LOG_TARGET, "Horizon sync: Nothing to roll back");
                return Ok(());
            },
        };
        let mut txn = DbTransaction::new();
        // Rollback added kernels
        let first_tmp_checkpoint_index =
            usize::try_from(sync_state.initial_kernel_checkpoint_count).map_err(|_| ChainStorageError::OutOfRange)?;
        let cp_count = db.count_checkpoints(MmrTree::Kernel)?;
        for i in first_tmp_checkpoint_index..cp_count {
            let cp = db
                .fetch_checkpoint_at_index(MmrTree::Kernel, i)?
                .unwrap_or_else(|| panic!("Database is corrupt: Failed to fetch kernel checkpoint at index {}", i));
            let (nodes_added, _) = cp.into_parts();
            for hash in nodes_added {
                txn.delete(DbKey::TransactionKernel(hash));
            }
        }
        txn.rewind_kernel_mmr(cp_count - first_tmp_checkpoint_index);
        // Rollback UTXO changes
        let first_tmp_checkpoint_index =
            usize::try_from(sync_state.initial_utxo_checkpoint_count).map_err(|_| ChainStorageError::OutOfRange)?;
        let cp_count = db.count_checkpoints(MmrTree::Utxo)?;
        for i in first_tmp_checkpoint_index..cp_count {
            let cp = db
                .fetch_checkpoint_at_index(MmrTree::Utxo, i)?
                .unwrap_or_else(|| panic!("Database is corrupt: Failed to fetch UTXO checkpoint at index {}", i));
            let (nodes_added, deleted) = cp.into_parts();
            for hash in nodes_added {
                txn.delete(DbKey::UnspentOutput(hash));
            }
            for pos in deleted.iter() {
                let (stxo_hash, is_deleted) = db.fetch_mmr_node(MmrTree::Utxo, pos, None)?;
                debug_assert!(is_deleted);
                txn.unspend_stxo(stxo_hash);
            }
        }
        txn.rewind_utxo_mmr(cp_count - first_tmp_checkpoint_index);
        // Rollback Rangeproof checkpoints
        let first_tmp_checkpoint_index = usize::try_from(sync_state.initial_rangeproof_checkpoint_count)
            .map_err(|_| ChainStorageError::OutOfRange)?;
        let rp_checkpoint_count = db.count_checkpoints(MmrTree::RangeProof)?;
        txn.rewind_rangeproof_mmr(rp_checkpoint_count - first_tmp_checkpoint_index);
        // Rollback metadata
        let metadata = sync_state.metadata;
        txn.set_metadata(
            MetadataKey::ChainHeight,
            MetadataValue::ChainHeight(metadata.height_of_longest_chain),
        );
        txn.set_metadata(MetadataKey::BestBlock, MetadataValue::BestBlock(metadata.best_block));
        txn.set_metadata(
            MetadataKey::AccumulatedWork,
            MetadataValue::AccumulatedWork(metadata.accumulated_difficulty),
        );
        txn.set_metadata(
            MetadataKey::EffectivePrunedHeight,
            MetadataValue::EffectivePrunedHeight(metadata.effective_pruned_height),
        );
        // Remove pending horizon sync state
        txn.delete_metadata(MetadataKey::HorizonSyncState);
        commit(&mut *db, txn)
    }
pub fn horizon_sync_rollback ( & self ) -> Result < ( ) , ChainStorageError > { let mut db = self . db_write_access ( ) ? ; let sync_state = match get_horizon_sync_state ( & * db ) ? { Some ( state ) => state , None => { debug ! ( target LOG_TARGET " " ) ; return Ok ( ( ) ) ; } , } ; let mut txn = DbTransaction :: new ( ) ; // Rollback added kernels let first_tmp_checkpoint_index = usize :: try_from ( sync_state . initial_kernel_checkpoint_count ) . map_err ( | _ | ChainStorageError :: OutOfRange ) ? ; let cp_count = db . count_checkpoints ( MmrTree :: Kernel ) ? ; for i in first_tmp_checkpoint_index .. cp_count { let cp = db . fetch_checkpoint_at_index ( MmrTree :: Kernel , i ) ? . unwrap_or_else ( | | panic ! ( " " i ) ) ; let ( nodes_added , _ ) = cp . into_parts ( ) ; for hash in nodes_added { txn . delete ( DbKey :: TransactionKernel ( hash ) ) ; } } txn . rewind_kernel_mmr ( cp_count - first_tmp_checkpoint_index ) ; // Rollback UTXO changes let first_tmp_checkpoint_index = usize :: try_from ( sync_state . initial_utxo_checkpoint_count ) . map_err ( | _ | ChainStorageError :: OutOfRange ) ? ; let cp_count = db . count_checkpoints ( MmrTree :: Utxo ) ? ; for i in first_tmp_checkpoint_index .. cp_count { let cp = db . fetch_checkpoint_at_index ( MmrTree :: Utxo , i ) ? . unwrap_or_else ( | | panic ! ( " " i ) ) ; let ( nodes_added , deleted ) = cp . into_parts ( ) ; for hash in nodes_added { txn . delete ( DbKey :: UnspentOutput ( hash ) ) ; } for pos in deleted . iter ( ) { let ( stxo_hash , is_deleted ) = db . fetch_mmr_node ( MmrTree :: Utxo , pos , None ) ? ; debug_assert ! ( is_deleted ) ; txn . unspend_stxo ( stxo_hash ) ; } } txn . rewind_utxo_mmr ( cp_count - first_tmp_checkpoint_index ) ; // Rollback Rangeproof checkpoints let first_tmp_checkpoint_index = usize :: try_from ( sync_state . initial_rangeproof_checkpoint_count ) . map_err ( | _ | ChainStorageError :: OutOfRange ) ? ; let rp_checkpoint_count = db . count_checkpoints ( MmrTree :: RangeProof ) ? ; txn . rewind_rangeproof_mmr ( rp_checkpoint_count - first_tmp_checkpoint_index ) ; // Rollback metadata let metadata = sync_state . metadata ; txn . set_metadata ( MetadataKey :: ChainHeight , MetadataValue :: ChainHeight ( metadata . height_of_longest_chain ) , ) ; txn . set_metadata ( MetadataKey :: BestBlock , MetadataValue :: BestBlock ( metadata . best_block ) ) ; txn . set_metadata ( MetadataKey :: AccumulatedWork , MetadataValue :: AccumulatedWork ( metadata . accumulated_difficulty ) , ) ; txn . set_metadata ( MetadataKey :: EffectivePrunedHeight , MetadataValue :: EffectivePrunedHeight ( metadata . effective_pruned_height ) , ) ; // Remove pending horizon sync state txn . delete_metadata ( MetadataKey :: HorizonSyncState ) ; commit ( & mut * db , txn ) }
Rollback the current synced horizon state to a consistent state.
Rollback the current synced horizon state to a consistent state .
&self