massa_models/
async_msg_id.rs

1#![allow(missing_docs)]
2
3use massa_serialization::{Deserializer, Serializer, U64VarIntDeserializer, U64VarIntSerializer};
4use nom::{
5    error::{context, ContextError, ParseError},
6    sequence::tuple,
7    IResult, Parser,
8};
9use num::rational::Ratio;
10use std::ops::Bound::{Excluded, Included};
11
12use crate::slot::{Slot, SlotDeserializer, SlotSerializer};
13
14const ASYNC_MESSAGE_ID_PREFIX: &str = "ASC";
15
16/// Unique identifier of a message.
17/// Also has the property of ordering by priority (highest first) following the triplet:
18/// `(rev(Ratio(msg.fee, max(msg.max_gas,1))), emission_slot, emission_index)`
19pub type AsyncMessageId = (std::cmp::Reverse<Ratio<u64>>, Slot, u64);
20
21#[derive(Clone)]
22pub struct AsyncMessageIdWrapper(pub AsyncMessageId);
23
24impl std::fmt::Display for AsyncMessageIdWrapper {
25    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26        let mut bytes = Vec::new();
27        let serializer = AsyncMessageIdSerializer::new();
28        serializer
29            .serialize(&self.0, &mut bytes)
30            .map_err(|_| std::fmt::Error)?;
31        write!(
32            f,
33            "{}{}",
34            ASYNC_MESSAGE_ID_PREFIX,
35            bs58::encode(&bytes).with_check().into_string()
36        )
37    }
38}
39
40#[derive(Clone)]
41pub struct AsyncMessageIdSerializer {
42    slot_serializer: SlotSerializer,
43    u64_serializer: U64VarIntSerializer,
44}
45
46impl AsyncMessageIdSerializer {
47    pub fn new() -> Self {
48        Self {
49            slot_serializer: SlotSerializer::new(),
50            u64_serializer: U64VarIntSerializer::new(),
51        }
52    }
53}
54
55impl Default for AsyncMessageIdSerializer {
56    fn default() -> Self {
57        Self::new()
58    }
59}
60
61impl Serializer<AsyncMessageId> for AsyncMessageIdSerializer {
62    /// ## Example
63    /// ```
64    /// use std::ops::Bound::Included;
65    /// use massa_serialization::Serializer;
66    /// use massa_models::{address::Address, amount::Amount, slot::Slot, async_msg_id::{AsyncMessageId, AsyncMessageIdSerializer}, async_msg::AsyncMessage};
67    /// use std::str::FromStr;
68    ///
69    /// let message = AsyncMessage::new(
70    ///     Slot::new(1, 0),
71    ///     0,
72    ///     Address::from_str("AU12dG5xP1RDEB5ocdHkymNVvvSJmUL9BgHwCksDowqmGWxfpm93x").unwrap(),
73    ///     Address::from_str("AU12htxRWiEm8jDJpJptr6cwEhWNcCSFWstN1MLSa96DDkVM9Y42G").unwrap(),
74    ///     String::from("test"),
75    ///     10000000,
76    ///     Amount::from_str("1").unwrap(),
77    ///     Amount::from_str("1").unwrap(),
78    ///     Slot::new(2, 0),
79    ///     Slot::new(3, 0),
80    ///     vec![1, 2, 3, 4],
81    ///     None,
82    ///     None
83    /// );
84    /// let id: AsyncMessageId = message.compute_id();
85    /// let mut serialized = Vec::new();
86    /// let serializer = AsyncMessageIdSerializer::new();
87    /// serializer.serialize(&id, &mut serialized).unwrap();
88    /// ```
89    fn serialize(
90        &self,
91        value: &AsyncMessageId,
92        buffer: &mut Vec<u8>,
93    ) -> Result<(), massa_serialization::SerializeError> {
94        self.u64_serializer.serialize(value.0 .0.numer(), buffer)?;
95        self.u64_serializer.serialize(value.0 .0.denom(), buffer)?;
96        self.slot_serializer.serialize(&value.1, buffer)?;
97        self.u64_serializer.serialize(&value.2, buffer)?;
98        Ok(())
99    }
100}
101
102#[derive(Clone)]
103pub struct AsyncMessageIdDeserializer {
104    slot_deserializer: SlotDeserializer,
105    numerator_deserializer: U64VarIntDeserializer,
106    denominator_deserializer: U64VarIntDeserializer,
107    emission_index_deserializer: U64VarIntDeserializer,
108}
109
110impl AsyncMessageIdDeserializer {
111    pub fn new(thread_count: u8) -> Self {
112        Self {
113            slot_deserializer: SlotDeserializer::new(
114                (Included(u64::MIN), Included(u64::MAX)),
115                (Included(0), Excluded(thread_count)),
116            ),
117            numerator_deserializer: U64VarIntDeserializer::new(
118                Included(u64::MIN),
119                Included(u64::MAX),
120            ),
121            denominator_deserializer: U64VarIntDeserializer::new(Included(1), Included(u64::MAX)),
122            emission_index_deserializer: U64VarIntDeserializer::new(
123                Included(u64::MIN),
124                Included(u64::MAX),
125            ),
126        }
127    }
128}
129
130impl Deserializer<AsyncMessageId> for AsyncMessageIdDeserializer {
131    /// ## Example
132    /// ```
133    /// use std::ops::Bound::Included;
134    /// use massa_serialization::{Serializer, Deserializer, DeserializeError};
135    /// use massa_models::{address::Address, amount::Amount, slot::Slot, async_msg_id::{AsyncMessageId, AsyncMessageIdDeserializer, AsyncMessageIdSerializer}};
136    /// use massa_models::async_msg::AsyncMessage;
137    /// use std::str::FromStr;
138    ///
139    /// let message = AsyncMessage::new(
140    ///     Slot::new(1, 0),
141    ///     0,
142    ///     Address::from_str("AU12dG5xP1RDEB5ocdHkymNVvvSJmUL9BgHwCksDowqmGWxfpm93x").unwrap(),
143    ///     Address::from_str("AU12htxRWiEm8jDJpJptr6cwEhWNcCSFWstN1MLSa96DDkVM9Y42G").unwrap(),
144    ///     String::from("test"),
145    ///     10000000,
146    ///     Amount::from_str("1").unwrap(),
147    ///     Amount::from_str("1").unwrap(),
148    ///     Slot::new(2, 0),
149    ///     Slot::new(3, 0),
150    ///     vec![1, 2, 3, 4],
151    ///     None,
152    ///     None
153    /// );
154    /// let id: AsyncMessageId = message.compute_id();
155    /// let mut serialized = Vec::new();
156    /// let serializer = AsyncMessageIdSerializer::new();
157    /// let deserializer = AsyncMessageIdDeserializer::new(10);
158    /// serializer.serialize(&id, &mut serialized).unwrap();
159    /// let (rest, id_deser) = deserializer.deserialize::<DeserializeError>(&serialized).unwrap();
160    /// assert!(rest.is_empty());
161    /// assert_eq!(id, id_deser);
162    /// ```
163    fn deserialize<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
164        &self,
165        buffer: &'a [u8],
166    ) -> IResult<&'a [u8], AsyncMessageId, E> {
167        context(
168            "Failed AsyncMessageId deserialization",
169            tuple((
170                context("Failed num deserialization", |input| {
171                    self.numerator_deserializer.deserialize(input)
172                }),
173                context("Failed denum deserialization", |input| {
174                    self.denominator_deserializer.deserialize(input)
175                }),
176                context("Failed emission_slot deserialization", |input| {
177                    self.slot_deserializer.deserialize(input)
178                }),
179                context("Failed emission_index deserialization", |input| {
180                    self.emission_index_deserializer.deserialize(input)
181                }),
182            )),
183        )
184        .map(|(fee, denom, slot, index)| (std::cmp::Reverse(Ratio::new(fee, denom)), slot, index))
185        .parse(buffer)
186    }
187}