amaru_kernel/cardano/
tip.rs1use std::fmt;
16
17use crate::{BlockHeight, HeaderHash, Point, Slot, cbor};
18
19#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, serde::Serialize, serde::Deserialize)]
20pub struct Tip(Point, BlockHeight);
21
22impl Tip {
23 pub fn origin() -> Self {
24 Self(Point::Origin, BlockHeight::from(0))
25 }
26
27 pub fn new(point: Point, block_height: BlockHeight) -> Self {
28 Self(point, block_height)
29 }
30
31 pub fn point(&self) -> Point {
32 self.0
33 }
34
35 pub fn slot(&self) -> Slot {
36 self.0.slot_or_default()
37 }
38
39 pub fn hash(&self) -> HeaderHash {
40 self.0.hash()
41 }
42
43 pub fn block_height(&self) -> BlockHeight {
44 self.1
45 }
46}
47
48impl fmt::Display for Tip {
49 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50 write!(f, "{}.{}", self.1, self.0.hash())
51 }
52}
53
54impl cbor::Encode<()> for Tip {
55 fn encode<W: cbor::encode::Write>(
56 &self,
57 e: &mut cbor::Encoder<W>,
58 _ctx: &mut (),
59 ) -> Result<(), cbor::encode::Error<W::Error>> {
60 e.array(2)?;
61 e.encode(self.0)?;
62 e.encode(self.1)?;
63 Ok(())
64 }
65}
66
67impl<'b> cbor::Decode<'b, ()> for Tip {
68 fn decode(d: &mut cbor::Decoder<'b>, _ctx: &mut ()) -> Result<Self, cbor::decode::Error> {
69 let len = d.array()?;
70 cbor::check_tagged_array_length(0, len, 2)?;
71 let point = d.decode()?;
72 let block_num = d.decode()?;
73 Ok(Tip(point, block_num))
74 }
75}
76
77#[cfg(any(test, feature = "test-utils"))]
78pub use tests::*;
79
80#[cfg(any(test, feature = "test-utils"))]
81mod tests {
82 use proptest::prop_compose;
83
84 use super::*;
85 use crate::{any_block_height, any_point, prop_cbor_roundtrip};
86
87 prop_cbor_roundtrip!(Tip, any_tip());
88
89 prop_compose! {
90 pub fn any_tip()(point in any_point(), block_height in any_block_height()) -> Tip {
91 Tip::new(point, block_height)
92 }
93 }
94}