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: duplicate_shred.rs
    path of file: ./repos/solana/gossip/src
    
    the code of the file until where you have to start completion: use {
    crate::crds_value::sanitize_wallclock,
    itertools::Itertools,
    solana_ledger::{
        blockstore::BlockstoreError,
        blockstore_meta::{DuplicateSlotProof, ErasureMeta},
        shred::{self, Shred, ShredType},
    },
    solana_sdk::{
        clock::Slot,
        pubkey::Pubkey,
        sanitize::{Sanitize, SanitizeError},
    },
    std::{
        collections::{hash_map::Entry, HashMap},
        convert::TryFrom,
        num::TryFromIntError,
    },
    thiserror::Error,
};

const DUPLICATE_SHRED_HEADER_SIZE: usize = 63;

pub(crate) type DuplicateShredIndex = u16;
pub(crate) const MAX_DUPLICATE_SHREDS: DuplicateShredIndex = 512;

#[derive(Clone, Debug, PartialEq, Eq, AbiExample, Deserialize, Serialize)]
pub struct DuplicateShred {
    pub(crate) from: Pubkey,
    pub(crate) wallclock: u64,
    pub(crate) slot: Slot,
    _unused: u32,
    _unused_shred_type: ShredType,
    // Serialized DuplicateSlotProof split into chunks.
    num_chunks: u8,
    chunk_index: u8,
    #[serde(with = "serde_bytes")]
    chunk: Vec<u8>,
}

impl DuplicateShred {
    #[inline]
    pub(crate) fn num_chunks(&self) -> u8 {
        self.num_chunks
    }

    #[inline]
    pub(crate) fn chunk_index(&self) -> u8 {
        self.chunk_index
    }
}

#[derive(Debug, Error)]
pub enum Error {
    #[error("bl
    
    fn test_merkle_root_conflict_invalid() {
        let mut rng = rand::thread_rng();
        let leader = Arc::new(Keypair::new());
        let (slot, parent_slot, reference_tick, version) = (53084024, 53084023, 0, 0);
        let shredder = Shredder::new(slot, parent_slot, reference_tick, version).unwrap();
        let next_shred_index = rng.gen_range(0..31_000);
        let leader_schedule = |s| {
            if s == slot {
                Some(leader.pubkey())
            } else {
                None
            }
        };

        let (data_shreds, coding_shreds) = new_rand_shreds(
            &mut rng,
            next_shred_index,
            next_shred_index,
            10,
            true,
            &shredder,
            &leader,
            true,
        );

        let (next_data_shreds, next_coding_shreds) = new_rand_shreds(
            &mut rng,
            next_shred_index + 1,
            next_shred_index + 1,
            10,
            true,
            &shredder,
            &leader,
            true,
        );

        let (legacy_data_shreds, legacy_coding_shreds) = new_rand_shreds(
            &mut rng,
            next_shred_index,
            next_shred_index,
            10,
            false,
            &shredder,
            &leader,
            true,
        );

        let test_cases = vec![
            // Same fec set same merkle root
            (coding_shreds[0].clone(), data_shreds[0].clone()),
            (data_shreds[0].clone(), coding_shreds[0].clone()),
            // Different FEC set different merkle root
            (coding_shreds[0].clone(), next_data_shreds[0].clone()),
            (next_coding_shreds[0].clone(), data_shreds[0].clone()),
            (data_shreds[0].clone(), next_coding_shreds[0].clone()),
            (next_data_shreds[0].clone(), coding_shreds[0].clone()),
            // Legacy shreds
            (
                legacy_coding_shreds[0].clone(),
                legacy_data_shreds[0].clone(),
            ),
            (
                legacy_data_shreds[0].clone(),
                legacy_coding_shreds[0].clone(),
            ),
            // Mix of legacy and merkle with different fec index
            (legacy_coding_shreds[0].clone(), next_data_shreds[0].clone()),
            (next_coding_shreds[0].clone(), legacy_data_shreds[0].clone()),
            (legacy_data_shreds[0].clone(), next_coding_shreds[0].clone()),
            (next_data_shreds[0].clone(), legacy_coding_shreds[0].clone()),
        ];
        for (shred1, shred2) in test_cases.into_iter() {
            assert_matches!(
                from_shred(
                    shred1.clone(),
                    Pubkey::new_unique(), // self_pubkey
                    shred2.payload().clone(),
                    Some(leader_schedule),
                    rng.gen(), // wallclock
                    512,       // max_size
                )
                .err()
                .unwrap(),
                Error::ShredTypeMismatch
            );

            let chunks: Vec<_> = from_shred_bypass_checks(
                shred1.clone(),
                Pubkey::new_unique(), // self_pubkey
                shred2.clone(),
                rng.gen(), // wallclock
                512,       // max_size
            )
            .unwrap()
            .collect();
            assert!(chunks.len() > 4);

            assert_matches!(
                into_shreds(&leader.pubkey(), chunks).err().unwrap(),
                Error::ShredTypeMismatch
            );
        }
    }