naries::new(dictionaries)));
        self.state = ZstdState::Ready;

        Ok(())
    }
}

mod dictionaries_serde {
    use super::*;

    pub(crate) fn serialize<S>(
        dictionaries: &Option<Arc<ZstdDictionaries<'static>>>,
        serializer: S,
    ) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match dictionaries {
            Some(dicts) => serializer.serialize_some(dicts.as_ref()),
            None => serializer.serialize_none(),
        }
    }

    pub(crate) fn deserialize<'de, D>(
        deserializer: D,
    ) -> Result<Option<Arc<ZstdDictionaries<'static>>>, D::Error>
    where
        D: Deserializer<'de>,
    {
        let dictionaries: Option<Vec<RawDictionary>> = Option::deserialize(deserializer)?;
        Ok(dictionaries.map(|dicts| Arc::new(ZstdDictionaries::load(dicts))))
    }
}

/// List of [`ZstdDictionary`]
#[cfg_attr(test, derive(PartialEq))]
#[derive(Serialize, Deserialize, Deref)]
pub(crate) struct ZstdDictionaries<'a>(Vec<ZstdDictionary<'a>>);

impl std::fmt::Debug for ZstdDictionaries<'_> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("ZstdDictionaries").field("num", &self.len()).finish_non_exhaustive()
    }
}

impl ZstdDictionaries<'_> {
    #[cfg(test)]
    /// Creates [`ZstdDictionaries`].
    pub(crate) fn new(raw: Vec<RawDictionary>) -> Self {
        Self(raw.into_iter().map(ZstdDictionary::Raw).collect())
    }

    /// Loads a list [`RawDictionary`] into a list of [`ZstdDictionary::Loaded`].
    pub(crate) fn load(raw: Vec<RawDictionary>) -> Self {
        Self(
            raw.into_iter()
                .map(|dict| ZstdDictionary::Loaded(DecoderDictionary::copy(&dict)))
                .collect(),
        )
    }

    /// Creates a list of decompressors from a list of [`ZstdDictionary::Loaded`].
    pub(crate) fn decompressors(&self) -> Result<Vec<Decompressor<'_>>, NippyJarError> {
        Ok(self
            .iter()
            .flat_map(|dict| {
                dict.loaded()
                    .ok_or(NippyJarError::DictionaryNotLoaded)
                    .map(Decompressor::with_prepared_dictionary)
            })
            .collect::<Result<Vec<_>, _>>()?)
    }

    /// Creates a list of compressors from a list of [`ZstdDictionary::Raw`].
    pub(crate) fn compressors(&self) -> Result<Vec<Compressor<'_>>, NippyJarError> {
        Ok(self
            .iter()
            .flat_map(|dict| {
                dict.raw()
                    .ok_or(NippyJarError::CompressorNotAllowed)
                    .map(|dict| Compressor::with_dictionary(0, dict))
            })
            .collect::<Result<Vec<_>, _>>()?)
    }
}

/// A Zstd dictionary. It's created and serialized with [`ZstdDictionary::Raw`], and deserialized as
/// [`ZstdDictionary::Loaded`].
pub(crate) enum ZstdDictionary<'a> {
    #[cfg_attr(not(test), expect(dead_code))]
    Raw(RawDictionary),
    Loaded(DecoderDictionary<'a>),
}

impl ZstdDictionary<'_> {
    /// Returns a reference to the expected `RawDictionary`
    pub(crate) const fn raw(&self) -> Option<&RawDictionary> {
        match self {
            ZstdDictionary::Raw(dict) => Some(dict),
            ZstdDictionary::Loaded(_) => None,
        }
    }

    /// Returns a reference to the expected `DecoderDictionary`
    pub(crate) const fn loaded(&self) -> Option<&DecoderDictionary<'_>> {
        match self {
            ZstdDictionary::Raw(_) => None,
            ZstdDictionary::Loaded(dict) => Some(dict),
        }
    }
}

impl<'de> Deserialize<'de> for ZstdDictionary<'_> {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let dict = RawDictionary::deserialize(deserializer)?;
        Ok(Self::Loaded(DecoderDictionary::copy(&dict)))
    }
}

impl Serialize for ZstdDictionary<'_> {

    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match self {
            ZstdDictionary::Raw(r) => r.serialize(serializer),
            ZstdDictionary::Loaded(_) => unreachable!(),
        }
    }

}

#[cfg(test)]
impl PartialEq for ZstdDictionary<'_> {
    fn eq(&self, other: &Self) -> bool {
        if let (Self::Raw(a), Self::Raw(b)) = (self, &other) {
            return a == b
        }
        unimplemented!(
            "`DecoderDictionary` can't be compared. So comparison should be done after decompressing a value."
        );
    }
}


       output: &mut Vec<u8>,
        decompressor: &mut Decompressor<'_>,
    ) -> Result<(), NippyJarError> {
        let previous_length = output.len();

        // SAFETY: We're setting len to the existing capacity.
        unsafe {
            output.set_len(output.capacity());
        }

        match decompressor.decompress_to_buffer(column_value, &mut output[previous_length..]) {
            Ok(written) => {
                // SAFETY: `decompress_to_buffer` can only write if there's enough capacity.
                // Therefore, it shouldn't write more than our capacity.
                unsafe {
                    output.set_len(previous_length + written);
                }
                Ok(())
            }
            Err(_) => {
                // SAFETY: we are resetting it to the previous value.
                unsafe {
                    output.set_len(previous_length);
                }
                Err(NippyJarError::OutputTooSmall)
            }
        }
    }
}

impl Compression for Zstd {
    fn decompress_to(&self, value: &[u8], dest: &mut Vec<u8>) -> Result<(), NippyJarError> {
        let mut decoder = zstd::Decoder::with_dictionary(value, &[])?;
        decoder.read_to_end(dest)?;
        Ok(())
    }

    fn decompress(&self, value: &[u8]) -> Result<Vec<u8>, NippyJarError> {
        let mut decompressed = Vec::with_capacity(value.len() * 2);
        let mut decoder = zstd::Decoder::new(value)?;
        decoder.read_to_end(&mut decompressed)?;
        Ok(decompressed)
    }

    fn compress_to(&self, src: &[u8], dest: &mut Vec<u8>) -> Result<usize, NippyJarError> {
        let before = dest.len();

        let mut encoder = zstd::Encoder::new(dest, self.level)?;
        encoder.write_all(src)?;

        let dest = encoder.finish()?;

        Ok(dest.len() - before)
    }

    fn compress(&self, src: &[u8]) -> Result<Vec<u8>, NippyJarError> {
        let mut compressed = Vec::with_capacity(src.len());

        self.compress_to(src, &mut compressed)?;

        Ok(compressed)
    }

    fn is_ready(&self) -> bool {
        matches!(self.state, ZstdState::Ready)
    }

    #[cfg(test)]
    /// If using it with dictionaries, prepares a dictionary for each column.
    fn prepare_compression(
        &mut self,
        columns: Vec<impl IntoIterator<Item = Vec<u8>>>,
    ) -> Result<(), NippyJarError> {
        if !self.use_dict {
            return Ok(())
        }

        // There's a per 2GB hard limit on each column data set for training
        // REFERENCE: https://github.com/facebook/zstd/blob/dev/programs/zstd.1.md#dictionary-builder
        // ```
        // -M#, --memory=#: Limit the amount of sample data loaded for training (default: 2 GB).
        // Note that the default (2 GB) is also the maximum. This parameter can be useful in
        // situations where the training set size is not well controlled and could be potentially
        // very large. Since speed of the training process is directly correlated to the size of the
        // training sample set, a smaller sample set leads to faster training.`
        // ```

        if columns.len() != self.columns {
            return Err(NippyJarError::ColumnLenMismatch(self.columns, columns.len()))
        }

        let mut dictionaries = Vec::with_capacity(columns.len());
        for column in columns {
            // ZSTD requires all training data to be continuous in memory, alongside the size of
            // each entry
            let mut sizes = vec![];
            let data: Vec<_> = column
                .into_iter()
                .flat_map(|data| {
                    sizes.push(data.len());
                    data
                })
                .collect();

            dictionaries.push(zstd::dict::from_continuous(&data, &sizes, self.max_dict_size)?);
        }

        debug_assert_eq!(dictionaries.len(), self.columns);

        self.dictionaries = Some(Arc::new(ZstdDictionaries::new(dictionaries)));
        self.state = ZstdState::Ready;

        Ok(())
    }
}

mod dictionaries_serde {
    use super::*;

    pub(crate) fn serialize<S>(
        dictionaries: &Option<Arc<ZstdDictionaries<'static>>>,
        serializer: S,
    ) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match dictionaries {
            Some(dicts) => serializer.serialize_some(dicts.as_ref()),
            None => serializer.serialize_none(),
        }
    }

    pub(crate) fn deserialize<'de, D>(
        deserializer: D,
    ) -> Result<Option<Arc<ZstdDictionaries<'static>>>, D::Error>
    where
        D: Deserializer<'de>,
    {
        let dictionaries: Option<Vec<RawDictionary>> = Option::deserialize(deserializer)?;
        Ok(dictionaries.map(|dicts| Arc::new(ZstdDictionaries::load(dicts))))
    }
}

/// List of [`ZstdDictionary`]
#[cfg_attr(test, derive(PartialEq))]
#[derive(Serialize, Deserialize, Deref)]
pub(crate) struct ZstdDictionaries<'a>(Vec<ZstdDictionary<'a>>);

impl std::fmt::Debug for ZstdDictionaries<'_> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("ZstdDictionaries").field("num", &self.len()).finish_non_exhaustive()
    }
}

impl ZstdDictionaries<'_> {
    #[cfg(test)]
    /// Creates [`ZstdDictionaries`].
    pub(crate) fn new(raw: Vec<RawDictionary>) -> Self {
        Self(raw.into_iter().map(ZstdDictionary::Raw).collect())
    }

    /// Loads a list [`RawDictionary`] into a list of [`ZstdDictionary::Loaded`].
    pub(crate) fn load(raw: Vec<RawDictionary>) -> Self {
        Self(
            raw.into_iter()
                .map(|dict| ZstdDictionary::Loaded(DecoderDictionary::copy(&dict)))
                .collect(),
        )
    }

    /// Creates a list of decompressors from a list of [`ZstdDictionary::Loaded`].
    pub(crate) fn decompressors(&self) -> Result<Vec<Decompressor<'_>>, NippyJarError> {
        Ok(self
            .iter()
            .flat_map(|dict| {
                dict.loaded()
                    .ok_or(NippyJarError::DictionaryNotLoaded)
                    .map(Decompressor::with_prepared_dictionary)
            })
            .collect::<Result<Vec<_>, _>>()?)
    }

    /// Creates a list of compressors from a list of [`ZstdDictionary::Raw`].
    pub(crate) fn compressors(&self) -> Result<Vec<Compressor<'_>>, NippyJarError> {
        Ok(self
            .iter()
            .flat_map(|dict| {
                dict.raw()
                    .ok_or(NippyJarError::CompressorNotAllowed)
                    .map(|dict| Compressor::with_dictionary(0, dict))
            })
            .collect::<Result<Vec<_>, _>>()?)
    }
}

/// A Zstd dictionary. It's created and serialized with [`ZstdDictionary::Raw`], and deserialized as
/// [`ZstdDictionary::Loaded`].
pub(crate) enum ZstdDictionary<'a> {
    #[cfg_attr(not(test), expect(dead_code))]
    Raw(RawDictionary),
    Loaded(DecoderDictionary<'a>),
}

impl ZstdDictionary<'_> {
    /// Returns a reference to the expected `RawDictionary`
    pub(crate) const fn raw(&self) -> Option<&RawDictionary> {
        match self {
            ZstdDictionary::Raw(dict) => Some(dict),
            ZstdDictionary::Loaded(_) => None,
        }
    }

    /// Returns a reference to the expected `DecoderDictionary`
    pub(crate) const fn loaded(&self) -> Option<&DecoderDictionary<'_>> {
        match self {
            ZstdDictionary::Raw(_) => None,
            ZstdDictionary::Loaded(dict) => Some(dict),
        }
    }
}

impl<'de> Deserialize<'de> for ZstdDictionary<'_> {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let dict = RawDictionary::deserialize(deserializer)?;
        Ok(Self::Loaded(DecoderDictionary::copy(&dict)))
    }
}

impl Serialize for ZstdDictionary<'_> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,

{
        match self {
            ZstdDictionary::Raw(r) => r.serialize(serializer),
            ZstdDictionary::Loaded(_) => unreachable!(),
        }
    }


t_len(output.capacity());
        }

        match decompressor.decompress_to_buffer(column_value, &mut output[previous_length..]) {
            Ok(written) => {
                // SAFETY: `decompress_to_buffer` can only write if there's enough capacity.
                // Therefore, it shouldn't write more than our capacity.
                unsafe {
                    output.set_len(previous_length + written);
                }
                Ok(())
            }
            Err(_) => {
                // SAFETY: we are resetting it to the previous value.
                unsafe {
                    output.set_len(previous_length);
                }
                Err(NippyJarError::OutputTooSmall)
            }
        }
    }
}

impl Compression for Zstd {
    fn decompress_to(&self, value: &[u8], dest: &mut Vec<u8>) -> Result<(), NippyJarError> {
        let mut decoder = zstd::Decoder::with_dictionary(value, &[])?;
        decoder.read_to_end(dest)?;
        Ok(())
    }

    fn decompress(&self, value: &[u8]) -> Result<Vec<u8>, NippyJarError> {
        let mut decompressed = Vec::with_capacity(value.len() * 2);
        let mut decoder = zstd::Decoder::new(value)?;
        decoder.read_to_end(&mut decompressed)?;
        Ok(decompressed)
    }

    fn compress_to(&self, src: &[u8], dest: &mut Vec<u8>) -> Result<usize, NippyJarError> {
        let before = dest.len();

        let mut encoder = zstd::Encoder::new(dest, self.level)?;
        encoder.write_all(src)?;

        let dest = encoder.finish()?;

        Ok(dest.len() - before)
    }

    fn compress(&self, src: &[u8]) -> Result<Vec<u8>, NippyJarError> {
        let mut compressed = Vec::with_capacity(src.len());

        self.compress_to(src, &mut compressed)?;

        Ok(compressed)
    }

    fn is_ready(&self) -> bool {
        matches!(self.state, ZstdState::Ready)
    }

    #[cfg(test)]
    /// If using it with dictionaries, prepares a dictionary for each column.
    fn prepare_compression(
        &mut self,
        columns: Vec<impl IntoIterator<Item = Vec<u8>>>,
    ) -> Result<(), NippyJarError> {
        if !self.use_dict {
            return Ok(())
        }

        // There's a per 2GB hard limit on each column data set for training
        // REFERENCE: https://github.com/facebook/zstd/blob/dev/programs/zstd.1.md#dictionary-builder
        // ```
        // -M#, --memory=#: Limit the amount of sample data loaded for training (default: 2 GB).
        // Note that the default (2 GB) is also the maximum. This parameter can be useful in
        // situations where the training set size is not well controlled and could be potentially
        // very large. Since speed of the training process is directly correlated to the size of the
        // training sample set, a smaller sample set leads to faster training.`
        // ```

        if columns.len() != self.columns {
            return Err(NippyJarError::ColumnLenMismatch(self.columns, columns.len()))
        }

        let mut dictionaries = Vec::with_capacity(columns.len());
        for column in columns {
            // ZSTD requires all training data to be continuous in memory, alongside the size of
            // each entry
            let mut sizes = vec![];
            let data: Vec<_> = column
                .into_iter()
                .flat_map(|data| {
                    sizes.push(data.len());
                    data
                })
                .collect();

            dictionaries.push(zstd::dict::from_continuous(&data, &sizes, self.max_dict_size)?);
        }

        debug_assert_eq!(dictionaries.len(), self.columns);

        self.dictionaries = Some(Arc::new(ZstdDictionaries::new(dictionaries)));
        self.state = ZstdState::Ready;

        Ok(())
    }
}

mod dictionaries_serde {
    use super::*;

    pub(crate) fn serialize<S>(
        dictionaries: &Option<Arc<ZstdDictionaries<'static>>>,
        serializer: S,
    ) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match dictionaries {
            Some(dicts) => serializer.serialize_some(dicts.as_ref()),
            None => serializer.serialize_none(),
        }
    }

    pub(crate) fn deserialize<'de, D>(
        deserializer: D,
    ) -> Result<Option<Arc<ZstdDictionaries<'static>>>, D::Error>
    where
        D: Deserializer<'de>,
    {
        let dictionaries: Option<Vec<RawDictionary>> = Option::deserialize(deserializer)?;
        Ok(dictionaries.map(|dicts| Arc::new(ZstdDictionaries::load(dicts))))
    }
}

/// List of [`ZstdDictionary`]
#[cfg_attr(test, derive(PartialEq))]
#[derive(Serialize, Deserialize, Deref)]
pub(crate) struct ZstdDictionaries<'a>(Vec<ZstdDictionary<'a>>);

impl std::fmt::Debug for ZstdDictionaries<'_> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("ZstdDictionaries").field("num", &self.len()).finish_non_exhaustive()
    }
}

impl ZstdDictionaries<'_> {
    #[cfg(test)]
    /// Creates [`ZstdDictionaries`].
    pub(crate) fn new(raw: Vec<RawDictionary>) -> Self {
        Self(raw.into_iter().map(ZstdDictionary::Raw).collect())
    }

    /// Loads a list [`RawDictionary`] into a list of [`ZstdDictionary::Loaded`].
    pub(crate) fn load(raw: Vec<RawDictionary>) -> Self {
        Self(
            raw.into_iter()
                .map(|dict| ZstdDictionary::Loaded(DecoderDictionary::copy(&dict)))
                .collect(),
        )
    }

    /// Creates a list of decompressors from a list of [`ZstdDictionary::Loaded`].
    pub(crate) fn decompressors(&self) -> Result<Vec<Decompressor<'_>>, NippyJarError> {
        Ok(self
            .iter()
            .flat_map(|dict| {
                dict.loaded()
                    .ok_or(NippyJarError::DictionaryNotLoaded)
                    .map(Decompressor::with_prepared_dictionary)
            })
            .collect::<Result<Vec<_>, _>>()?)
    }

    /// Creates a list of compressors from a list of [`ZstdDictionary::Raw`].
    pub(crate) fn compressors(&self) -> Result<Vec<Compressor<'_>>, NippyJarError> {
        Ok(self
            .iter()
            .flat_map(|dict| {
                dict.raw()
                    .ok_or(NippyJarError::CompressorNotAllowed)
                    .map(|dict| Compressor::with_dictionary(0, dict))
            })
            .collect::<Result<Vec<_>, _>>()?)
    }
}

/// A Zstd dictionary. It's created and serialized with [`ZstdDictionary::Raw`], and deserialized as
/// [`ZstdDictionary::Loaded`].
pub(crate) enum ZstdDictionary<'a> {
    #[cfg_attr(not(test), expect(dead_code))]
    Raw(RawDictionary),
    Loaded(DecoderDictionary<'a>),
}

impl ZstdDictionary<'_> {
    /// Returns a reference to the expected `RawDictionary`
    pub(crate) const fn raw(&self) -> Option<&RawDictionary> {
        match self {
            ZstdDictionary::Raw(dict) => Some(dict),
            ZstdDictionary::Loaded(_) => None,
        }
    }

    /// Returns a reference to the expected `DecoderDictionary`
    pub(crate) const fn loaded(&self) -> Option<&DecoderDictionary<'_>> {
        match self {
            ZstdDictionary::Raw(_) => None,
            ZstdDictionary::Loaded(dict) => Some(dict),
        }
    }
}

impl<'de> Deserialize<'de> for ZstdDictionary<'_> {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let dict = RawDictionary::deserialize(deserializer)?;
        Ok(Self::Loaded(DecoderDictionary::copy(&dict)))
    }
}

impl Serialize for ZstdDictionary<'_> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match self {
            ZstdDictionary::Raw(r) => r.serialize(serializer),
            ZstdDictionary::Loaded(_) => unreachable!(),
        }
    }
}

#[cfg(test)]
impl PartialEq for ZstdDictionary<'_> {
    fn eq(&self, other: &Self) -> bool {
        if let (Self::Raw(a), Self::Raw(b)) = (self, &other) {
            return a == b
        }
        unimplemented!(
            "`DecoderDictionary` can't be compared. So comparison should be done after decompressing a value."
        );
    }
}


        }

        match decompressor.decompress_to_buffer(column_value, &mut output[previous_length..]) {
            Ok(written) => {
                // SAFETY: `decompress_to_buffer` can only write if there's enough capacity.
                // Therefore, it shouldn't write more than our capacity.
                unsafe {
                    output.set_len(previous_length + written);
                }
                Ok(())
            }
            Err(_) => {
                // SAFETY: we are resetting it to the previous value.
                unsafe {
                    output.set_len(previous_length);
                }
                Err(NippyJarError::OutputTooSmall)
            }
        }
    }
}

impl Compression for Zstd {
    fn decompress_to(&self, value: &[u8], dest: &mut Vec<u8>) -> Result<(), NippyJarError> {
        let mut decoder = zstd::Decoder::with_dictionary(value, &[])?;
        decoder.read_to_end(dest)?;
        Ok(())
    }

    fn decompress(&self, value: &[u8]) -> Result<Vec<u8>, NippyJarError> {
        let mut decompressed = Vec::with_capacity(value.len() * 2);
        let mut decoder = zstd::Decoder::new(value)?;
        decoder.read_to_end(&mut decompressed)?;
        Ok(decompressed)
    }

    fn compress_to(&self, src: &[u8], dest: &mut Vec<u8>) -> Result<usize, NippyJarError> {
        let before = dest.len();

        let mut encoder = zstd::Encoder::new(dest, self.level)?;
        encoder.write_all(src)?;

        let dest = encoder.finish()?;

        Ok(dest.len() - before)
    }

    fn compress(&self, src: &[u8]) -> Result<Vec<u8>, NippyJarError> {
        let mut compressed = Vec::with_capacity(src.len());

        self.compress_to(src, &mut compressed)?;

        Ok(compressed)
    }

    fn is_ready(&self) -> bool {
        matches!(self.state, ZstdState::Ready)
    }

    #[cfg(test)]
    /// If using it with dictionaries, prepares a dictionary for each column.
    fn prepare_compression(
        &mut self,
        columns: Vec<impl IntoIterator<Item = Vec<u8>>>,
    ) -> Result<(), NippyJarError> {
        if !self.use_dict {
            return Ok(())
        }

        // There's a per 2GB hard limit on each column data set for training
        // REFERENCE: https://github.com/facebook/zstd/blob/dev/programs/zstd.1.md#dictionary-builder
        // ```
        // -M#, --memory=#: Limit the amount of sample data loaded for training (default: 2 GB).
        // Note that the default (2 GB) is also the maximum. This parameter can be useful in
        // situations where the training set size is not well controlled and could be potentially
        // very large. Since speed of the training process is directly correlated to the size of the
        // training sample set, a smaller sample set leads to faster training.`
        // ```

        if columns.len() != self.columns {
            return Err(NippyJarError::ColumnLenMismatch(self.columns, columns.len()))
        }

        let mut dictionaries = Vec::with_capacity(columns.len());
        for column in columns {
            // ZSTD requires all training data to be continuous in memory, alongside the size of
            // each entry
            let mut sizes = vec![];
            let data: Vec<_> = column
                .into_iter()
                .flat_map(|data| {
                    sizes.push(data.len());
                    data
                })
                .collect();

            dictionaries.push(zstd::dict::from_continuous(&data, &sizes, self.max_dict_size)?);
        }

        debug_assert_eq!(dictionaries.len(), self.columns);

        self.dictionaries = Some(Arc::new(ZstdDictionaries::new(dictionaries)));
        self.state = ZstdState::Ready;

        Ok(())
    }
}

mod dictionaries_serde {
    use super::*;

    pub(crate) fn serialize<S>(
        dictionaries: &Option<Arc<ZstdDictionaries<'static>>>,
        serializer: S,
    ) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match dictionaries {
            Some(dicts) => serializer.serialize_some(dicts.as_ref()),
            None => serializer.serialize_none(),
        }
    }

    pub(crate) fn deserialize<'de, D>(
        deserializer: D,
    ) -> Result<Option<Arc<ZstdDictionaries<'static>>>, D::Error>
    where
        D: Deserializer<'de>,
    {
        let dictionaries: Option<Vec<RawDictionary>> = Option::deserialize(deserializer)?;
        Ok(dictionaries.map(|dicts| Arc::new(ZstdDictionaries::load(dicts))))
    }
}

/// List of [`ZstdDictionary`]
#[cfg_attr(test, derive(PartialEq))]
#[derive(Serialize, Deserialize, Deref)]
pub(crate) struct ZstdDictionaries<'a>(Vec<ZstdDictionary<'a>>);

impl std::fmt::Debug for ZstdDictionaries<'_> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("ZstdDictionaries").field("num", &self.len()).finish_non_exhaustive()
    }
}

impl ZstdDictionaries<'_> {
    #[cfg(test)]
    /// Creates [`ZstdDictionaries`].
    pub(crate) fn new(raw: Vec<RawDictionary>) -> Self {
        Self(raw.into_iter().map(ZstdDictionary::Raw).collect())
    }

    /// Loads a list [`RawDictionary`] into a list of [`ZstdDictionary::Loaded`].
    pub(crate) fn load(raw: Vec<RawDictionary>) -> Self {
        Self(
            raw.into_iter()
                .map(|dict| ZstdDictionary::Loaded(DecoderDictionary::copy(&dict)))
                .collect(),
        )
    }

    /// Creates a list of decompressors from a list of [`ZstdDictionary::Loaded`].
    pub(crate) fn decompressors(&self) -> Result<Vec<Decompressor<'_>>, NippyJarError> {
        Ok(self
            .iter()
            .flat_map(|dict| {
                dict.loaded()
                    .ok_or(NippyJarError::DictionaryNotLoaded)
                    .map(Decompressor::with_prepared_dictionary)
            })
            .collect::<Result<Vec<_>, _>>()?)
    }

    /// Creates a list of compressors from a list of [`ZstdDictionary::Raw`].
    pub(crate) fn compressors(&self) -> Result<Vec<Compressor<'_>>, NippyJarError> {
        Ok(self
            .iter()
            .flat_map(|dict| {
                dict.raw()
                    .ok_or(NippyJarError::CompressorNotAllowed)
                    .map(|dict| Compressor::with_dictionary(0, dict))
            })
            .collect::<Result<Vec<_>, _>>()?)
    }
}

/// A Zstd dictionary. It's created and serialized with [`ZstdDictionary::Raw`], and deserialized as
/// [`ZstdDictionary::Loaded`].
pub(crate) enum ZstdDictionary<'a> {
    #[cfg_attr(not(test), expect(dead_code))]
    Raw(RawDictionary),
    Loaded(DecoderDictionary<'a>),
}

impl ZstdDictionary<'_> {
    /// Returns a reference to the expected `RawDictionary`
    pub(crate) const fn raw(&self) -> Option<&RawDictionary> {
        match self {
            ZstdDictionary::Raw(dict) => Some(dict),
            ZstdDictionary::Loaded(_) => None,
        }
    }

    /// Returns a reference to the expected `DecoderDictionary`
    pub(crate) const fn loaded(&self) -> Option<&DecoderDictionary<'_>> {
        match self {
            ZstdDictionary::Raw(_) => None,
            ZstdDictionary::Loaded(dict) => Some(dict),
        }
    }
}

impl<'de> Deserialize<'de> for ZstdDictionary<'_> {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let dict = RawDictionary::deserialize(deserializer)?;
        Ok(Self::Loaded(DecoderDictionary::copy(&dict)))
    }
}

impl Serialize for ZstdDictionary<'_> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match self {
            ZstdDictionary::Raw(r) => r.serialize(serializer),
            ZstdDictionary::Loaded(_) => unreachable!(),
        }
    }
}

#[cfg(test)]
impl PartialEq for ZstdDictionary<'_> {

    fn eq(&self, other: &Self) -> bool {
        if let (Self::Raw(a), Self::Raw(b)) = (self, &other) {
            return a == b
        }
        unimplemented!(
            "`DecoderDictionary` can't be compared. So comparison should be done after decompressing a value."
        );
    }


 {
            Some(dicts) => serializer.serialize_some(dicts.as_ref()),
            None => serializer.serialize_none(),
        }
    }

    pub(crate) fn deserialize<'de, D>(
        deserializer: D,
    ) -> Result<Option<Arc<ZstdDictionaries<'static>>>, D::Error>
    where
        D: Deserializer<'de>,
    {
        let dictionaries: Option<Vec<RawDictionary>> = Option::deserialize(deserializer)?;
        Ok(dictionaries.map(|dicts| Arc::new(ZstdDictionaries::load(dicts))))
    }
}

/// List of [`ZstdDictionary`]
#[cfg_attr(test, derive(PartialEq))]
#[derive(Serialize, Deserialize, Deref)]
pub(crate) struct ZstdDictionaries<'a>(Vec<ZstdDictionary<'a>>);

impl std::fmt::Debug for ZstdDictionaries<'_> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("ZstdDictionaries").field("num", &self.len()).finish_non_exhaustive()
    }
}

impl ZstdDictionaries<'_> {
    #[cfg(test)]
    /// Creates [`ZstdDictionaries`].
    pub(crate) fn new(raw: Vec<RawDictionary>) -> Self {
        Self(raw.into_iter().map(ZstdDictionary::Raw).collect())
    }

    /// Loads a list [`RawDictionary`] into a list of [`ZstdDictionary::Loaded`].
    pub(crate) fn load(raw: Vec<RawDictionary>) -> Self {
        Self(
            raw.into_iter()
                .map(|dict| ZstdDictionary::Loaded(DecoderDictionary::copy(&dict)))
                .collect(),
        )
    }

    /// Creates a list of decompressors from a list of [`ZstdDictionary::Loaded`].
    pub(crate) fn decompressors(&self) -> Result<Vec<Decompressor<'_>>, NippyJarError> {
        Ok(self
            .iter()
            .flat_map(|dict| {
                dict.loaded()
                    .ok_or(NippyJarError::DictionaryNotLoaded)
                    .map(Decompressor::with_prepared_dictionary)
            })
            .collect::<Result<Vec<_>, _>>()?)
    }

    /// Creates a list of compressors from a list of [`ZstdDictionary::Raw`].
    pub(crate) fn compressors(&self) -> Result<Vec<Compressor<'_>>, NippyJarError> {
        Ok(self
            .iter()
            .flat_map(|dict| {
                dict.raw()
                    .ok_or(NippyJarError::CompressorNotAllowed)
                    .map(|dict| Compressor::with_dictionary(0, dict))
            })
            .collect::<Result<Vec<_>, _>>()?)
    }
}

/// A Zstd dictionary. It's created and serialized with [`ZstdDictionary::Raw`], and deserialized as
/// [`ZstdDictionary::Loaded`].
pub(crate) enum ZstdDictionary<'a> {
    #[cfg_attr(not(test), expect(dead_code))]
    Raw(RawDictionary),
    Loaded(DecoderDictionary<'a>),
}

impl ZstdDictionary<'_> {
    /// Returns a reference to the expected `RawDictionary`
    pub(crate) const fn raw(&self) -> Option<&RawDictionary> {
        match self {
            ZstdDictionary::Raw(dict) => Some(dict),
            ZstdDictionary::Loaded(_) => None,
        }
    }

    /// Returns a reference to the expected `DecoderDictionary`
    pub(crate) const fn loaded(&self) -> Option<&DecoderDictionary<'_>> {
        match self {
            ZstdDictionary::Raw(_) => None,
            ZstdDictionary::Loaded(dict) => Some(dict),
        }
    }
}

impl<'de> Deserialize<'de> for ZstdDictionary<'_> {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let dict = RawDictionary::deserialize(deserializer)?;
        Ok(Self::Loaded(DecoderDictionary::copy(&dict)))
    }
}

impl Serialize for ZstdDictionary<'_> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match self {
            ZstdDictionary::Raw(r) => r.serialize(serializer),
            ZstdDictionary::Loaded(_) => unreachable!(),
        }
    }
}

#[cfg(test)]
impl PartialEq for ZstdDictionary<'_> {
    fn eq(&self, other: &Self) -> bool

{
        if let (Self::Raw(a), Self::Raw(b)) = (self, &other) {
            return a == b
        }
        unimplemented!(
            "`DecoderDictionary` can't be compared. So comparison should be done after decompressing a value."
        );
    }


//! Testing namespace for building a block in a single call.
//!
//! This follows the `testing_buildBlockV1` specification. **Highly sensitive:**
//! testing-only, powerful enough to include arbitrary transactions; must stay
//! disabled by default and never be exposed on public-facing RPC without an
//! explicit operator flag.

use jsonrpsee::proc_macros::rpc;

pub use alloy_rpc_types_engine::{TestingBuildBlockRequestV1, TESTING_BUILD_BLOCK_V1};

/// Testing RPC interface for building a block in a single call.
///
/// # Enabling
///
/// This namespace is disabled by default for security reasons. To enable it,
/// add `testing` to the `--http.api` flag:
///
/// ```sh
/// reth node --http --http.api eth,testing
/// ```
///
/// **Warning:** Never expose this on public-facing RPC endpoints without proper
/// authentication.
#[cfg_attr(not(feature = "client"), rpc(server, namespace = "testing"))]
#[cfg_attr(feature = "client", rpc(server, client, namespace = "testing"))]
pub trait TestingApi {
    /// Builds a block using the provided parent, payload attributes, and transactions.
    ///
    /// See <https://github.com/marcindsobczak/execution-apis/blob/main/src/testing/testing_buildBlockV1.md>
    #[method(name = "buildBlockV1")]
    async fn build_block_v1(
        &self,
        request: TestingBuildBlockRequestV1,
    ) -> jsonrpsee::core::RpcResult<ExecutionPayloadEnvelopeV5>;
}


//! Testing namespace for building a block in a single call.
//!
//! This follows the `testing_buildBlockV1` specification. **Highly sensitive:**
//! testing-only, powerful enough to include arbitrary transactions; must stay
//! disabled by default and never be exposed on public-facing RPC without an
//! explicit operator flag.

use alloy_rpc_types_engine::ExecutionPayloadEnvelopeV5;

pub use alloy_rpc_types_engine::{TestingBuildBlockRequestV1, TESTING_BUILD_BLOCK_V1};

/// Testing RPC interface for building a block in a single call.
///
/// # Enabling
///
/// This namespace is disabled by default for security reasons. To enable it,
/// add `testing` to the `--http.api` flag:
///
/// ```sh
/// reth node --http --http.api eth,testing
/// ```
///
/// **Warning:** Never expose this on public-facing RPC endpoints without proper
/// authentication.
#[cfg_attr(not(feature = "client"), rpc(server, namespace = "testing"))]
#[cfg_attr(feature = "client", rpc(server, client, namespace = "testing"))]
pub trait TestingApi {
    /// Builds a block using the provided parent, payload attributes, and transactions.
    ///
    /// See <https://github.com/marcindsobczak/execution-apis/blob/main/src/testing/testing_buildBlockV1.md>
    #[method(name = "buildBlockV1")]
    async fn build_block_v1(
        &self,
        request: TestingBuildBlockRequestV1,
    ) -> jsonrpsee::core::RpcResult<ExecutionPayloadEnvelopeV5>;
}


//! Testing namespace for building a block in a single call.
//!
//! This follows the `testing_buildBlockV1` specification. **Highly sensitive:**
//! testing-only, powerful enough to include arbitrary transactions; must stay
//! disabled by default and never be exposed on public-facing RPC without an
//! explicit operator flag.

use alloy_rpc_types_engine::ExecutionPayloadEnvelopeV5;
use jsonrpsee::proc_macros::rpc;

pub use alloy_rpc_types_engine::{TestingBuildBlockRequestV1, TESTING_BUILD_BLOCK_V1};

/// Testing RPC interface for building a block in a single call.
///
/// # Enabling
///
/// This namespace is disabled by default for security reasons. To enable it,
/// add `testing` to the `--http.api` flag:
///
/// ```sh
/// reth node --http --http.api eth,testing
/// ```
///
/// **Warning:** Never expose this on public-facing RPC endpoints without proper
/// authentication.
#[cfg_attr(not(feature = "client"), rpc(server, namespace = "testing"))]
#[cfg_attr(feature = "client", rpc(server, client, namespace = "testing"))]
pub trait TestingApi {
    /// Builds a block using the provided parent, payload attributes, and transactions.
    ///
    /// See <https://github.com/marcindsobczak/execution-apis/blob/main/src/testing/testing_buildBlockV1.md>
    #[method(name = "buildBlockV1")]
    async fn build_block_v1(
        &self,
        request: TestingBuildBlockRequestV1,
    ) -> jsonrpsee::core::RpcResult<ExecutionPayloadEnvelopeV5>;
}


/// Static File compression types.
#[derive(Debug, Copy, Clone, Default, AsRefStr)]
#[cfg_attr(feature = "clap", derive(clap::ValueEnum))]
pub enum Compression {
    /// LZ4 compression algorithm.
    #[strum(serialize = "lz4")]
    Lz4,
    /// Zstandard (Zstd) compression algorithm.
    #[strum(serialize = "zstd")]
    Zstd,
    /// Zstandard (Zstd) compression algorithm with a dictionary.
    #[strum(serialize = "zstd-dict")]
    ZstdWithDictionary,
    /// No compression.
    #[strum(serialize = "uncompressed")]
    #[default]
    Uncompressed,
}


use crate::{
    hashed_cursor::{HashedCursor, HashedCursorFactory, HashedStorageCursor},
    node_iter::{TrieElement, TrieNodeIter},
    prefix_set::{PrefixSet, TriePrefixSets},
    progress::{
        IntermediateRootState, IntermediateStateRootState, IntermediateStorageRootState,
        StateRootProgress, StorageRootProgress,
    },
    stats::TrieTracker,
    trie_cursor::{TrieCursor, TrieCursorFactory},
    updates::{StorageTrieUpdates, TrieUpdates},
    walker::TrieWalker,
    HashBuilder, Nibbles, TRIE_ACCOUNT_RLP_MAX_SIZE,
};

use alloy_consensus::EMPTY_ROOT_HASH;
use alloy_primitives::{keccak256, Address, B256};
use alloy_rlp::{BufMut, Encodable};
use alloy_trie::proof::AddedRemovedKeys;
use reth_execution_errors::{StateRootError, StorageRootError};
use reth_primitives_traits::Account;
use tracing::{debug, instrument, trace, Span};

/// The default updates after which root algorithms should return intermediate progress rather than
/// finishing the computation.
const DEFAULT_INTERMEDIATE_THRESHOLD: u64 = 100_000;

#[cfg(feature = "metrics")]
use crate::metrics::{StateRootMetrics, TrieRootMetrics};

/// `StateRoot` is used to compute the root node of a state trie.
#[derive(Debug)]
pub struct StateRoot<T, H> {
    /// The factory for trie cursors.
    pub trie_cursor_factory: T,
    /// The factory for hashed cursors.
    pub hashed_cursor_factory: H,
    /// A set of prefix sets that have changed.
    pub prefix_sets: TriePrefixSets,
    /// Previous intermediate state.
    previous_state: Option<IntermediateStateRootState>,
    /// The number of updates after which the intermediate progress should be returned.
    threshold: u64,
    #[cfg(feature = "metrics")]
    /// State root metrics.
    metrics: StateRootMetrics,
}

impl<T, H> StateRoot<T, H> {
    /// Creates [`StateRoot`] with `trie_cursor_factory` and `hashed_cursor_factory`. All other
    /// parameters are set to reasonable defaults.
    ///
    /// The cursors created by given factories are then used to walk through the accounts and
    /// calculate the state root value with.
    pub fn new(trie_cursor_factory: T, hashed_cursor_factory: H) -> Self {
        Self {
            trie_cursor_factory,
            hashed_cursor_factory,
            prefix_sets: TriePrefixSets::default(),
            previous_state: None,
            threshold: DEFAULT_INTERMEDIATE_THRESHOLD,
            #[cfg(feature = "metrics")]
            metrics: StateRootMetrics::default(),
        }
    }

    /// Set the prefix sets.
    pub fn with_prefix_sets(mut self, prefix_sets: TriePrefixSets) -> Self {
        self.prefix_sets = prefix_sets;
        self
    }

    /// Set the threshold.
    pub const fn with_threshold(mut self, threshold: u64) -> Self {
        self.threshold = threshold;
        self
    }

    /// Set the threshold to maximum value so that intermediate progress is not returned.
    pub const fn with_no_threshold(mut self) -> Self {
        self.threshold = u64::MAX;
        self
    }

    /// Set the previously recorded intermediate state.
    pub fn with_intermediate_state(mut self, state: Option<IntermediateStateRootState>) -> Self {
        self.previous_state = state;
        self
    }

    /// Set the hashed cursor factory.
    pub fn with_hashed_cursor_factory<HF>(self, hashed_cursor_factory: HF) -> StateRoot<T, HF> {
        StateRoot {
            trie_cursor_factory: self.trie_cursor_factory,
            hashed_cursor_factory,
            prefix_sets: self.prefix_sets,
            threshold: self.threshold,
            previous_state: self.previous_state,
            #[cfg(feature = "metrics")]
            metrics: self.metrics,
        }
    }

    /// Set the trie cursor factory.
    pub fn with_trie_cursor_factory<TF>(self, trie_cursor_factory: TF) -> StateRoot<TF, H> {
        StateRoot {
            trie_cursor_factory,
            hashed_cursor_factory: self.hashed_cursor_factory,
            prefix_sets: self.prefix_sets,
            threshold: self.threshold,
            previous_state: self.previous_state,
            #[cfg(feature = "metrics")]
            metrics: self.metrics,
        }
    }
}

impl<T, H> StateRoot<T, H>
where
    T: TrieCursorFactory + Clone,
    H: HashedCursorFactory + Clone,
{


use crate::{
    hashed_cursor::{HashedCursor, HashedCursorFactory, HashedStorageCursor},
    node_iter::{TrieElement, TrieNodeIter},
    prefix_set::{PrefixSet, TriePrefixSets},
    progress::{
        IntermediateRootState, IntermediateStateRootState, IntermediateStorageRootState,
        StateRootProgress, StorageRootProgress,
    },
    stats::TrieTracker,
    trie_cursor::{TrieCursor, TrieCursorFactory},
    updates::{StorageTrieUpdates, TrieUpdates},
    walker::TrieWalker,
    HashBuilder, Nibbles, TRIE_ACCOUNT_RLP_MAX_SIZE,
};

use alloy_primitives::{keccak256, Address, B256};
use alloy_rlp::{BufMut, Encodable};
use alloy_trie::proof::AddedRemovedKeys;
use reth_execution_errors::{StateRootError, StorageRootError};
use reth_primitives_traits::Account;
use tracing::{debug, instrument, trace, Span};

/// The default updates after which root algorithms should return intermediate progress rather than
/// finishing the computation.
const DEFAULT_INTERMEDIATE_THRESHOLD: u64 = 100_000;

#[cfg(feature = "metrics")]
use crate::metrics::{StateRootMetrics, TrieRootMetrics};

/// `StateRoot` is used to compute the root node of a state trie.
#[derive(Debug)]
pub struct StateRoot<T, H> {
    /// The factory for trie cursors.
    pub trie_cursor_factory: T,
    /// The factory for hashed cursors.
    pub hashed_cursor_factory: H,
    /// A set of prefix sets that have changed.
    pub prefix_sets: TriePrefixSets,
    /// Previous intermediate state.
    previous_state: Option<IntermediateStateRootState>,
    /// The number of updates after which the intermediate progress should be returned.
    threshold: u64,
    #[cfg(feature = "metrics")]
    /// State root metrics.
    metrics: StateRootMetrics,
}

impl<T, H> StateRoot<T, H> {
    /// Creates [`StateRoot`] with `trie_cursor_factory` and `hashed_cursor_factory`. All other
    /// parameters are set to reasonable defaults.
    ///
    /// The cursors created by given factories are then used to walk through the accounts and
    /// calculate the state root value with.
    pub fn new(trie_cursor_factory: T, hashed_cursor_factory: H) -> Self {
        Self {
            trie_cursor_factory,
            hashed_cursor_factory,
            prefix_sets: TriePrefixSets::default(),
            previous_state: None,
            threshold: DEFAULT_INTERMEDIATE_THRESHOLD,
            #[cfg(feature = "metrics")]
            metrics: StateRootMetrics::default(),
        }
    }

    /// Set the prefix sets.
    pub fn with_prefix_sets(mut self, prefix_sets: TriePrefixSets) -> Self {
        self.prefix_sets = prefix_sets;
        self
    }

    /// Set the threshold.
    pub const fn with_threshold(mut self, threshold: u64) -> Self {
        self.threshold = threshold;
        self
    }

    /// Set the threshold to maximum value so that intermediate progress is not returned.
    pub const fn with_no_threshold(mut self) -> Self {
        self.threshold = u64::MAX;
        self
    }

    /// Set the previously recorded intermediate state.
    pub fn with_intermediate_state(mut self, state: Option<IntermediateStateRootState>) -> Self {
        self.previous_state = state;
        self
    }

    /// Set the hashed cursor factory.
    pub fn with_hashed_cursor_factory<HF>(self, hashed_cursor_factory: HF) -> StateRoot<T, HF> {
        StateRoot {
            trie_cursor_factory: self.trie_cursor_factory,
            hashed_cursor_factory,
            prefix_sets: self.prefix_sets,
            threshold: self.threshold,
            previous_state: self.previous_state,
            #[cfg(feature = "metrics")]
            metrics: self.metrics,
        }
    }

    /// Set the trie cursor factory.
    pub fn with_trie_cursor_factory<TF>(self, trie_cursor_factory: TF) -> StateRoot<TF, H> {
        StateRoot {
            trie_cursor_factory,
            hashed_cursor_factory: self.hashed_cursor_factory,
            prefix_sets: self.prefix_sets,
            threshold: self.threshold,
            previous_state: self.previous_state,
            #[cfg(feature = "metrics")]
            metrics: self.metrics,
        }
    }
}

impl<T, H> StateRoot<T, H>
where
    T: TrieCursorFactory + Clone,
    H: HashedCursorFactory + Clone,
{
    /// Walks the intermediate nodes of existing state trie (if any) and hashed entries. Feeds the
    /// nodes into the hash builder. Collects the updates in the process.
    ///
    /// Ignores the threshold.
    ///
    /// # Returns
    ///
    /// The state root and the trie updates.
    pub fn root_with_updates(self) -> Result<(B256, TrieUpdates), StateRootError> {
        match self.with_no_threshold().calculate(true)? {
            StateRootProgress::Complete(root, _, updates) => Ok((root, updates)),
            StateRootProgress::Progress(..) => unreachable!(), // unreachable threshold
        }
    }

    /// Walks the intermediate nodes of existing state trie (if any) and hashed entries. Feeds the
    /// nodes into the hash builder.
    ///
    /// # Returns
    ///
    /// The state root hash.
    pub fn root(self) -> Result<B256, StateRootError> {
        match self.calculate(false)? {
            StateRootProgress::Complete(root, _, _) => Ok(root),
            StateRootProgress::Progress(..) => unreachable!(), // update retention is disabled
        }
    }

    /// Walks the intermediate nodes of existing state trie (if any) and hashed entries. Feeds the
    /// nodes into the hash builder. Collects the updates in the process.
    ///
    /// # Returns
    ///
    /// The intermediate progress of state root computation.
    pub fn root_with_progress(self) -> Result<StateRootProgress, StateRootError> {
        self.calculate(true)
    }

    fn calculate(self, retain_updates: bool) -> Result<StateRootProgress, StateRootError> {
        trace!(target: "trie::state_root", "calculating state root");
        let mut tracker = TrieTracker::default();

        let trie_cursor = self.trie_cursor_factory.account_trie_cursor()?;
        let hashed_account_cursor = self.hashed_cursor_factory.hashed_account_cursor()?;

        // create state root context once for reuse
        let mut storage_ctx = StateRootContext::new();

        // first handle any in-progress storage root calculation
        let (mut hash_builder, mut account_node_iter) = if let Some(state) = self.previous_state {
            let IntermediateStateRootState { account_root_state, storage_root_state } = state;

            // resume account trie iteration
            let mut hash_builder = account_root_state.hash_builder.with_updates(retain_updates);
            let walker = TrieWalker::<_>::state_trie_from_stack(
                trie_cursor,
                account_root_state.walker_stack,
                self.prefix_sets.account_prefix_set,
            )
            .with_deletions_retained(retain_updates);
            let account_node_iter = TrieNodeIter::state_trie(walker, hashed_account_cursor)
                .with_last_hashed_key(account_root_state.last_hashed_key);

            // if we have an in-progress storage root, complete it first
            if let Some(storage_state) = storage_root_state {
                let hashed_address = account_root_state.last_hashed_key;
                let account = storage_state.account;

                debug!(
                    target: "trie::state_root",
                    account_nonce = account.nonce,
                    account_balance = ?account.balance,
                    last_hashed_key = ?account_root_state.last_hashed_key,
                    "Resuming storage root calculation"
                );

                // resume the storage root calculation
                let remaining_threshold = self.threshold.saturating_sub(
                    storage_ctx.total_updates_len(&account_node_iter, &hash_builder),
                );

                let storage_root_calculator = StorageRoot::new_hashed(
                    self.trie_cursor_factory.clone(),
                    self.hashed_cursor_factory.clone(),
                    hashed_address,
                    self.prefix_sets
                        .storage_prefix_sets
                        .get(&hashed_address)
                        .cloned()
                        .unwrap_or_default(),
                    #[cfg(feature = "metrics")]
                    self.metrics.storage_trie.clone(),
                )
                .with_intermediate_state(Some(storage_state.state))
                .with_threshold(remaining_threshold);


use crate::{
    hashed_cursor::{HashedCursor, HashedCursorFactory, HashedStorageCursor},
    node_iter::{TrieElement, TrieNodeIter},
    prefix_set::{PrefixSet, TriePrefixSets},
    progress::{
        IntermediateRootState, IntermediateStateRootState, IntermediateStorageRootState,
        StateRootProgress, StorageRootProgress,
    },
    stats::TrieTracker,
    trie_cursor::{TrieCursor, TrieCursorFactory},
    updates::{StorageTrieUpdates, TrieUpdates},
    walker::TrieWalker,
    HashBuilder, Nibbles, TRIE_ACCOUNT_RLP_MAX_SIZE,
};
use alloy_consensus::EMPTY_ROOT_HASH;

use alloy_primitives::{keccak256, Address, B256};

use alloy_rlp::{BufMut, Encodable};
use alloy_trie::proof::AddedRemovedKeys;
use reth_execution_errors::{StateRootError, StorageRootError};
use reth_primitives_traits::Account;
use tracing::{debug, instrument, trace, Span};

/// The default updates after which root algorithms should return intermediate progress rather than
/// finishing the computation.
const DEFAULT_INTERMEDIATE_THRESHOLD: u64 = 100_000;

#[cfg(feature = "metrics")]
use crate::metrics::{StateRootMetrics, TrieRootMetrics};

/// `StateRoot` is used to compute the root node of a state trie.
#[derive(Debug)]
pub struct StateRoot<T, H> {
    /// The factory for trie cursors.
    pub trie_cursor_factory: T,
    /// The factory for hashed cursors.
    pub hashed_cursor_factory: H,
    /// A set of prefix sets that have changed.
    pub prefix_sets: TriePrefixSets,
    /// Previous intermediate state.
    previous_state: Option<IntermediateStateRootState>,
    /// The number of updates after which the intermediate progress should be returned.
    threshold: u64,
    #[cfg(feature = "metrics")]
    /// State root metrics.
    metrics: StateRootMetrics,
}

impl<T, H> StateRoot<T, H> {
    /// Creates [`StateRoot`] with `trie_cursor_factory` and `hashed_cursor_factory`. All other
    /// parameters are set to reasonable defaults.
    ///
    /// The cursors created by given factories are then used to walk through the accounts and
    /// calculate the state root value with.
    pub fn new(trie_cursor_factory: T, hashed_cursor_factory: H) -> Self {
        Self {
            trie_cursor_factory,
            hashed_cursor_factory,
            prefix_sets: TriePrefixSets::default(),
            previous_state: None,
            threshold: DEFAULT_INTERMEDIATE_THRESHOLD,
            #[cfg(feature = "metrics")]
            metrics: StateRootMetrics::default(),
        }
    }

    /// Set the prefix sets.
    pub fn with_prefix_sets(mut self, prefix_sets: TriePrefixSets) -> Self {
        self.prefix_sets = prefix_sets;
        self
    }

    /// Set the threshold.
    pub const fn with_threshold(mut self, threshold: u64) -> Self {
        self.threshold = threshold;
        self
    }

    /// Set the threshold to maximum value so that intermediate progress is not returned.
    pub const fn with_no_threshold(mut self) -> Self {
        self.threshold = u64::MAX;
        self
    }

    /// Set the previously recorded intermediate state.
    pub fn with_intermediate_state(mut self, state: Option<IntermediateStateRootState>) -> Self {
        self.previous_state = state;
        self
    }

    /// Set the hashed cursor factory.
    pub fn with_hashed_cursor_factory<HF>(self, hashed_cursor_factory: HF) -> StateRoot<T, HF> {
        StateRoot {
            trie_cursor_factory: self.trie_cursor_factory,
            hashed_cursor_factory,
            prefix_sets: self.prefix_sets,
            threshold: self.threshold,
            previous_state: self.previous_state,
            #[cfg(feature = "metrics")]
            metrics: self.metrics,
        }
    }

    /// Set the trie cursor factory.
    pub fn with_trie_cursor_factory<TF>(self, trie_cursor_factory: TF) -> StateRoot<TF, H> {
        StateRoot {
            trie_cursor_factory,
            hashed_cursor_factory: self.hashed_cursor_factory,
            prefix_sets: self.prefix_sets,
            threshold: self.threshold,
            previous_state: self.previous_state,
            #[cfg(feature = "metrics")]
            metrics: self.metrics,
        }
    }
}

impl<T, H> StateRoot<T, H>
where
    T: TrieCursorFactory + Clone,
    H: HashedCursorFactory + Clone,
{
    /// Walks the intermediate nodes of existing state trie (if any) and hashed entries. Feeds the
    /// nodes into the hash builder. Collects the updates in the process.
    ///
    /// Ignores the threshold.
    ///
    /// # Returns
    ///
    /// The state root and the trie updates.
    pub fn root_with_updates(self) -> Result<(B256, TrieUpdates), StateRootError> {
        match self.with_no_threshold().calculate(true)? {
            StateRootProgress::Complete(root, _, updates) => Ok((root, updates)),
            StateRootProgress::Progress(..) => unreachable!(), // unreachable threshold
        }
    }

    /// Walks the intermediate nodes of existing state trie (if any) and hashed entries. Feeds the
    /// nodes into the hash builder.
    ///
    /// # Returns
    ///
    /// The state root hash.
    pub fn root(self) -> Result<B256, StateRootError> {
        match self.calculate(false)? {
            StateRootProgress::Complete(root, _, _) => Ok(root),
            StateRootProgress::Progress(..) => unreachable!(), // update retention is disabled
        }
    }

    /// Walks the intermediate nodes of existing state trie (if any) and hashed entries. Feeds the
    /// nodes into the hash builder. Collects the updates in the process.
    ///
    /// # Returns
    ///
    /// The intermediate progress of state root computation.
    pub fn root_with_progress(self) -> Result<StateRootProgress, StateRootError> {
        self.calculate(true)
    }

    fn calculate(self, retain_updates: bool) -> Result<StateRootProgress, StateRootError> {
        trace!(target: "trie::state_root", "calculating state root");
        let mut tracker = TrieTracker::default();

        let trie_cursor = self.trie_cursor_factory.account_trie_cursor()?;
        let hashed_account_cursor = self.hashed_cursor_factory.hashed_account_cursor()?;

        // create state root context once for reuse
        let mut storage_ctx = StateRootContext::new();

        // first handle any in-progress storage root calculation
        let (mut hash_builder, mut account_node_iter) = if let Some(state) = self.previous_state {
            let IntermediateStateRootState { account_root_state, storage_root_state } = state;

            // resume account trie iteration
            let mut hash_builder = account_root_state.hash_builder.with_updates(retain_updates);
            let walker = TrieWalker::<_>::state_trie_from_stack(
                trie_cursor,
                account_root_state.walker_stack,
                self.prefix_sets.account_prefix_set,
            )
            .with_deletions_retained(retain_updates);
            let account_node_iter = TrieNodeIter::state_trie(walker, hashed_account_cursor)
                .with_last_hashed_key(account_root_state.last_hashed_key);

            // if we have an in-progress storage root, complete it first
            if let Some(storage_state) = storage_root_state {
                let hashed_address = account_root_state.last_hashed_key;
                let account = storage_state.account;

                debug!(
                    target: "trie::state_root",
                    account_nonce = account.nonce,
                    account_balance = ?account.balance,
                    last_hashed_key = ?account_root_state.last_hashed_key,
                    "Resuming storage root calculation"
                );

                // resume the storage root calculation
                let remaining_threshold = self.threshold.saturating_sub(
                    storage_ctx.total_updates_len(&account_node_iter, &hash_builder),
                );

                let storage_root_calculator = StorageRoot::new_hashed(
                    self.trie_cursor_factory.clone(),
                    self.hashed_cursor_factory.clone(),
                    hashed_address,
                    self.prefix_sets
                        .storage_prefix_sets
                        .get(&hashed_address)
                        .cloned()
                        .unwrap_or_default(),
                    #[cfg(feature = "metrics")]
                    self.metrics.storage_trie.clone(),
                )
                .with_intermediate_state(Some(storage_state.state))
                .with_threshold(remaining_threshold);

                let storage_result = storage


use crate::{
    hashed_cursor::{HashedCursor, HashedCursorFactory, HashedStorageCursor},
    node_iter::{TrieElement, TrieNodeIter},
    prefix_set::{PrefixSet, TriePrefixSets},
    progress::{
        IntermediateRootState, IntermediateStateRootState, IntermediateStorageRootState,
        StateRootProgress, StorageRootProgress,
    },
    stats::TrieTracker,
    trie_cursor::{TrieCursor, TrieCursorFactory},
    updates::{StorageTrieUpdates, TrieUpdates},
    walker::TrieWalker,
    HashBuilder, Nibbles, TRIE_ACCOUNT_RLP_MAX_SIZE,
};
use alloy_consensus::EMPTY_ROOT_HASH;
use alloy_primitives::{keccak256, Address, B256};

use alloy_trie::proof::AddedRemovedKeys;
use reth_execution_errors::{StateRootError, StorageRootError};
use reth_primitives_traits::Account;
use tracing::{debug, instrument, trace, Span};

/// The default updates after which root algorithms should return intermediate progress rather than
/// finishing the computation.
const DEFAULT_INTERMEDIATE_THRESHOLD: u64 = 100_000;

#[cfg(feature = "metrics")]
use crate::metrics::{StateRootMetrics, TrieRootMetrics};

/// `StateRoot` is used to compute the root node of a state trie.
#[derive(Debug)]
pub struct StateRoot<T, H> {
    /// The factory for trie cursors.
    pub trie_cursor_factory: T,
    /// The factory for hashed cursors.
    pub hashed_cursor_factory: H,
    /// A set of prefix sets that have changed.
    pub prefix_sets: TriePrefixSets,
    /// Previous intermediate state.
    previous_state: Option<IntermediateStateRootState>,
    /// The number of updates after which the intermediate progress should be returned.
    threshold: u64,
    #[cfg(feature = "metrics")]
    /// State root metrics.
    metrics: StateRootMetrics,
}

impl<T, H> StateRoot<T, H> {
    /// Creates [`StateRoot`] with `trie_cursor_factory` and `hashed_cursor_factory`. All other
    /// parameters are set to reasonable defaults.
    ///
    /// The cursors created by given factories are then used to walk through the accounts and
    /// calculate the state root value with.
    pub fn new(trie_cursor_factory: T, hashed_cursor_factory: H) -> Self {
        Self {
            trie_cursor_factory,
            hashed_cursor_factory,
            prefix_sets: TriePrefixSets::default(),
            previous_state: None,
            threshold: DEFAULT_INTERMEDIATE_THRESHOLD,
            #[cfg(feature = "metrics")]
            metrics: StateRootMetrics::default(),
        }
    }

    /// Set the prefix sets.
    pub fn with_prefix_sets(mut self, prefix_sets: TriePrefixSets) -> Self {
        self.prefix_sets = prefix_sets;
        self
    }

    /// Set the threshold.
    pub const fn with_threshold(mut self, threshold: u64) -> Self {
        self.threshold = threshold;
        self
    }

    /// Set the threshold to maximum value so that intermediate progress is not returned.
    pub const fn with_no_threshold(mut self) -> Self {
        self.threshold = u64::MAX;
        self
    }

    /// Set the previously recorded intermediate state.
    pub fn with_intermediate_state(mut self, state: Option<IntermediateStateRootState>) -> Self {
        self.previous_state = state;
        self
    }

    /// Set the hashed cursor factory.
    pub fn with_hashed_cursor_factory<HF>(self, hashed_cursor_factory: HF) -> StateRoot<T, HF> {
        StateRoot {
            trie_cursor_factory: self.trie_cursor_factory,
            hashed_cursor_factory,
            prefix_sets: self.prefix_sets,
            threshold: self.threshold,
            previous_state: self.previous_state,
            #[cfg(feature = "metrics")]
            metrics: self.metrics,
        }
    }

    /// Set the trie cursor factory.
    pub fn with_trie_cursor_factory<TF>(self, trie_cursor_factory: TF) -> StateRoot<TF, H> {
        StateRoot {
            trie_cursor_factory,
            hashed_cursor_factory: self.hashed_cursor_factory,
            prefix_sets: self.prefix_sets,
            threshold: self.threshold,
            previous_state: self.previous_state,
            #[cfg(feature = "metrics")]
            metrics: self.metrics,
        }
    }
}

impl<T, H> StateRoot<T, H>
where
    T: TrieCursorFactory + Clone,
    H: HashedCursorFactory + Clone,
{
    /// Walks the intermediate nodes of existing state trie (if any) and hashed entries. Feeds the
    /// nodes into the hash builder. Collects the updates in the process.
    ///
    /// Ignores the threshold.
    ///
    /// # Returns
    ///
    /// The state root and the trie updates.
    pub fn root_with_updates(self) -> Result<(B256, TrieUpdates), StateRootError> {
        match self.with_no_threshold().calculate(true)? {
            StateRootProgress::Complete(root, _, updates) => Ok((root, updates)),
            StateRootProgress::Progress(..) => unreachable!(), // unreachable threshold
        }
    }

    /// Walks the intermediate nodes of existing state trie (if any) and hashed entries. Feeds the
    /// nodes into the hash builder.
    ///
    /// # Returns
    ///
    /// The state root hash.
    pub fn root(self) -> Result<B256, StateRootError> {
        match self.calculate(false)? {
            StateRootProgress::Complete(root, _, _) => Ok(root),
            StateRootProgress::Progress(..) => unreachable!(), // update retention is disabled
        }
    }

    /// Walks the intermediate nodes of existing state trie (if any) and hashed entries. Feeds the
    /// nodes into the hash builder. Collects the updates in the process.
    ///
    /// # Returns
    ///
    /// The intermediate progress of state root computation.
    pub fn root_with_progress(self) -> Result<StateRootProgress, StateRootError> {
        self.calculate(true)
    }

    fn calculate(self, retain_updates: bool) -> Result<StateRootProgress, StateRootError> {
        trace!(target: "trie::state_root", "calculating state root");
        let mut tracker = TrieTracker::default();

        let trie_cursor = self.trie_cursor_factory.account_trie_cursor()?;
        let hashed_account_cursor = self.hashed_cursor_factory.hashed_account_cursor()?;

        // create state root context once for reuse
        let mut storage_ctx = StateRootContext::new();

        // first handle any in-progress storage root calculation
        let (mut hash_builder, mut account_node_iter) = if let Some(state) = self.previous_state {
            let IntermediateStateRootState { account_root_state, storage_root_state } = state;

            // resume account trie iteration
            let mut hash_builder = account_root_state.hash_builder.with_updates(retain_updates);
            let walker = TrieWalker::<_>::state_trie_from_stack(
                trie_cursor,
                account_root_state.walker_stack,
                self.prefix_sets.account_prefix_set,
            )
            .with_deletions_retained(retain_updates);
            let account_node_iter = TrieNodeIter::state_trie(walker, hashed_account_cursor)
                .with_last_hashed_key(account_root_state.last_hashed_key);

            // if we have an in-progress storage root, complete it first
            if let Some(storage_state) = storage_root_state {
                let hashed_address = account_root_state.last_hashed_key;
                let account = storage_state.account;

                debug!(
                    target: "trie::state_root",
                    account_nonce = account.nonce,
                    account_balance = ?account.balance,
                    last_hashed_key = ?account_root_state.last_hashed_key,
                    "Resuming storage root calculation"
                );

                // resume the storage root calculation
                let remaining_threshold = self.threshold.saturating_sub(
                    storage_ctx.total_updates_len(&account_node_iter, &hash_builder),
                );

                let storage_root_calculator = StorageRoot::new_hashed(
                    self.trie_cursor_factory.clone(),
                    self.hashed_cursor_factory.clone(),
                    hashed_address,
                    self.prefix_sets
                        .storage_prefix_sets
                        .get(&hashed_address)
                        .cloned()
                        .unwrap_or_default(),
                    #[cfg(feature = "metrics")]
                    self.metrics.storage_trie.clone(),
                )
                .with_intermediate_state(Some(storage_state.state))
                .with_threshold(remaining_threshold);

                let storage_result = storage_root_calculator.calculate(retain_updates)?


use crate::{
    hashed_cursor::{HashedCursor, HashedCursorFactory, HashedStorageCursor},
    node_iter::{TrieElement, TrieNodeIter},
    prefix_set::{PrefixSet, TriePrefixSets},
    progress::{
        IntermediateRootState, IntermediateStateRootState, IntermediateStorageRootState,
        StateRootProgress, StorageRootProgress,
    },
    stats::TrieTracker,
    trie_cursor::{TrieCursor, TrieCursorFactory},
    updates::{StorageTrieUpdates, TrieUpdates},
    walker::TrieWalker,
    HashBuilder, Nibbles, TRIE_ACCOUNT_RLP_MAX_SIZE,
};
use alloy_consensus::EMPTY_ROOT_HASH;
use alloy_primitives::{keccak256, Address, B256};
use alloy_rlp::{BufMut, Encodable};

use reth_execution_errors::{StateRootError, StorageRootError};
use reth_primitives_traits::Account;
use tracing::{debug, instrument, trace, Span};

/// The default updates after which root algorithms should return intermediate progress rather than
/// finishing the computation.
const DEFAULT_INTERMEDIATE_THRESHOLD: u64 = 100_000;

#[cfg(feature = "metrics")]
use crate::metrics::{StateRootMetrics, TrieRootMetrics};

/// `StateRoot` is used to compute the root node of a state trie.
#[derive(Debug)]
pub struct StateRoot<T, H> {
    /// The factory for trie cursors.
    pub trie_cursor_factory: T,
    /// The factory for hashed cursors.
    pub hashed_cursor_factory: H,
    /// A set of prefix sets that have changed.
    pub prefix_sets: TriePrefixSets,
    /// Previous intermediate state.
    previous_state: Option<IntermediateStateRootState>,
    /// The number of updates after which the intermediate progress should be returned.
    threshold: u64,
    #[cfg(feature = "metrics")]
    /// State root metrics.
    metrics: StateRootMetrics,
}

impl<T, H> StateRoot<T, H> {
    /// Creates [`StateRoot`] with `trie_cursor_factory` and `hashed_cursor_factory`. All other
    /// parameters are set to reasonable defaults.
    ///
    /// The cursors created by given factories are then used to walk through the accounts and
    /// calculate the state root value with.
    pub fn new(trie_cursor_factory: T, hashed_cursor_factory: H) -> Self {
        Self {
            trie_cursor_factory,
            hashed_cursor_factory,
            prefix_sets: TriePrefixSets::default(),
            previous_state: None,
            threshold: DEFAULT_INTERMEDIATE_THRESHOLD,
            #[cfg(feature = "metrics")]
            metrics: StateRootMetrics::default(),
        }
    }

    /// Set the prefix sets.
    pub fn with_prefix_sets(mut self, prefix_sets: TriePrefixSets) -> Self {
        self.prefix_sets = prefix_sets;
        self
    }

    /// Set the threshold.
    pub const fn with_threshold(mut self, threshold: u64) -> Self {
        self.threshold = threshold;
        self
    }

    /// Set the threshold to maximum value so that intermediate progress is not returned.
    pub const fn with_no_threshold(mut self) -> Self {
        self.threshold = u64::MAX;
        self
    }

    /// Set the previously recorded intermediate state.
    pub fn with_intermediate_state(mut self, state: Option<IntermediateStateRootState>) -> Self {
        self.previous_state = state;
        self
    }

    /// Set the hashed cursor factory.
    pub fn with_hashed_cursor_factory<HF>(self, hashed_cursor_factory: HF) -> StateRoot<T, HF> {
        StateRoot {
            trie_cursor_factory: self.trie_cursor_factory,
            hashed_cursor_factory,
            prefix_sets: self.prefix_sets,
            threshold: self.threshold,
            previous_state: self.previous_state,
            #[cfg(feature = "metrics")]
            metrics: self.metrics,
        }
    }

    /// Set the trie cursor factory.
    pub fn with_trie_cursor_factory<TF>(self, trie_cursor_factory: TF) -> StateRoot<TF, H> {
        StateRoot {
            trie_cursor_factory,
            hashed_cursor_factory: self.hashed_cursor_factory,
            prefix_sets: self.prefix_sets,
            threshold: self.threshold,
            previous_state: self.previous_state,
            #[cfg(feature = "metrics")]
            metrics: self.metrics,
        }
    }
}

impl<T, H> StateRoot<T, H>
where
    T: TrieCursorFactory + Clone,
    H: HashedCursorFactory + Clone,
{
    /// Walks the intermediate nodes of existing state trie (if any) and hashed entries. Feeds the
    /// nodes into the hash builder. Collects the updates in the process.
    ///
    /// Ignores the threshold.
    ///
    /// # Returns
    ///
    /// The state root and the trie updates.
    pub fn root_with_updates(self) -> Result<(B256, TrieUpdates), StateRootError> {
        match self.with_no_threshold().calcu


use crate::{
    hashed_cursor::{HashedCursor, HashedCursorFactory, HashedStorageCursor},
    node_iter::{TrieElement, TrieNodeIter},
    prefix_set::{PrefixSet, TriePrefixSets},
    progress::{
        IntermediateRootState, IntermediateStateRootState, IntermediateStorageRootState,
        StateRootProgress, StorageRootProgress,
    },
    stats::TrieTracker,
    trie_cursor::{TrieCursor, TrieCursorFactory},
    updates::{StorageTrieUpdates, TrieUpdates},
    walker::TrieWalker,
    HashBuilder, Nibbles, TRIE_ACCOUNT_RLP_MAX_SIZE,
};
use alloy_consensus::EMPTY_ROOT_HASH;
use alloy_primitives::{keccak256, Address, B256};
use alloy_rlp::{BufMut, Encodable};
use alloy_trie::proof::AddedRemovedKeys;

use reth_primitives_traits::Account;
use tracing::{debug, instrument, trace, Span};

/// The default updates after which root algorithms should return intermediate progress rather than
/// finishing the computation.
const DEFAULT_INTERMEDIATE_THRESHOLD: u64 = 100_000;

#[cfg(feature = "metrics")]
use crate::metrics::{StateRootMetrics, TrieRootMetrics};

/// `StateRoot` is used to compute the root node of a state trie.
#[derive(Debug)]
pub struct StateRoot<T, H> {
    /// The factory for trie cursors.
    pub trie_cursor_factory: T,
    /// The factory for hashed cursors.
    pub hashed_cursor_factory: H,
    /// A set of prefix sets that have changed.
    pub prefix_sets: TriePrefixSets,
    /// Previous intermediate state.
    previous_state: Option<IntermediateStateRootState>,
    /// The number of updates after which the intermediate progress should be returned.
    threshold: u64,
    #[cfg(feature = "metrics")]
    /// State root metrics.
    metrics: StateRootMetrics,
}

impl<T, H> StateRoot<T, H> {
    /// Creates [`StateRoot`] with `trie_cursor_factory` and `hashed_cursor_factory`. All other
    /// parameters are set to reasonable defaults.
    ///
    /// The cursors created by given factories are then used to walk through the accounts and
    /// calculate the state root value with.
    pub fn new(trie_cursor_factory: T, hashed_cursor_factory: H) -> Self {
        Self {
            trie_cursor_factory,
            hashed_cursor_factory,
            prefix_sets: TriePrefixSets::default(),
            previous_state: None,
            threshold: DEFAULT_INTERMEDIATE_THRESHOLD,
            #[cfg(feature = "metrics")]
            metrics: StateRootMetrics::default(),
        }
    }

    /// Set the prefix sets.
    pub fn with_prefix_sets(mut self, prefix_sets: TriePrefixSets) -> Self {
        self.prefix_sets = prefix_sets;
        self
    }

    /// Set the threshold.
    pub const fn with_threshold(mut self, threshold: u64) -> Self {
        self.threshold = threshold;
        self
    }

    /// Set the threshold to maximum value so that intermediate progress is not returned.
    pub const fn with_no_threshold(mut self) -> Self {
        self.threshold = u64::MAX;
        self
    }

    /// Set the previously recorded intermediate state.
    pub fn with_intermediate_state(mut self, state: Option<IntermediateStateRootState>) -> Self {
        self.previous_state = state;
        self
    }

    /// Set the hashed cursor factory.
    pub fn with_hashed_cursor_factory<HF>(self, hashed_cursor_factory: HF) -> StateRoot<T, HF> {
        StateRoot {
            trie_cursor_factory: self.trie_cursor_factory,
            hashed_cursor_factory,
            prefix_sets: self.prefix_sets,
            threshold: self.threshold,
            previous_state: self.previous_state,
            #[cfg(feature = "metrics")]
            metrics: self.metrics,
        }
    }

    /// Set the trie cursor factory.
    pub fn with_trie_cursor_factory<TF>(self, trie_cursor_factory: TF) -> StateRoot<TF, H> {
        StateRoot {
            trie_cursor_factory,
            hashed_cursor_factory: self.hashed_cursor_factory,
            prefix_sets: self.prefix_sets,
            threshold: self.threshold,
            previous_state: self.previous_state,
            #[cfg(feature = "metrics")]
            metrics: self.metrics,
        }
    }
}

impl<T, H> StateRoot<T, H>
where
    T: TrieCursorFactory + Clone,
    H: HashedCursorFactory + Clone,
{
    /// Walks the intermediate nodes of existing state trie (if any) and hashed entries. Feeds the
    /// nodes into the hash builder. Collects the updates in the process.
    ///
    /// Ignores the threshold.
    ///
    /// # Returns
    ///
    /// The state root and the trie updates.
    pub fn root_with_updates(self) -> Result<(B256, TrieUpdates), StateRootError> {
        match self.with_no_threshold().calculate(true)? {
            StateRootProgress::Complete(root, _, updates) => Ok((root, updates)),
            StateRootProgress::Progress(..) => unreachable!(), // unreachable threshold
        }
    }

    /// Walks the intermediate nodes of existing state trie (if any) and hashed entries. Feeds the
    /// nodes into the hash builder.
    ///
    /// # Returns
    ///
    /// The state root hash.
    pub fn root(self) -> Result<B256, StateRootError> {
        match self.calculate(false)? {
            StateRootProgress::Complete(root, _, _) => Ok(root),
            StateRootProgress::Progress(..) => unreachable!(), // update retention is disabled
        }
    }

    /// Walks the intermediate nodes of existing state trie (if any) and hashed entries. Feeds the
    /// nodes into the hash builder. Collects the updates in the process.
    ///
    /// # Returns
    ///
    /// The intermediate progress of state root computation.
    pub fn root_with_progress(self) -> Result<StateRootProgress, StateRootError> {
        self.calculate(true)
    }

    fn calculate(self, retain_updates: bool) -> Result<StateRootProgress, StateRootError> {
        trace!(target: "trie::state_root", "calculating state root");
        let mut tracker = TrieTracker::default();

        let trie_cursor = self.trie_cursor_factory.account_trie_cursor()?;
        let hashed_account_cursor = self.hashed_cursor_factory.hashed_account_cursor()?;

        // create state root context once for reuse
        let mut storage_ctx = StateRootContext::new();

        // first handle any in-progress storage root calculation
        let (mut hash_builder, mut account_node_iter) = if let Some(state) = self.previous_state {
            let IntermediateStateRootState { account_root_state, storage_root_state } = state;

            // resume account trie iteration
            let mut hash_builder = account_root_state.hash_builder.with_updates(retain_updates);
            let walker = TrieWalker::<_>::state_trie_from_stack(
                trie_cursor,
                account_root_state.walker_stack,
                self.prefix_sets.account_prefix_set,
            )
            .with_deletions_retained(retain_updates);
            let account_node_iter = TrieNodeIter::state_trie(walker, hashed_account_cursor)
                .with_last_hashed_key(account_root_state.last_hashed_key);

            // if we have an in-progress storage root, complete it first
            if let Some(storage_state) = storage_root_state {
                let hashed_address = account_root_state.last_hashed_key;
                let account = storage_state.account;

                debug!(
                    target: "trie::state_root",
                    account_nonce = account.nonce,
                    account_balance = ?account.balance,
                    last_hashed_key = ?account_root_state.last_hashed_key,
                    "Resuming storage root calculation"
                );

                // resume the storage root calculation
                let remaining_threshold = self.threshold.saturating_sub(
                    storage_ctx.total_updates_len(&account_node_iter, &hash_builder),
                );

                let storage_root_calculator = StorageRoot::new_hashed(
                    self.trie_cursor_factory.clone(),
                    self.hashed_cursor_factory.clone(),
                    hashed_address,
                    self.prefix_sets
                        .storage_prefix_sets
                        .get(&hashed_address)
                        .cloned()
                        .unwrap_or_default(),
                    #[cfg(feature = "metrics")]
                    self.metrics.storage_trie.clone(),
                )
                .with_intermediate_state(Some(storage_state.state))
                .with_threshold(remaining_threshold);

                let storage_result = storage_root_calculator.calculate(retain_updates)?;
                if let Some(storage_state) = storage_ctx.process_storage_root_result(


use crate::{
    hashed_cursor::{HashedCursor, HashedCursorFactory, HashedStorageCursor},
    node_iter::{TrieElement, TrieNodeIter},
    prefix_set::{PrefixSet, TriePrefixSets},
    progress::{
        IntermediateRootState, IntermediateStateRootState, IntermediateStorageRootState,
        StateRootProgress, StorageRootProgress,
    },
    stats::TrieTracker,
    trie_cursor::{TrieCursor, TrieCursorFactory},
    updates::{StorageTrieUpdates, TrieUpdates},
    walker::TrieWalker,
    HashBuilder, Nibbles, TRIE_ACCOUNT_RLP_MAX_SIZE,
};
use alloy_consensus::EMPTY_ROOT_HASH;
use alloy_primitives::{keccak256, Address, B256};
use alloy_rlp::{BufMut, Encodable};
use alloy_trie::proof::AddedRemovedKeys;
use reth_execution_errors::{StateRootError, StorageRootError};

use tracing::{debug, instrument, trace, Span};

/// The default updates after which root algorithms should return intermediate progress rather than
/// finishing the computation.
const DEFAULT_INTERMEDIATE_THRESHOLD: u64 = 100_000;

#[cfg(feature = "metrics")]
use crate::metrics::{StateRootMetrics, TrieRootMetrics};

/// `StateRoot` is used to compute the root node of a state trie.
#[derive(Debug)]
pub struct StateRoot<T, H> {
    /// The factory for trie cursors.
    pub trie_cursor_factory: T,
    /// The factory for hashed cursors.
    pub hashed_cursor_factory: H,
    /// A set of prefix sets that have changed.
    pub prefix_sets: TriePrefixSets,
    /// Previous intermediate state.
    previous_state: Option<IntermediateStateRootState>,
    /// The number of updates after which the intermediate progress should be returned.
    threshold: u64,
    #[cfg(feature = "metrics")]
    /// State root metrics.
    metrics: StateRootMetrics,
}

impl<T, H> StateRoot<T, H> {
    /// Creates [`StateRoot`] with `trie_cursor_factory` and `hashed_cursor_factory`. All other
    /// parameters are set to reasonable defaults.
    ///
    /// The cursors created by given factories are then used to walk through the accounts and
    /// calculate the state root value with.
    pub fn new(trie_cursor_factory: T, hashed_cursor_factory: H) -> Self {
        Self {
            trie_cursor_factory,
            hashed_cursor_factory,
            prefix_sets: TriePrefixSets::default(),
            previous_state: None,
            threshold: DEFAULT_INTERMEDIATE_THRESHOLD,
            #[cfg(feature = "metrics")]
            metrics: StateRootMetrics::default(),
        }
    }

    /// Set the prefix sets.
    pub fn with_prefix_sets(mut self, prefix_sets: TriePrefixSets) -> Self {
        self.prefix_sets = prefix_sets;
        self
    }

    /// Set the threshold.
    pub const fn with_threshold(mut self, threshold: u64) -> Self {
        self.threshold = threshold;
        self
    }

    /// Set the threshold to maximum value so that intermediate progress is not returned.
    pub const fn with_no_threshold(mut self) -> Self {
        self.threshold = u64::MAX;
        self
    }

    /// Set the previously recorded intermediate state.
    pub fn with_intermediate_state(mut self, state: Option<IntermediateStateRootState>) -> Self {
        self.previous_state = state;
        self
    }

    /// Set the hashed cursor factory.
    pub fn with_hashed_cursor_factory<HF>(self, hashed_cursor_factory: HF) -> StateRoot<T, HF> {
        StateRoot {
            trie_cursor_factory: self.trie_cursor_factory,
            hashed_cursor_factory,
            prefix_sets: self.prefix_sets,
            threshold: self.threshold,
            previous_state: self.previous_state,
            #[cfg(feature = "metrics")]
            metrics: self.metrics,
        }
    }

    /// Set the trie cursor factory.
    pub fn with_trie_cursor_factory<TF>(self, trie_cursor_factory: TF) -> StateRoot<TF, H> {
        StateRoot {
            trie_cursor_factory,
            hashed_cursor_factory: self.hashed_cursor_factory,
            prefix_sets: self.prefix_sets,
            threshold: self.threshold,
            previous_state: self.previous_state,
            #[cfg(feature = "metrics")]
            metrics: self.metrics,
        }
    }
}

impl<T, H> StateRoot<T, H>
where
    T: TrieCursorFactory + Clone,
    H: HashedCursorFactory + Clone,
{
    /// Walks the intermediate nodes of existing state trie (if any) and hashed entries. Feeds the
    /// nodes into the hash builder. Collects the updates in the process.
    ///
    /// Ignores the threshold.
    ///
    /// # Returns
    ///
    /// The state root and the trie updates.
    pub fn root_with_updates(self) -> Result<(B256, TrieUpdates), StateRootError> {
        match self.with_no_threshold().calculate(true)? {
            StateRootProgress::Complete(root, _, updates) => Ok((root, updates)),


use crate::{
    hashed_cursor::{HashedCursor, HashedCursorFactory, HashedStorageCursor},
    node_iter::{TrieElement, TrieNodeIter},
    prefix_set::{PrefixSet, TriePrefixSets},
    progress::{
        IntermediateRootState, IntermediateStateRootState, IntermediateStorageRootState,
        StateRootProgress, StorageRootProgress,
    },
    stats::TrieTracker,
    trie_cursor::{TrieCursor, TrieCursorFactory},
    updates::{StorageTrieUpdates, TrieUpdates},
    walker::TrieWalker,
    HashBuilder, Nibbles, TRIE_ACCOUNT_RLP_MAX_SIZE,
};
use alloy_consensus::EMPTY_ROOT_HASH;
use alloy_primitives::{keccak256, Address, B256};
use alloy_rlp::{BufMut, Encodable};
use alloy_trie::proof::AddedRemovedKeys;
use reth_execution_errors::{StateRootError, StorageRootError};
use reth_primitives_traits::Account;

use tracing::{debug, instrument, trace, Span};

/// The default updates after which root algorithms should return intermediate progress rather than
/// finishing the computation.
const DEFAULT_INTERMEDIATE_THRESHOLD: u64 = 100_000;

#[cfg(feature = "metrics")]
use crate::metrics::{StateRootMetrics, TrieRootMetrics};

/// `StateRoot` is used to compute the root node of a state trie.
#[derive(Debug)]
pub struct StateRoot<T, H> {
    /// The factory for trie cursors.
    pub trie_cursor_factory: T,
    /// The factory for hashed cursors.
    pub hashed_cursor_factory: H,
    /// A set of prefix sets that have changed.
    pub prefix_sets: TriePrefixSets,
    /// Previous intermediate state.
    previous_state: Option<IntermediateStateRootState>,
    /// The number of updates after which the intermediate progress should be returned.
    threshold: u64,
    #[cfg(feature = "metrics")]
    /// State root metrics.
    metrics: StateRootMetrics,
}

impl<T, H> StateRoot<T, H> {
    /// Creates [`StateRoot`] with `trie_cursor_factory` and `hashed_cursor_factory`. All other
    /// parameters are set to reasonable defaults.
    ///
    /// The cursors created by given factories are then used to walk through the accounts and
    /// calculate the state root value with.
    pub fn new(trie_cursor_factory: T, hashed_cursor_factory: H) -> Self {
        Self {
            trie_cursor_factory,
            hashed_cursor_factory,
            prefix_sets: TriePrefixSets::default(),
            previous_state: None,
            threshold: DEFAULT_INTERMEDIATE_THRESHOLD,
            #[cfg(feature = "metrics")]
            metrics: StateRootMetrics::default(),
        }
    }

    /// Set the prefix sets.
    pub fn with_prefix_sets(mut self, prefix_sets: TriePrefixSets) -> Self {
        self.prefix_sets = prefix_sets;
        self
    }

    /// Set the threshold.
    pub const fn with_threshold(mut self, threshold: u64) -> Self {
        self.threshold = threshold;
        self
    }

    /// Set the threshold to maximum value so that intermediate progress is not returned.
    pub const fn with_no_threshold(mut self) -> Self {
        self.threshold = u64::MAX;
        self
    }

    /// Set the previously recorded intermediate state.
    pub fn with_intermediate_state(mut self, state: Option<IntermediateStateRootState>) -> Self {
        self.previous_state = state;
        self
    }

    /// Set the hashed cursor factory.
    pub fn with_hashed_cursor_factory<HF>(self, hashed_cursor_factory: HF) -> StateRoot<T, HF> {
        StateRoot {
            trie_cursor_factory: self.trie_cursor_factory,
            hashed_cursor_factory,
            prefix_sets: self.prefix_sets,
            threshold: self.threshold,
            previous_state: self.previous_state,
            #[cfg(feature = "metrics")]
            metrics: self.metrics,
        }
    }

    /// Set the trie cursor factory.
    pub fn with_trie_cursor_factory<TF>(self, trie_cursor_factory: TF) -> StateRoot<TF, H> {
        StateRoot {
            trie_cursor_factory,
            hashed_cursor_factory: self.hashed_cursor_factory,
            prefix_sets: self.prefix_sets,
            threshold: self.threshold,
            previous_state: self.previous_state,
            #[cfg(feature = "metrics")]
            metrics: self.metrics,
        }
    }
}

impl<T, H> StateRoot<T, H>
where
    T: TrieCursorFactory + Clone,
    H: HashedCursorFactory + Clone,
{
    /// Walks the intermediate nodes of existing state trie (if any) and hashed entries. Feeds the
    /// nodes into the hash builder. Collects the updates in the process.
    ///
    /// Ignores the threshold.
    ///
    /// # Returns
    ///
    /// The state root and the trie updates.
    pub fn root_with_updates(self) -> Result<(B256, TrieUpdates), StateRootError> {
        match self.with_no_threshold().calculate(true)? {
            StateRootProgress::Complete(root, _, updates) => Ok((root, updates)),
            StateRootProgress::Progress(..) => u


use crate::{
    hashed_cursor::{HashedCursor, HashedCursorFactory, HashedStorageCursor},
    node_iter::{TrieElement, TrieNodeIter},
    prefix_set::{PrefixSet, TriePrefixSets},
    progress::{
        IntermediateRootState, IntermediateStateRootState, IntermediateStorageRootState,
        StateRootProgress, StorageRootProgress,
    },
    stats::TrieTracker,
    trie_cursor::{TrieCursor, TrieCursorFactory},
    updates::{StorageTrieUpdates, TrieUpdates},
    walker::TrieWalker,
    HashBuilder, Nibbles, TRIE_ACCOUNT_RLP_MAX_SIZE,
};
use alloy_consensus::EMPTY_ROOT_HASH;
use alloy_primitives::{keccak256, Address, B256};
use alloy_rlp::{BufMut, Encodable};
use alloy_trie::proof::AddedRemovedKeys;
use reth_execution_errors::{StateRootError, StorageRootError};
use reth_primitives_traits::Account;
use tracing::{debug, instrument, trace, Span};

/// The default updates after which root algorithms should return intermediate progress rather than
/// finishing the computation.
const DEFAULT_INTERMEDIATE_THRESHOLD: u64 = 100_000;

#[cfg(feature = "metrics")]
use crate::metrics::{StateRootMetrics, TrieRootMetrics};

/// `StateRoot` is used to compute the root node of a state trie.
#[derive(Debug)]
pub struct StateRoot<T, H> {
    /// The factory for trie cursors.
    pub trie_cursor_factory: T,
    /// The factory for hashed cursors.
    pub hashed_cursor_factory: H,
    /// A set of prefix sets that have changed.
    pub prefix_sets: TriePrefixSets,
    /// Previous intermediate state.
    previous_state: Option<IntermediateStateRootState>,
    /// The number of updates after which the intermediate progress should be returned.
    threshold: u64,
    #[cfg(feature = "metrics")]
    /// State root metrics.
    metrics: StateRootMetrics,
}

impl<T, H> StateRoot<T, H> {
    /// Creates [`StateRoot`] with `trie_cursor_factory` and `hashed_cursor_factory`. All other
    /// parameters are set to reasonable defaults.
    ///
    /// The cursors created by given factories are then used to walk through the accounts and
    /// calculate the state root value with.
    pub fn new(trie_cursor_factory: T, hashed_cursor_factory: H) -> Self {
        Self {
            trie_cursor_factory,
            hashed_cursor_factory,
            prefix_sets: TriePrefixSets::default(),
            previous_state: None,
            threshold: DEFAULT_INTERMEDIATE_THRESHOLD,
            #[cfg(feature = "metrics")]
            metrics: StateRootMetrics::default(),
        }
    }

    /// Set the prefix sets.
    pub fn with_prefix_sets(mut self, prefix_sets: TriePrefixSets) -> Self {
        self.prefix_sets = prefix_sets;
        self
    }

    /// Set the threshold.
    pub const fn with_threshold(mut self, threshold: u64) -> Self {
        self.threshold = threshold;
        self
    }

    /// Set the threshold to maximum value so that intermediate progress is not returned.
    pub const fn with_no_threshold(mut self) -> Self {
        self.threshold = u64::MAX;
        self
    }

    /// Set the previously recorded intermediate state.
    pub fn with_intermediate_state(mut self, state: Option<IntermediateStateRootState>) -> Self {
        self.previous_state = state;
        self
    }

    /// Set the hashed cursor factory.
    pub fn with_hashed_cursor_factory<HF>(self, hashed_cursor_factory: HF) -> StateRoot<T, HF> {
        StateRoot {
            trie_cursor_factory: self.trie_cursor_factory,
            hashed_cursor_factory,
            prefix_sets: self.prefix_sets,
            threshold: self.threshold,
            previous_state: self.previous_state,
            #[cfg(feature = "metrics")]
            metrics: self.metrics,
        }
    }

    /// Set the trie cursor factory.
    pub fn with_trie_cursor_factory<TF>(self, trie_cursor_factory: TF) -> StateRoot<TF, H> {
        StateRoot {
            trie_cursor_factory,
            hashed_cursor_factory: self.hashed_cursor_factory,
            prefix_sets: self.prefix_sets,
            threshold: self.threshold,
            previous_state: self.previous_state,
            #[cfg(feature = "metrics")]
            metrics: self.metrics,
        }
    }
}

impl<T, H> StateRoot<T, H>
where
    T: TrieCursorFactory + Clone,
    H: HashedCursorFactory + Clone,
{
    /// Walks the intermediate nodes of existing state trie (if any) and hashed entries. Feeds the
    /// nodes into the hash builder. Collects the updates in the process.
    ///
    /// Ignores the threshold.
    ///
    /// # Returns
    ///
    /// The state root and the trie updates.
    pub fn root_with_updates(self) -> Result<(B256, TrieUpdates), StateRootError> {
        match self.with_no_threshold().calculate(true)? {
            StateRootProgress::Complete(root, _, updates) => Ok((root, updates)),
            StateRootProgress::Progress(..) => unreachable!(), // unreachable threshold
        }
    }

    /// Walks the intermediate nodes of existing state trie (if any) and hashed entries. Feeds the
    /// nodes into the hash builder.
    ///
    /// # Returns
    ///
    /// The state root hash.
    pub fn root(self) -> Result<B256, StateRootError> {
        match self.calculate(false)? {
            StateRootProgress::Complete(root, _, _) => Ok(root),
            StateRootProgress::Progress(..) => unreachable!(), // update retention is disabled
        }
    }

    /// Walks the intermediate nodes of existing state trie (if any) and hashed entries. Feeds the
    /// nodes into the hash builder. Collects the updates in the process.
    ///
    /// # Returns
    ///
    /// The intermediate progress of state root computation.
    pub fn root_with_progress(self) -> Result<StateRootProgress, StateRootError> {
        self.calculate(true)
    }

    fn calculate(self, retain_updates: bool) -> Result<StateRootProgress, StateRootError> {
        trace!(target: "trie::state_root", "calculating state root");
        let mut tracker = TrieTracker::default();

        let trie_cursor = self.trie_cursor_factory.account_trie_cursor()?;
        let hashed_account_cursor = self.hashed_cursor_factory.hashed_account_cursor()?;

        // create state root context once for reuse
        let mut storage_ctx = StateRootContext::new();

        // first handle any in-progress storage root calculation
        let (mut hash_builder, mut account_node_iter) = if let Some(state) = self.previous_state {
            let IntermediateStateRootState { account_root_state, storage_root_state } = state;

            // resume account trie iteration
            let mut hash_builder = account_root_state.hash_builder.with_updates(retain_updates);
            let walker = TrieWalker::<_>::state_trie_from_stack(
                trie_cursor,
                account_root_state.walker_stack,
                self.prefix_sets.account_prefix_set,
            )
            .with_deletions_retained(retain_updates);
            let account_node_iter = TrieNodeIter::state_trie(walker, hashed_account_cursor)
                .with_last_hashed_key(account_root_state.last_hashed_key);

            // if we have an in-progress storage root, complete it first
            if let Some(storage_state) = storage_root_state {
                let hashed_address = account_root_state.last_hashed_key;
                let account = storage_state.account;

                debug!(
                    target: "trie::state_root",
                    account_nonce = account.nonce,
                    account_balance = ?account.balance,
                    last_hashed_key = ?account_root_state.last_hashed_key,
                    "Resuming storage root calculation"
                );

                // resume the storage root calculation
                let remaining_threshold = self.threshold.saturating_sub(
                    storage_ctx.total_updates_len(&account_node_iter, &hash_builder),
                );

                let storage_root_calculator = StorageRoot::new_hashed(
                    self.trie_cursor_factory.clone(),
                    self.hashed_cursor_factory.clone(),
                    hashed_address,
                    self.prefix_sets
                        .storage_prefix_sets
                        .get(&hashed_address)
                        .cloned()
                        .unwrap_or_default(),
                    #[cfg(feature = "metrics")]
                    self.metrics.storage_trie.clone(),
                )
                .with_intermediate_state(Some(storage_state.state))
                .with_threshold(remaining_threshold);

                let storage_result = storage_root_calculator.calculate(retain_updates)?;
                if let Some(storage_state) = storage_ctx.process_storage_root_result(
                    storage_result,
                    hashed_address,
                    account,
                    &mut hash_builder,
                    retain_updates,
                )? {