saito_core/core/consensus/
hop.rs

1use std::fmt::Display;
2use std::io::{Error, ErrorKind};
3
4use serde::{Deserialize, Serialize};
5
6use crate::core::consensus::transaction::Transaction;
7use crate::core::defs::{PrintForLog, SaitoPrivateKey, SaitoPublicKey, SaitoSignature};
8use crate::core::util::crypto::sign;
9
10pub const HOP_SIZE: usize = 130;
11
12#[serde_with::serde_as]
13#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
14pub struct Hop {
15    #[serde_as(as = "[_; 33]")]
16    pub from: SaitoPublicKey,
17    #[serde_as(as = "[_; 33]")]
18    pub to: SaitoPublicKey,
19    #[serde_as(as = "[_; 64]")]
20    pub sig: SaitoSignature,
21}
22impl Display for Hop {
23    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
24        writeln!(f, "Hop : {{")?;
25        writeln!(f, " from : {}", self.from.to_base58())?;
26        writeln!(f, " to : {}", self.to.to_base58())?;
27        writeln!(f, " sig: {}", self.sig.to_hex())?;
28        writeln!(f, "}}")
29    }
30}
31impl Default for Hop {
32    fn default() -> Self {
33        Hop {
34            from: [0; 33],
35            to: [0; 33],
36            sig: [0; 64],
37        }
38    }
39}
40
41impl Hop {
42    pub fn generate(
43        my_private_key: &SaitoPrivateKey,
44        my_public_key: &SaitoPublicKey,
45        to_public_key: &SaitoPublicKey,
46        tx: &Transaction,
47    ) -> Hop {
48        let mut hop = Hop::default();
49
50        // msg-to-sign is hash of transaction signature + next_peer.public_key
51        let buffer: Vec<u8> = [tx.signature.as_slice(), to_public_key.as_slice()].concat();
52
53        hop.from = my_public_key.clone();
54        hop.to = to_public_key.clone();
55        hop.sig = sign(buffer.as_slice(), &my_private_key);
56
57        hop
58    }
59
60    pub fn deserialize_from_net(bytes: &Vec<u8>) -> Result<Hop, Error> {
61        if bytes.len() != HOP_SIZE {
62            return Err(Error::from(ErrorKind::InvalidInput));
63        }
64        let from: SaitoPublicKey = bytes[..33]
65            .try_into()
66            .or(Err(Error::from(ErrorKind::InvalidData)))?;
67        let to: SaitoPublicKey = bytes[33..66]
68            .try_into()
69            .or(Err(Error::from(ErrorKind::InvalidData)))?;
70        let sig: SaitoSignature = bytes[66..130]
71            .try_into()
72            .or(Err(Error::from(ErrorKind::InvalidData)))?;
73
74        let mut hop = Hop::default();
75        hop.from = from;
76        hop.to = to;
77        hop.sig = sig;
78
79        Ok(hop)
80    }
81
82    pub fn serialize_for_net(&self) -> Vec<u8> {
83        let vbytes: Vec<u8> = [
84            self.from.as_slice(),
85            self.to.as_slice(),
86            self.sig.as_slice(),
87        ]
88        .concat();
89        // vbytes.extend(&self.from);
90        // vbytes.extend(&self.to);
91        // vbytes.extend(&self.sig);
92        vbytes
93    }
94}
95
96#[cfg(test)]
97mod tests {
98    use std::sync::Arc;
99
100    use tokio::sync::RwLock;
101
102    use crate::core::consensus::hop::Hop;
103    use crate::core::consensus::wallet::Wallet;
104    use crate::core::defs::SaitoPublicKey;
105    use crate::core::util::crypto::{generate_keys, verify};
106
107    use super::*;
108
109    #[test]
110    fn hop_new_test() {
111        let hop = Hop::default();
112        assert_eq!(hop.from, [0; 33]);
113        assert_eq!(hop.to, [0; 33]);
114        assert_eq!(hop.sig, [0; 64]);
115    }
116
117    #[tokio::test]
118    async fn generate_test() {
119        let keys = generate_keys();
120        let wallet = Arc::new(RwLock::new(Wallet::new(keys.1, keys.0)));
121        let sender_public_key: SaitoPublicKey;
122
123        {
124            let wallet = wallet.read().await;
125
126            sender_public_key = wallet.public_key;
127        }
128
129        let tx = Transaction::default();
130        let (receiver_public_key, _receiver_private_key) = generate_keys();
131
132        let wallet = wallet.read().await;
133        let hop = Hop::generate(
134            &wallet.private_key,
135            &wallet.public_key,
136            &receiver_public_key,
137            &tx,
138        );
139
140        assert_eq!(hop.from, sender_public_key);
141        assert_eq!(hop.to, receiver_public_key);
142    }
143
144    #[tokio::test]
145    async fn serialize_and_deserialize_test() {
146        let keys = generate_keys();
147        let wallet = Arc::new(RwLock::new(Wallet::new(keys.1, keys.0)));
148        let mut tx = Transaction::default();
149        {
150            let wallet = wallet.read().await;
151            tx.sign(&wallet.private_key);
152        }
153        let (receiver_public_key, _receiver_private_key) = generate_keys();
154
155        let wallet = wallet.read().await;
156        let hop = Hop::generate(
157            &wallet.private_key,
158            &wallet.public_key,
159            &receiver_public_key,
160            &tx,
161        );
162
163        let hop2 = Hop::deserialize_from_net(&hop.serialize_for_net()).unwrap();
164
165        assert_eq!(hop.from, hop2.from);
166        assert_eq!(hop.to, hop2.to);
167        assert_eq!(hop.sig, hop2.sig);
168
169        let mut buffer = vec![];
170        buffer.extend(tx.signature.to_vec());
171        buffer.extend(hop.to.to_vec());
172        let result = verify(buffer.as_slice(), &hop.sig, &hop.from);
173        assert!(result);
174
175        let result = Hop::deserialize_from_net(&vec![]);
176        assert!(result.is_err());
177    }
178}