pallas_handshake/
common.rs

1use itertools::Itertools;
2use pallas_machines::{CodecError, DecodePayload, EncodePayload, PayloadEncoder};
3use std::{collections::HashMap, fmt::Debug};
4
5pub const TESTNET_MAGIC: u64 = 1097911063;
6pub const MAINNET_MAGIC: u64 = 764824073;
7
8#[derive(Debug, Clone)]
9pub struct VersionTable<T>
10where
11    T: Debug + Clone + EncodePayload + DecodePayload,
12{
13    pub values: HashMap<u64, T>,
14}
15
16impl<T> EncodePayload for VersionTable<T>
17where
18    T: Debug + Clone + EncodePayload + DecodePayload,
19{
20    fn encode_payload(&self, e: &mut PayloadEncoder) -> Result<(), Box<dyn std::error::Error>> {
21        e.map(self.values.len() as u64)?;
22
23        for key in self.values.keys().sorted() {
24            e.u64(*key)?;
25            self.values[key].encode_payload(e)?;
26        }
27
28        Ok(())
29    }
30}
31
32pub type NetworkMagic = u64;
33
34pub type VersionNumber = u64;
35
36#[derive(Debug)]
37pub enum RefuseReason {
38    VersionMismatch(Vec<VersionNumber>),
39    HandshakeDecodeError(VersionNumber, String),
40    Refused(VersionNumber, String),
41}
42
43impl EncodePayload for RefuseReason {
44    fn encode_payload(&self, e: &mut PayloadEncoder) -> Result<(), Box<dyn std::error::Error>> {
45        match self {
46            RefuseReason::VersionMismatch(versions) => {
47                e.array(2)?;
48                e.u16(0)?;
49                e.array(versions.len() as u64)?;
50                for v in versions.iter() {
51                    e.u64(*v)?;
52                }
53
54                Ok(())
55            }
56            RefuseReason::HandshakeDecodeError(version, msg) => {
57                e.array(3)?;
58                e.u16(1)?;
59                e.u64(*version)?;
60                e.str(msg)?;
61
62                Ok(())
63            }
64            RefuseReason::Refused(version, msg) => {
65                e.array(3)?;
66                e.u16(2)?;
67                e.u64(*version)?;
68                e.str(msg)?;
69
70                Ok(())
71            }
72        }
73    }
74}
75
76impl DecodePayload for RefuseReason {
77    fn decode_payload(
78        d: &mut pallas_machines::PayloadDecoder,
79    ) -> Result<Self, Box<dyn std::error::Error>> {
80        d.array()?;
81
82        match d.u16()? {
83            0 => {
84                let versions = d.array_iter::<u64>()?;
85                let versions = versions.try_collect()?;
86                Ok(RefuseReason::VersionMismatch(versions))
87            }
88            1 => {
89                let version = d.u64()?;
90                let msg = d.str()?;
91
92                Ok(RefuseReason::HandshakeDecodeError(version, msg.to_string()))
93            }
94            2 => {
95                let version = d.u64()?;
96                let msg = d.str()?;
97
98                Ok(RefuseReason::Refused(version, msg.to_string()))
99            }
100            x => Err(Box::new(CodecError::BadLabel(x))),
101        }
102    }
103}