sphinx_packet/
route.rs

1// Copyright 2020 Nym Technologies SA
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use crate::constants::{DESTINATION_ADDRESS_LENGTH, IDENTIFIER_LENGTH, NODE_ADDRESS_LENGTH};
16use crate::{Error, ErrorKind, Result};
17use std::fmt::{self, Display, Formatter};
18
19// in paper delta
20#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Hash)]
21pub struct DestinationAddressBytes([u8; DESTINATION_ADDRESS_LENGTH]);
22
23impl DestinationAddressBytes {
24    pub fn as_base58_string(&self) -> String {
25        bs58::encode(&self.0).into_string()
26    }
27
28    pub fn try_from_base58_string<S: Into<String>>(val: S) -> Result<Self> {
29        let decoded = match bs58::decode(val.into()).into_vec() {
30            Ok(decoded) => decoded,
31            Err(e) => {
32                return Err(Error::new(
33                    ErrorKind::InvalidRouting,
34                    format!("failed to decode destination from b58 string: {:?}", e),
35                ))
36            }
37        };
38
39        if decoded.len() != DESTINATION_ADDRESS_LENGTH {
40            return Err(Error::new(
41                ErrorKind::InvalidRouting,
42                "decoded destination address has invalid length",
43            ));
44        }
45
46        let mut address_bytes = [0; DESTINATION_ADDRESS_LENGTH];
47        address_bytes.copy_from_slice(&decoded[..]);
48
49        Ok(DestinationAddressBytes(address_bytes))
50    }
51
52    pub fn from_bytes(b: [u8; DESTINATION_ADDRESS_LENGTH]) -> Self {
53        DestinationAddressBytes(b)
54    }
55
56    pub fn try_from_byte_slice(b: &[u8]) -> Result<Self> {
57        if b.len() != DESTINATION_ADDRESS_LENGTH {
58            return Err(Error::new(
59                ErrorKind::InvalidRouting,
60                "received bytes got invalid length",
61            ));
62        }
63
64        let mut address_bytes = [0; DESTINATION_ADDRESS_LENGTH];
65        address_bytes.copy_from_slice(b);
66
67        Ok(DestinationAddressBytes(address_bytes))
68    }
69
70    /// View this `DestinationAddressBytes` as an array of bytes.
71    pub fn as_bytes_ref(&self) -> &[u8; DESTINATION_ADDRESS_LENGTH] {
72        &self.0
73    }
74
75    /// Convert this `DestinationAddressBytes` to an array of bytes.
76    pub fn as_bytes(&self) -> [u8; DESTINATION_ADDRESS_LENGTH] {
77        self.0
78    }
79}
80
81impl Display for DestinationAddressBytes {
82    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
83        self.as_base58_string().fmt(f)
84    }
85}
86
87// in paper nu
88#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Hash)]
89pub struct NodeAddressBytes([u8; NODE_ADDRESS_LENGTH]);
90
91impl NodeAddressBytes {
92    pub fn as_base58_string(&self) -> String {
93        bs58::encode(&self.0).into_string()
94    }
95
96    pub fn try_from_base58_string<S: Into<String>>(val: S) -> Result<Self> {
97        let decoded = match bs58::decode(val.into()).into_vec() {
98            Ok(decoded) => decoded,
99            Err(e) => {
100                return Err(Error::new(
101                    ErrorKind::InvalidRouting,
102                    format!("failed to decode node address from b58 string: {:?}", e),
103                ))
104            }
105        };
106
107        if decoded.len() != NODE_ADDRESS_LENGTH {
108            return Err(Error::new(
109                ErrorKind::InvalidRouting,
110                "decoded node address has invalid length",
111            ));
112        }
113
114        let mut address_bytes = [0; NODE_ADDRESS_LENGTH];
115        address_bytes.copy_from_slice(&decoded[..]);
116
117        Ok(NodeAddressBytes(address_bytes))
118    }
119
120    pub fn try_from_byte_slice(b: &[u8]) -> Result<Self> {
121        if b.len() != NODE_ADDRESS_LENGTH {
122            return Err(Error::new(
123                ErrorKind::InvalidRouting,
124                "received bytes got invalid length",
125            ));
126        }
127
128        let mut address_bytes = [0; NODE_ADDRESS_LENGTH];
129        address_bytes.copy_from_slice(b);
130
131        Ok(NodeAddressBytes(address_bytes))
132    }
133
134    pub fn from_bytes(b: [u8; NODE_ADDRESS_LENGTH]) -> Self {
135        NodeAddressBytes(b)
136    }
137
138    /// View this `NodeAddressBytes` as an array of bytes.
139    pub fn as_bytes(&self) -> &[u8; NODE_ADDRESS_LENGTH] {
140        &self.0
141    }
142
143    /// Convert this `NodeAddressBytes` to an array of bytes.
144    pub fn to_bytes(&self) -> [u8; NODE_ADDRESS_LENGTH] {
145        self.0
146    }
147}
148
149impl Display for NodeAddressBytes {
150    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
151        self.as_base58_string().fmt(f)
152    }
153}
154
155// in paper I
156pub type SURBIdentifier = [u8; IDENTIFIER_LENGTH];
157
158#[derive(Clone, Debug, PartialEq, Eq)]
159pub struct Destination {
160    // address in theory could be changed to a vec<u8> as it does not need to be strictly DESTINATION_ADDRESS_LENGTH long
161    // but cannot be longer than that (assuming longest possible route)
162    pub address: DestinationAddressBytes,
163    pub identifier: SURBIdentifier,
164}
165
166impl Destination {
167    pub fn new(address: DestinationAddressBytes, identifier: SURBIdentifier) -> Self {
168        Self {
169            address,
170            identifier,
171        }
172    }
173}
174
175#[derive(Clone, Debug)]
176pub struct Node {
177    pub address: NodeAddressBytes,
178    pub pub_key: x25519_dalek::PublicKey,
179}
180
181impl Node {
182    pub fn new(address: NodeAddressBytes, pub_key: x25519_dalek::PublicKey) -> Self {
183        Self { address, pub_key }
184    }
185}
186
187#[cfg(test)]
188mod address_encoding {
189    use super::*;
190
191    #[test]
192    fn it_is_possible_to_encode_and_decode_address() {
193        let dummy_address = NodeAddressBytes([42u8; 32]);
194        let dummy_address_str = dummy_address.as_base58_string();
195        let recovered = NodeAddressBytes::try_from_base58_string(dummy_address_str).unwrap();
196        assert_eq!(dummy_address, recovered)
197    }
198}