massa_versioning/
versioning_ser_der.rs

1use std::collections::BTreeMap;
2use std::ops::Bound::{Excluded, Included};
3
4use nom::{
5    bytes::complete::take,
6    error::context,
7    error::{ContextError, ParseError},
8    multi::length_count,
9    sequence::tuple,
10    IResult, Parser,
11};
12use num::rational::Ratio;
13
14use crate::versioning::{
15    Active, AdvanceLW, ComponentState, ComponentStateTypeId, LockedIn, MipComponent, MipInfo,
16    MipState, MipStatsConfig, MipStoreRaw, MipStoreStats, Started,
17};
18
19use massa_models::config::MIP_STORE_STATS_BLOCK_CONSIDERED;
20use massa_serialization::{
21    Deserializer, RatioDeserializer, RatioSerializer, SerializeError, Serializer,
22    U32VarIntDeserializer, U32VarIntSerializer, U64VarIntDeserializer, U64VarIntSerializer,
23};
24use massa_time::{MassaTime, MassaTimeDeserializer, MassaTimeSerializer};
25
26// Ser / Der
27
28const MIP_INFO_NAME_MAX_LEN: u32 = 255;
29const MIP_INFO_COMPONENTS_MAX_ENTRIES: u32 = 8;
30const COMPONENT_STATE_VARIANT_COUNT: u32 = ComponentStateTypeId::VARIANT_COUNT as u32;
31const COMPONENT_STATE_ID_VARIANT_COUNT: u32 = ComponentStateTypeId::VARIANT_COUNT as u32;
32const MIP_STORE_MAX_ENTRIES: u32 = 4096;
33#[allow(dead_code)]
34const MIP_STORE_MAX_SIZE: usize = 2097152;
35
36/// Serializer for `MipInfo`
37pub struct MipInfoSerializer {
38    u32_serializer: U32VarIntSerializer,
39    time_serializer: MassaTimeSerializer, // start / timeout
40}
41
42impl MipInfoSerializer {
43    /// Creates a new `Serializer`
44    pub fn new() -> Self {
45        MipInfoSerializer {
46            u32_serializer: U32VarIntSerializer::new(),
47            time_serializer: MassaTimeSerializer::new(),
48        }
49    }
50}
51
52impl Default for MipInfoSerializer {
53    fn default() -> Self {
54        Self::new()
55    }
56}
57
58impl Serializer<MipInfo> for MipInfoSerializer {
59    fn serialize(&self, value: &MipInfo, buffer: &mut Vec<u8>) -> Result<(), SerializeError> {
60        // name
61        let name_len_ = value.name.len();
62        let name_len = u32::try_from(name_len_).map_err(|_| {
63            SerializeError::GeneralError(format!("Cannot convert name_len ({}) to u32", name_len_))
64        })?;
65        self.u32_serializer.serialize(&name_len, buffer)?;
66        buffer.extend(value.name.as_bytes());
67        // version
68        self.u32_serializer.serialize(&value.version, buffer)?;
69
70        // Components
71        let components_len_ = value.components.len();
72        let components_len = u32::try_from(components_len_).map_err(|_| {
73            SerializeError::GeneralError(format!(
74                "Cannot convert component_len ({}) to u32",
75                components_len_
76            ))
77        })?;
78        // ser hashmap len
79        self.u32_serializer.serialize(&components_len, buffer)?;
80        // ser hashmap items
81        for (component, component_version) in value.components.iter() {
82            // component
83            self.u32_serializer
84                .serialize(&component.clone().into(), buffer)?;
85            // component version
86            self.u32_serializer.serialize(component_version, buffer)?;
87        }
88
89        // start
90        self.time_serializer.serialize(&value.start, buffer)?;
91        // timeout
92        self.time_serializer.serialize(&value.timeout, buffer)?;
93        // activation delay
94        self.time_serializer
95            .serialize(&value.activation_delay, buffer)?;
96        Ok(())
97    }
98}
99
100/// Deserializer for `MipInfo`
101pub struct MipInfoDeserializer {
102    u32_deserializer: U32VarIntDeserializer,
103    name_len_deserializer: U32VarIntDeserializer,
104    components_len_deserializer: U32VarIntDeserializer,
105    time_deserializer: MassaTimeDeserializer,
106}
107
108impl MipInfoDeserializer {
109    /// Creates a new `MipInfoDeserializer`
110    pub fn new() -> Self {
111        Self {
112            u32_deserializer: U32VarIntDeserializer::new(Included(0), Excluded(u32::MAX)),
113            name_len_deserializer: U32VarIntDeserializer::new(
114                Included(0),
115                Included(MIP_INFO_NAME_MAX_LEN),
116            ),
117            components_len_deserializer: U32VarIntDeserializer::new(
118                Included(0),
119                Included(MIP_INFO_COMPONENTS_MAX_ENTRIES),
120            ),
121            time_deserializer: MassaTimeDeserializer::new((
122                Included(MassaTime::from_millis(0)),
123                Included(MassaTime::from_millis(u64::MAX)),
124            )),
125        }
126    }
127}
128
129// Make clippy happy again!
130impl Default for MipInfoDeserializer {
131    fn default() -> Self {
132        Self::new()
133    }
134}
135
136impl Deserializer<MipInfo> for MipInfoDeserializer {
137    fn deserialize<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
138        &self,
139        buffer: &'a [u8],
140    ) -> IResult<&'a [u8], MipInfo, E> {
141        context(
142            "Failed MipInfo deserialization",
143            tuple((
144                context("Failed name deserialization", |input| {
145                    // Note: this is bounded to MIP_INFO_NAME_MAX_LEN
146                    let (input_, len_) = self.name_len_deserializer.deserialize(input)?;
147                    // Safe to unwrap as it returns Result<usize, Infallible>
148                    let len = usize::try_from(len_).unwrap();
149                    let (rem, slice) = take(len)(input_)?;
150                    let name = String::from_utf8(slice.to_vec()).map_err(|_| {
151                        nom::Err::Error(ParseError::from_error_kind(
152                            input_,
153                            nom::error::ErrorKind::Fail,
154                        ))
155                    })?;
156                    IResult::Ok((rem, name))
157                }),
158                context("Failed version deserialization", |input| {
159                    self.u32_deserializer.deserialize(input)
160                }),
161                context(
162                    "Failed components deserialization",
163                    length_count(
164                        context("Failed components length deserialization", |input| {
165                            // Note: this is bounded to MIP_INFO_COMPONENTS_MAX_ENTRIES
166                            self.components_len_deserializer.deserialize(input)
167                        }),
168                        tuple((
169                            context("Failed component deserialization", |input| {
170                                let (rem, component_) = self.u32_deserializer.deserialize(input)?;
171                                let component = MipComponent::from(component_);
172                                IResult::Ok((rem, component))
173                            }),
174                            context("Failed component version deserialization", |input| {
175                                self.u32_deserializer.deserialize(input)
176                            }),
177                        )),
178                    ),
179                ),
180                context("Failed start deserialization", |input| {
181                    self.time_deserializer.deserialize(input)
182                }),
183                context("Failed timeout deserialization", |input| {
184                    self.time_deserializer.deserialize(input)
185                }),
186                context("Failed activation delay deserialization", |input| {
187                    self.time_deserializer.deserialize(input)
188                }),
189            )),
190        )
191        .map(
192            |(name, version, components, start, timeout, activation_delay)| MipInfo {
193                name,
194                version,
195                components: components.into_iter().collect(),
196                start,
197                timeout,
198                activation_delay,
199            },
200        )
201        .parse(buffer)
202    }
203}
204
205// End MipInfo
206
207// ComponentState
208
209/// Serializer for `ComponentState`
210pub struct ComponentStateSerializer {
211    u32_serializer: U32VarIntSerializer,
212    ratio_serializer: RatioSerializer<u64, U64VarIntSerializer>,
213    time_serializer: MassaTimeSerializer,
214}
215
216impl ComponentStateSerializer {
217    /// Creates a new `Serializer`
218    pub fn new() -> Self {
219        Self {
220            u32_serializer: U32VarIntSerializer::new(),
221            ratio_serializer: RatioSerializer::new(U64VarIntSerializer::new()),
222            time_serializer: MassaTimeSerializer::new(),
223        }
224    }
225}
226
227impl Default for ComponentStateSerializer {
228    fn default() -> Self {
229        Self::new()
230    }
231}
232
233impl Serializer<ComponentState> for ComponentStateSerializer {
234    fn serialize(
235        &self,
236        value: &ComponentState,
237        buffer: &mut Vec<u8>,
238    ) -> Result<(), SerializeError> {
239        let state_id = u32::from(ComponentStateTypeId::from(value));
240        self.u32_serializer.serialize(&state_id, buffer)?;
241        match value {
242            ComponentState::Started(Started {
243                vote_ratio: threshold,
244            }) => {
245                // self.amount_serializer.serialize(threshold, buffer)?;
246                self.ratio_serializer.serialize(threshold, buffer)?;
247            }
248            ComponentState::LockedIn(LockedIn { at }) => {
249                self.time_serializer.serialize(at, buffer)?;
250            }
251            ComponentState::Active(Active { at }) => {
252                self.time_serializer.serialize(at, buffer)?;
253            }
254            _ => {}
255        }
256        Ok(())
257    }
258}
259
260/// A Deserializer for ComponentState`
261pub struct ComponentStateDeserializer {
262    state_deserializer: U32VarIntDeserializer,
263    ratio_deserializer: RatioDeserializer<u64, U64VarIntDeserializer>,
264    time_deserializer: MassaTimeDeserializer,
265}
266
267impl ComponentStateDeserializer {
268    /// Creates a new ``
269    pub fn new() -> Self {
270        Self {
271            state_deserializer: U32VarIntDeserializer::new(
272                Included(0),
273                Excluded(COMPONENT_STATE_VARIANT_COUNT),
274            ),
275            ratio_deserializer: RatioDeserializer::new(U64VarIntDeserializer::new(
276                Included(0),
277                Included(u64::MAX),
278            )),
279            time_deserializer: MassaTimeDeserializer::new((
280                Included(MassaTime::from_millis(0)),
281                Included(MassaTime::from_millis(u64::MAX)),
282            )),
283        }
284    }
285}
286
287impl Default for ComponentStateDeserializer {
288    fn default() -> Self {
289        Self::new()
290    }
291}
292
293impl Deserializer<ComponentState> for ComponentStateDeserializer {
294    fn deserialize<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
295        &self,
296        buffer: &'a [u8],
297    ) -> IResult<&'a [u8], ComponentState, E> {
298        let (rem, enum_value_) = context("Failed enum value der", |input| {
299            self.state_deserializer.deserialize(input)
300        })
301        .parse(buffer)?;
302
303        let enum_value = ComponentStateTypeId::try_from(enum_value_).map_err(|_| {
304            nom::Err::Error(ParseError::from_error_kind(
305                buffer,
306                nom::error::ErrorKind::Eof,
307            ))
308        })?;
309        let (rem2, state): (&[u8], ComponentState) = match enum_value {
310            ComponentStateTypeId::Defined => (rem, ComponentState::defined()),
311            ComponentStateTypeId::Started => {
312                let (rem2, threshold) = context("Failed threshold value der", |input| {
313                    self.ratio_deserializer.deserialize(input)
314                })
315                .parse(rem)?;
316                (rem2, ComponentState::started(threshold))
317            }
318            ComponentStateTypeId::LockedIn => {
319                let (rem2, at) = context("Failed delay value der", |input| {
320                    self.time_deserializer.deserialize(input)
321                })
322                .parse(rem)?;
323                (rem2, ComponentState::locked_in(at))
324            }
325            ComponentStateTypeId::Active => {
326                let (rem2, at) = context("Failed at value der", |input| {
327                    self.time_deserializer.deserialize(input)
328                })
329                .parse(rem)?;
330                (rem2, ComponentState::active(at))
331            }
332            ComponentStateTypeId::Failed => (rem, ComponentState::failed()),
333            _ => (rem, ComponentState::Error),
334        };
335
336        IResult::Ok((rem2, state))
337    }
338}
339
340// End ComponentState
341
342// AdvanceLW
343
344/// Serializer for `AdvanceLW`
345pub struct AdvanceLWSerializer {
346    ratio_serializer: RatioSerializer<u64, U64VarIntSerializer>,
347    time_serializer: MassaTimeSerializer,
348}
349
350impl AdvanceLWSerializer {
351    /// Creates a new `Serializer`
352    pub fn new() -> Self {
353        Self {
354            ratio_serializer: RatioSerializer::new(U64VarIntSerializer::new()),
355            time_serializer: MassaTimeSerializer::new(),
356        }
357    }
358}
359
360impl Default for AdvanceLWSerializer {
361    fn default() -> Self {
362        Self::new()
363    }
364}
365
366impl Serializer<AdvanceLW> for AdvanceLWSerializer {
367    fn serialize(&self, value: &AdvanceLW, buffer: &mut Vec<u8>) -> Result<(), SerializeError> {
368        // vote ratio
369        self.ratio_serializer.serialize(&value.threshold, buffer)?;
370        // now
371        self.time_serializer.serialize(&value.now, buffer)?;
372        Ok(())
373    }
374}
375
376/// A Deserializer for `AdvanceLW`
377pub struct AdvanceLWDeserializer {
378    ratio_deserializer: RatioDeserializer<u64, U64VarIntDeserializer>,
379    time_deserializer: MassaTimeDeserializer,
380}
381
382impl AdvanceLWDeserializer {
383    /// Creates a new `AdvanceLWDeserializer`
384    pub fn new() -> Self {
385        Self {
386            ratio_deserializer: RatioDeserializer::new(U64VarIntDeserializer::new(
387                Included(0),
388                Included(u64::MAX),
389            )),
390            time_deserializer: MassaTimeDeserializer::new((
391                Included(MassaTime::from_millis(0)),
392                Included(MassaTime::from_millis(u64::MAX)),
393            )),
394        }
395    }
396}
397
398impl Default for AdvanceLWDeserializer {
399    fn default() -> Self {
400        Self::new()
401    }
402}
403
404impl Deserializer<AdvanceLW> for AdvanceLWDeserializer {
405    fn deserialize<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
406        &self,
407        buffer: &'a [u8],
408    ) -> IResult<&'a [u8], AdvanceLW, E> {
409        context(
410            "Failed Advance deserialization",
411            tuple((
412                context("Failed threshold deserialization", |input| {
413                    self.ratio_deserializer.deserialize(input)
414                }),
415                context("Failed now deserialization", |input| {
416                    self.time_deserializer.deserialize(input)
417                }),
418            )),
419        )
420        .map(|(threshold, now)| AdvanceLW { threshold, now })
421        .parse(buffer)
422    }
423}
424
425// End AdvanceLW
426
427// MipState
428
429/// Serializer for `MipState`
430pub struct MipStateSerializer {
431    state_serializer: ComponentStateSerializer,
432    advance_serializer: AdvanceLWSerializer,
433    u32_serializer: U32VarIntSerializer,
434}
435
436impl MipStateSerializer {
437    /// Creates a new `MipStateSerializer`
438    pub fn new() -> Self {
439        Self {
440            state_serializer: Default::default(),
441            advance_serializer: Default::default(),
442            u32_serializer: U32VarIntSerializer,
443        }
444    }
445}
446
447impl Default for MipStateSerializer {
448    fn default() -> Self {
449        Self::new()
450    }
451}
452
453impl Serializer<MipState> for MipStateSerializer {
454    fn serialize(&self, value: &MipState, buffer: &mut Vec<u8>) -> Result<(), SerializeError> {
455        self.state_serializer.serialize(&value.state, buffer)?;
456        // history len
457        self.u32_serializer.serialize(
458            &value.history.len().try_into().map_err(|err| {
459                SerializeError::GeneralError(format!("too many history: {}", err))
460            })?,
461            buffer,
462        )?;
463        // history
464        for (advance, state_id) in value.history.iter() {
465            self.advance_serializer.serialize(advance, buffer)?;
466            self.u32_serializer
467                .serialize(&u32::from(state_id.clone()), buffer)?;
468        }
469        Ok(())
470    }
471}
472
473/// A Deserializer for `MipState`
474pub struct MipStateDeserializer {
475    state_deserializer: ComponentStateDeserializer,
476    advance_deserializer: AdvanceLWDeserializer,
477    state_id_deserializer: U32VarIntDeserializer,
478    u32_deserializer: U32VarIntDeserializer,
479}
480
481impl MipStateDeserializer {
482    /// Creates a new `MipStateDeserializer`
483    pub fn new() -> Self {
484        Self {
485            state_deserializer: ComponentStateDeserializer::new(),
486            advance_deserializer: AdvanceLWDeserializer::new(),
487            state_id_deserializer: U32VarIntDeserializer::new(
488                Included(0),
489                Excluded(COMPONENT_STATE_ID_VARIANT_COUNT),
490            ),
491            u32_deserializer: U32VarIntDeserializer::new(Included(0), Excluded(u32::MAX)),
492        }
493    }
494}
495
496impl Default for MipStateDeserializer {
497    fn default() -> Self {
498        Self::new()
499    }
500}
501
502impl Deserializer<MipState> for MipStateDeserializer {
503    fn deserialize<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
504        &self,
505        buffer: &'a [u8],
506    ) -> IResult<&'a [u8], MipState, E> {
507        // Der component state
508        let (rem, component_state) = context("Failed component state deserialization", |input| {
509            self.state_deserializer.deserialize(input)
510        })
511        .parse(buffer)?;
512        // Der history
513        let (rem2, history) = context(
514            "Failed history deserialization",
515            length_count(
516                context("Failed length deserialization", |input| {
517                    self.u32_deserializer.deserialize(input)
518                }),
519                context(
520                    "Failed history items deserialization",
521                    tuple((
522                        context("Failed advance deserialization", |input| {
523                            self.advance_deserializer.deserialize(input)
524                        }),
525                        context("Failed state id deserialization", |input| {
526                            // TEST NOTE: deser fails here for last two tests
527                            let (res, state_id_) = self.state_id_deserializer.deserialize(input)?;
528
529                            let state_id =
530                                ComponentStateTypeId::try_from(state_id_).map_err(|_e| {
531                                    nom::Err::Error(ParseError::from_error_kind(
532                                        buffer,
533                                        nom::error::ErrorKind::Fail,
534                                    ))
535                                })?;
536
537                            IResult::Ok((res, state_id))
538                        }),
539                    )),
540                ),
541            ),
542        )
543        .map(|items| {
544            items
545                .into_iter()
546                .collect::<BTreeMap<AdvanceLW, ComponentStateTypeId>>()
547        })
548        .parse(rem)?;
549
550        IResult::Ok((
551            rem2,
552            MipState {
553                state: component_state,
554                history,
555            },
556        ))
557    }
558}
559
560// End MipState
561
562// MipStoreStats
563
564/// Serializer for `VersioningStoreRaw`
565pub struct MipStoreStatsSerializer {
566    u32_serializer: U32VarIntSerializer,
567    u64_serializer: U64VarIntSerializer,
568}
569
570impl MipStoreStatsSerializer {
571    /// Creates a new `Serializer`
572    pub fn new() -> Self {
573        Self {
574            u32_serializer: U32VarIntSerializer::new(),
575            u64_serializer: U64VarIntSerializer::new(),
576        }
577    }
578}
579
580impl Default for MipStoreStatsSerializer {
581    fn default() -> Self {
582        Self::new()
583    }
584}
585
586impl Serializer<MipStoreStats> for MipStoreStatsSerializer {
587    fn serialize(&self, value: &MipStoreStats, buffer: &mut Vec<u8>) -> Result<(), SerializeError> {
588        // stats data
589        {
590            let entry_count_ = value.latest_announcements.len();
591            let entry_count = u32::try_from(entry_count_).map_err(|e| {
592                SerializeError::GeneralError(format!("Could not convert to u32: {}", e))
593            })?;
594            let entry_count_max = u32::try_from(MIP_STORE_STATS_BLOCK_CONSIDERED).map_err(|e| {
595                SerializeError::GeneralError(format!("Could not convert to u32: {}", e))
596            })?;
597
598            if entry_count > entry_count_max {
599                return Err(SerializeError::GeneralError(format!(
600                    "Too many entries in MipStoreStats latest announcements, max: {}, received: {}",
601                    entry_count_max, entry_count
602                )));
603            }
604            self.u32_serializer.serialize(&entry_count, buffer)?;
605            for v in value.latest_announcements.iter() {
606                self.u32_serializer.serialize(v, buffer)?;
607            }
608        }
609
610        {
611            let entry_count_2_ = value.network_version_counters.len();
612            let entry_count_2 = u32::try_from(entry_count_2_).map_err(|e| {
613                SerializeError::GeneralError(format!("Could not convert to u32: {}", e))
614            })?;
615            let entry_count_2_max =
616                u32::try_from(MIP_STORE_STATS_BLOCK_CONSIDERED).map_err(|e| {
617                    SerializeError::GeneralError(format!("Could not convert to u32: {}", e))
618                })?;
619
620            if entry_count_2 > entry_count_2_max {
621                return Err(SerializeError::GeneralError(format!(
622                    "Too many entries in MipStoreStats version counters, max: {}, received: {}",
623                    entry_count_2_max, entry_count_2
624                )));
625            }
626            self.u32_serializer.serialize(&entry_count_2, buffer)?;
627            for (v, c) in value.network_version_counters.iter() {
628                self.u32_serializer.serialize(v, buffer)?;
629                self.u64_serializer.serialize(c, buffer)?;
630            }
631        }
632
633        Ok(())
634    }
635}
636
637/// A Deserializer for `MipStoreStats
638pub struct MipStoreStatsDeserializer {
639    config: MipStatsConfig,
640    u32_deserializer: U32VarIntDeserializer,
641    u64_deserializer: U64VarIntDeserializer,
642}
643
644impl MipStoreStatsDeserializer {
645    /// Creates a new ``
646    pub fn new(block_count_considered: usize, warn_announced_version_ratio: Ratio<u64>) -> Self {
647        Self {
648            config: MipStatsConfig {
649                block_count_considered,
650                warn_announced_version_ratio,
651            },
652            u32_deserializer: U32VarIntDeserializer::new(Included(0), Included(u32::MAX)),
653            u64_deserializer: U64VarIntDeserializer::new(Included(0), Included(u64::MAX)),
654        }
655    }
656}
657
658impl Deserializer<MipStoreStats> for MipStoreStatsDeserializer {
659    fn deserialize<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
660        &self,
661        buffer: &'a [u8],
662    ) -> IResult<&'a [u8], MipStoreStats, E> {
663        let cfg_block_considered: u32 =
664            u32::try_from(self.config.block_count_considered).map_err(|_e| {
665                nom::Err::Error(ParseError::from_error_kind(
666                    buffer,
667                    nom::error::ErrorKind::Fail,
668                ))
669            })?;
670
671        let (rem3, latest_announcements_) = context(
672            "Failed MipStoreStats latest announcements der",
673            length_count(
674                context("Failed latest announcements count der", |input| {
675                    let (rem, count) = self.u32_deserializer.deserialize(input)?;
676                    if count > cfg_block_considered {
677                        return IResult::Err(nom::Err::Error(ParseError::from_error_kind(
678                            input,
679                            nom::error::ErrorKind::Fail,
680                        )));
681                    }
682                    IResult::Ok((rem, count))
683                }),
684                context("Failed latest announcement data der", |input| {
685                    self.u32_deserializer.deserialize(input)
686                }),
687            ),
688        )
689        .parse(buffer)?;
690
691        let (rem4, network_version_counters) = context(
692            "Failed MipStoreStats network version counters der",
693            length_count(
694                context("Failed counters len der", |input| {
695                    let (rem, count) = self.u32_deserializer.deserialize(input)?;
696                    if count > cfg_block_considered {
697                        return IResult::Err(nom::Err::Error(ParseError::from_error_kind(
698                            input,
699                            nom::error::ErrorKind::Fail,
700                        )));
701                    }
702                    IResult::Ok((rem, count))
703                }),
704                context("Failed counters data der", |input| {
705                    let (rem, v) = self.u32_deserializer.deserialize(input)?;
706                    let (rem2, c) = self.u64_deserializer.deserialize(rem)?;
707                    IResult::Ok((rem2, (v, c)))
708                }),
709            ),
710        )
711        .parse(rem3)?;
712
713        IResult::Ok((
714            rem4,
715            MipStoreStats {
716                config: self.config.clone(),
717                latest_announcements: latest_announcements_.into_iter().collect(),
718                network_version_counters: network_version_counters.into_iter().collect(),
719            },
720        ))
721    }
722}
723
724// End MipStoreStats
725
726// MipStoreRaw
727
728/// Serializer for `VersioningStoreRaw`
729pub struct MipStoreRawSerializer {
730    u32_serializer: U32VarIntSerializer,
731    info_serializer: MipInfoSerializer,
732    state_serializer: MipStateSerializer,
733    stats_serializer: MipStoreStatsSerializer,
734}
735
736impl MipStoreRawSerializer {
737    /// Creates a new `Serializer`
738    pub fn new() -> Self {
739        Self {
740            u32_serializer: U32VarIntSerializer::new(),
741            info_serializer: MipInfoSerializer::new(),
742            state_serializer: MipStateSerializer::new(),
743            stats_serializer: MipStoreStatsSerializer::new(),
744        }
745    }
746}
747
748impl Default for MipStoreRawSerializer {
749    fn default() -> Self {
750        Self::new()
751    }
752}
753
754impl Serializer<MipStoreRaw> for MipStoreRawSerializer {
755    fn serialize(&self, value: &MipStoreRaw, buffer: &mut Vec<u8>) -> Result<(), SerializeError> {
756        let entry_count_ = value.store.len();
757        let entry_count = u32::try_from(entry_count_).map_err(|e| {
758            SerializeError::GeneralError(format!("Could not convert to u32: {}", e))
759        })?;
760        if entry_count > MIP_STORE_MAX_ENTRIES {
761            return Err(SerializeError::GeneralError(format!(
762                "Too many entries in VersioningStoreRaw, max: {}, received: {}",
763                MIP_STORE_MAX_ENTRIES, entry_count
764            )));
765        }
766        self.u32_serializer.serialize(&entry_count, buffer)?;
767        for (key, value) in value.store.iter() {
768            self.info_serializer.serialize(key, buffer)?;
769            self.state_serializer.serialize(value, buffer)?;
770        }
771        self.stats_serializer.serialize(&value.stats, buffer)?;
772        Ok(())
773    }
774}
775
776/// A Deserializer for `VersioningStoreRaw
777pub struct MipStoreRawDeserializer {
778    entry_count_deserializer: U32VarIntDeserializer,
779    info_deserializer: MipInfoDeserializer,
780    state_deserializer: MipStateDeserializer,
781    stats_deserializer: MipStoreStatsDeserializer,
782}
783
784impl MipStoreRawDeserializer {
785    /// Creates a new ``
786    pub fn new(block_count_considered: usize, warn_announced_version_ratio: Ratio<u64>) -> Self {
787        Self {
788            entry_count_deserializer: U32VarIntDeserializer::new(
789                Included(0),
790                Included(MIP_STORE_MAX_ENTRIES),
791            ),
792            info_deserializer: MipInfoDeserializer::new(),
793            state_deserializer: MipStateDeserializer::new(),
794            stats_deserializer: MipStoreStatsDeserializer::new(
795                block_count_considered,
796                warn_announced_version_ratio,
797            ),
798        }
799    }
800}
801
802impl Deserializer<MipStoreRaw> for MipStoreRawDeserializer {
803    fn deserialize<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
804        &self,
805        buffer: &'a [u8],
806    ) -> IResult<&'a [u8], MipStoreRaw, E> {
807        context(
808            "Failed MipStoreRaw der",
809            tuple((
810                length_count(
811                    context("Failed entry count der", |input| {
812                        self.entry_count_deserializer.deserialize(input)
813                    }),
814                    context("Failed items der", |input| {
815                        let (rem, vi) = self.info_deserializer.deserialize(input)?;
816                        let (rem2, vs) = self.state_deserializer.deserialize(rem)?;
817                        IResult::Ok((rem2, (vi, vs)))
818                    }),
819                ),
820                context("Failed mip store stats der", |input| {
821                    self.stats_deserializer.deserialize(input)
822                }),
823            )),
824        )
825        .map(|(items, stats)| MipStoreRaw {
826            store: items.into_iter().collect(),
827            stats,
828        })
829        .parse(buffer)
830    }
831}
832
833// End MipStoreRaw
834
835#[cfg(test)]
836mod test {
837    use super::*;
838
839    use assert_matches::assert_matches;
840    use std::mem::{size_of, size_of_val};
841
842    use more_asserts::assert_lt;
843    use num::rational::Ratio;
844    use num::FromPrimitive;
845
846    use crate::test_helpers::versioning_helpers::advance_state_until;
847
848    use massa_serialization::DeserializeError;
849    use massa_time::MassaTime;
850
851    #[test]
852    fn test_mip_component_non_exhaustive() {
853        let last_variant__ = MipComponent::VARIANT_COUNT - 2; // -1 for Nonexhaustive, -1 for index start at 0
854        let last_variant_ = u32::try_from(last_variant__).unwrap();
855        let last_variant = MipComponent::from(last_variant_);
856
857        match last_variant {
858            MipComponent::__Nonexhaustive => {
859                panic!("Should be a known enum value")
860            }
861            _ => {
862                // all good
863                println!("last variant of MipComponent is: {:?}", last_variant);
864            }
865        }
866
867        {
868            let variant__ = MipComponent::VARIANT_COUNT - 1;
869            let variant_ = u32::try_from(variant__).unwrap();
870            assert_matches!(MipComponent::from(variant_), MipComponent::__Nonexhaustive);
871        }
872
873        {
874            let variant__ = MipComponent::VARIANT_COUNT;
875            let variant_ = u32::try_from(variant__).unwrap();
876            assert_matches!(MipComponent::from(variant_), MipComponent::__Nonexhaustive);
877        }
878    }
879
880    #[test]
881    fn test_mip_info_ser_der() {
882        let mi_1 = MipInfo {
883            name: "MIP-0002".to_string(),
884            version: 2,
885            components: BTreeMap::from([(MipComponent::Address, 1)]),
886            start: MassaTime::from_millis(2),
887            timeout: MassaTime::from_millis(5),
888            activation_delay: MassaTime::from_millis(2),
889        };
890
891        let mut buf = Vec::new();
892        let mip_info_ser = MipInfoSerializer::new();
893        mip_info_ser.serialize(&mi_1, &mut buf).unwrap();
894
895        let mip_info_der = MipInfoDeserializer::new();
896
897        let (rem, mi_1_der) = mip_info_der.deserialize::<DeserializeError>(&buf).unwrap();
898
899        assert!(rem.is_empty());
900        assert_eq!(mi_1, mi_1_der);
901    }
902
903    #[test]
904    fn test_mip_info_ser_der_err() {
905        {
906            // A MIP info with too many MIP Component
907            let mi_1 = MipInfo {
908                name: "MIP-0002".to_string(),
909                version: 2,
910                components: BTreeMap::from([
911                    (MipComponent::Address, 1),
912                    (MipComponent::KeyPair, 2),
913                    (MipComponent::Block, 3),
914                    (MipComponent::VM, 4),
915                    (MipComponent::FinalStateHashKind, 5),
916                    (MipComponent::__Nonexhaustive, 6),
917                ]),
918                start: MassaTime::from_millis(2),
919                timeout: MassaTime::from_millis(5),
920                activation_delay: MassaTime::from_millis(2),
921            };
922
923            {
924                let mut buf = Vec::new();
925                let mip_info_ser = MipInfoSerializer::new();
926                mip_info_ser.serialize(&mi_1, &mut buf).unwrap();
927
928                let mut mip_info_der = MipInfoDeserializer::new();
929                // Allow only a max of 2 components per MIP info
930                mip_info_der.components_len_deserializer =
931                    U32VarIntDeserializer::new(Included(0), Included(2));
932
933                let res = mip_info_der.deserialize::<DeserializeError>(&buf);
934                assert!(res.is_err());
935            }
936        }
937
938        {
939            // A MIP info with a very long name
940            let mi_2 = MipInfo {
941                name: "a".repeat(MIP_INFO_NAME_MAX_LEN as usize + 1),
942                version: 2,
943                components: BTreeMap::from([(MipComponent::Address, 1)]),
944                start: MassaTime::from_millis(2),
945                timeout: MassaTime::from_millis(5),
946                activation_delay: MassaTime::from_millis(2),
947            };
948
949            {
950                let mut buf = Vec::new();
951                let mip_info_ser = MipInfoSerializer::new();
952                mip_info_ser.serialize(&mi_2, &mut buf).unwrap();
953
954                let mip_info_der = MipInfoDeserializer::new();
955
956                let res = mip_info_der.deserialize::<DeserializeError>(&buf);
957                assert!(res.is_err());
958            }
959        }
960
961        {
962            // A MIP info, tweak to have an incorrect length (for name)
963
964            let mip_info_name = "MIP-0002".to_string();
965            let mi_1 = MipInfo {
966                name: mip_info_name.clone(),
967                version: 2,
968                components: BTreeMap::from([
969                    (MipComponent::Address, 1),
970                    (MipComponent::KeyPair, 2),
971                    (MipComponent::Block, 3),
972                ]),
973                start: MassaTime::from_millis(2),
974                timeout: MassaTime::from_millis(5),
975                activation_delay: MassaTime::from_millis(2),
976            };
977
978            let mut buf = Vec::new();
979            let mip_info_ser = MipInfoSerializer::new();
980            mip_info_ser.serialize(&mi_1, &mut buf).unwrap();
981
982            assert_eq!(buf[0], mip_info_name.len() as u8);
983            // Now name len will be way too long
984            buf[0] = buf.len() as u8 + 1;
985            let mip_info_der = MipInfoDeserializer::new();
986            let res = mip_info_der.deserialize::<DeserializeError>(&buf);
987            assert!(res.is_err());
988        }
989    }
990
991    #[test]
992    fn test_component_state_ser_der() {
993        let state_ser = ComponentStateSerializer::new();
994        let state_der = ComponentStateDeserializer::new();
995
996        {
997            let st_1 = ComponentState::failed();
998
999            let mut buf = Vec::new();
1000            state_ser.serialize(&st_1, &mut buf).unwrap();
1001
1002            let (rem, st_1_der) = state_der.deserialize::<DeserializeError>(&buf).unwrap();
1003
1004            assert!(rem.is_empty());
1005            assert_eq!(st_1, st_1_der);
1006        }
1007
1008        {
1009            let st_2 = ComponentState::Started(Started {
1010                vote_ratio: Ratio::from_f32(0.9842).unwrap(),
1011            });
1012
1013            let mut buf = Vec::new();
1014            state_ser.serialize(&st_2, &mut buf).unwrap();
1015            let (rem, st_2_der) = state_der.deserialize::<DeserializeError>(&buf).unwrap();
1016
1017            assert!(rem.is_empty());
1018            assert_eq!(st_2, st_2_der);
1019        }
1020    }
1021
1022    #[test]
1023    fn test_component_state_ser_der_err() {
1024        let state_ser = ComponentStateSerializer::new();
1025        let state_der = ComponentStateDeserializer::new();
1026
1027        let st_2 = ComponentState::Started(Started {
1028            vote_ratio: Ratio::from_f32(0.9842).unwrap(),
1029        });
1030
1031        let mut buf = Vec::new();
1032        state_ser.serialize(&st_2, &mut buf).unwrap();
1033        // ComponentState is encoded as a u32 varint
1034        // Here by modifying the first value of buf, we set the ComponentState encoded value to
1035        // a unknown value
1036        buf[0] = 99;
1037
1038        let res = state_der.deserialize::<DeserializeError>(&buf);
1039        assert!(res.is_err());
1040    }
1041
1042    #[test]
1043    fn test_advance_ser_der() {
1044        let now = MassaTime::from_utc_ymd_hms(2017, 5, 11, 11, 33, 44).unwrap();
1045
1046        let adv_lw = AdvanceLW {
1047            threshold: Default::default(),
1048            now,
1049        };
1050
1051        let mut buf = Vec::new();
1052        let adv_ser = AdvanceLWSerializer::new();
1053        adv_ser.serialize(&adv_lw, &mut buf).unwrap();
1054
1055        let state_der = AdvanceLWDeserializer::new();
1056
1057        let (rem, adv_der) = state_der.deserialize::<DeserializeError>(&buf).unwrap();
1058
1059        assert!(rem.is_empty());
1060        assert_eq!(adv_lw, adv_der);
1061    }
1062
1063    #[test]
1064    fn test_mip_state_ser_der() {
1065        let state_1 = MipState::new(MassaTime::from_millis(100));
1066
1067        let mut buf = Vec::new();
1068        let state_ser = MipStateSerializer::new();
1069        state_ser.serialize(&state_1, &mut buf).unwrap();
1070
1071        let state_der = MipStateDeserializer::new();
1072
1073        let (rem, state_der_res) = state_der.deserialize::<DeserializeError>(&buf).unwrap();
1074
1075        assert!(rem.is_empty());
1076        assert_eq!(state_1, state_der_res);
1077        buf.clear();
1078
1079        let mi_1 = MipInfo {
1080            name: "MIP-0002".to_string(),
1081            version: 2,
1082            components: BTreeMap::from([(MipComponent::Address, 1)]),
1083            start: MassaTime::from_millis(2),
1084            timeout: MassaTime::from_millis(5),
1085            activation_delay: MassaTime::from_millis(2),
1086        };
1087
1088        let state_2 =
1089            advance_state_until(ComponentState::locked_in(MassaTime::from_millis(3)), &mi_1);
1090        state_ser.serialize(&state_2, &mut buf).unwrap();
1091        let (rem2, state_der_res) = state_der.deserialize::<DeserializeError>(&buf).unwrap();
1092
1093        assert!(rem2.is_empty());
1094        assert_eq!(state_2, state_der_res);
1095    }
1096
1097    #[test]
1098    fn test_mip_store_stats_ser_der() {
1099        let mip_stats_cfg = MipStatsConfig {
1100            block_count_considered: 10,
1101            warn_announced_version_ratio: Ratio::new_raw(30, 100),
1102        };
1103
1104        let mip_stats = MipStoreStats {
1105            config: mip_stats_cfg.clone(),
1106            latest_announcements: Default::default(),
1107            network_version_counters: Default::default(),
1108        };
1109
1110        let mut buf = Vec::new();
1111        let store_stats_ser = MipStoreStatsSerializer::new();
1112        store_stats_ser.serialize(&mip_stats, &mut buf).unwrap();
1113
1114        let store_stats_der = MipStoreStatsDeserializer::new(
1115            mip_stats_cfg.block_count_considered,
1116            mip_stats_cfg.warn_announced_version_ratio,
1117        );
1118        let (rem, store_stats_der_res) = store_stats_der
1119            .deserialize::<DeserializeError>(&buf)
1120            .unwrap();
1121
1122        assert!(rem.is_empty());
1123        assert_eq!(mip_stats, store_stats_der_res);
1124    }
1125
1126    #[test]
1127    fn test_mip_store_raw_ser_der() {
1128        let mip_stats_cfg = MipStatsConfig {
1129            block_count_considered: 10,
1130            warn_announced_version_ratio: Ratio::new_raw(30, 100),
1131        };
1132
1133        let mi_2 = MipInfo {
1134            name: "MIP-0002".to_string(),
1135            version: 2,
1136            components: BTreeMap::from([(MipComponent::Address, 1)]),
1137            start: MassaTime::from_millis(2),
1138            timeout: MassaTime::from_millis(5),
1139            activation_delay: MassaTime::from_millis(2),
1140        };
1141
1142        let mi_3 = MipInfo {
1143            name: "MIP-0003".to_string(),
1144            version: 3,
1145            components: BTreeMap::from([(MipComponent::Block, 1)]),
1146            start: MassaTime::from_millis(12),
1147            timeout: MassaTime::from_millis(17),
1148            activation_delay: MassaTime::from_millis(2),
1149        };
1150
1151        let _time = MassaTime::now();
1152        let state_2 = advance_state_until(ComponentState::active(_time), &mi_2);
1153        let state_3 = advance_state_until(ComponentState::started(Ratio::new_raw(42, 100)), &mi_3);
1154
1155        let store_raw =
1156            MipStoreRaw::try_from(([(mi_2, state_2), (mi_3, state_3)], mip_stats_cfg.clone()))
1157                .unwrap();
1158
1159        let mut buf = Vec::new();
1160        let store_raw_ser = MipStoreRawSerializer::new();
1161        store_raw_ser.serialize(&store_raw, &mut buf).unwrap();
1162
1163        let store_raw_der = MipStoreRawDeserializer::new(
1164            mip_stats_cfg.block_count_considered,
1165            mip_stats_cfg.warn_announced_version_ratio,
1166        );
1167        let (rem, store_raw_der_res) = store_raw_der.deserialize::<DeserializeError>(&buf).unwrap();
1168
1169        assert!(rem.is_empty());
1170        assert_eq!(store_raw, store_raw_der_res);
1171    }
1172
1173    #[test]
1174    #[ignore]
1175    fn mip_store_raw_max_size() {
1176        let mut mi_base = MipInfo {
1177            name: "A".repeat(254),
1178            version: 0,
1179            components: BTreeMap::from([(MipComponent::Address, 0)]),
1180            start: MassaTime::from_millis(0),
1181            timeout: MassaTime::from_millis(2),
1182            activation_delay: MassaTime::from_millis(2),
1183        };
1184
1185        // Note: we did not add the name ptr and hashmap ptr, only the data inside
1186        let mi_base_size = size_of_val(&mi_base.name[..])
1187            + size_of_val(&mi_base.version)
1188            + mi_base.components.len() * size_of::<u32>() * 2
1189            + size_of_val(&mi_base.start)
1190            + size_of_val(&mi_base.timeout);
1191
1192        let mut all_state_size = 0;
1193
1194        let _time = MassaTime::now();
1195        let store_raw_: Vec<(MipInfo, MipState)> = (0..MIP_STORE_MAX_ENTRIES)
1196            .map(|_i| {
1197                mi_base.version += 1;
1198                mi_base
1199                    .components
1200                    .entry(MipComponent::Address)
1201                    .and_modify(|e| *e += 1);
1202                mi_base.start = mi_base.timeout.saturating_add(MassaTime::from_millis(1));
1203                mi_base.timeout = mi_base.start.saturating_add(MassaTime::from_millis(2));
1204
1205                let state = advance_state_until(ComponentState::active(_time), &mi_base);
1206
1207                all_state_size += size_of_val(&state.state);
1208                all_state_size += state.history.len() * (size_of::<AdvanceLW>() + size_of::<u32>());
1209
1210                (mi_base.clone(), state)
1211            })
1212            .collect();
1213
1214        // Cannot use update_with ou try_from here as the names are not uniques
1215        let store_raw = MipStoreRaw {
1216            store: BTreeMap::from_iter(store_raw_),
1217            stats: MipStoreStats::new(MipStatsConfig {
1218                block_count_considered: 10,
1219                warn_announced_version_ratio: Ratio::new(30, 100),
1220            }),
1221        };
1222        assert_eq!(store_raw.store.len(), MIP_STORE_MAX_ENTRIES as usize);
1223
1224        let store_raw_size = (store_raw.store.len() * mi_base_size) + all_state_size;
1225        assert_lt!(store_raw_size, MIP_STORE_MAX_SIZE);
1226
1227        // Now check SER / DER with this huge store
1228        let mut buf = Vec::new();
1229        let store_raw_ser = MipStoreRawSerializer::new();
1230
1231        store_raw_ser
1232            .serialize(&store_raw, &mut buf)
1233            .expect("Unable to serialize");
1234
1235        let store_raw_der = MipStoreRawDeserializer::new(10, Ratio::new(30, 100));
1236        let (rem, store_raw_der_res) = store_raw_der.deserialize::<DeserializeError>(&buf).unwrap();
1237
1238        assert!(rem.is_empty());
1239        assert_eq!(store_raw, store_raw_der_res);
1240    }
1241}