// Reorganize the main chain with the provided fork chain, starting at the specified height.
Reorganize the main chain with the provided fork chain, starting at the specified height.
Reorganize the main chain with the provided fork chain starting at the specified height .
fn reorganize_chain<T: BlockchainBackend>(
    db: &mut T,
    block_validator: &StatefulValidator<Block, T>,
    height: u64,
    chain: VecDeque<Arc<Block>>,
) -> Result<Vec<Arc<Block>>, ChainStorageError>
{
    let removed_blocks = rewind_to_height(db, height)?;
    debug!(
        target: LOG_TARGET,
        "Validate and add {} chain block(s) from height {}. Rewound blocks: [{}]",
        chain.len(),
        height,
        removed_blocks
            .iter()
            .map(|b| b.header.height.to_string())
            .collect::<Vec<_>>()
            .join(", ")
    );
    for block in chain {
        let mut txn = DbTransaction::new();
        let block_hash = block.hash();
        let block_hash_hex = block_hash.to_hex();
        txn.delete(DbKey::OrphanBlock(block_hash));
        if let Err(e) = block_validator.validate(&block, db) {
            warn!(
                target: LOG_TARGET,
                "Orphan block {} ({}) failed validation during chain reorg: {}", block.header.height, block_hash_hex, e
            );
            remove_orphan(db, block.hash())?;
            info!(target: LOG_TARGET, "Restoring previous chain after failed reorg.");
            restore_reorged_chain(db, height, removed_blocks)?;
            return Err(e.into());
        }
        store_new_block(&mut txn, unwrap_or_clone(block))?;
        // Failed to store the block - this should typically never happen unless there is a bug in the validator
        // (e.g. does not catch a double spend). In any case, we still need to restore the chain to a
        // good state before returning.
        if let Err(e) = commit(db, txn) {
            warn!(
                target: LOG_TARGET,
                "Failed to commit reorg chain: {}. Restoring last chain.", e
            );
            restore_reorged_chain(db, height, removed_blocks)?;
            return Err(e);
        }
    }
    Ok(removed_blocks)
}
fn reorganize_chain < T : BlockchainBackend > ( db : & mut T , block_validator : & StatefulValidator < Block , T > , height : u64 , chain : VecDeque < Arc < Block > > , ) -> Result < Vec < Arc < Block > > , ChainStorageError > { let removed_blocks = rewind_to_height ( db , height ) ? ; debug ! ( target LOG_TARGET " " chain len ( ) height removed_blocks iter ( ) map ( b b header height to_string ( ) ) collect Vec ( ) join ( " " ) ) ; for block in chain { let mut txn = DbTransaction :: new ( ) ; let block_hash = block . hash ( ) ; let block_hash_hex = block_hash . to_hex ( ) ; txn . delete ( DbKey :: OrphanBlock ( block_hash ) ) ; if let Err ( e ) = block_validator . validate ( & block , db ) { warn ! ( target LOG_TARGET " " block header height block_hash_hex e ) ; remove_orphan ( db , block . hash ( ) ) ? ; info ! ( target LOG_TARGET " " ) ; restore_reorged_chain ( db , height , removed_blocks ) ? ; return Err ( e . into ( ) ) ; } store_new_block ( & mut txn , unwrap_or_clone ( block ) ) ? ; // Failed to store the block - this should typically never happen unless there is a bug in the validator // (e.g. does not catch a double spend). In any case, we still need to restore the chain to a // good state before returning. if let Err ( e ) = commit ( db , txn ) { warn ! ( target LOG_TARGET " " e ) ; restore_reorged_chain ( db , height , removed_blocks ) ? ; return Err ( e ) ; } } Ok ( removed_blocks ) }
Reorganize the main chain with the provided fork chain, starting at the specified height.
Reorganize the main chain with the provided fork chain starting at the specified height .
db
&mut T
block_validator
&StatefulValidator<Block, T>
height
u64
chain
VecDeque<Arc<Block>>