1use crate::internal_prelude::*;
2
3define_single_versioned! {
4 #[derive(Debug, Clone, PartialEq, Eq, Sbor)]
5 pub ProtocolUpdateStatusSummarySubstate(ProtocolUpdateStatusSummaryVersions) => ProtocolUpdateStatusSummary = ProtocolUpdateStatusSummaryV1,
6 outer_attributes: [
7 #[derive(ScryptoSborAssertion)]
8 #[sbor_assert(backwards_compatible(
9 cuttlefish = "FILE:protocol_update_status_substate_cuttlefish_schema.bin",
10 ))]
11 ]
12}
13
14impl ProtocolUpdateStatusSummarySubstate {
15 pub fn load(database: &impl SubstateDatabase) -> Self {
16 let substate = database.get_substate(
17 TRANSACTION_TRACKER,
18 PROTOCOL_UPDATE_STATUS_PARTITION,
19 ProtocolUpdateStatusField::Summary,
20 );
21 if let Some(value) = substate {
22 return value;
23 }
24 let protocol_version = if database
26 .get_raw_substate(
27 TRANSACTION_TRACKER,
28 BOOT_LOADER_PARTITION,
29 BootLoaderField::SystemBoot,
30 )
31 .is_some()
32 {
33 ProtocolVersion::Bottlenose
34 } else if database
35 .get_raw_substate(
36 TRANSACTION_TRACKER,
37 BOOT_LOADER_PARTITION,
38 BootLoaderField::VmBoot,
39 )
40 .is_some()
41 {
42 ProtocolVersion::Anemone
43 } else if database
44 .get_raw_substate(
45 TRANSACTION_TRACKER,
46 TYPE_INFO_FIELD_PARTITION,
47 TypeInfoField::TypeInfo,
48 )
49 .is_some()
50 {
51 ProtocolVersion::Babylon
52 } else {
53 ProtocolVersion::Unbootstrapped
54 };
55
56 ProtocolUpdateStatusSummaryV1 {
57 protocol_version,
58 update_status: ProtocolUpdateStatus::Complete,
59 }
60 .into()
61 }
62}
63
64#[derive(Debug, Clone, PartialEq, Eq, Sbor)]
65pub struct ProtocolUpdateStatusSummaryV1 {
66 pub protocol_version: ProtocolVersion,
67 pub update_status: ProtocolUpdateStatus,
68}
69
70#[derive(Debug, Clone, PartialEq, Eq, Sbor)]
71pub enum ProtocolUpdateStatus {
72 Complete,
73 InProgress {
74 latest_commit: LatestProtocolUpdateCommitBatch,
75 },
76}
77
78#[derive(Debug, Clone, PartialEq, Eq, Sbor)]
79pub struct LatestProtocolUpdateCommitBatch {
80 pub batch_group_index: usize,
81 pub batch_group_name: String,
82 pub batch_index: usize,
83 pub batch_name: String,
84}
85
86macro_rules! count {
87 (
88 $ident: ident, $($other_idents: ident),* $(,)?
89 ) => {
90 1 + count!( $($other_idents),* )
91 };
92 (
93 $ident: ident $(,)?
94 ) => {
95 1
96 }
97}
98
99macro_rules! latest {
100 (
101 $enum_ident: ident, $ident: ident, $($other_idents: ident),* $(,)?
102 ) => {
103 latest!( $enum_ident, $($other_idents),* )
104 };
105 (
106 $enum_ident: ident, $ident: ident $(,)?
107 ) => {
108 $enum_ident :: $ident
109 }
110}
111
112macro_rules! define_enum {
113 (
114 $ident:ident,
115 $(
116 (
117 $variant_name: ident,
118 $logical_name: expr,
119 $display_name: expr
120 )
121 ),* $(,)?
122 ) => {
123 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Sbor)]
124 pub enum $ident {
125 $($variant_name),*
126 }
127
128 impl $ident {
129 const VARIANTS: [Self; count!( $($variant_name),* )] = [
130 $(
131 Self::$variant_name
132 ),*
133 ];
134
135 pub const LATEST: $ident = latest!( $ident, $($variant_name),* );
136
137 pub const fn logical_name(&self) -> &'static str {
138 match self {
139 $(
140 Self::$variant_name => $logical_name
141 ),*
142 }
143 }
144
145 pub const fn display_name(&self) -> &'static str {
146 match self {
147 $(
148 Self::$variant_name => $display_name
149 ),*
150 }
151 }
152
153 pub fn try_from_logical_name(logical_name: &str) -> Option<Self> {
154 match logical_name {
155 $(
156 $logical_name => Some(Self::$variant_name)
157 ),*,
158 _ => None
159 }
160 }
161
162 pub fn try_from_display_name(display_name: &str) -> Option<Self> {
163 match display_name {
164 $(
165 $display_name => Some(Self::$variant_name)
166 ),*,
167 _ => None
168 }
169 }
170 }
171 };
172}
173
174macro_rules! define_protocol_version_and_updates {
175 (
176 pregenesis: {
177 variant_name: $pregenesis_variant_name: ident,
178 logical_name: $pregenesis_logical_name: expr,
179 display_name: $pregenesis_display_name: expr $(,)?
180 },
181 genesis: {
182 variant_name: $genesis_variant_name: ident,
183 logical_name: $genesis_logical_name: expr,
184 display_name: $genesis_display_name: expr $(,)?
185 },
186 protocol_updates: [
187 $(
188 {
189 variant_name: $protocol_update_variant_name: ident,
190 logical_name: $protocol_update_logical_name: expr,
191 display_name: $protocol_update_display_name: expr $(,)?
192 }
193 ),* $(,)?
194 ]
195 ) => {
196 define_enum!(
197 ProtocolVersion,
198 ($pregenesis_variant_name, $pregenesis_logical_name, $pregenesis_display_name),
199 ($genesis_variant_name, $genesis_logical_name, $genesis_display_name),
200 $(($protocol_update_variant_name, $protocol_update_logical_name, $protocol_update_display_name)),*
201 );
202
203 impl ProtocolVersion {
204 pub const PRE_GENESIS: Self = Self::$pregenesis_variant_name;
205 pub const GENESIS: Self = Self::$genesis_variant_name;
206 }
207 };
208}
209
210impl ProtocolVersion {
211 #[allow(non_upper_case_globals)]
214 pub const Cuttlefish: Self = Self::CuttlefishPart2;
215}
216
217define_protocol_version_and_updates! {
225 pregenesis: {
226 variant_name: Unbootstrapped,
227 logical_name: "unbootstrapped",
228 display_name: "Unbootstrapped",
229 },
230 genesis: {
231 variant_name: Babylon,
232 logical_name: "babylon",
233 display_name: "Babylon",
234 },
235 protocol_updates: [
236 {
237 variant_name: Anemone,
238 logical_name: "anemone",
239 display_name: "Anemone",
240 },
241 {
242 variant_name: Bottlenose,
243 logical_name: "bottlenose",
244 display_name: "Bottlenose",
245 },
246 {
247 variant_name: CuttlefishPart1,
248 logical_name: "cuttlefish",
249 display_name: "Cuttlefish (Part 1)",
250 },
251 {
252 variant_name: CuttlefishPart2,
253 logical_name: "cuttlefish-part2",
254 display_name: "Cuttlefish (Part 2)",
255 }
256 ]
257}
258
259impl ProtocolVersion {
260 pub fn all_from(
261 from_version_inclusive: ProtocolVersion,
262 ) -> impl Iterator<Item = ProtocolVersion> {
263 Self::VARIANTS
264 .into_iter()
265 .skip_while(move |v| *v < from_version_inclusive)
266 }
267
268 pub fn all_between_inclusive(
269 from_version_inclusive: ProtocolVersion,
270 to_version_inclusive: ProtocolVersion,
271 ) -> impl Iterator<Item = ProtocolVersion> {
272 Self::VARIANTS
273 .into_iter()
274 .skip_while(move |v| *v < from_version_inclusive)
275 .take_while(move |v| *v <= to_version_inclusive)
276 }
277
278 pub fn all_between(
279 from_version_inclusive: ProtocolVersion,
280 to_version_exclusive: ProtocolVersion,
281 ) -> impl Iterator<Item = ProtocolVersion> {
282 Self::VARIANTS
283 .into_iter()
284 .skip_while(move |v| *v < from_version_inclusive)
285 .take_while(move |v| *v < to_version_exclusive)
286 }
287
288 pub fn next(&self) -> Option<Self> {
289 Self::VARIANTS
290 .iter()
291 .skip_while(|v| v <= &self)
292 .next()
293 .cloned()
294 }
295}
296
297#[cfg(test)]
298mod tests {
299 use super::*;
300
301 #[test]
302 fn assert_latest_protocol_version_is_as_expected() {
303 assert_eq!(ProtocolVersion::LATEST, ProtocolVersion::CuttlefishPart2);
304 }
305
306 #[test]
307 fn test_next() {
308 assert_eq!(
309 ProtocolVersion::PRE_GENESIS.next(),
310 Some(ProtocolVersion::GENESIS)
311 );
312 assert_eq!(
313 ProtocolVersion::GENESIS.next(),
314 Some(ProtocolVersion::Anemone)
315 );
316 assert_eq!(
317 ProtocolVersion::Anemone.next(),
318 Some(ProtocolVersion::Bottlenose)
319 );
320 assert_eq!(ProtocolVersion::LATEST.next(), None);
321 }
322
323 #[test]
324 fn assert_protocol_versions_have_the_expected_order() {
325 let variants =
326 ProtocolVersion::all_from(ProtocolVersion::Unbootstrapped).collect::<Vec<_>>();
327
328 assert_eq!(
329 variants,
330 vec![
331 ProtocolVersion::Unbootstrapped,
332 ProtocolVersion::Babylon,
333 ProtocolVersion::Anemone,
334 ProtocolVersion::Bottlenose,
335 ProtocolVersion::CuttlefishPart1,
336 ProtocolVersion::CuttlefishPart2,
337 ],
338 );
339 assert!(variants.windows(2).all(|item| item[0] < item[1]))
340 }
341
342 #[test]
343 fn assert_protocol_version_range_queries_work() {
344 assert_eq!(
345 ProtocolVersion::all_between(ProtocolVersion::Babylon, ProtocolVersion::Bottlenose,)
346 .collect::<Vec<_>>(),
347 vec![ProtocolVersion::Babylon, ProtocolVersion::Anemone,],
348 );
349 assert_eq!(
350 ProtocolVersion::all_between_inclusive(
351 ProtocolVersion::Babylon,
352 ProtocolVersion::Bottlenose,
353 )
354 .collect::<Vec<_>>(),
355 vec![
356 ProtocolVersion::Babylon,
357 ProtocolVersion::Anemone,
358 ProtocolVersion::Bottlenose,
359 ],
360 );
361 }
362}