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