mithril_cardano_node_chain/entities/
raw_cardano_point.rs

1use pallas_network::miniprotocols::Point as PallasPoint;
2use std::fmt::{Debug, Formatter};
3
4use mithril_common::entities::{ChainPoint, SlotNumber};
5
6use crate::entities::ScannedBlock;
7
8/// Point internal representation in the Cardano chain.
9#[derive(Clone, PartialEq)]
10pub struct RawCardanoPoint {
11    /// The [slot number](https://docs.cardano.org/learn/cardano-node/#slotsandepochs)
12    pub slot_number: SlotNumber,
13
14    /// Hex array of the block hash
15    pub block_hash: Vec<u8>,
16}
17
18impl RawCardanoPoint {
19    /// Instantiate a new `RawCardanoPoint`
20    pub fn new<T: Into<Vec<u8>>>(slot_number: SlotNumber, block_hash: T) -> Self {
21        RawCardanoPoint {
22            slot_number,
23            block_hash: block_hash.into(),
24        }
25    }
26
27    /// Create a new origin `RawCardanoPoint`
28    pub fn origin() -> Self {
29        RawCardanoPoint {
30            slot_number: SlotNumber(0),
31            block_hash: Vec::new(),
32        }
33    }
34
35    /// Check if origin
36    pub fn is_origin(&self) -> bool {
37        self.slot_number == 0 && self.block_hash.is_empty()
38    }
39}
40
41impl From<&ChainPoint> for RawCardanoPoint {
42    fn from(point: &ChainPoint) -> Self {
43        RawCardanoPoint {
44            slot_number: point.slot_number,
45            block_hash: hex::decode(&point.block_hash).unwrap(),
46        }
47    }
48}
49
50impl From<ChainPoint> for RawCardanoPoint {
51    fn from(point: ChainPoint) -> Self {
52        Self::from(&point)
53    }
54}
55
56impl Debug for RawCardanoPoint {
57    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
58        let mut debug = f.debug_struct("RawCardanoPoint");
59        debug
60            .field("slot_number", &self.slot_number)
61            .field("block_hash", &hex::encode(&self.block_hash))
62            .finish()
63    }
64}
65
66impl From<RawCardanoPoint> for PallasPoint {
67    fn from(raw_point: RawCardanoPoint) -> Self {
68        match raw_point.is_origin() {
69            true => Self::Origin,
70            false => Self::Specific(*raw_point.slot_number, raw_point.block_hash),
71        }
72    }
73}
74
75impl From<PallasPoint> for RawCardanoPoint {
76    fn from(point: PallasPoint) -> Self {
77        match point {
78            PallasPoint::Specific(slot_number, block_hash) => Self {
79                slot_number: SlotNumber(slot_number),
80                block_hash,
81            },
82            PallasPoint::Origin => Self::origin(),
83        }
84    }
85}
86
87impl From<&ScannedBlock> for RawCardanoPoint {
88    fn from(scanned_block: &ScannedBlock) -> Self {
89        RawCardanoPoint {
90            slot_number: scanned_block.slot_number,
91            block_hash: scanned_block.block_hash.clone(),
92        }
93    }
94}
95
96impl From<ScannedBlock> for RawCardanoPoint {
97    fn from(scanned_block: ScannedBlock) -> Self {
98        Self::from(&scanned_block)
99    }
100}
101
102#[cfg(test)]
103mod tests {
104    use mithril_common::entities::BlockNumber;
105
106    use super::*;
107
108    #[test]
109    fn from_chain_point_to_raw_cardano_point_conversions() {
110        let expected_hash = vec![4, 2, 12, 9, 7];
111        let chain_point =
112            ChainPoint::new(SlotNumber(8), BlockNumber(23), hex::encode(&expected_hash));
113
114        assert_eq!(
115            RawCardanoPoint::new(SlotNumber(8), expected_hash.clone()),
116            RawCardanoPoint::from(&chain_point)
117        );
118        assert_eq!(
119            RawCardanoPoint::new(SlotNumber(8), expected_hash.clone()),
120            RawCardanoPoint::from(chain_point)
121        );
122    }
123
124    #[test]
125    fn from_scanned_block_to_raw_cardano_point_conversions() {
126        let expected_hash = vec![7, 1, 13, 7, 8];
127        let scanned_block = ScannedBlock::new(
128            expected_hash.clone(),
129            BlockNumber(31),
130            SlotNumber(4),
131            Vec::<&str>::new(),
132        );
133        assert_eq!(
134            RawCardanoPoint::new(SlotNumber(4), expected_hash.clone()),
135            RawCardanoPoint::from(&scanned_block)
136        );
137        assert_eq!(
138            RawCardanoPoint::new(SlotNumber(4), expected_hash.clone()),
139            RawCardanoPoint::from(scanned_block)
140        );
141    }
142}