cardano_sdk/protocol/
basic.rs

1use crate::chain::{Block, BlockCompat, HeaderHash};
2use cbored::CborRepr;
3use cbored::{Decode, DecodeError, DecodeErrorKind, Encode, Reader, Writer};
4use std::fmt;
5
6#[derive(Clone, Debug)]
7pub struct Time(pub u32);
8
9impl Time {
10    pub fn now() -> Self {
11        Time(std::time::Instant::now().elapsed().as_micros() as u32)
12    }
13}
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
16#[repr(u64)]
17pub enum Version {
18    V6 = 0x6,
19    V7 = 0x7,
20    V8 = 0x8,
21}
22
23impl Version {
24    pub const KNOWN: [Self; 3] = [Version::V6, Version::V7, Version::V8];
25
26    pub fn from_integer(v: u64) -> Option<Version> {
27        for k in Self::KNOWN {
28            if k as u64 == v {
29                return Some(k);
30            }
31        }
32        None
33    }
34}
35
36impl Decode for Version {
37    fn decode<'a>(reader: &mut Reader<'a>) -> Result<Self, DecodeError> {
38        let ver = reader.decode()?;
39        Version::from_integer(ver).ok_or(
40            cbored::DecodeErrorKind::Custom(format!("unknown version : {}", ver)).context::<Self>(),
41        )
42    }
43}
44
45impl Encode for Version {
46    fn encode(&self, writer: &mut Writer) {
47        writer.encode(&(*self as u64))
48    }
49}
50
51crate::vec_structure!(Versions, Version);
52
53#[derive(Clone, Copy, Debug, PartialEq, Eq)]
54pub enum DiffusionMode {
55    InitiatorOnly,
56    InitiatorAndResponder,
57}
58
59impl Encode for DiffusionMode {
60    fn encode(&self, writer: &mut Writer) {
61        match self {
62            DiffusionMode::InitiatorOnly => writer.bool(false),
63            DiffusionMode::InitiatorAndResponder => writer.bool(true),
64        }
65    }
66}
67
68impl Decode for DiffusionMode {
69    fn decode<'a>(reader: &mut Reader<'a>) -> Result<Self, DecodeError> {
70        match reader
71            .bool()
72            .map_err(DecodeErrorKind::ReaderError)
73            .map_err(|e| e.context::<Self>())?
74        {
75            true => Ok(DiffusionMode::InitiatorAndResponder),
76            false => Ok(DiffusionMode::InitiatorOnly),
77        }
78    }
79}
80
81/// Network Magic
82#[derive(Debug, Clone, Copy, PartialEq, Eq, CborRepr)]
83#[cborrepr(structure = "flat")]
84pub struct Magic(pub u64);
85
86impl Magic {
87    pub const PREPROD: Self = Magic(1);
88    pub const PREVIEW: Self = Magic(2);
89    pub const TESTNET: Self = Magic(1097911063);
90    pub const MAINNET: Self = Magic(764824073);
91
92    pub const fn raw(value: u64) -> Self {
93        Magic(value)
94    }
95}
96
97#[derive(Debug, Clone, PartialEq, Eq)]
98pub enum Point {
99    Origin,
100    BlockHeader { slot_nb: u64, hash: HeaderHash },
101}
102
103impl fmt::Display for Point {
104    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
105        match self {
106            Point::Origin => write!(f, "origin"),
107            Point::BlockHeader { slot_nb, hash } => {
108                write!(f, "{}@{}", slot_nb, hash)
109            }
110        }
111    }
112}
113
114impl Point {
115    pub const ORIGIN: Self = Point::Origin;
116
117    pub fn from_raw(slot_nb: u64, s: &str) -> Option<Self> {
118        let hash = HeaderHash::from_hex(s)?;
119        Some(Point::BlockHeader { slot_nb, hash })
120    }
121
122    pub fn hash(&self) -> HeaderHash {
123        match self {
124            Point::Origin => HeaderHash([0; 32]),
125            Point::BlockHeader { slot_nb: _, hash } => hash.clone(),
126        }
127    }
128
129    pub fn slot_nb(&self) -> u64 {
130        match self {
131            Point::Origin => 0,
132            Point::BlockHeader { slot_nb, hash: _ } => *slot_nb,
133        }
134    }
135}
136
137impl Decode for Point {
138    fn decode<'a>(reader: &mut Reader<'a>) -> Result<Self, DecodeError> {
139        let array = reader
140            .array()
141            .map_err(DecodeErrorKind::ReaderError)
142            .map_err(|e| e.context::<Self>())?;
143        if array.len() == 0 {
144            Ok(Point::Origin)
145        } else if array.len() == 2 {
146            let slot_nb = array[0]
147                .decode()
148                .map_err(|e| e.push_str("slot_nb").push::<Self>())?;
149            let hash = array[1]
150                .decode()
151                .map_err(|e| e.push_str("hash").push::<Self>())?;
152            Ok(Point::BlockHeader { slot_nb, hash })
153        } else {
154            Err(DecodeErrorKind::Custom(format!(
155                "wrong expected length of 0 or 2, got {}",
156                array.len()
157            ))
158            .context::<Self>())
159        }
160    }
161}
162
163impl Encode for Point {
164    fn encode(&self, writer: &mut Writer) {
165        match self {
166            Point::Origin => {
167                let len = cbored::StructureLength::from(0);
168                writer.array_build(len, |_| {});
169            }
170            Point::BlockHeader { slot_nb, hash } => {
171                let len = cbored::StructureLength::from(2);
172                writer.array_build(len, |writer| {
173                    writer.encode(slot_nb);
174                    writer.encode(hash);
175                });
176            }
177        }
178    }
179}
180
181#[derive(Debug, Clone)]
182pub struct SerializedHeader(Vec<u8>);
183
184impl Decode for SerializedHeader {
185    fn decode<'a>(reader: &mut Reader<'a>) -> Result<Self, DecodeError> {
186        let cbor = reader
187            .decode::<cbored::tagged::EncodedCBOR>()
188            .map_err(|e| e.push::<Self>())?;
189        Ok(Self(cbor.to_bytes()))
190    }
191}
192
193impl Encode for SerializedHeader {
194    fn encode(&self, writer: &mut Writer) {
195        writer.encode(&cbored::tagged::EncodedCBOR::from_bytes(&self.0))
196    }
197}
198
199impl AsRef<[u8]> for SerializedHeader {
200    fn as_ref(&self) -> &[u8] {
201        &self.0
202    }
203}
204
205#[derive(Debug, Clone)]
206pub struct SerializedBlock(Vec<u8>);
207
208impl SerializedBlock {
209    pub fn unserialize(&self) -> Result<Block, DecodeError> {
210        let mut reader = Reader::new(&self.0);
211        let block = reader.decode_one()?;
212        Ok(block)
213    }
214
215    pub fn unserialize_compat(&self) -> Result<BlockCompat, DecodeError> {
216        let mut reader = Reader::new(&self.0);
217        let block = reader.decode_one()?;
218        Ok(block)
219    }
220}
221
222impl Decode for SerializedBlock {
223    fn decode<'a>(reader: &mut Reader<'a>) -> Result<Self, DecodeError> {
224        let cbor = reader
225            .decode::<cbored::tagged::EncodedCBOR>()
226            .map_err(|e| e.push::<Self>())?;
227        Ok(Self(cbor.to_bytes()))
228    }
229}
230
231impl Encode for SerializedBlock {
232    fn encode(&self, writer: &mut Writer) {
233        writer.encode(&cbored::tagged::EncodedCBOR::from_bytes(&self.0))
234    }
235}
236
237impl AsRef<[u8]> for SerializedBlock {
238    fn as_ref(&self) -> &[u8] {
239        &self.0
240    }
241}