pub fn prune(db: &dyn Database, merkle_root: &str) -> Result<Vec<String>, StateDatabaseError> {
        let root_bytes = ::hex::decode(merkle_root).map_err(|_| {
            StateDatabaseError::InvalidHash(format!("{} is not a valid hash", merkle_root))
        })?;
        let mut db_writer = db.get_writer()?;

        let change_log = get_change_log(db_writer.as_reader(), &root_bytes)?;

        if change_log.is_none() {
            // There's no change log for this entry
            return Ok(vec![]);
        }

        let mut change_log = change_log.unwrap();
        let removed_addresses = if change_log.successors.len() > 1 {
            // Currently, we don't clean up a parent with multiple successors
            vec![]
        } else if change_log.successors.is_empty() {
            // deleting the tip of a trie lineage

            let (deletion_candidates, duplicates) = MerkleRadixTree::remove_duplicate_hashes(
                db_writer.as_reader(),
                change_log.additions,
            )?;

            for hash in &deletion_candidates {
                let hash_hex = ::hex::encode(hash);
                delete_ignore_missing(&mut *db_writer, hash_hex.as_bytes())?
            }

            for hash in &duplicates {
                decrement_ref_count(&mut *db_writer, hash)?;
            }

            db_writer.index_delete(CHANGE_LOG_INDEX, &root_bytes)?;
            let parent_root_bytes = &change_log.parent;

            if let Some(ref mut parent_change_log) =
                get_change_log(db_writer.as_reader(), parent_root_bytes)?.as_mut()
            {
                let successors = parent_change_log.take_successors();
                let new_successors = successors
                    .into_iter()
                    .filter(|successor| root_bytes != successor.successor)
                    .collect::<Vec<_>>();
                parent_change_log.successors = new_successors;

                write_change_log(&mut *db_writer, parent_root_bytes, &parent_change_log)?;
            }

            deletion_candidates.into_iter().collect()
        } else {
            // deleting a parent
            let mut successor = change_log.successors.pop().unwrap();
            successor.deletions.push(root_bytes.clone());

            let (deletion_candidates, duplicates): (Vec<Vec<u8>>, Vec<Vec<u8>>) =
                MerkleRadixTree::remove_duplicate_hashes(
                    db_writer.as_reader(),
                    successor.deletions,
                )?;

            for hash in &deletion_candidates {
                let hash_hex = ::hex::encode(hash);
                delete_ignore_missing(&mut *db_writer, hash_hex.as_bytes())?
            }

            for hash in &duplicates {
                decrement_ref_count(&mut *db_writer, hash)?;
            }

            db_writer.index_delete(CHANGE_LOG_INDEX, &root_bytes)?;

            deletion_candidates.into_iter().collect()
        };

        db_writer.commit()?;
        Ok(removed_addresses.iter().map(::hex::encode).collect())
    }
/// Prunes nodes that are no longer needed under a given state root
/// Returns a list of addresses that were deleted
Prunes nodes that are no longer needed under a given state root
Returns a list of addresses that were deleted
Prunes nodes that are no longer needed under a given state root Returns a list of addresses that were deleted
pub fn prune(db: &dyn Database, merkle_root: &str) -> Result<Vec<String>, StateDatabaseError> {
        let root_bytes = ::hex::decode(merkle_root).map_err(|_| {
            StateDatabaseError::InvalidHash(format!("{} is not a valid hash", merkle_root))
        })?;
        let mut db_writer = db.get_writer()?;
        let change_log = get_change_log(db_writer.as_reader(), &root_bytes)?;
        if change_log.is_none() {
            // There's no change log for this entry
            return Ok(vec![]);
        }
        let mut change_log = change_log.unwrap();
        let removed_addresses = if change_log.successors.len() > 1 {
            // Currently, we don't clean up a parent with multiple successors
            vec![]
        } else if change_log.successors.is_empty() {
            // deleting the tip of a trie lineage
            let (deletion_candidates, duplicates) = MerkleRadixTree::remove_duplicate_hashes(
                db_writer.as_reader(),
                change_log.additions,
            )?;
            for hash in &deletion_candidates {
                let hash_hex = ::hex::encode(hash);
                delete_ignore_missing(&mut *db_writer, hash_hex.as_bytes())?
            }
            for hash in &duplicates {
                decrement_ref_count(&mut *db_writer, hash)?;
            }
            db_writer.index_delete(CHANGE_LOG_INDEX, &root_bytes)?;
            let parent_root_bytes = &change_log.parent;
            if let Some(ref mut parent_change_log) =
                get_change_log(db_writer.as_reader(), parent_root_bytes)?.as_mut()
            {
                let successors = parent_change_log.take_successors();
                let new_successors = successors
                    .into_iter()
                    .filter(|successor| root_bytes != successor.successor)
                    .collect::<Vec<_>>();
                parent_change_log.successors = new_successors;
                write_change_log(&mut *db_writer, parent_root_bytes, &parent_change_log)?;
            }
            deletion_candidates.into_iter().collect()
        } else {
            // deleting a parent
            let mut successor = change_log.successors.pop().unwrap();
            successor.deletions.push(root_bytes.clone());
            let (deletion_candidates, duplicates): (Vec<Vec<u8>>, Vec<Vec<u8>>) =
                MerkleRadixTree::remove_duplicate_hashes(
                    db_writer.as_reader(),
                    successor.deletions,
                )?;
            for hash in &deletion_candidates {
                let hash_hex = ::hex::encode(hash);
                delete_ignore_missing(&mut *db_writer, hash_hex.as_bytes())?
            }
            for hash in &duplicates {
                decrement_ref_count(&mut *db_writer, hash)?;
            }
            db_writer.index_delete(CHANGE_LOG_INDEX, &root_bytes)?;
            deletion_candidates.into_iter().collect()
        };
        db_writer.commit()?;
        Ok(removed_addresses.iter().map(::hex::encode).collect())
    }
pub fn prune ( db : & dyn Database , merkle_root : & str ) -> Result < Vec < String > , StateDatabaseError > { let root_bytes = :: hex :: decode ( merkle_root ) . map_err ( | _ | { StateDatabaseError :: InvalidHash ( format ! ( " " merkle_root ) ) } ) ? ; let mut db_writer = db . get_writer ( ) ? ; let change_log = get_change_log ( db_writer . as_reader ( ) , & root_bytes ) ? ; if change_log . is_none ( ) { // There's no change log for this entry return Ok ( vec ! [ ] ) ; } let mut change_log = change_log . unwrap ( ) ; let removed_addresses = if change_log . successors . len ( ) > 1 { // Currently, we don't clean up a parent with multiple successors vec ! [ ] } else if change_log . successors . is_empty ( ) { // deleting the tip of a trie lineage let ( deletion_candidates , duplicates ) = MerkleRadixTree :: remove_duplicate_hashes ( db_writer . as_reader ( ) , change_log . additions , ) ? ; for hash in & deletion_candidates { let hash_hex = :: hex :: encode ( hash ) ; delete_ignore_missing ( & mut * db_writer , hash_hex . as_bytes ( ) ) ? } for hash in & duplicates { decrement_ref_count ( & mut * db_writer , hash ) ? ; } db_writer . index_delete ( CHANGE_LOG_INDEX , & root_bytes ) ? ; let parent_root_bytes = & change_log . parent ; if let Some ( ref mut parent_change_log ) = get_change_log ( db_writer . as_reader ( ) , parent_root_bytes ) ? . as_mut ( ) { let successors = parent_change_log . take_successors ( ) ; let new_successors = successors . into_iter ( ) . filter ( | successor | root_bytes != successor . successor ) . collect :: < Vec < _ > > ( ) ; parent_change_log . successors = new_successors ; write_change_log ( & mut * db_writer , parent_root_bytes , & parent_change_log ) ? ; } deletion_candidates . into_iter ( ) . collect ( ) } else { // deleting a parent let mut successor = change_log . successors . pop ( ) . unwrap ( ) ; successor . deletions . push ( root_bytes . clone ( ) ) ; let ( deletion_candidates , duplicates ) : ( Vec < Vec < u8 > > , Vec < Vec < u8 > > ) = MerkleRadixTree :: remove_duplicate_hashes ( db_writer . as_reader ( ) , successor . deletions , ) ? ; for hash in & deletion_candidates { let hash_hex = :: hex :: encode ( hash ) ; delete_ignore_missing ( & mut * db_writer , hash_hex . as_bytes ( ) ) ? } for hash in & duplicates { decrement_ref_count ( & mut * db_writer , hash ) ? ; } db_writer . index_delete ( CHANGE_LOG_INDEX , & root_bytes ) ? ; deletion_candidates . into_iter ( ) . collect ( ) } ; db_writer . commit ( ) ? ; Ok ( removed_addresses . iter ( ) . map ( :: hex :: encode ) . collect ( ) ) }
Prunes nodes that are no longer needed under a given state root
Returns a list of addresses that were deleted
Prunes nodes that are no longer needed under a given state root Returns a list of addresses that were deleted
db
&dyn Database
merkle_root
&str
db
&dyn Database
merkle_root
&str