iota_genesis_builder/stardust/types/
snapshot.rs1use iota_sdk::types::block::{
5 payload::milestone::{MilestoneId, MilestoneIndex, MilestoneOption},
6 protocol::ProtocolParameters,
7};
8use iota_types::stardust::error::StardustError;
9use packable::{
10 Packable, PackableExt,
11 error::{UnpackError, UnpackErrorExt},
12 packer::Packer,
13 unpacker::Unpacker,
14};
15
16const SNAPSHOT_VERSION: u8 = 2;
18
19#[derive(Copy, Clone, Debug)]
20struct MilestoneDiffCount(u32);
21
22impl Packable for MilestoneDiffCount {
23 type UnpackVisitor = ();
24 type UnpackError = StardustError;
25
26 fn pack<P: Packer>(&self, packer: &mut P) -> Result<(), P::Error> {
27 self.0.pack(packer)?;
28
29 Ok(())
30 }
31
32 fn unpack<U: Unpacker, const VERIFY: bool>(
33 unpacker: &mut U,
34 _: &(),
35 ) -> Result<Self, UnpackError<Self::UnpackError, U::Error>> {
36 let milestone_diff_count = u32::unpack::<_, VERIFY>(unpacker, &()).coerce()?;
37
38 if VERIFY && milestone_diff_count != 0 {
39 return Err(UnpackError::Packable(
40 StardustError::InvalidHornetGenesisSnapshot(milestone_diff_count),
41 ));
42 }
43
44 Ok(Self(milestone_diff_count))
45 }
46}
47
48#[derive(Clone, Debug)]
50pub struct FullSnapshotHeader {
51 genesis_milestone_index: MilestoneIndex,
52 target_milestone_index: MilestoneIndex,
53 target_milestone_timestamp: u32,
54 target_milestone_id: MilestoneId,
55 ledger_milestone_index: MilestoneIndex,
56 treasury_output_milestone_id: MilestoneId,
57 treasury_output_amount: u64,
58 parameters_milestone_option: MilestoneOption,
59 pub(crate) output_count: u64,
60 milestone_diff_count: MilestoneDiffCount,
61 sep_count: u16,
62}
63
64impl FullSnapshotHeader {
65 pub const LENGTH: usize = std::mem::size_of::<Self>();
67
68 pub fn genesis_milestone_index(&self) -> MilestoneIndex {
70 self.genesis_milestone_index
71 }
72
73 pub fn target_milestone_index(&self) -> MilestoneIndex {
75 self.target_milestone_index
76 }
77
78 pub fn target_milestone_timestamp(&self) -> u32 {
80 self.target_milestone_timestamp
81 }
82
83 pub fn target_milestone_id(&self) -> &MilestoneId {
85 &self.target_milestone_id
86 }
87
88 pub fn ledger_milestone_index(&self) -> MilestoneIndex {
90 self.ledger_milestone_index
91 }
92
93 pub fn treasury_output_milestone_id(&self) -> &MilestoneId {
95 &self.treasury_output_milestone_id
96 }
97
98 pub fn treasury_output_amount(&self) -> u64 {
100 self.treasury_output_amount
101 }
102
103 pub fn parameters_milestone_option(&self) -> &MilestoneOption {
105 &self.parameters_milestone_option
106 }
107
108 pub fn output_count(&self) -> u64 {
110 self.output_count
111 }
112
113 pub fn milestone_diff_count(&self) -> u32 {
117 self.milestone_diff_count.0
118 }
119
120 pub fn sep_count(&self) -> u16 {
122 self.sep_count
123 }
124}
125
126impl Packable for FullSnapshotHeader {
127 type UnpackVisitor = ();
128 type UnpackError = StardustError;
129
130 fn pack<P: Packer>(&self, packer: &mut P) -> Result<(), P::Error> {
131 SNAPSHOT_VERSION.pack(packer)?;
132 SnapshotKind::Full.pack(packer)?;
133
134 self.genesis_milestone_index.pack(packer)?;
135 self.target_milestone_index.pack(packer)?;
136 self.target_milestone_timestamp.pack(packer)?;
137 self.target_milestone_id.pack(packer)?;
138 self.ledger_milestone_index.pack(packer)?;
139 self.treasury_output_milestone_id.pack(packer)?;
140 self.treasury_output_amount.pack(packer)?;
141 (self.parameters_milestone_option.packed_len() as u16).pack(packer)?;
143 self.parameters_milestone_option.pack(packer)?;
144 self.output_count.pack(packer)?;
145 self.milestone_diff_count.pack(packer)?;
146 self.sep_count.pack(packer)?;
147
148 Ok(())
149 }
150
151 fn unpack<U: Unpacker, const VERIFY: bool>(
152 unpacker: &mut U,
153 _: &(),
154 ) -> Result<Self, UnpackError<Self::UnpackError, U::Error>> {
155 let version = u8::unpack::<_, VERIFY>(unpacker, &()).coerce()?;
156
157 if VERIFY && SNAPSHOT_VERSION != version {
158 return Err(UnpackError::Packable(
159 StardustError::UnsupportedHornetSnapshotVersion(SNAPSHOT_VERSION, version),
160 ));
161 }
162
163 let kind = SnapshotKind::unpack::<_, VERIFY>(unpacker, &()).coerce()?;
164
165 if VERIFY && kind != SnapshotKind::Full {
166 return Err(UnpackError::Packable(
167 StardustError::InvalidHornetSnapshotKind(kind as u8),
168 ));
169 }
170
171 let genesis_milestone_index =
172 MilestoneIndex::unpack::<_, VERIFY>(unpacker, &()).coerce()?;
173 let target_milestone_index = MilestoneIndex::unpack::<_, VERIFY>(unpacker, &()).coerce()?;
174 let target_milestone_timestamp = u32::unpack::<_, VERIFY>(unpacker, &()).coerce()?;
175 let target_milestone_id = MilestoneId::unpack::<_, VERIFY>(unpacker, &()).coerce()?;
176 let ledger_milestone_index = MilestoneIndex::unpack::<_, VERIFY>(unpacker, &()).coerce()?;
177 let treasury_output_milestone_id =
178 MilestoneId::unpack::<_, VERIFY>(unpacker, &()).coerce()?;
179 let treasury_output_amount = u64::unpack::<_, VERIFY>(unpacker, &()).coerce()?;
180 let _parameters_milestone_option_length =
182 u16::unpack::<_, VERIFY>(unpacker, &()).coerce()?;
183 let parameters_milestone_option =
184 MilestoneOption::unpack::<_, true>(unpacker, &ProtocolParameters::default())
185 .coerce()?;
186 let output_count = u64::unpack::<_, VERIFY>(unpacker, &()).coerce()?;
187 let milestone_diff_count =
188 MilestoneDiffCount::unpack::<_, VERIFY>(unpacker, &()).coerce()?;
189 let sep_count = u16::unpack::<_, VERIFY>(unpacker, &()).coerce()?;
190
191 Ok(Self {
192 genesis_milestone_index,
193 target_milestone_index,
194 target_milestone_timestamp,
195 target_milestone_id,
196 ledger_milestone_index,
197 treasury_output_milestone_id,
198 treasury_output_amount,
199 parameters_milestone_option,
200 output_count,
201 milestone_diff_count,
202 sep_count,
203 })
204 }
205}
206
207#[repr(u8)]
209#[derive(Debug, Copy, Clone, Eq, PartialEq, packable::Packable)]
210#[packable(unpack_error = StardustError)]
211pub enum SnapshotKind {
212 Full = 0,
216 Delta = 1,
220}