You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: blockchain.rs
    path of file: ./repos/akula/src/consensus
    
    the code of the file until where you have to start completion: use crate::{
    consensus::*,
    execution::{analysis_cache::AnalysisCache, processor::ExecutionProcessor, tracer::NoopTracer},
    models::*,
    state::*,
};
use anyhow::format_err;
use std::{collections::HashMap, convert::TryFrom};

#[derive(Debug)]
pub struct Blockchain<'state> {
    state: &'state mut InMemoryState,
    config: ChainSpec,
    engine: Box<dyn Consensus>,
    bad_blocks: HashMap<H256, ValidationError>,
    receipts: Vec<Receipt>,
}

impl<'state> Blockchain<'state> {
    pub fn new(
        state: &'state mut InMemoryState,
        config: ChainSpec,
        genesis_block: Block,
    ) -> anyhow::Result<Blockchain<'state>> {
        Self::new_with_consensus(
            state,
            engine_factory(None, config.clone(), None)?,
            config,
            genesis_block,
        )
    }

 
    
    pub fn insert_block(&mut self, block: Block, check_state_root: bool) -> Result<(), DuoError> {
        let parent = self
            .state
            .read_parent_header(&block.header)?
            .ok_or_else(|| format_err!("no parent header"))?;
        self.engine
            .validate_block_header(&block.header, &parent, true)?;
        self.engine.pre_validate_block(&block, &self.state)?;

        let hash = block.header.hash();
        if let Some(error) = self.bad_blocks.get(&hash) {
            return Err(error.clone().into());
        }

        let b = BlockWithSenders::from(block.clone());

        let ancestor = self.canonical_ancestor(&b.header, hash)?;

        let current_canonical_block = self.state.current_canonical_block();

        self.unwind_last_changes(ancestor, current_canonical_block)?;

        let block_number = b.header.number;

        let mut chain = self.intermediate_chain(
            BlockNumber(block_number.0 - 1),
            b.header.parent_hash,
            ancestor,
        )?;
        chain.push(WithHash { inner: b, hash });

        let mut num_of_executed_chain_blocks = 0;
        for x in &chain {
            self.execute_block(&x.inner, check_state_root)
                .or_else(|e| {
                    Err(match e {
                        DuoError::Validation(e) => {
                            self.bad_blocks.insert(hash, e.clone());
                            self.unwind_last_changes(
                                ancestor,
                                ancestor.0 + num_of_executed_chain_blocks,
                            )?;
                            self.re_execute_canonical_chain(ancestor, current_canonical_block)?;

                            DuoError::Validation(e)
                        }
                        DuoError::Internal(e) => DuoError::Internal(
                            e.context(format!("Failed to execute block #{}", block_number)),
                        ),
                    })
                })?;

            num_of_executed_chain_blocks += 1;
        }

        self.state.insert_block(block, hash);

        let current_total_difficulty = self
            .state
            .total_difficulty(
                current_canonical_block,
                self.state.canonical_hash(current_canonical_block).unwrap(),
            )
            .unwrap();

        if self.state.total_difficulty(block_number, hash).unwrap() > current_total_difficulty {
            // canonize the new chain
            for i in (ancestor + 1..=current_canonical_block).rev() {
                self.state.decanonize_block(i);
            }

            for x in chain {
                self.state.canonize_block(x.header.number, x.hash);
            }
        } else {
            self.unwind_last_changes(ancestor, ancestor + num_of_executed_chain_blocks)?;
            self.re_execute_canonical_chain(ancestor, current_canonical_block)?;
        }

        Ok(())
    }