casper_types/block/
block_body.rs

1mod block_body_v1;
2mod block_body_v2;
3
4pub use block_body_v1::BlockBodyV1;
5pub use block_body_v2::BlockBodyV2;
6
7use alloc::vec::Vec;
8use core::fmt::{self, Display, Formatter};
9
10#[cfg(feature = "datasize")]
11use datasize::DataSize;
12use serde::{Deserialize, Serialize};
13
14use crate::bytesrepr::{self, FromBytes, ToBytes, U8_SERIALIZED_LENGTH};
15
16const TAG_LENGTH: usize = U8_SERIALIZED_LENGTH;
17
18/// Tag for block body v1.
19pub const BLOCK_BODY_V1_TAG: u8 = 0;
20/// Tag for block body v2.
21pub const BLOCK_BODY_V2_TAG: u8 = 1;
22
23/// The versioned body portion of a block. It encapsulates different variants of the BlockBody
24/// struct.
25#[cfg_attr(feature = "datasize", derive(DataSize))]
26#[cfg_attr(any(feature = "testing", test), derive(PartialEq))]
27#[derive(Clone, Serialize, Deserialize, Debug)]
28#[allow(clippy::large_enum_variant)]
29pub enum BlockBody {
30    /// The legacy, initial version of the body portion of a block.
31    #[serde(rename = "Version1")]
32    V1(BlockBodyV1),
33    /// The version 2 of the body portion of a block, which includes the
34    /// `past_finality_signatures`.
35    #[serde(rename = "Version2")]
36    V2(BlockBodyV2),
37}
38
39impl Display for BlockBody {
40    fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
41        match self {
42            BlockBody::V1(v1) => Display::fmt(&v1, formatter),
43            BlockBody::V2(v2) => Display::fmt(&v2, formatter),
44        }
45    }
46}
47
48impl From<BlockBodyV1> for BlockBody {
49    fn from(body: BlockBodyV1) -> Self {
50        BlockBody::V1(body)
51    }
52}
53
54impl From<&BlockBodyV2> for BlockBody {
55    fn from(body: &BlockBodyV2) -> Self {
56        BlockBody::V2(body.clone())
57    }
58}
59
60impl ToBytes for BlockBody {
61    fn to_bytes(&self) -> Result<Vec<u8>, bytesrepr::Error> {
62        let mut buffer = bytesrepr::allocate_buffer(self)?;
63        match self {
64            BlockBody::V1(v1) => {
65                buffer.insert(0, BLOCK_BODY_V1_TAG);
66                buffer.extend(v1.to_bytes()?);
67            }
68            BlockBody::V2(v2) => {
69                buffer.insert(0, BLOCK_BODY_V2_TAG);
70                buffer.extend(v2.to_bytes()?);
71            }
72        }
73        Ok(buffer)
74    }
75
76    fn serialized_length(&self) -> usize {
77        TAG_LENGTH
78            + match self {
79                BlockBody::V1(v1) => v1.serialized_length(),
80                BlockBody::V2(v2) => v2.serialized_length(),
81            }
82    }
83}
84
85impl FromBytes for BlockBody {
86    fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), bytesrepr::Error> {
87        let (tag, remainder) = u8::from_bytes(bytes)?;
88        match tag {
89            BLOCK_BODY_V1_TAG => {
90                let (body, remainder): (BlockBodyV1, _) = FromBytes::from_bytes(remainder)?;
91                Ok((Self::V1(body), remainder))
92            }
93            BLOCK_BODY_V2_TAG => {
94                let (body, remainder): (BlockBodyV2, _) = FromBytes::from_bytes(remainder)?;
95                Ok((Self::V2(body), remainder))
96            }
97            _ => Err(bytesrepr::Error::Formatting),
98        }
99    }
100}
101
102#[cfg(test)]
103mod tests {
104    use crate::{bytesrepr, testing::TestRng, TestBlockBuilder, TestBlockV1Builder};
105
106    #[test]
107    fn bytesrepr_roundtrip() {
108        let rng = &mut TestRng::new();
109
110        let block_body_v1 = TestBlockV1Builder::new().build_versioned(rng).clone_body();
111        bytesrepr::test_serialization_roundtrip(&block_body_v1);
112
113        let block_body_v2 = TestBlockBuilder::new().build_versioned(rng).clone_body();
114        bytesrepr::test_serialization_roundtrip(&block_body_v2);
115    }
116}