bee_block/payload/milestone/
essence.rs1use alloc::vec::Vec;
5
6use crypto::hashes::{blake2b::Blake2b256, Digest};
7use packable::{
8 bounded::BoundedU16,
9 error::{UnpackError, UnpackErrorExt},
10 packer::Packer,
11 prefix::BoxedSlicePrefix,
12 unpacker::Unpacker,
13 Packable, PackableExt,
14};
15
16use crate::{
17 parent::Parents,
18 payload::milestone::{MerkleRoot, MilestoneId, MilestoneIndex, MilestoneOptions},
19 protocol::ProtocolParameters,
20 Error,
21};
22
23pub(crate) type MilestoneMetadataLength = BoundedU16<{ u16::MIN }, { u16::MAX }>;
24
25#[derive(Clone, Debug, Eq, PartialEq)]
28#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
29pub struct MilestoneEssence {
30 index: MilestoneIndex,
31 timestamp: u32,
32 protocol_version: u8,
33 previous_milestone_id: MilestoneId,
34 parents: Parents,
35 inclusion_merkle_root: MerkleRoot,
36 applied_merkle_root: MerkleRoot,
37 metadata: BoxedSlicePrefix<u8, MilestoneMetadataLength>,
38 options: MilestoneOptions,
39}
40
41impl MilestoneEssence {
42 #[allow(clippy::too_many_arguments)]
44 pub fn new(
45 index: MilestoneIndex,
46 timestamp: u32,
47 protocol_version: u8,
48 previous_milestone_id: MilestoneId,
49 parents: Parents,
50 inclusion_merkle_root: MerkleRoot,
51 applied_merkle_root: MerkleRoot,
52 metadata: Vec<u8>,
53 options: MilestoneOptions,
54 ) -> Result<Self, Error> {
55 let metadata = metadata
56 .into_boxed_slice()
57 .try_into()
58 .map_err(Error::InvalidMilestoneMetadataLength)?;
59
60 Ok(Self {
61 index,
62 timestamp,
63 protocol_version,
64 previous_milestone_id,
65 parents,
66 inclusion_merkle_root,
67 applied_merkle_root,
68 metadata,
69 options,
70 })
71 }
72
73 pub fn index(&self) -> MilestoneIndex {
75 self.index
76 }
77
78 pub fn timestamp(&self) -> u32 {
80 self.timestamp
81 }
82
83 pub fn protocol_version(&self) -> u8 {
85 self.protocol_version
86 }
87
88 pub fn previous_milestone_id(&self) -> &MilestoneId {
90 &self.previous_milestone_id
91 }
92
93 pub fn parents(&self) -> &Parents {
95 &self.parents
96 }
97
98 pub fn inclusion_merkle_root(&self) -> &MerkleRoot {
100 &self.inclusion_merkle_root
101 }
102
103 pub fn applied_merkle_root(&self) -> &MerkleRoot {
105 &self.applied_merkle_root
106 }
107
108 pub fn metadata(&self) -> &[u8] {
110 &self.metadata
111 }
112
113 pub fn options(&self) -> &MilestoneOptions {
115 &self.options
116 }
117
118 pub fn hash(&self) -> [u8; 32] {
120 Blake2b256::digest(&self.pack_to_vec()).into()
121 }
122}
123
124impl Packable for MilestoneEssence {
125 type UnpackError = Error;
126 type UnpackVisitor = ProtocolParameters;
127
128 fn pack<P: Packer>(&self, packer: &mut P) -> Result<(), P::Error> {
129 self.index.pack(packer)?;
130 self.timestamp.pack(packer)?;
131 self.protocol_version.pack(packer)?;
132 self.previous_milestone_id.pack(packer)?;
133 self.parents.pack(packer)?;
134 self.inclusion_merkle_root.pack(packer)?;
135 self.applied_merkle_root.pack(packer)?;
136 self.metadata.pack(packer)?;
137 self.options.pack(packer)?;
138
139 Ok(())
140 }
141
142 fn unpack<U: Unpacker, const VERIFY: bool>(
143 unpacker: &mut U,
144 visitor: &Self::UnpackVisitor,
145 ) -> Result<Self, UnpackError<Self::UnpackError, U::Error>> {
146 let index = MilestoneIndex::unpack::<_, VERIFY>(unpacker, &()).coerce()?;
147 let timestamp = u32::unpack::<_, VERIFY>(unpacker, &()).coerce()?;
148 let protocol_version = u8::unpack::<_, VERIFY>(unpacker, &()).coerce()?;
149
150 if VERIFY && protocol_version != visitor.protocol_version() {
151 return Err(UnpackError::Packable(Error::ProtocolVersionMismatch {
152 expected: visitor.protocol_version(),
153 actual: protocol_version,
154 }));
155 }
156
157 let previous_milestone_id = MilestoneId::unpack::<_, VERIFY>(unpacker, &()).coerce()?;
158 let parents = Parents::unpack::<_, VERIFY>(unpacker, &())?;
159 let inclusion_merkle_root = MerkleRoot::unpack::<_, VERIFY>(unpacker, &()).coerce()?;
160 let applied_merkle_root = MerkleRoot::unpack::<_, VERIFY>(unpacker, &()).coerce()?;
161
162 let metadata = BoxedSlicePrefix::<u8, MilestoneMetadataLength>::unpack::<_, VERIFY>(unpacker, &())
163 .map_packable_err(|e| Error::InvalidMilestoneMetadataLength(e.into_prefix_err().into()))?;
164
165 let options = MilestoneOptions::unpack::<_, VERIFY>(unpacker, visitor)?;
166
167 Ok(Self {
168 index,
169 timestamp,
170 protocol_version,
171 previous_milestone_id,
172 parents,
173 inclusion_merkle_root,
174 applied_merkle_root,
175 metadata,
176 options,
177 })
178 }
179}