Skip to main content

amaru_kernel/cardano/
era_bound.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::{Epoch, Slot, cbor, utils::cbor::SerialisedAsPico};
18
19#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
20pub struct EraBound {
21    #[serde(deserialize_with = "SerialisedAsPico::deserialize")]
22    #[serde(serialize_with = "SerialisedAsPico::serialize")]
23    pub time: Duration,
24    pub slot: Slot,
25    pub epoch: Epoch,
26}
27
28impl<C> cbor::Encode<C> for EraBound {
29    fn encode<W: cbor::encode::Write>(
30        &self,
31        e: &mut cbor::Encoder<W>,
32        ctx: &mut C,
33    ) -> Result<(), cbor::encode::Error<W::Error>> {
34        e.array(3)?;
35        SerialisedAsPico::from(self.time).encode(e, ctx)?;
36        self.slot.encode(e, ctx)?;
37        self.epoch.encode(e, ctx)?;
38        Ok(())
39    }
40}
41
42impl<'b, C> cbor::Decode<'b, C> for EraBound {
43    fn decode(d: &mut cbor::Decoder<'b>, ctx: &mut C) -> Result<Self, cbor::decode::Error> {
44        cbor::heterogeneous_array(d, |d, assert_len| {
45            assert_len(3)?;
46            let time = From::<SerialisedAsPico>::from(d.decode()?);
47            let slot = d.decode()?;
48            let epoch = d.decode_with(ctx)?;
49            Ok(EraBound { time, slot, epoch })
50        })
51    }
52}
53
54#[cfg(any(test, feature = "test-utils"))]
55pub use tests::*;
56
57#[cfg(any(test, feature = "test-utils"))]
58mod tests {
59    use proptest::prelude::*;
60
61    use super::*;
62    use crate::prop_cbor_roundtrip;
63
64    prop_compose! {
65        pub fn any_era_bound_time()(secs in any::<u32>()) -> Duration {
66            Duration::from_secs(secs as u64)
67        }
68    }
69
70    prop_compose! {
71        pub fn any_era_bound()(time in any_era_bound_time(), slot in any::<u32>(), epoch in any::<Epoch>()) -> EraBound {
72            EraBound {
73                time, slot: Slot::new(slot as u64), epoch
74            }
75        }
76    }
77
78    prop_compose! {
79        pub fn any_era_bound_for_epoch(epoch: Epoch)(time in any_era_bound_time(), slot in any::<u32>()) -> EraBound {
80            EraBound {
81                time, slot: Slot::new(slot as u64), epoch
82            }
83        }
84    }
85
86    prop_cbor_roundtrip!(EraBound, any_era_bound());
87}