Skip to main content

amaru_kernel/cardano/
era_params.rs

1// Copyright 2026 PRAGMA
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::time::Duration;
16
17use crate::{EraName, cbor, utils::cbor::SerialisedAsMillis};
18
19#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
20pub struct EraParams {
21    pub epoch_size_slots: u64,
22    #[serde(deserialize_with = "SerialisedAsMillis::deserialize")]
23    #[serde(serialize_with = "SerialisedAsMillis::serialize")]
24    pub slot_length: Duration,
25    pub era_name: EraName,
26}
27
28impl EraParams {
29    pub fn new(epoch_size_slots: u64, slot_length: Duration, era_name: EraName) -> Option<Self> {
30        if epoch_size_slots == 0 {
31            return None;
32        }
33        if slot_length.is_zero() {
34            return None;
35        }
36        Some(EraParams { epoch_size_slots, slot_length, era_name })
37    }
38}
39
40impl<C> cbor::Encode<C> for EraParams {
41    fn encode<W: cbor::encode::Write>(
42        &self,
43        e: &mut cbor::Encoder<W>,
44        ctx: &mut C,
45    ) -> Result<(), cbor::encode::Error<W::Error>> {
46        e.array(3)?;
47        self.epoch_size_slots.encode(e, ctx)?;
48        SerialisedAsMillis::from(self.slot_length).encode(e, ctx)?;
49        self.era_name.encode(e, ctx)?;
50        Ok(())
51    }
52}
53
54impl<'b, C> cbor::Decode<'b, C> for EraParams {
55    fn decode(d: &mut cbor::Decoder<'b>, _ctx: &mut C) -> Result<Self, cbor::decode::Error> {
56        let len = d.array()?;
57        if len != Some(3) {
58            return Err(cbor::decode::Error::message(format!("Expected 3 elements in EraParams, got {len:?}")));
59        }
60        let epoch_size_slots = d.decode()?;
61        let slot_length: SerialisedAsMillis = d.decode()?;
62        let era_name = d.decode()?;
63        Ok(EraParams { epoch_size_slots, slot_length: Duration::from(slot_length), era_name })
64    }
65}
66
67#[cfg(any(test, feature = "test-utils"))]
68pub use tests::*;
69
70#[cfg(any(test, feature = "test-utils"))]
71mod tests {
72    use proptest::prelude::*;
73
74    use super::*;
75    use crate::{any_era_name, prop_cbor_roundtrip};
76
77    prop_compose! {
78        pub fn any_era_params()(epoch_size_slots in 1u64..65535, slot_length in 1u64..65535, era_name in any_era_name()) -> EraParams {
79            EraParams {
80                epoch_size_slots,
81                slot_length: Duration::from_secs(slot_length),
82                era_name,
83            }
84        }
85    }
86
87    prop_cbor_roundtrip!(EraParams, any_era_params());
88}