lumina_node/store/
utils.rs

1use celestia_types::ExtendedHeader;
2use lumina_utils::executor::yield_now;
3#[cfg(not(target_arch = "wasm32"))]
4use tendermint_proto::Protobuf;
5
6use crate::store::Result;
7#[cfg(not(target_arch = "wasm32"))]
8use crate::store::{SamplingMetadata, StoreError};
9
10pub(crate) const VALIDATIONS_PER_YIELD: usize = 4;
11
12/// Span of header that's been verified internally
13#[derive(Clone)]
14pub struct VerifiedExtendedHeaders(Vec<ExtendedHeader>);
15
16impl IntoIterator for VerifiedExtendedHeaders {
17    type Item = ExtendedHeader;
18    type IntoIter = std::vec::IntoIter<Self::Item>;
19
20    fn into_iter(self) -> Self::IntoIter {
21        self.0.into_iter()
22    }
23}
24
25impl<'a> TryFrom<&'a [ExtendedHeader]> for VerifiedExtendedHeaders {
26    type Error = celestia_types::Error;
27
28    fn try_from(value: &'a [ExtendedHeader]) -> Result<Self, Self::Error> {
29        value.to_vec().try_into()
30    }
31}
32
33impl From<VerifiedExtendedHeaders> for Vec<ExtendedHeader> {
34    fn from(value: VerifiedExtendedHeaders) -> Self {
35        value.0
36    }
37}
38
39impl AsRef<[ExtendedHeader]> for VerifiedExtendedHeaders {
40    fn as_ref(&self) -> &[ExtendedHeader] {
41        &self.0
42    }
43}
44
45/// 1-length hedaer span is internally verified, this is valid
46impl From<[ExtendedHeader; 1]> for VerifiedExtendedHeaders {
47    fn from(value: [ExtendedHeader; 1]) -> Self {
48        Self(value.into())
49    }
50}
51
52impl From<ExtendedHeader> for VerifiedExtendedHeaders {
53    fn from(value: ExtendedHeader) -> Self {
54        Self(vec![value])
55    }
56}
57
58impl From<&ExtendedHeader> for VerifiedExtendedHeaders {
59    fn from(value: &ExtendedHeader) -> Self {
60        Self(vec![value.to_owned()])
61    }
62}
63
64impl TryFrom<Vec<ExtendedHeader>> for VerifiedExtendedHeaders {
65    type Error = celestia_types::Error;
66
67    fn try_from(headers: Vec<ExtendedHeader>) -> Result<Self, Self::Error> {
68        let Some(head) = headers.first() else {
69            return Ok(VerifiedExtendedHeaders(Vec::default()));
70        };
71
72        head.verify_adjacent_range(&headers[1..])?;
73
74        Ok(Self(headers))
75    }
76}
77
78impl VerifiedExtendedHeaders {
79    /// Create a new instance out of pre-checked vec of headers
80    ///
81    /// # Safety
82    ///
83    /// This function may produce invalid `VerifiedExtendedHeaders`, if passed range is not
84    /// validated manually
85    pub unsafe fn new_unchecked(headers: Vec<ExtendedHeader>) -> Self {
86        Self(headers)
87    }
88}
89
90#[allow(unused)]
91pub(crate) async fn validate_headers(headers: &[ExtendedHeader]) -> celestia_types::Result<()> {
92    for headers in headers.chunks(VALIDATIONS_PER_YIELD) {
93        for header in headers {
94            header.validate()?;
95        }
96
97        // Validation is computation heavy so we yield on every chunk
98        yield_now().await;
99    }
100
101    Ok(())
102}
103
104/// Deserializes [`SamplingMetadata`] and returns [`StoreError::StoredDataError`] on failure.
105#[cfg(not(target_arch = "wasm32"))]
106pub(crate) fn deserialize_sampling_metadata(bytes: &[u8]) -> Result<SamplingMetadata> {
107    SamplingMetadata::decode(bytes).map_err(|e| {
108        let s = format!("Stored SamplingMetadata cannot be deserialized: {e}");
109        StoreError::StoredDataError(s)
110    })
111}
112
113/// Deserializes [`ExtendedHeader`] and returns [`StoreError::StoredDataError`] on failure.
114#[cfg(not(target_arch = "wasm32"))]
115pub(crate) fn deserialize_extended_header(bytes: &[u8]) -> Result<ExtendedHeader> {
116    ExtendedHeader::decode(bytes).map_err(|e| {
117        let s = format!("Stored ExtendedHeader cannot be deserialized: {e}");
118        StoreError::StoredDataError(s)
119    })
120}