massa_models/
async_msg.rs

1//! Copyright (c) 2022 MASSA LABS <info@massa.net>
2
3//! This file defines the structure representing an asynchronous message
4#![allow(missing_docs)]
5use crate::address::{AddressDeserializer, AddressSerializer};
6use crate::amount::{AmountDeserializer, AmountSerializer};
7use crate::async_msg_id::AsyncMessageId;
8use crate::config::GENESIS_KEY;
9use crate::serialization::{StringDeserializer, StringSerializer};
10use crate::slot::{SlotDeserializer, SlotSerializer};
11use crate::types::{Applicable, SetOrKeep, SetOrKeepDeserializer, SetOrKeepSerializer};
12use crate::{
13    address::Address,
14    amount::Amount,
15    serialization::{VecU8Deserializer, VecU8Serializer},
16    slot::Slot,
17};
18use massa_serialization::{
19    BoolDeserializer, BoolSerializer, Deserializer, OptionDeserializer, OptionSerializer,
20    SerializeError, Serializer, U16VarIntDeserializer, U16VarIntSerializer, U64VarIntDeserializer,
21    U64VarIntSerializer,
22};
23use nom::error::{context, ContextError, ParseError};
24use nom::sequence::tuple;
25use nom::{IResult, Parser};
26use num::rational::Ratio;
27use serde::{Deserialize, Serialize};
28use std::ops::Bound::{Excluded, Included};
29
30/// Structure defining a trigger for an asynchronous message
31#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
32pub struct AsyncMessageTrigger {
33    /// Filter on the address
34    pub address: Address,
35
36    /// Filter on the datastore key
37    pub datastore_key: Option<Vec<u8>>,
38}
39
40#[derive(Clone)]
41/// Serializer for a trigger for an asynchronous message
42pub struct AsyncMessageTriggerSerializer {
43    address_serializer: AddressSerializer,
44    key_serializer: OptionSerializer<Vec<u8>, VecU8Serializer>,
45}
46
47impl AsyncMessageTriggerSerializer {
48    pub fn new() -> Self {
49        Self {
50            address_serializer: AddressSerializer::new(),
51            key_serializer: OptionSerializer::new(VecU8Serializer::new()),
52        }
53    }
54}
55
56impl Default for AsyncMessageTriggerSerializer {
57    fn default() -> Self {
58        Self::new()
59    }
60}
61
62impl Serializer<AsyncMessageTrigger> for AsyncMessageTriggerSerializer {
63    fn serialize(
64        &self,
65        value: &AsyncMessageTrigger,
66        buffer: &mut Vec<u8>,
67    ) -> Result<(), SerializeError> {
68        self.address_serializer.serialize(&value.address, buffer)?;
69        self.key_serializer
70            .serialize(&value.datastore_key, buffer)?;
71        Ok(())
72    }
73}
74
75#[derive(Clone)]
76/// Deserializer for a trigger for an asynchronous message
77pub struct AsyncMessageTriggerDeserializer {
78    address_deserializer: AddressDeserializer,
79    key_serializer: OptionDeserializer<Vec<u8>, VecU8Deserializer>,
80}
81
82impl AsyncMessageTriggerDeserializer {
83    pub fn new(max_key_length: u32) -> Self {
84        Self {
85            address_deserializer: AddressDeserializer::new(),
86            key_serializer: OptionDeserializer::new(VecU8Deserializer::new(
87                Included(0),
88                Included(max_key_length as u64),
89            )),
90        }
91    }
92}
93
94impl Deserializer<AsyncMessageTrigger> for AsyncMessageTriggerDeserializer {
95    fn deserialize<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
96        &self,
97        buffer: &'a [u8],
98    ) -> IResult<&'a [u8], AsyncMessageTrigger, E> {
99        context(
100            "Failed AsyncMessageTrigger deserialization",
101            tuple((
102                context("Failed address deserialization", |input| {
103                    self.address_deserializer.deserialize(input)
104                }),
105                context("Failed datastore_key deserialization", |input| {
106                    self.key_serializer.deserialize(input)
107                }),
108            )),
109        )
110        .map(|(address, datastore_key)| AsyncMessageTrigger {
111            address,
112            datastore_key,
113        })
114        .parse(buffer)
115    }
116}
117
118/// Structure defining an asynchronous smart contract message
119#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
120pub struct AsyncMessage {
121    /// Slot at which the message was emitted
122    pub emission_slot: Slot,
123
124    /// Index of the emitted message within the `emission_slot`.
125    /// This is used for disambiguate the emission of multiple messages at the same slot.
126    pub emission_index: u64,
127
128    /// The address that sent the message
129    pub sender: Address,
130
131    /// The address towards which the message is being sent
132    pub destination: Address,
133
134    /// the function function name within the destination address' bytecode
135    pub function: String,
136
137    /// Maximum gas to use when processing the message
138    pub max_gas: u64,
139
140    /// Fee paid by the sender when the message is processed.
141    pub fee: Amount,
142
143    /// Coins sent from the sender to the target address of the message.
144    /// Those coins are spent by the sender address when the message is sent,
145    /// and credited to the destination address when receiving the message.
146    /// In case of failure or discard, those coins are reimbursed to the sender.
147    pub coins: Amount,
148
149    /// Slot at which the message starts being valid (bound included in the validity range)
150    pub validity_start: Slot,
151
152    /// Slot at which the message stops being valid (bound included in the validity range)
153    pub validity_end: Slot,
154
155    /// Raw payload parameters to call the function with
156    pub function_params: Vec<u8>,
157
158    /// Trigger that define whenever a message can be executed
159    pub trigger: Option<AsyncMessageTrigger>,
160
161    /// Boolean that determine if the message can be executed. For messages without filter this boolean is always true.
162    /// For messages with filter, this boolean is true if the filter has been matched at any slot up to
163    /// the current one, including before `validity_start`: arming is not restricted to the validity
164    /// interval, which only bounds execution. Once true, this boolean is never set back to false.
165    pub can_be_executed: bool,
166}
167
168impl Default for AsyncMessage {
169    #[allow(unconditional_recursion)]
170    fn default() -> Self {
171        let genesis_address = Address::from_public_key(&(*GENESIS_KEY).get_public_key());
172        let slot_zero = Slot::new(0, 0);
173        Self {
174            emission_slot: slot_zero,
175            sender: genesis_address,
176            destination: genesis_address,
177            validity_start: slot_zero,
178            validity_end: slot_zero,
179            ..Default::default()
180        }
181    }
182}
183
184impl AsyncMessage {
185    #[allow(clippy::too_many_arguments)]
186    /// Take an `AsyncMessage` and return it
187    pub fn new(
188        emission_slot: Slot,
189        emission_index: u64,
190        sender: Address,
191        destination: Address,
192        function: String,
193        max_gas: u64,
194        fee: Amount,
195        coins: Amount,
196        validity_start: Slot,
197        validity_end: Slot,
198        function_params: Vec<u8>,
199        trigger: Option<AsyncMessageTrigger>,
200        can_be_executed: Option<bool>,
201    ) -> Self {
202        AsyncMessage {
203            emission_slot,
204            emission_index,
205            sender,
206            destination,
207            function,
208            max_gas,
209            fee,
210            coins,
211            validity_start,
212            validity_end,
213            function_params,
214            can_be_executed: can_be_executed.unwrap_or(trigger.is_none()),
215            trigger,
216        }
217    }
218
219    /// Compute the ID of the message for use when choosing which operations to keep in priority (highest score) on pool overflow.
220    ///
221    /// Uses `fee / max(max_gas, 1)`. Prefer [`Self::compute_priority_id`] when ranking must
222    /// match the gas actually charged at execution (`max_gas + async_msg_cst_gas_cost`) to avoid any pricing issue.
223    /// The pricing mismatch between the two functions is real, but small in practice: `send_message` rejects `max_gas` below
224    /// `gas_costs.max_instance_cost` (2.1M gas), so the skew `(max_gas + cst) / max_gas` is at
225    /// most `1 + 1M/2.1M ≈ 1.48×`. Emitting costs 40M gas of ABI per message (~107 per block
226    /// at most, by taking the whole block), so the priority advantage tops out around 48% for a
227    /// sender paying full blocks.
228    pub fn compute_id(&self) -> AsyncMessageId {
229        self.compute_priority_id(0)
230    }
231
232    /// Priority key used for pool ordering / batch selection.
233    ///
234    /// Ranks by `fee / max(max_gas + extra_gas_cost, 1)`, then `emission_slot`, then
235    /// `emission_index`. Pass the fixed per-message gas surcharge as `extra_gas_cost` so
236    /// priority matches the budget consumed in `take_batch_to_execute`.
237    pub fn compute_priority_id(&self, extra_gas_cost: u64) -> AsyncMessageId {
238        let denom = match self.max_gas.saturating_add(extra_gas_cost) {
239            0 => 1,
240            d => d,
241        };
242        (
243            std::cmp::Reverse(Ratio::new(self.fee.to_raw(), denom)),
244            self.emission_slot,
245            self.emission_index,
246        )
247    }
248}
249
250#[derive(Clone)]
251pub struct AsyncMessageSerializer {
252    pub slot_serializer: SlotSerializer,
253    pub function_serializer: StringSerializer<U16VarIntSerializer, u16>,
254    pub amount_serializer: AmountSerializer,
255    pub u64_serializer: U64VarIntSerializer,
256    pub function_params_serializer: VecU8Serializer,
257    pub address_serializer: AddressSerializer,
258    pub trigger_serializer: OptionSerializer<AsyncMessageTrigger, AsyncMessageTriggerSerializer>,
259    pub bool_serializer: BoolSerializer,
260    pub for_db: bool,
261}
262
263impl AsyncMessageSerializer {
264    pub fn new(for_db: bool) -> Self {
265        Self {
266            slot_serializer: SlotSerializer::new(),
267            amount_serializer: AmountSerializer::new(),
268            u64_serializer: U64VarIntSerializer::new(),
269            function_serializer: StringSerializer::new(U16VarIntSerializer::new()),
270            function_params_serializer: VecU8Serializer::new(),
271            address_serializer: AddressSerializer::new(),
272            trigger_serializer: OptionSerializer::new(AsyncMessageTriggerSerializer::new()),
273            bool_serializer: BoolSerializer::new(),
274            for_db,
275        }
276    }
277}
278
279impl Default for AsyncMessageSerializer {
280    fn default() -> Self {
281        Self::new(false)
282    }
283}
284
285impl Serializer<AsyncMessage> for AsyncMessageSerializer {
286    /// ## Example
287    /// ```
288    /// use massa_models::{address::Address, amount::Amount, slot::Slot, async_msg::{AsyncMessage, AsyncMessageSerializer, AsyncMessageTrigger}};
289    /// use massa_serialization::Serializer;
290    /// use std::str::FromStr;
291    ///
292    /// let message = AsyncMessage::new(
293    ///     Slot::new(1, 0),
294    ///     0,
295    ///     Address::from_str("AU12dG5xP1RDEB5ocdHkymNVvvSJmUL9BgHwCksDowqmGWxfpm93x").unwrap(),
296    ///     Address::from_str("AU12htxRWiEm8jDJpJptr6cwEhWNcCSFWstN1MLSa96DDkVM9Y42G").unwrap(),
297    ///     String::from("test"),
298    ///     10000000,
299    ///     Amount::from_str("1").unwrap(),
300    ///     Amount::from_str("1").unwrap(),
301    ///     Slot::new(2, 0),
302    ///     Slot::new(3, 0),
303    ///     vec![1, 2, 3, 4],
304    ///     Some(AsyncMessageTrigger {
305    ///         address: Address::from_str("AU12dG5xP1RDEB5ocdHkymNVvvSJmUL9BgHwCksDowqmGWxfpm93x").unwrap(),
306    ///         datastore_key: Some(vec![1, 2, 3, 4])
307    ///     }),
308    ///     None,
309    /// );
310    /// let mut buffer = Vec::new();
311    /// let message_serializer = AsyncMessageSerializer::new(false);
312    /// message_serializer.serialize(&message, &mut buffer).unwrap();
313    /// ```
314    fn serialize(
315        &self,
316        value: &AsyncMessage,
317        buffer: &mut Vec<u8>,
318    ) -> Result<(), massa_serialization::SerializeError> {
319        self.slot_serializer
320            .serialize(&value.emission_slot, buffer)?;
321        self.u64_serializer
322            .serialize(&value.emission_index, buffer)?;
323        self.address_serializer.serialize(&value.sender, buffer)?;
324        self.address_serializer
325            .serialize(&value.destination, buffer)?;
326        self.function_serializer
327            .serialize(&value.function, buffer)?;
328        self.u64_serializer.serialize(&value.max_gas, buffer)?;
329        self.amount_serializer.serialize(&value.fee, buffer)?;
330        self.amount_serializer.serialize(&value.coins, buffer)?;
331        self.slot_serializer
332            .serialize(&value.validity_start, buffer)?;
333        self.slot_serializer
334            .serialize(&value.validity_end, buffer)?;
335        self.function_params_serializer
336            .serialize(&value.function_params, buffer)?;
337        self.trigger_serializer.serialize(&value.trigger, buffer)?;
338        if self.for_db {
339            self.bool_serializer
340                .serialize(&value.can_be_executed, buffer)?;
341        }
342        Ok(())
343    }
344}
345
346#[derive(Clone)]
347pub struct AsyncMessageDeserializer {
348    pub slot_deserializer: SlotDeserializer,
349    pub amount_deserializer: AmountDeserializer,
350    pub emission_index_deserializer: U64VarIntDeserializer,
351    pub max_gas_deserializer: U64VarIntDeserializer,
352    pub function_deserializer: StringDeserializer<U16VarIntDeserializer, u16>,
353    pub function_params_deserializer: VecU8Deserializer,
354    pub address_deserializer: AddressDeserializer,
355    pub trigger_deserializer:
356        OptionDeserializer<AsyncMessageTrigger, AsyncMessageTriggerDeserializer>,
357    pub bool_deserializer: BoolDeserializer,
358    pub for_db: bool,
359}
360
361impl AsyncMessageDeserializer {
362    pub fn new(
363        thread_count: u8,
364        max_function_length: u16,
365        max_function_params_length: u64,
366        max_key_length: u32,
367        for_db: bool,
368    ) -> Self {
369        Self {
370            slot_deserializer: SlotDeserializer::new(
371                (Included(0), Included(u64::MAX)),
372                (Included(0), Excluded(thread_count)),
373            ),
374            amount_deserializer: AmountDeserializer::new(
375                Included(Amount::MIN),
376                Included(Amount::MAX),
377            ),
378            emission_index_deserializer: U64VarIntDeserializer::new(
379                Included(0),
380                Included(u64::MAX),
381            ),
382            max_gas_deserializer: U64VarIntDeserializer::new(Included(0), Included(u64::MAX)),
383            function_deserializer: StringDeserializer::new(U16VarIntDeserializer::new(
384                Included(0),
385                Included(max_function_length),
386            )),
387            function_params_deserializer: VecU8Deserializer::new(
388                Included(0),
389                Included(max_function_params_length),
390            ),
391            address_deserializer: AddressDeserializer::new(),
392            trigger_deserializer: OptionDeserializer::new(AsyncMessageTriggerDeserializer::new(
393                max_key_length,
394            )),
395            bool_deserializer: BoolDeserializer::new(),
396            for_db,
397        }
398    }
399}
400
401impl Deserializer<AsyncMessage> for AsyncMessageDeserializer {
402    /// ## Example
403    /// ```
404    /// use massa_models::{address::Address, amount::Amount, slot::Slot, async_msg::{AsyncMessage, AsyncMessageSerializer, AsyncMessageDeserializer, AsyncMessageTrigger}};
405    /// use massa_serialization::{Serializer, Deserializer, DeserializeError};
406    /// use std::str::FromStr;
407    ///
408    /// let message = AsyncMessage::new(
409    ///     Slot::new(1, 0),
410    ///     0,
411    ///     Address::from_str("AU12dG5xP1RDEB5ocdHkymNVvvSJmUL9BgHwCksDowqmGWxfpm93x").unwrap(),
412    ///     Address::from_str("AS12htxRWiEm8jDJpJptr6cwEhWNcCSFWstN1MLSa96DDkVM9Y42G").unwrap(),
413    ///     String::from("test"),
414    ///     10000000,
415    ///     Amount::from_str("1").unwrap(),
416    ///     Amount::from_str("1").unwrap(),
417    ///     Slot::new(2, 0),
418    ///     Slot::new(3, 0),
419    ///     vec![1, 2, 3, 4],
420    ///     Some(AsyncMessageTrigger {
421    ///        address: Address::from_str("AU12dG5xP1RDEB5ocdHkymNVvvSJmUL9BgHwCksDowqmGWxfpm93x").unwrap(),
422    ///        datastore_key: Some(vec![1, 2, 3, 4]),
423    ///     }),
424    ///     None,
425    /// );
426    /// let message_serializer = AsyncMessageSerializer::new(false);
427    /// let mut serialized = Vec::new();
428    /// message_serializer.serialize(&message, &mut serialized).unwrap();
429    /// let message_deserializer = AsyncMessageDeserializer::new(32, 10000, 100000, 255, false);
430    /// // dbg!(&serialized);
431    /// let (rest, message_deserialized) = message_deserializer.deserialize::<DeserializeError>(&serialized).unwrap();
432    /// assert!(rest.is_empty());
433    /// assert_eq!(message, message_deserialized);
434    /// ```
435    fn deserialize<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
436        &self,
437        buffer: &'a [u8],
438    ) -> IResult<&'a [u8], AsyncMessage, E> {
439        context(
440            "Failed AsyncMessage deserialization",
441            tuple((
442                context("Failed emission_slot deserialization", |input| {
443                    self.slot_deserializer.deserialize(input)
444                }),
445                context("Failed emission_index deserialization", |input| {
446                    self.emission_index_deserializer.deserialize(input)
447                }),
448                context("Failed sender deserialization", |input| {
449                    self.address_deserializer.deserialize(input)
450                }),
451                context("Failed destination deserialization", |input| {
452                    self.address_deserializer.deserialize(input)
453                }),
454                context("Failed function deserialization", |input| {
455                    self.function_deserializer.deserialize(input)
456                }),
457                context("Failed max_gas deserialization", |input| {
458                    self.max_gas_deserializer.deserialize(input)
459                }),
460                context("Failed fee deserialization", |input| {
461                    self.amount_deserializer.deserialize(input)
462                }),
463                context("Failed coins deserialization", |input| {
464                    self.amount_deserializer.deserialize(input)
465                }),
466                context("Failed validity_start deserialization", |input| {
467                    self.slot_deserializer.deserialize(input)
468                }),
469                context("Failed validity_end deserialization", |input| {
470                    self.slot_deserializer.deserialize(input)
471                }),
472                context("Failed data deserialization", |input| {
473                    self.function_params_deserializer.deserialize(input)
474                }),
475                context("Failed filter deserialization", |input| {
476                    self.trigger_deserializer.deserialize(input)
477                }),
478                context("Failed can_be_executed deserialization", |input| {
479                    if self.for_db {
480                        self.bool_deserializer.deserialize(input)
481                    } else {
482                        Ok((input, false))
483                    }
484                }),
485            )),
486        )
487        .map(
488            |(
489                emission_slot,
490                emission_index,
491                sender,
492                destination,
493                function,
494                max_gas,
495                fee,
496                coins,
497                validity_start,
498                validity_end,
499                function_params,
500                filter,
501                can_be_executed,
502            )| {
503                AsyncMessage::new(
504                    emission_slot,
505                    emission_index,
506                    sender,
507                    destination,
508                    function,
509                    max_gas,
510                    fee,
511                    coins,
512                    validity_start,
513                    validity_end,
514                    function_params,
515                    filter,
516                    if self.for_db {
517                        Some(can_be_executed)
518                    } else {
519                        None
520                    },
521                )
522            },
523        )
524        .parse(buffer)
525    }
526}
527
528/// represents an update to one or more fields of a `AsyncMessage`
529#[derive(Default, Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
530pub struct AsyncMessageUpdate {
531    /// Slot at which the message was emitted
532    pub emission_slot: SetOrKeep<Slot>,
533
534    /// Index of the emitted message within the `emission_slot`.
535    /// This is used for disambiguate the emission of multiple messages at the same slot.
536    pub emission_index: SetOrKeep<u64>,
537
538    /// The address that sent the message
539    pub sender: SetOrKeep<Address>,
540
541    /// The address towards which the message is being sent
542    pub destination: SetOrKeep<Address>,
543
544    /// the function function name within the destination address' bytecode
545    pub function: SetOrKeep<String>,
546
547    /// Maximum gas to use when processing the message
548    pub max_gas: SetOrKeep<u64>,
549
550    /// Fee paid by the sender when the message is processed.
551    pub fee: SetOrKeep<Amount>,
552
553    /// Coins sent from the sender to the target address of the message.
554    /// Those coins are spent by the sender address when the message is sent,
555    /// and credited to the destination address when receiving the message.
556    /// In case of failure or discard, those coins are reimbursed to the sender.
557    pub coins: SetOrKeep<Amount>,
558
559    /// Slot at which the message starts being valid (bound included in the validity range)
560    pub validity_start: SetOrKeep<Slot>,
561
562    /// Slot at which the message stops being valid (bound not included in the validity range)
563    pub validity_end: SetOrKeep<Slot>,
564
565    /// Raw payload parameters to call the function with
566    pub function_params: SetOrKeep<Vec<u8>>,
567
568    /// Trigger that define whenever a message can be executed
569    pub trigger: SetOrKeep<Option<AsyncMessageTrigger>>,
570
571    /// Boolean that determine if the message can be executed. For messages without filter this boolean is always true.
572    /// For messages with filter, this boolean is true if the filter has been matched at any slot up to
573    /// the current one, including before `validity_start`: arming is not restricted to the validity
574    /// interval, which only bounds execution. Once true, this boolean is never set back to false.
575    pub can_be_executed: SetOrKeep<bool>,
576}
577
578/// Serializer for `AsyncMessageUpdate`
579pub struct AsyncMessageUpdateSerializer {
580    slot_serializer: SetOrKeepSerializer<Slot, SlotSerializer>,
581    amount_serializer: SetOrKeepSerializer<Amount, AmountSerializer>,
582    u64_serializer: SetOrKeepSerializer<u64, U64VarIntSerializer>,
583    function_serializer: SetOrKeepSerializer<String, StringSerializer<U16VarIntSerializer, u16>>,
584    function_params_serializer: SetOrKeepSerializer<Vec<u8>, VecU8Serializer>,
585    address_serializer: SetOrKeepSerializer<Address, AddressSerializer>,
586    trigger_serializer: SetOrKeepSerializer<
587        Option<AsyncMessageTrigger>,
588        OptionSerializer<AsyncMessageTrigger, AsyncMessageTriggerSerializer>,
589    >,
590    bool_serializer: SetOrKeepSerializer<bool, BoolSerializer>,
591    for_db: bool,
592}
593
594impl AsyncMessageUpdateSerializer {
595    /// Creates a new `AsyncMessageUpdateSerializer`
596    pub fn new(for_db: bool) -> Self {
597        Self {
598            slot_serializer: SetOrKeepSerializer::new(SlotSerializer::new()),
599            amount_serializer: SetOrKeepSerializer::new(AmountSerializer::new()),
600            u64_serializer: SetOrKeepSerializer::new(U64VarIntSerializer::new()),
601            function_serializer: SetOrKeepSerializer::new(StringSerializer::new(
602                U16VarIntSerializer::new(),
603            )),
604            function_params_serializer: SetOrKeepSerializer::new(VecU8Serializer::new()),
605            address_serializer: SetOrKeepSerializer::new(AddressSerializer::new()),
606            trigger_serializer: SetOrKeepSerializer::new(OptionSerializer::new(
607                AsyncMessageTriggerSerializer::new(),
608            )),
609            bool_serializer: SetOrKeepSerializer::new(BoolSerializer::new()),
610            for_db,
611        }
612    }
613}
614
615impl Default for AsyncMessageUpdateSerializer {
616    fn default() -> Self {
617        Self::new(false)
618    }
619}
620
621impl Serializer<AsyncMessageUpdate> for AsyncMessageUpdateSerializer {
622    fn serialize(
623        &self,
624        value: &AsyncMessageUpdate,
625        buffer: &mut Vec<u8>,
626    ) -> Result<(), SerializeError> {
627        self.slot_serializer
628            .serialize(&value.emission_slot, buffer)?;
629        self.u64_serializer
630            .serialize(&value.emission_index, buffer)?;
631        self.address_serializer.serialize(&value.sender, buffer)?;
632        self.address_serializer
633            .serialize(&value.destination, buffer)?;
634        self.function_serializer
635            .serialize(&value.function, buffer)?;
636        self.u64_serializer.serialize(&value.max_gas, buffer)?;
637        self.amount_serializer.serialize(&value.fee, buffer)?;
638        self.amount_serializer.serialize(&value.coins, buffer)?;
639        self.slot_serializer
640            .serialize(&value.validity_start, buffer)?;
641        self.slot_serializer
642            .serialize(&value.validity_end, buffer)?;
643        self.function_params_serializer
644            .serialize(&value.function_params, buffer)?;
645        self.trigger_serializer.serialize(&value.trigger, buffer)?;
646        if self.for_db {
647            self.bool_serializer
648                .serialize(&value.can_be_executed, buffer)?;
649        }
650        Ok(())
651    }
652}
653
654/// Deserializer for `AsyncMessageUpdate`
655pub struct AsyncMessageUpdateDeserializer {
656    slot_deserializer: SetOrKeepDeserializer<Slot, SlotDeserializer>,
657    amount_deserializer: SetOrKeepDeserializer<Amount, AmountDeserializer>,
658    emission_index_deserializer: SetOrKeepDeserializer<u64, U64VarIntDeserializer>,
659    max_gas_deserializer: SetOrKeepDeserializer<u64, U64VarIntDeserializer>,
660    function_deserializer:
661        SetOrKeepDeserializer<String, StringDeserializer<U16VarIntDeserializer, u16>>,
662    function_params_deserializer: SetOrKeepDeserializer<Vec<u8>, VecU8Deserializer>,
663    address_deserializer: SetOrKeepDeserializer<Address, AddressDeserializer>,
664    trigger_deserializer: SetOrKeepDeserializer<
665        Option<AsyncMessageTrigger>,
666        OptionDeserializer<AsyncMessageTrigger, AsyncMessageTriggerDeserializer>,
667    >,
668    bool_deserializer: SetOrKeepDeserializer<bool, BoolDeserializer>,
669    for_db: bool,
670}
671
672impl AsyncMessageUpdateDeserializer {
673    /// Creates a new `AsyncMessageUpdateDeserializer`
674    pub fn new(
675        thread_count: u8,
676        max_function_length: u16,
677        max_function_params_length: u64,
678        max_key_length: u32,
679        for_db: bool,
680    ) -> Self {
681        Self {
682            slot_deserializer: SetOrKeepDeserializer::new(SlotDeserializer::new(
683                (Included(0), Included(u64::MAX)),
684                (Included(0), Excluded(thread_count)),
685            )),
686            amount_deserializer: SetOrKeepDeserializer::new(AmountDeserializer::new(
687                Included(Amount::MIN),
688                Included(Amount::MAX),
689            )),
690            emission_index_deserializer: SetOrKeepDeserializer::new(U64VarIntDeserializer::new(
691                Included(0),
692                Included(u64::MAX),
693            )),
694            max_gas_deserializer: SetOrKeepDeserializer::new(U64VarIntDeserializer::new(
695                Included(0),
696                Included(u64::MAX),
697            )),
698            function_deserializer: SetOrKeepDeserializer::new(StringDeserializer::new(
699                U16VarIntDeserializer::new(Included(0), Included(max_function_length)),
700            )),
701            function_params_deserializer: SetOrKeepDeserializer::new(VecU8Deserializer::new(
702                Included(0),
703                Included(max_function_params_length),
704            )),
705            address_deserializer: SetOrKeepDeserializer::new(AddressDeserializer::new()),
706            trigger_deserializer: SetOrKeepDeserializer::new(OptionDeserializer::new(
707                AsyncMessageTriggerDeserializer::new(max_key_length),
708            )),
709            bool_deserializer: SetOrKeepDeserializer::new(BoolDeserializer::new()),
710            for_db,
711        }
712    }
713}
714
715impl Deserializer<AsyncMessageUpdate> for AsyncMessageUpdateDeserializer {
716    fn deserialize<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
717        &self,
718        buffer: &'a [u8],
719    ) -> IResult<&'a [u8], AsyncMessageUpdate, E> {
720        context(
721            "Failed AsyncMessageUpdate deserialization",
722            tuple((
723                context("Failed emission_slot deserialization", |input| {
724                    self.slot_deserializer.deserialize(input)
725                }),
726                context("Failed emission_index deserialization", |input| {
727                    self.emission_index_deserializer.deserialize(input)
728                }),
729                context("Failed sender deserialization", |input| {
730                    self.address_deserializer.deserialize(input)
731                }),
732                context("Failed destination deserialization", |input| {
733                    self.address_deserializer.deserialize(input)
734                }),
735                context("Failed function deserialization", |input| {
736                    self.function_deserializer.deserialize(input)
737                }),
738                context("Failed max_gas deserialization", |input| {
739                    self.max_gas_deserializer.deserialize(input)
740                }),
741                context("Failed fee deserialization", |input| {
742                    self.amount_deserializer.deserialize(input)
743                }),
744                context("Failed coins deserialization", |input| {
745                    self.amount_deserializer.deserialize(input)
746                }),
747                context("Failed validity_start deserialization", |input| {
748                    self.slot_deserializer.deserialize(input)
749                }),
750                context("Failed validity_end deserialization", |input| {
751                    self.slot_deserializer.deserialize(input)
752                }),
753                context("Failed function_params deserialization", |input| {
754                    self.function_params_deserializer.deserialize(input)
755                }),
756                context("Failed filter deserialization", |input| {
757                    self.trigger_deserializer.deserialize(input)
758                }),
759                context("Failed can_be_executed deserialization", |input| {
760                    if self.for_db {
761                        self.bool_deserializer.deserialize(input)
762                    } else {
763                        Ok((input, SetOrKeep::Keep))
764                    }
765                }),
766            )),
767        )
768        .map(
769            |(
770                emission_slot,
771                emission_index,
772                sender,
773                destination,
774                function,
775                max_gas,
776                fee,
777                coins,
778                validity_start,
779                validity_end,
780                function_params,
781                trigger,
782                can_be_executed,
783            )| {
784                AsyncMessageUpdate {
785                    emission_slot,
786                    emission_index,
787                    sender,
788                    destination,
789                    function,
790                    max_gas,
791                    fee,
792                    coins,
793                    validity_start,
794                    validity_end,
795                    function_params,
796                    trigger,
797                    can_be_executed,
798                }
799            },
800        )
801        .parse(buffer)
802    }
803}
804
805impl Applicable<AsyncMessageUpdate> for AsyncMessageUpdate {
806    /// extends the `AsyncMessageUpdate` with another one
807    fn apply(&mut self, update: AsyncMessageUpdate) {
808        self.emission_slot.apply(update.emission_slot);
809        self.emission_index.apply(update.emission_index);
810        self.sender.apply(update.sender);
811        self.destination.apply(update.destination);
812        self.function.apply(update.function);
813        self.max_gas.apply(update.max_gas);
814        self.fee.apply(update.fee);
815        self.coins.apply(update.coins);
816        self.validity_start.apply(update.validity_start);
817        self.validity_end.apply(update.validity_end);
818        self.function_params.apply(update.function_params);
819        self.trigger.apply(update.trigger);
820        self.can_be_executed.apply(update.can_be_executed);
821    }
822}
823
824impl Applicable<AsyncMessageUpdate> for AsyncMessage {
825    /// extends the `AsyncMessage` with a `AsyncMessageUpdate`
826    fn apply(&mut self, update: AsyncMessageUpdate) {
827        update.emission_slot.apply_to(&mut self.emission_slot);
828        update.emission_index.apply_to(&mut self.emission_index);
829        update.sender.apply_to(&mut self.sender);
830        update.destination.apply_to(&mut self.destination);
831        update.function.apply_to(&mut self.function);
832        update.max_gas.apply_to(&mut self.max_gas);
833        update.fee.apply_to(&mut self.fee);
834        update.coins.apply_to(&mut self.coins);
835        update.validity_start.apply_to(&mut self.validity_start);
836        update.validity_end.apply_to(&mut self.validity_end);
837        update.function_params.apply_to(&mut self.function_params);
838        update.trigger.apply_to(&mut self.trigger);
839        update.can_be_executed.apply_to(&mut self.can_be_executed);
840    }
841}
842
843#[cfg(test)]
844mod tests {
845    use crate::{
846        async_msg::{
847            AsyncMessage, AsyncMessageDeserializer, AsyncMessageSerializer, AsyncMessageTrigger,
848            AsyncMessageUpdate, AsyncMessageUpdateDeserializer, AsyncMessageUpdateSerializer,
849        },
850        async_msg_id::{AsyncMessageId, AsyncMessageIdDeserializer, AsyncMessageIdSerializer},
851        types::{Applicable, SetOrKeep},
852    };
853    use massa_serialization::{DeserializeError, Deserializer, Serializer};
854    use num::rational::Ratio;
855
856    use crate::{
857        address::Address,
858        amount::Amount,
859        config::{
860            MAX_DATASTORE_KEY_LENGTH, MAX_FUNCTION_NAME_LENGTH, MAX_PARAMETERS_SIZE, THREAD_COUNT,
861        },
862        slot::Slot,
863    };
864    use std::str::FromStr;
865
866    #[test]
867    fn no_apply_update_message() {
868        // Init an AsyncMessage, try to apply an update (with no modifications at all)
869        // Original async message and 'updated' async message should be ==
870
871        let mut msg = AsyncMessage {
872            emission_slot: Slot::new(0, 0),
873            emission_index: 0,
874            sender: Address::from_str("AU12dG5xP1RDEB5ocdHkymNVvvSJmUL9BgHwCksDowqmGWxfpm93x")
875                .unwrap(),
876            destination: Address::from_str("AU12htxRWiEm8jDJpJptr6cwEhWNcCSFWstN1MLSa96DDkVM9Y42G")
877                .unwrap(),
878            function: String::from(""),
879            max_gas: 0,
880            fee: Amount::from_str("0").unwrap(),
881            coins: Amount::from_str("0").unwrap(),
882            validity_start: Slot::new(0, 0),
883            validity_end: Slot::new(0, 0),
884            function_params: vec![],
885            trigger: None,
886            can_be_executed: false,
887        };
888        let old_message = msg.clone();
889
890        let update = AsyncMessageUpdate {
891            emission_slot: SetOrKeep::Keep,
892            emission_index: SetOrKeep::Keep,
893            sender: SetOrKeep::Keep,
894            destination: SetOrKeep::Keep,
895            function: SetOrKeep::Keep,
896            max_gas: SetOrKeep::Keep,
897            fee: SetOrKeep::Keep,
898            coins: SetOrKeep::Keep,
899            validity_start: SetOrKeep::Keep,
900            validity_end: SetOrKeep::Keep,
901            function_params: SetOrKeep::Keep,
902            trigger: SetOrKeep::Keep,
903            can_be_executed: SetOrKeep::Keep,
904        };
905        msg.apply(update);
906        assert_eq!(old_message, msg);
907    }
908
909    #[test]
910    fn apply_update_message() {
911        // Init an AsyncMessage, try to apply an update (with modifications for all fields)
912        // Original async message and 'updated' async message should be !=
913
914        let mut msg = AsyncMessage {
915            emission_slot: Slot::new(0, 0),
916            emission_index: 0,
917            sender: Address::from_str("AU12dG5xP1RDEB5ocdHkymNVvvSJmUL9BgHwCksDowqmGWxfpm93x")
918                .unwrap(),
919            destination: Address::from_str("AU12htxRWiEm8jDJpJptr6cwEhWNcCSFWstN1MLSa96DDkVM9Y42G")
920                .unwrap(),
921            function: String::from(""),
922            max_gas: 0,
923            fee: Amount::from_str("0").unwrap(),
924            coins: Amount::from_str("0").unwrap(),
925            validity_start: Slot::new(0, 0),
926            validity_end: Slot::new(0, 0),
927            function_params: vec![],
928            trigger: None,
929            can_be_executed: false,
930        };
931        let old_message = msg.clone();
932
933        let update = AsyncMessageUpdate {
934            emission_slot: SetOrKeep::Set(Slot::new(u64::MAX, THREAD_COUNT - 1)),
935            emission_index: SetOrKeep::Set(u64::MAX),
936            sender: SetOrKeep::Set(
937                Address::from_str("AU12dG5xP1RDEB5ocdHkymNVvvSJmUL9BgHwCksDowqmGWxfpm93x").unwrap(),
938            ),
939            destination: SetOrKeep::Set(
940                Address::from_str("AU12htxRWiEm8jDJpJptr6cwEhWNcCSFWstN1MLSa96DDkVM9Y42G").unwrap(),
941            ),
942            function: SetOrKeep::Set(
943                (0..MAX_FUNCTION_NAME_LENGTH)
944                    .map(|_| "X")
945                    .collect::<String>(),
946            ),
947            max_gas: SetOrKeep::Set(u64::MAX),
948            fee: SetOrKeep::Set(Amount::from_raw(u64::MAX)),
949            coins: SetOrKeep::Set(Amount::from_raw(u64::MAX)),
950            validity_start: SetOrKeep::Set(Slot::new(u64::MAX, THREAD_COUNT - 1)),
951            validity_end: SetOrKeep::Set(Slot::new(u64::MAX, THREAD_COUNT - 1)),
952            function_params: SetOrKeep::Set(vec![0; MAX_PARAMETERS_SIZE as usize]),
953            trigger: SetOrKeep::Set(Some(AsyncMessageTrigger {
954                address: Address::from_str("AU12dG5xP1RDEB5ocdHkymNVvvSJmUL9BgHwCksDowqmGWxfpm93x")
955                    .unwrap(),
956                datastore_key: Some(vec![0; MAX_DATASTORE_KEY_LENGTH as usize]),
957            })),
958            can_be_executed: SetOrKeep::Set(true),
959        };
960        msg.apply(update);
961
962        assert_ne!(old_message, msg);
963
964        let new_msg = AsyncMessage {
965            emission_slot: Slot::new(u64::MAX, THREAD_COUNT - 1),
966            emission_index: u64::MAX,
967            sender: Address::from_str("AU12dG5xP1RDEB5ocdHkymNVvvSJmUL9BgHwCksDowqmGWxfpm93x")
968                .unwrap(),
969            destination: Address::from_str("AU12htxRWiEm8jDJpJptr6cwEhWNcCSFWstN1MLSa96DDkVM9Y42G")
970                .unwrap(),
971            function: (0..MAX_FUNCTION_NAME_LENGTH)
972                .map(|_| "X")
973                .collect::<String>(),
974            max_gas: u64::MAX,
975            fee: Amount::from_raw(u64::MAX),
976            coins: Amount::from_raw(u64::MAX),
977            validity_start: Slot::new(u64::MAX, THREAD_COUNT - 1),
978            validity_end: Slot::new(u64::MAX, THREAD_COUNT - 1),
979            function_params: vec![0; MAX_PARAMETERS_SIZE as usize],
980            trigger: Some(AsyncMessageTrigger {
981                address: Address::from_str("AU12dG5xP1RDEB5ocdHkymNVvvSJmUL9BgHwCksDowqmGWxfpm93x")
982                    .unwrap(),
983                datastore_key: Some(vec![0; MAX_DATASTORE_KEY_LENGTH as usize]),
984            }),
985            can_be_executed: true,
986        };
987        assert_eq!(new_msg, msg);
988    }
989
990    #[test]
991    fn apply_update_on_update_message() {
992        // Apply AsyncMessageUpdate on a AsyncMessageUpdate then apply to an AsyncMessage
993
994        let mut msg = AsyncMessage {
995            emission_slot: Slot::new(0, 0),
996            emission_index: 0,
997            sender: Address::from_str("AU12dG5xP1RDEB5ocdHkymNVvvSJmUL9BgHwCksDowqmGWxfpm93x")
998                .unwrap(),
999            destination: Address::from_str("AU12htxRWiEm8jDJpJptr6cwEhWNcCSFWstN1MLSa96DDkVM9Y42G")
1000                .unwrap(),
1001            function: String::from(""),
1002            max_gas: 0,
1003            fee: Amount::from_str("0").unwrap(),
1004            coins: Amount::from_str("0").unwrap(),
1005            validity_start: Slot::new(0, 0),
1006            validity_end: Slot::new(0, 0),
1007            function_params: vec![],
1008            trigger: None,
1009            can_be_executed: false,
1010        };
1011
1012        let mut update = AsyncMessageUpdate {
1013            emission_slot: SetOrKeep::Keep,
1014            emission_index: SetOrKeep::Keep,
1015            sender: SetOrKeep::Keep,
1016            destination: SetOrKeep::Keep,
1017            function: SetOrKeep::Keep,
1018            max_gas: SetOrKeep::Keep,
1019            fee: SetOrKeep::Keep,
1020            coins: SetOrKeep::Keep,
1021            validity_start: SetOrKeep::Keep,
1022            validity_end: SetOrKeep::Keep,
1023            function_params: SetOrKeep::Keep,
1024            trigger: SetOrKeep::Keep,
1025            can_be_executed: SetOrKeep::Keep,
1026        };
1027
1028        let update_update = AsyncMessageUpdate {
1029            emission_slot: SetOrKeep::Set(Slot::new(u64::MAX, THREAD_COUNT - 1)),
1030            emission_index: SetOrKeep::Set(u64::MAX),
1031            sender: SetOrKeep::Set(
1032                Address::from_str("AU12dG5xP1RDEB5ocdHkymNVvvSJmUL9BgHwCksDowqmGWxfpm93x").unwrap(),
1033            ),
1034            destination: SetOrKeep::Set(
1035                Address::from_str("AU12htxRWiEm8jDJpJptr6cwEhWNcCSFWstN1MLSa96DDkVM9Y42G").unwrap(),
1036            ),
1037            function: SetOrKeep::Set(
1038                (0..MAX_FUNCTION_NAME_LENGTH)
1039                    .map(|_| "X")
1040                    .collect::<String>(),
1041            ),
1042            max_gas: SetOrKeep::Set(u64::MAX),
1043            fee: SetOrKeep::Set(Amount::from_raw(u64::MAX)),
1044            coins: SetOrKeep::Set(Amount::from_raw(u64::MAX)),
1045            validity_start: SetOrKeep::Set(Slot::new(u64::MAX, THREAD_COUNT - 1)),
1046            validity_end: SetOrKeep::Set(Slot::new(u64::MAX, THREAD_COUNT - 1)),
1047            function_params: SetOrKeep::Set(vec![0; MAX_PARAMETERS_SIZE as usize]),
1048            trigger: SetOrKeep::Set(Some(AsyncMessageTrigger {
1049                address: Address::from_str("AU12dG5xP1RDEB5ocdHkymNVvvSJmUL9BgHwCksDowqmGWxfpm93x")
1050                    .unwrap(),
1051                datastore_key: Some(vec![0; MAX_DATASTORE_KEY_LENGTH as usize]),
1052            })),
1053            can_be_executed: SetOrKeep::Set(true),
1054        };
1055
1056        update.apply(update_update);
1057
1058        msg.apply(update);
1059
1060        let new_msg = AsyncMessage {
1061            emission_slot: Slot::new(u64::MAX, THREAD_COUNT - 1),
1062            emission_index: u64::MAX,
1063            sender: Address::from_str("AU12dG5xP1RDEB5ocdHkymNVvvSJmUL9BgHwCksDowqmGWxfpm93x")
1064                .unwrap(),
1065            destination: Address::from_str("AU12htxRWiEm8jDJpJptr6cwEhWNcCSFWstN1MLSa96DDkVM9Y42G")
1066                .unwrap(),
1067            function: (0..MAX_FUNCTION_NAME_LENGTH)
1068                .map(|_| "X")
1069                .collect::<String>(),
1070            max_gas: u64::MAX,
1071            fee: Amount::from_raw(u64::MAX),
1072            coins: Amount::from_raw(u64::MAX),
1073            validity_start: Slot::new(u64::MAX, THREAD_COUNT - 1),
1074            validity_end: Slot::new(u64::MAX, THREAD_COUNT - 1),
1075            function_params: vec![0; MAX_PARAMETERS_SIZE as usize],
1076            trigger: Some(AsyncMessageTrigger {
1077                address: Address::from_str("AU12dG5xP1RDEB5ocdHkymNVvvSJmUL9BgHwCksDowqmGWxfpm93x")
1078                    .unwrap(),
1079                datastore_key: Some(vec![0; MAX_DATASTORE_KEY_LENGTH as usize]),
1080            }),
1081            can_be_executed: true,
1082        };
1083
1084        assert_eq!(new_msg, msg);
1085    }
1086
1087    #[test]
1088    fn lower_limit_ser_deser_id() {
1089        // Serialize then Deserialize an AsyncMessageId (with lowest values)
1090
1091        let id: AsyncMessageId = (std::cmp::Reverse(Ratio::new(0, 1)), Slot::new(0, 0), 0);
1092
1093        let mut buffer = Vec::new();
1094        let serializer = AsyncMessageIdSerializer::new();
1095        serializer.serialize(&id, &mut buffer).unwrap();
1096        let deserializer = AsyncMessageIdDeserializer::new(32);
1097        let (rest, deserialized) = deserializer
1098            .deserialize::<DeserializeError>(&buffer)
1099            .unwrap();
1100        assert!(rest.is_empty());
1101        assert_eq!(id, deserialized);
1102    }
1103
1104    #[test]
1105    fn higher_limit_ser_deser_id() {
1106        // Serialize then Deserialize an AsyncMessageId (with highest values)
1107
1108        let id: AsyncMessageId = (
1109            std::cmp::Reverse(Ratio::new(u64::MAX, u64::MAX)),
1110            Slot::new(u64::MAX, THREAD_COUNT - 1),
1111            u64::MAX,
1112        );
1113
1114        let mut buffer = Vec::new();
1115        let serializer = AsyncMessageIdSerializer::new();
1116        serializer.serialize(&id, &mut buffer).unwrap();
1117        let deserializer = AsyncMessageIdDeserializer::new(32);
1118        let (rest, deserialized) = deserializer
1119            .deserialize::<DeserializeError>(&buffer)
1120            .unwrap();
1121        assert!(rest.is_empty());
1122        assert_eq!(id, deserialized);
1123    }
1124
1125    #[test]
1126    fn wrong_denom_ser_deser_id() {
1127        let id: AsyncMessageId = (
1128            // Ratio with 0 as a denominator -> will fail to deserialize
1129            std::cmp::Reverse(Ratio::new_raw(u64::MAX, 0)),
1130            Slot::new(u64::MAX, THREAD_COUNT - 1),
1131            u64::MAX,
1132        );
1133
1134        let mut buffer = Vec::new();
1135        let serializer = AsyncMessageIdSerializer::new();
1136        serializer.serialize(&id, &mut buffer).unwrap();
1137        let deserializer = AsyncMessageIdDeserializer::new(32);
1138        let _ = deserializer
1139            .deserialize::<DeserializeError>(&buffer)
1140            .expect_err("Failed to deserialize");
1141    }
1142
1143    #[test]
1144    fn lower_limit_ser_deser_message() {
1145        // Serialize then Deserialize an AsyncMessage (with lowest values)
1146
1147        let msg = AsyncMessage {
1148            emission_slot: Slot::new(0, 0),
1149            emission_index: 0,
1150            sender: Address::from_str("AU12dG5xP1RDEB5ocdHkymNVvvSJmUL9BgHwCksDowqmGWxfpm93x")
1151                .unwrap(),
1152            destination: Address::from_str("AU12htxRWiEm8jDJpJptr6cwEhWNcCSFWstN1MLSa96DDkVM9Y42G")
1153                .unwrap(),
1154            function: String::from(""),
1155            max_gas: 0,
1156            fee: Amount::from_str("0").unwrap(),
1157            coins: Amount::from_str("0").unwrap(),
1158            validity_start: Slot::new(0, 0),
1159            validity_end: Slot::new(0, 0),
1160            function_params: vec![],
1161            trigger: None,
1162            can_be_executed: false,
1163        };
1164
1165        let mut buffer = Vec::new();
1166        let serializer = AsyncMessageSerializer::new(true);
1167        serializer.serialize(&msg, &mut buffer).unwrap();
1168        let deserializer = AsyncMessageDeserializer::new(
1169            THREAD_COUNT,
1170            MAX_FUNCTION_NAME_LENGTH,
1171            MAX_PARAMETERS_SIZE as u64,
1172            MAX_DATASTORE_KEY_LENGTH as u32,
1173            true,
1174        );
1175        let (rest, deserialized) = deserializer
1176            .deserialize::<DeserializeError>(&buffer)
1177            .unwrap();
1178        assert!(rest.is_empty());
1179        assert_eq!(msg, deserialized);
1180    }
1181
1182    #[test]
1183    fn higher_limit_ser_deser_message() {
1184        // Serialize then Deserialize an AsyncMessage (with max values in most of its fields)
1185
1186        let msg = AsyncMessage {
1187            emission_slot: Slot::new(u64::MAX, THREAD_COUNT - 1),
1188            emission_index: u64::MAX,
1189            sender: Address::from_str("AU12dG5xP1RDEB5ocdHkymNVvvSJmUL9BgHwCksDowqmGWxfpm93x")
1190                .unwrap(),
1191            destination: Address::from_str("AU12htxRWiEm8jDJpJptr6cwEhWNcCSFWstN1MLSa96DDkVM9Y42G")
1192                .unwrap(),
1193            function: (0..MAX_FUNCTION_NAME_LENGTH)
1194                .map(|_| "X")
1195                .collect::<String>(),
1196            max_gas: u64::MAX,
1197            fee: Amount::from_raw(u64::MAX),
1198            coins: Amount::from_raw(u64::MAX),
1199            validity_start: Slot::new(u64::MAX, THREAD_COUNT - 1),
1200            validity_end: Slot::new(u64::MAX, THREAD_COUNT - 1),
1201            function_params: vec![0; MAX_PARAMETERS_SIZE as usize],
1202            trigger: Some(AsyncMessageTrigger {
1203                address: Address::from_str("AU12dG5xP1RDEB5ocdHkymNVvvSJmUL9BgHwCksDowqmGWxfpm93x")
1204                    .unwrap(),
1205                datastore_key: Some(vec![0; MAX_DATASTORE_KEY_LENGTH as usize]),
1206            }),
1207            can_be_executed: true,
1208        };
1209
1210        let mut buffer = Vec::new();
1211        let serializer = AsyncMessageSerializer::new(true);
1212        serializer.serialize(&msg, &mut buffer).unwrap();
1213        let deserializer = AsyncMessageDeserializer::new(
1214            THREAD_COUNT,
1215            MAX_FUNCTION_NAME_LENGTH,
1216            MAX_PARAMETERS_SIZE as u64,
1217            MAX_DATASTORE_KEY_LENGTH as u32,
1218            true,
1219        );
1220        let (rest, deserialized) = deserializer
1221            .deserialize::<DeserializeError>(&buffer)
1222            .unwrap();
1223        assert!(rest.is_empty());
1224        assert_eq!(msg, deserialized);
1225    }
1226
1227    #[test]
1228    fn lower_limit_ser_deser_message_update() {
1229        let msg = AsyncMessageUpdate {
1230            emission_slot: SetOrKeep::Keep,
1231            emission_index: SetOrKeep::Keep,
1232            sender: SetOrKeep::Keep,
1233            destination: SetOrKeep::Keep,
1234            function: SetOrKeep::Keep,
1235            max_gas: SetOrKeep::Keep,
1236            fee: SetOrKeep::Keep,
1237            coins: SetOrKeep::Keep,
1238            validity_start: SetOrKeep::Keep,
1239            validity_end: SetOrKeep::Keep,
1240            function_params: SetOrKeep::Keep,
1241            trigger: SetOrKeep::Keep,
1242            can_be_executed: SetOrKeep::Keep,
1243        };
1244
1245        let mut buffer = Vec::new();
1246        let serializer = AsyncMessageUpdateSerializer::new(true);
1247        serializer.serialize(&msg, &mut buffer).unwrap();
1248        let deserializer = AsyncMessageUpdateDeserializer::new(
1249            THREAD_COUNT,
1250            MAX_FUNCTION_NAME_LENGTH,
1251            MAX_PARAMETERS_SIZE as u64,
1252            MAX_DATASTORE_KEY_LENGTH as u32,
1253            true,
1254        );
1255        let (rest, deserialized) = deserializer
1256            .deserialize::<DeserializeError>(&buffer)
1257            .unwrap();
1258        assert!(rest.is_empty());
1259        assert_eq!(msg, deserialized);
1260    }
1261
1262    #[test]
1263    fn higher_limit_ser_deser_message_update() {
1264        let msg = AsyncMessageUpdate {
1265            emission_slot: SetOrKeep::Set(Slot::new(u64::MAX, THREAD_COUNT - 1)),
1266            emission_index: SetOrKeep::Set(u64::MAX),
1267            sender: SetOrKeep::Set(
1268                Address::from_str("AU12dG5xP1RDEB5ocdHkymNVvvSJmUL9BgHwCksDowqmGWxfpm93x").unwrap(),
1269            ),
1270            destination: SetOrKeep::Set(
1271                Address::from_str("AU12htxRWiEm8jDJpJptr6cwEhWNcCSFWstN1MLSa96DDkVM9Y42G").unwrap(),
1272            ),
1273            function: SetOrKeep::Set(
1274                (0..MAX_FUNCTION_NAME_LENGTH)
1275                    .map(|_| "X")
1276                    .collect::<String>(),
1277            ),
1278            max_gas: SetOrKeep::Set(u64::MAX),
1279            fee: SetOrKeep::Set(Amount::from_raw(u64::MAX)),
1280            coins: SetOrKeep::Set(Amount::from_raw(u64::MAX)),
1281            validity_start: SetOrKeep::Set(Slot::new(u64::MAX, THREAD_COUNT - 1)),
1282            validity_end: SetOrKeep::Set(Slot::new(u64::MAX, THREAD_COUNT - 1)),
1283            function_params: SetOrKeep::Set(vec![0; MAX_PARAMETERS_SIZE as usize]),
1284            trigger: SetOrKeep::Set(Some(AsyncMessageTrigger {
1285                address: Address::from_str("AU12dG5xP1RDEB5ocdHkymNVvvSJmUL9BgHwCksDowqmGWxfpm93x")
1286                    .unwrap(),
1287                datastore_key: Some(vec![0; MAX_DATASTORE_KEY_LENGTH as usize]),
1288            })),
1289            can_be_executed: SetOrKeep::Set(true),
1290        };
1291
1292        let mut buffer = Vec::new();
1293        let serializer = AsyncMessageUpdateSerializer::new(true);
1294        serializer.serialize(&msg, &mut buffer).unwrap();
1295        let deserializer = AsyncMessageUpdateDeserializer::new(
1296            THREAD_COUNT,
1297            MAX_FUNCTION_NAME_LENGTH,
1298            MAX_PARAMETERS_SIZE as u64,
1299            MAX_DATASTORE_KEY_LENGTH as u32,
1300            true,
1301        );
1302        let (rest, deserialized) = deserializer
1303            .deserialize::<DeserializeError>(&buffer)
1304            .unwrap();
1305        assert!(rest.is_empty());
1306        assert_eq!(msg, deserialized);
1307    }
1308
1309    #[test]
1310    fn bad_serialization_message() {
1311        // Serialize an AsyncMessage, write some crap in the result and try to deserialize it
1312
1313        let message = AsyncMessage::new(
1314            Slot::new(1, 2),
1315            0,
1316            Address::from_str("AU12dG5xP1RDEB5ocdHkymNVvvSJmUL9BgHwCksDowqmGWxfpm93x").unwrap(),
1317            Address::from_str("AU12htxRWiEm8jDJpJptr6cwEhWNcCSFWstN1MLSa96DDkVM9Y42G").unwrap(),
1318            String::from("test"),
1319            10000000,
1320            Amount::from_str("1").unwrap(),
1321            Amount::from_str("1").unwrap(),
1322            Slot::new(2, 0),
1323            Slot::new(3, 0),
1324            vec![1, 2, 3, 4],
1325            Some(AsyncMessageTrigger {
1326                address: Address::from_str("AU12htxRWiEm8jDJpJptr6cwEhWNcCSFWstN1MLSa96DDkVM9Y42G")
1327                    .unwrap(),
1328                datastore_key: None,
1329            }),
1330            None,
1331        );
1332        let message_serializer = AsyncMessageSerializer::new(false);
1333        let mut serialized = Vec::new();
1334        message_serializer
1335            .serialize(&message, &mut serialized)
1336            .unwrap();
1337        let message_deserializer = AsyncMessageDeserializer::new(
1338            THREAD_COUNT,
1339            MAX_FUNCTION_NAME_LENGTH,
1340            MAX_PARAMETERS_SIZE as u64,
1341            MAX_DATASTORE_KEY_LENGTH as u32,
1342            false,
1343        );
1344        // Will break the deserialization
1345        serialized[1] = 50;
1346        message_deserializer
1347            .deserialize::<DeserializeError>(&serialized)
1348            .unwrap_err();
1349    }
1350}