#[cfg(test)]
mod slicer;
#[cfg(test)]
mod verifier;
#[derive(Clone, Default)]
pub struct FakeSnapshotMptDb {
    db: BTreeMap<Vec<u8>, SnapshotMptNode>,
    in_place_mode: bool,
    already_written: HashSet<Vec<u8>>,
    discard_write: bool,
}
impl FakeSnapshotMptDb {
    pub fn new_discard_write() -> Self {
        Self {
            discard_write: true,
            ..Default::default()
        }
    }
    #[cfg(test)]
    fn reset(&mut self, in_place_mode: bool) {
        self.in_place_mode = in_place_mode;
        self.already_written.clear();
    }
    #[cfg(test)]
    fn assert_eq(&self, expected: &Self) {
        for (k, node) in &expected.db {
            let maybe_got_node = self.db.get(k);
            match maybe_got_node {
                None => panic!("key {:?} not found in resulting mpt.", k),
                Some(got_node) => {
                    for (child_index, child_ref) in
                        node.get_children_table_ref().iter()
                    {
                        match got_node
                            .get_children_table_ref()
                            .get_child(child_index)
                        {
                            None => {
                                panic!(
                                    "Child {} not found. Expected\n\t{:?}\n\
                                    got\n\t{:?}\nkey {:?}",
                                    child_index, node, got_node, k,
                                )
                            }
                            Some(got_child_ref) => {
                                assert_eq!(
                                    child_ref.subtree_size, got_child_ref.subtree_size,
                                    "Subtree size of child {} mismatch. Expected\n\t{:?}\n\
                                    got\n\t{:?}\nkey {:?}",
                                    child_index, node, got_node, k,
                                )
                            }
                        }
                    }
                }
            }
        }
    }
}
struct FakeSnapshotMptDbIter<'a>(
    btree_map::Range<'a, Vec<u8>, SnapshotMptNode>,
);
impl SnapshotMptTraitRead for FakeSnapshotMptDb {
    fn get_merkle_root(&self) -> MerkleHash { unimplemented!() }
    fn load_node(
        &mut self, path: &dyn CompressedPathTrait,
    ) -> Result<Option<SnapshotMptNode>> {
        let result = Ok(self.db.get(&mpt_node_path_to_db_key(path)).cloned());
        if CHECK_LOADED_SNAPSHOT_MPT_NODE {
            if let Ok(Some(node)) = &result {
                node.is_valid(path);
            }
        }
        result
    }
}
impl SnapshotMptTraitReadAndIterate for FakeSnapshotMptDb {
    fn iterate_subtree_trie_nodes_without_root(
        &mut self, path: &dyn CompressedPathTrait,
    ) -> Result<Box<dyn SnapshotMptIteraterTrait + '_>> {
        let begin_key_excl = mpt_node_path_to_db_key(path);
        let mut end_key_excl = begin_key_excl.clone();
        *end_key_excl.last_mut().unwrap() += 1;
        Ok(Box::new(FakeSnapshotMptDbIter(self.db.range((
            Excluded(begin_key_excl),
            Excluded(end_key_excl),
        )))))
    }
}
impl SnapshotMptTraitRw for FakeSnapshotMptDb {
    fn delete_node(&mut self, path: &dyn CompressedPathTrait) -> Result<()> {
        if self.discard_write {
            return Ok(());
        }
        let key = mpt_node_path_to_db_key(path);
        let old_value = self.db.remove(&key);
        if self.in_place_mode {
            assert!(
                old_value.is_some(),
                "Shouldn't delete node {:?} in in-place mode",
                key
            );
        } else {
            panic!("Shouldn't call delete_node in save-as mode. key {:?}", key);
        }
        if self.already_written.contains(&key) {
            panic!("Shouldn't delete a newly written node. key {:?}", key);
        }
        Ok(())
    }
    fn write_node(
        &mut self, path: &dyn CompressedPathTrait, trie_node: &SnapshotMptNode,
    ) -> Result<()> {
        if self.discard_write {
            return Ok(());
        }
        let key = mpt_node_path_to_db_key(path);
        self.db.insert(key.clone(), trie_node.clone());
        if !self.already_written.insert(key.clone()) {
            panic!("Shouldn't write a node more than one time. key {:?}", key);
        }
        Ok(())
    }
}
impl FallibleIterator for FakeSnapshotMptDbIter<'_> {
    type Error = Error;
    type Item = (CompressedPathRaw, SnapshotMptNode);
    fn next(&mut self) -> Result<Option<Self::Item>> {
        match self.0.next() {
            Some((k, v)) => {
                Ok(Some((mpt_node_path_from_db_key(k)?, v.clone())))
            }
            None => Ok(None),
        }
    }
}
#[cfg(test)]
fn assert_snapshot_mpt_formation(mpt_kv_iter: &DumpedMptKvIterator) {
    let snapshot_mpt_nodes;
    let delta_mpt_root = {
        let state_manager = new_state_manager_for_unit_test();
        let mut state = state_manager.get_state_for_genesis_write();
        for (key, value) in &mpt_kv_iter.kv {
            state
                .set(
                    StorageKey::AccountKey(key).with_native_space(),
                    value.clone(),
                )
                .expect("Failed to insert key.");
        }
        let mut epoch_id = EpochId::default();
        epoch_id.as_bytes_mut()[0] = 1;
        let root = state.compute_state_root().unwrap().state_root;
        state.commit(epoch_id).unwrap();
        snapshot_mpt_nodes =
            state_manager.number_committed_nodes.load(Ordering::Relaxed);
        root.delta_root
    };
    println!(
        "Checking snapshot mpt formation of {} keys with expected \
         merkle_root {:?} and number of nodes {}",
        mpt_kv_iter.kv.len(),
        delta_mpt_root,
        snapshot_mpt_nodes
    );
    let mut empty_snapshot_mpt = FakeSnapshotMptDb::default();
    let mut new_snapshot_mpt = FakeSnapshotMptDb::default();
    new_snapshot_mpt.reset(true);
    let snapshot_merkle_root =
        MptMerger::new(Some(&mut empty_snapshot_mpt), &mut new_snapshot_mpt)
            .merge(&mpt_kv_iter)
            .unwrap();
    assert_eq!(delta_mpt_root, snapshot_merkle_root);
    assert_eq!(new_snapshot_mpt.db.len(), snapshot_mpt_nodes);
    empty_snapshot_mpt.reset(true);
    let snapshot_merkle_root = MptMerger::new(None, &mut empty_snapshot_mpt)
        .merge(&mpt_kv_iter)
        .unwrap();
    assert_eq!(delta_mpt_root, snapshot_merkle_root);
    assert_eq!(empty_snapshot_mpt.db.len(), snapshot_mpt_nodes);
}
#[cfg(test)]
#[test]
fn test_mpt_node_path_to_from_db_key() {
    let mpt_kv = [
        (vec![0x00, 0x10, 0x00, 0x00], vec![0x00]),
        (vec![0x00, 0x01, 0x00, 0x00, 0x02], vec![0x00]),
        (vec![0x00, 0x01, 0x00, 0x00, 0x03], vec![0x00]),
        (vec![0x00, 0x01, 0x02, 0x00], vec![0x00]),
    ];
    let state_manager = new_state_manager_for_unit_test();
    let mut state = state_manager.get_state_for_genesis_write();
    for (key, value) in &mpt_kv {
        state
            .set(
                StorageKey::AccountKey(key).with_native_space(),
                value.clone().into_boxed_slice(),
            )
            .expect("Failed to insert key.");
    }
    let mut epoch_id = EpochId::default();
    epoch_id.as_bytes_mut()[0] = 1;
    state.compute_state_root().unwrap();
    let state_root_with_aux_info = state.commit(epoch_id).unwrap();
    let state = state_manager
        .get_state_no_commit_inner(
            StateIndex::new_for_readonly(&epoch_id, &state_root_with_aux_info),
            false,
            true,
        )
        .unwrap()
        .unwrap();
    for (key, value) in &mpt_kv {
        let (v, proof) = state
            .get_with_proof(StorageKey::AccountKey(key).with_native_space())
            .unwrap();
        assert_eq!(v, Some(value.clone().into_boxed_slice()));
        for node in proof.delta_proof.unwrap().get_proof_nodes() {
            let compressed_path = node.compressed_path_ref();
            if CompressedPathRaw::second_nibble(compressed_path.path_mask())
                == CompressedPathRaw::NO_MISSING_NIBBLE
            {
                let db_key = mpt_node_path_to_db_key(&compressed_path);
                let loaded_compressed_path =
                    mpt_node_path_from_db_key(&db_key).unwrap();
                assert_eq!(
                    &compressed_path as &dyn CompressedPathTrait,
                    &loaded_compressed_path as &dyn CompressedPathTrait,
                );
            }
        }
    }
}
#[cfg(test)]
#[test]
fn test_merkle_root() {
    assert_snapshot_mpt_formation(&DumpedMptKvIterator::default());
    let mut rng = get_rng_for_test();
    for _i in 0..5 {
        let keys: Vec<Vec<u8>> = generate_keys(TEST_NUMBER_OF_KEYS)
            .iter()
            .filter(|_| rng.gen_bool(0.1))
            .cloned()
            .collect();
        let mpt_kv_iter = DumpedMptKvIterator {
            kv: keys.iter().map(|k| (k[..].into(), k[..].into())).collect(),
        };
        assert_snapshot_mpt_formation(&mpt_kv_iter);
    }
}
#[cfg(test)]
#[test]
fn test_delete_all() {
    let mut rng = get_rng_for_test();
    let keys: Vec<Vec<u8>> = generate_keys(TEST_NUMBER_OF_KEYS)
        .iter()
        .filter(|_| rng.gen_bool(0.5))
        .cloned()
        .collect();
    let mpt_kv_iter = DumpedMptKvIterator {
        kv: keys.iter().map(|k| (k[..].into(), k[..].into())).collect(),
    };
    let mut empty_snapshot_mpt = FakeSnapshotMptDb::default();
    let mut snapshot_mpt = FakeSnapshotMptDb::default();
    snapshot_mpt.reset(false);
    MptMerger::new(Some(&mut empty_snapshot_mpt), &mut snapshot_mpt)
        .merge(&mpt_kv_iter)
        .unwrap();
    let mpt_deleter = DumpedMptKvIterator {
        kv: keys
            .iter()
            .map(|k| (k[..].into(), Default::default()))
            .collect(),
    };
    empty_snapshot_mpt.reset(false);
    let merkle_root =
        MptMerger::new(Some(&mut snapshot_mpt), &mut empty_snapshot_mpt)
            .merge(&mpt_deleter)
            .unwrap();
    assert_eq!(MERKLE_NULL_NODE, merkle_root);
    assert_eq!(0, empty_snapshot_mpt.db.len());
    snapshot_mpt.reset(true);
    let merkle_root = MptMerger::new(None, &mut snapshot_mpt)
        .merge(&mpt_deleter)
        .unwrap();
    assert_eq!(MERKLE_NULL_NODE, merkle_root);
    assert_eq!(0, snapshot_mpt.db.len());
}
#[cfg(test)]
#[test]
fn test_inserts_deletes_and_subtree_size() {
    let keys: Vec<Vec<u8>> = generate_keys(TEST_NUMBER_OF_KEYS);
    let set_size = TEST_NUMBER_OF_KEYS / 10;
    let (keys_unchanged, keys_overwritten, keys_delete, keys_new) = (
        &keys[0..set_size],
        &keys[set_size..set_size * 2],
        &keys[set_size * 2..set_size * 3],
        &keys[set_size * 3..set_size * 4],
    );
    let mpt_kv_iter = DumpedMptKvIterator {
        kv: keys_delete
            .iter()
            .map(|k| (k[..].into(), k[..].into()))
            .collect(),
    };
    let mut in_place_mod_mpt = FakeSnapshotMptDb::default();
    in_place_mod_mpt.reset(true);
    let init_merkle_root = MptMerger::new(None, &mut in_place_mod_mpt)
        .merge(&mpt_kv_iter)
        .unwrap();
    let mut in_place_mod_mpt_discard_write =
        FakeSnapshotMptDb::new_discard_write();
    in_place_mod_mpt_discard_write.reset(true);
    let merkle_root = MptMerger::new(None, &mut in_place_mod_mpt_discard_write)
        .merge(&mpt_kv_iter)
        .unwrap();
    assert_eq!(init_merkle_root, merkle_root);
    let mpt_kv_iter = DumpedMptKvIterator {
        kv: keys_new
            .iter()
            .map(|k| (k[..].into(), k[..].into()))
            .collect(),
    };
    let mut new_snapshot_mpt = FakeSnapshotMptDb::default();
    new_snapshot_mpt.reset(true);
    let supposed_merkle_root = MptMerger::new(None, &mut new_snapshot_mpt)
        .merge(&mpt_kv_iter)
        .unwrap();
    let delta_mpt_iter = DumpedMptKvIterator {
        kv: [
            keys_delete
                .iter()
                .map(|k| (Vec::<u8>::from(&k[..]), Box::<[u8]>::default()))
                .collect::<Vec<_>>(),
            keys_new
                .iter()
                .map(|k| (Vec::<u8>::from(&k[..]), Box::<[u8]>::from(&k[..])))
                .collect::<Vec<_>>(),
        ]
        .concat(),
    };
    let mut save_as_mode_mpt = FakeSnapshotMptDb::default();
    let new_merkle_root =
        MptMerger::new(Some(&mut in_place_mod_mpt), &mut save_as_mode_mpt)
            .merge(&delta_mpt_iter)
            .unwrap();
    assert_eq!(new_merkle_root, supposed_merkle_root);
    save_as_mode_mpt.assert_eq(&new_snapshot_mpt);
    in_place_mod_mpt.reset(true);
    let new_merkle_root = MptMerger::new(None, &mut in_place_mod_mpt)
        .merge(&delta_mpt_iter)
        .unwrap();
    assert_eq!(new_merkle_root, supposed_merkle_root);
    in_place_mod_mpt.assert_eq(&new_snapshot_mpt);
    let mpt_kv_iter = DumpedMptKvIterator {
        kv: [
            keys_unchanged
                .iter()
                .map(|k| (Vec::<u8>::from(&k[..]), Box::<[u8]>::from(&k[..])))
                .collect::<Vec<_>>(),
            keys_delete
                .iter()
                .map(|k| (Vec::<u8>::from(&k[..]), Box::<[u8]>::from(&k[..])))
                .collect::<Vec<_>>(),
            keys_overwritten
                .iter()
                .map(|k| (Vec::<u8>::from(&k[..]), Box::<[u8]>::from(&k[0..2])))
                .collect::<Vec<_>>(),
        ]
        .concat(),
    };
    let mut in_place_mod_mpt = FakeSnapshotMptDb::default();
    in_place_mod_mpt.reset(true);
    MptMerger::new(None, &mut in_place_mod_mpt)
        .merge(&mpt_kv_iter)
        .unwrap();
    let mpt_kv_iter = DumpedMptKvIterator {
        kv: [
            keys_unchanged
                .iter()
                .map(|k| (Vec::<u8>::from(&k[..]), Box::<[u8]>::from(&k[..])))
                .collect::<Vec<_>>(),
            keys_new
                .iter()
                .map(|k| (Vec::<u8>::from(&k[..]), Box::<[u8]>::from(&k[..])))
                .collect::<Vec<_>>(),
            keys_overwritten
                .iter()
                .map(|k| (Vec::<u8>::from(&k[..]), Box::<[u8]>::from(&k[..])))
                .collect::<Vec<_>>(),
        ]
        .concat(),
    };
    let mut new_snapshot_mpt = FakeSnapshotMptDb::default();
    new_snapshot_mpt.reset(true);
    let supposed_merkle_root = MptMerger::new(None, &mut new_snapshot_mpt)
        .merge(&mpt_kv_iter)
        .unwrap();
    let new_snapshot_db = Arc::new(Mutex::new(FakeSnapshotDb::new(
        &mpt_kv_iter.kv,
        &new_snapshot_mpt,
    )));
    verify_snapshot_db(&new_snapshot_db);
    let delta_mpt_iter = DumpedMptKvIterator {
        kv: [
            keys_delete
                .iter()
                .map(|k| (Vec::<u8>::from(&k[..]), Box::<[u8]>::default()))
                .collect::<Vec<_>>(),
            keys_new
                .iter()
                .map(|k| (Vec::<u8>::from(&k[..]), Box::<[u8]>::from(&k[..])))
                .collect::<Vec<_>>(),
            keys_overwritten
                .iter()
                .map(|k| (Vec::<u8>::from(&k[..]), Box::<[u8]>::from(&k[..])))
                .collect::<Vec<_>>(),
        ]
        .concat(),
    };
    let mut save_as_mode_mpt = FakeSnapshotMptDb::default();
    let new_merkle_root =
        MptMerger::new(Some(&mut in_place_mod_mpt), &mut save_as_mode_mpt)
            .merge(&delta_mpt_iter)
            .unwrap();
    assert_eq!(new_merkle_root, supposed_merkle_root);
    new_snapshot_mpt.assert_eq(&save_as_mode_mpt);
    in_place_mod_mpt.reset(true);
    let new_merkle_root = MptMerger::new(None, &mut in_place_mod_mpt)
        .merge(&delta_mpt_iter)
        .unwrap();
    let in_place_mode_snapshot_db = Arc::new(Mutex::new(FakeSnapshotDb::new(
        &mpt_kv_iter.kv,
        &in_place_mod_mpt,
    )));
    verify_snapshot_db(&in_place_mode_snapshot_db);
    assert_eq!(new_merkle_root, supposed_merkle_root);
    in_place_mod_mpt.assert_eq(&new_snapshot_mpt);
}
#[cfg(test)]
#[test]
fn test_two_way_merge() {
    let keys: Vec<Vec<u8>> = generate_keys(TEST_NUMBER_OF_KEYS);
    let set_size = TEST_NUMBER_OF_KEYS / 10;
    let (keys_unchanged, keys_overwritten, keys_delete, keys_new) = (
        &keys[0..set_size],
        &keys[set_size..set_size * 2],
        &keys[set_size * 2..set_size * 3],
        &keys[set_size * 3..set_size * 4],
    );
    let mpt_kv_iter = DumpedMptKvIterator {
        kv: [
            keys_unchanged
                .iter()
                .map(|k| (Vec::<u8>::from(&k[..]), Box::<[u8]>::from(&k[..])))
                .collect::<Vec<_>>(),
            keys_delete
                .iter()
                .map(|k| (Vec::<u8>::from(&k[..]), Box::<[u8]>::from(&k[..])))
                .collect::<Vec<_>>(),
            keys_overwritten
                .iter()
                .map(|k| (Vec::<u8>::from(&k[..]), Box::<[u8]>::from(&k[0..2])))
                .collect::<Vec<_>>(),
        ]
        .concat(),
    };
    let mut in_place_mod_mpt = FakeSnapshotMptDb::default();
    in_place_mod_mpt.reset(true);
    MptMerger::new(None, &mut in_place_mod_mpt)
        .merge(&mpt_kv_iter)
        .unwrap();
    let delta_mpt_iter = DumpedMptKvIterator {
        kv: [
            keys_delete
                .iter()
                .map(|k| (Vec::<u8>::from(&k[..]), Box::<[u8]>::default()))
                .collect::<Vec<_>>(),
            keys_new
                .iter()
                .map(|k| (Vec::<u8>::from(&k[..]), Box::<[u8]>::from(&k[..])))
                .collect::<Vec<_>>(),
            keys_overwritten
                .iter()
                .map(|k| (Vec::<u8>::from(&k[..]), Box::<[u8]>::from(&k[..])))
                .collect::<Vec<_>>(),
        ]
        .concat(),
    };
    let mut save_as_mode_mpt = FakeSnapshotMptDb::default();
    let supposed_merkle_root =
        MptMerger::new(Some(&mut in_place_mod_mpt), &mut save_as_mode_mpt)
            .merge(&delta_mpt_iter)
            .unwrap();
    in_place_mod_mpt.reset(true);
    let mut keys_deletion = Vec::from(keys_delete);
    keys_deletion.sort();
    let deletion = keys_deletion
        .iter()
        .map(|k| Ok((Vec::<u8>::from(&k[..]), ())))
        .collect::<Vec<_>>();
    let mut keys_insertion = [keys_new, keys_overwritten].concat();
    keys_insertion.sort();
    let insertion = keys_insertion
        .iter()
        .map(|k| Ok((Vec::<u8>::from(&k[..]), Box::<[u8]>::from(&k[..]))))
        .collect::<Vec<_>>();
    let new_merkle_root = MptMerger::new(None, &mut in_place_mod_mpt)
        .merge_insertion_deletion_separated(
            fallible_iterator::convert(deletion.into_iter()),
            fallible_iterator::convert(insertion.into_iter()),
            false,
        )
        .unwrap();
    assert_eq!(new_merkle_root, supposed_merkle_root);
    in_place_mod_mpt.assert_eq(&save_as_mode_mpt);
}
#[allow(unused)]
fn test_delta_subtree_size() {
    unimplemented!()
}
use crate::{
    impls::{
        errors::*,
        merkle_patricia_trie::{CompressedPathRaw, CompressedPathTrait},
        storage_db::snapshot_mpt::{
            mpt_node_path_from_db_key, mpt_node_path_to_db_key,
        },
    },
    storage_db::{
        snapshot_mpt::CHECK_LOADED_SNAPSHOT_MPT_NODE, SnapshotMptIteraterTrait,
        SnapshotMptNode, SnapshotMptTraitRead, SnapshotMptTraitReadAndIterate,
        SnapshotMptTraitRw,
    },
};
use fallible_iterator::FallibleIterator;
use primitives::MerkleHash;
use std::{
    collections::{btree_map, BTreeMap, HashSet},
    ops::Bound::Excluded,
};
#[cfg(test)]
use crate::{
    impls::merkle_patricia_trie::{MptMerger, TrieNodeTrait},
    impls::storage_db::snapshot_mpt::tests::verify_snapshot_db,
    state_manager::StateManagerTrait,
    tests::{
        generate_keys, get_rng_for_test, new_state_manager_for_unit_test,
        snapshot::verifier::FakeSnapshotDb, DumpedMptKvIterator,
        TEST_NUMBER_OF_KEYS,
    },
    StateIndex, StorageStateTraitExt,
};
#[cfg(test)]
use parking_lot::Mutex;
#[cfg(test)]
use primitives::{EpochId, StorageKey, MERKLE_NULL_NODE};
#[cfg(test)]
use rand::Rng;
#[cfg(test)]
use std::sync::{atomic::Ordering, Arc};