massa_models/
deferred_calls.rs

1#![allow(unused_macros)]
2
3use std::{fmt::Debug, ops::Bound, str::FromStr};
4
5use massa_serialization::{
6    DeserializeError, Deserializer, SerializeError, Serializer, U64VarIntDeserializer,
7    U64VarIntSerializer,
8};
9use nom::{
10    error::{ContextError, ParseError},
11    IResult,
12};
13use transition::Versioned;
14
15use crate::{
16    config::THREAD_COUNT,
17    error::ModelsError,
18    serialization::{VecU8Deserializer, VecU8Serializer},
19    slot::{Slot, SlotDeserializer, SlotSerializer},
20};
21
22const DEFERRED_CALL_ID_PREFIX: &str = "D";
23
24#[allow(missing_docs)]
25#[transition::versioned(versions("0"))]
26#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
27pub struct DeferredCallId(Vec<u8>);
28
29/// Serializer for `DeferredCallId`
30#[derive(Default, Clone)]
31pub struct DeferredCallIdSerializer {
32    bytes_serializer: VecU8Serializer,
33}
34
35impl DeferredCallIdSerializer {
36    /// Serializes an `DeferredCallId` into a `Vec<u8>`
37    pub fn new() -> Self {
38        Self {
39            bytes_serializer: VecU8Serializer::new(),
40        }
41    }
42}
43
44impl Serializer<DeferredCallId> for DeferredCallIdSerializer {
45    fn serialize(
46        &self,
47        value: &DeferredCallId,
48        buffer: &mut Vec<u8>,
49    ) -> Result<(), SerializeError> {
50        match value {
51            DeferredCallId::DeferredCallIdV0(id) => {
52                self.bytes_serializer.serialize(&id.0, buffer)?;
53            }
54        }
55        Ok(())
56    }
57}
58
59/// Deserializer for `DeferredCallId`
60#[derive(Clone)]
61pub struct DeferredCallIdDeserializer {
62    bytes_deserializer: VecU8Deserializer,
63}
64
65impl DeferredCallIdDeserializer {
66    /// Deserializes a `Vec<u8>` into an `DeferredCallId`
67    pub fn new() -> Self {
68        Self {
69            bytes_deserializer: VecU8Deserializer::new(
70                std::ops::Bound::Included(0),
71                std::ops::Bound::Included(128),
72            ),
73        }
74    }
75}
76
77impl Default for DeferredCallIdDeserializer {
78    fn default() -> Self {
79        Self::new()
80    }
81}
82
83impl Deserializer<DeferredCallId> for DeferredCallIdDeserializer {
84    fn deserialize<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
85        &self,
86        buffer: &'a [u8],
87    ) -> IResult<&'a [u8], DeferredCallId, E> {
88        let (rest, bytes) = self.bytes_deserializer.deserialize(buffer)?;
89        Ok((
90            rest,
91            DeferredCallId::DeferredCallIdV0(DeferredCallIdV0(bytes)),
92        ))
93    }
94}
95
96impl FromStr for DeferredCallId {
97    type Err = ModelsError;
98
99    fn from_str(s: &str) -> Result<Self, Self::Err> {
100        if !s.starts_with(DEFERRED_CALL_ID_PREFIX) {
101            return Err(ModelsError::DeserializeError(format!(
102                "Invalid prefix for DeferredCallId: {}",
103                s
104            )));
105        }
106        let s = &s[DEFERRED_CALL_ID_PREFIX.len()..];
107        let bytes = bs58::decode(s).with_check(None).into_vec().map_err(|_| {
108            ModelsError::DeserializeError(format!(
109                "Invalid base58 string for DeferredCallId: {}",
110                s
111            ))
112        })?;
113        DeferredCallId::from_bytes(&bytes)
114    }
115}
116
117impl std::fmt::Display for DeferredCallId {
118    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
119        write!(
120            f,
121            "{}{}",
122            DEFERRED_CALL_ID_PREFIX,
123            bs58::encode(self.as_bytes()).with_check().into_string()
124        )
125    }
126}
127
128impl ::serde::Serialize for DeferredCallId {
129    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
130    where
131        S: ::serde::Serializer,
132    {
133        if serializer.is_human_readable() {
134            serializer.collect_str(&self.to_string())
135        } else {
136            serializer.serialize_bytes(self.as_bytes())
137        }
138    }
139}
140
141impl<'de> ::serde::Deserialize<'de> for DeferredCallId {
142    fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<DeferredCallId, D::Error> {
143        if d.is_human_readable() {
144            struct DeferredCallIdVisitor;
145
146            impl<'de> ::serde::de::Visitor<'de> for DeferredCallIdVisitor {
147                type Value = DeferredCallId;
148
149                fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
150                    formatter.write_str("ASC + base58::encode(bytes)")
151                }
152
153                fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
154                where
155                    E: ::serde::de::Error,
156                {
157                    if let Ok(v_str) = std::str::from_utf8(v) {
158                        DeferredCallId::from_str(v_str).map_err(E::custom)
159                    } else {
160                        Err(E::invalid_value(::serde::de::Unexpected::Bytes(v), &self))
161                    }
162                }
163
164                fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
165                where
166                    E: ::serde::de::Error,
167                {
168                    DeferredCallId::from_str(v).map_err(E::custom)
169                }
170            }
171            d.deserialize_str(DeferredCallIdVisitor)
172        } else {
173            struct BytesVisitor;
174
175            impl<'de> ::serde::de::Visitor<'de> for BytesVisitor {
176                type Value = DeferredCallId;
177
178                fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
179                    formatter.write_str("[u64varint-of-addr-variant][u64varint-of-version][bytes]")
180                }
181
182                fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
183                where
184                    E: ::serde::de::Error,
185                {
186                    DeferredCallId::from_bytes(v).map_err(E::custom)
187                }
188            }
189
190            d.deserialize_bytes(BytesVisitor)
191        }
192    }
193}
194
195impl DeferredCallId {
196    /// Return the slot of the `DeferredCallId`
197    pub fn get_slot(&self) -> Result<Slot, ModelsError> {
198        let version_deserializer = U64VarIntDeserializer::new(
199            std::ops::Bound::Included(0),
200            std::ops::Bound::Included(u64::MAX),
201        );
202
203        let slot_deser = SlotDeserializer::new(
204            (Bound::Included(0), Bound::Included(u64::MAX)),
205            (Bound::Included(0), Bound::Excluded(THREAD_COUNT)),
206        );
207
208        let (rest, _version) = version_deserializer
209            .deserialize::<DeserializeError>(self.as_bytes())
210            .map_err(|_e| ModelsError::DeferredCallIdParseError)?;
211        let (_rest, slot) = slot_deser
212            .deserialize::<DeserializeError>(rest)
213            .map_err(|_e| ModelsError::DeferredCallIdParseError)?;
214        Ok(slot)
215    }
216
217    /// Create a new `DeferredCallId`
218    pub fn new(
219        version: u64,
220        target_slot: Slot,
221        index: u64,
222        trail_hash: &[u8],
223    ) -> Result<Self, ModelsError> {
224        let mut id: Vec<u8> = Vec::new();
225        match version {
226            0 => {
227                let version_serializer = U64VarIntSerializer::new();
228                let slot_serializer = SlotSerializer::new();
229                version_serializer.serialize(&version, &mut id)?;
230                slot_serializer.serialize(&target_slot, &mut id)?;
231                id.extend(index.to_be_bytes());
232                id.extend(trail_hash);
233                Ok(DeferredCallId::DeferredCallIdV0(DeferredCallIdV0(id)))
234            }
235            _ => Err(ModelsError::InvalidVersionError(format!(
236                "Invalid version to create an DeferredCallId: {}",
237                version
238            ))),
239        }
240    }
241
242    /// Return the version of the `DeferredCallId` as bytes
243    pub fn as_bytes(&self) -> &[u8] {
244        match self {
245            DeferredCallId::DeferredCallIdV0(block_id) => block_id.as_bytes(),
246        }
247    }
248
249    /// Create an `DeferredCallId` from bytes
250    pub fn from_bytes(bytes: &[u8]) -> Result<Self, ModelsError> {
251        if bytes.is_empty() {
252            return Err(ModelsError::SerializeError("Empty bytes".to_string()));
253        }
254        let version = U64VarIntDeserializer::new(
255            std::ops::Bound::Included(0),
256            std::ops::Bound::Included(u64::MAX),
257        );
258        let (_, version) = version.deserialize(bytes)?;
259        match version {
260            0 => {
261                let id = DeferredCallIdV0::from_bytes(bytes)?;
262                Ok(DeferredCallId::DeferredCallIdV0(id))
263            }
264            _ => Err(ModelsError::InvalidVersionError(format!(
265                "Invalid version to create an DeferredCallId: {}",
266                version
267            ))),
268        }
269    }
270}
271
272#[transition::impl_version(versions("0"))]
273impl DeferredCallId {
274    /// Return the version of the `DeferredCallId` as bytes
275    pub fn as_bytes(&self) -> &[u8] {
276        &self.0
277    }
278
279    /// Create an `DeferredCallId` from bytes
280    pub fn from_bytes(bytes: &[u8]) -> Result<Self, ModelsError> {
281        Ok(DeferredCallId(bytes.to_vec()))
282    }
283}
284
285#[cfg(test)]
286mod tests {
287    use massa_serialization::DeserializeError;
288
289    use super::*;
290    use crate::slot::Slot;
291
292    #[test]
293    fn test_deferred_call_id_ser_deser() {
294        let slot = Slot::new(1, 2);
295        let index = 3;
296        let trail_hash = [4, 5, 6];
297        let id = DeferredCallId::new(0, slot, index, &trail_hash).unwrap();
298        let serializer = DeferredCallIdSerializer::new();
299        let mut buffer = Vec::new();
300        serializer.serialize(&id, &mut buffer).unwrap();
301        let deserializer = DeferredCallIdDeserializer::new();
302        let (rest, deserialized_id) = deserializer
303            .deserialize::<DeserializeError>(&buffer)
304            .unwrap();
305        assert_eq!(deserialized_id, id);
306        assert!(rest.is_empty());
307    }
308
309    #[test]
310    fn test_deferred_call_id_from_str() {
311        let slot = Slot::new(1, 2);
312        let index = 3;
313        let trail_hash = [4, 5, 6];
314        let id = DeferredCallId::new(0, slot, index, &trail_hash).unwrap();
315        let id_str = id.to_string();
316        let deserialized_id = DeferredCallId::from_str(&id_str).unwrap();
317        assert_eq!(deserialized_id, id);
318    }
319
320    #[test]
321    fn test_get_slot() {
322        let slot = Slot::new(1, 2);
323        let index = 3;
324        let trail_hash = [4, 5, 6];
325        let id = DeferredCallId::new(0, slot, index, &trail_hash).unwrap();
326        assert_eq!(id.get_slot().unwrap(), slot);
327    }
328}