waves_rust/model/account/
public_key.rs

1use crate::error::Error::InvalidBytesLength;
2use crate::error::{Error, Result};
3use crate::model::account::Address;
4use crate::model::ByteString;
5use crate::util::Base58;
6use std::fmt;
7
8#[derive(Clone, Eq, PartialEq, Hash)]
9pub struct PublicKey {
10    bytes: Vec<u8>,
11}
12
13impl fmt::Debug for PublicKey {
14    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
15        write!(f, "PublicKey {{ {} }}", self.encoded())
16    }
17}
18
19impl std::str::FromStr for PublicKey {
20    type Err = Error;
21
22    fn from_str(base58string: &str) -> Result<PublicKey> {
23        let bytes = Base58::decode(base58string)?;
24        Ok(PublicKey { bytes })
25    }
26}
27
28impl PublicKey {
29    pub fn from_bytes(bytes: &[u8]) -> Result<PublicKey> {
30        if bytes.len() != 32 {
31            Err(InvalidBytesLength {
32                expected_len: 32,
33                actual_len: bytes.len(),
34            })?;
35        }
36        Ok(PublicKey {
37            bytes: Vec::from(bytes),
38        })
39    }
40
41    pub fn from_string(base58string: &str) -> Result<PublicKey> {
42        let bytes = Base58::decode(base58string)?;
43        Ok(PublicKey { bytes })
44    }
45
46    pub fn address(&self, chain_id: u8) -> Result<Address> {
47        Address::from_public_key(chain_id, self)
48    }
49}
50
51impl ByteString for PublicKey {
52    fn bytes(&self) -> Vec<u8> {
53        self.bytes.clone()
54    }
55
56    fn encoded(&self) -> String {
57        Base58::encode(&self.bytes, false)
58    }
59
60    fn encoded_with_prefix(&self) -> String {
61        Base58::encode(&self.bytes, true)
62    }
63}
64
65impl TryFrom<&str> for PublicKey {
66    type Error = Error;
67
68    fn try_from(value: &str) -> Result<Self> {
69        PublicKey::from_string(value)
70    }
71}
72
73impl TryFrom<String> for PublicKey {
74    type Error = Error;
75
76    fn try_from(value: String) -> Result<Self> {
77        PublicKey::from_string(&value)
78    }
79}
80
81#[cfg(test)]
82mod tests {
83    use std::str::FromStr;
84
85    use crate::error::Error::InvalidBytesLength;
86    use crate::error::Result;
87    use crate::model::account::{PrivateKey, PublicKey};
88    use crate::model::ByteString;
89    use crate::util::{Base58, Crypto};
90
91    #[test]
92    fn test_public_key_from_bytes() -> Result<()> {
93        let seed_phrase = "blame vacant regret company chase trip grant funny brisk innocent";
94
95        let expected_public_key_from_nonce_0 = "8cj6YzvQPhSHGvnjupNTW8zrADTT8CMAAd2xTuej84gB";
96        let expected_public_key_from_nonce_128 = "DTvCW1nzFr7mHrHkGf1apstRfwPp4yYL19YvjjLEAPBh";
97        let expected_public_key_from_nonce_255 = "esjbpqVWSg8iCaPYQA3SoxZo3oUkdRJSi9tKLoqKQoC";
98
99        assert_eq!(
100            PublicKey::from_bytes(&public_key_bytes(seed_phrase, 0))?.encoded(),
101            expected_public_key_from_nonce_0
102        );
103        assert_eq!(
104            PublicKey::from_bytes(&public_key_bytes(seed_phrase, 128))?.encoded(),
105            expected_public_key_from_nonce_128
106        );
107        assert_eq!(
108            PublicKey::from_bytes(&public_key_bytes(seed_phrase, 255))?.encoded(),
109            expected_public_key_from_nonce_255
110        );
111        Ok(())
112    }
113
114    fn public_key_bytes(seed_phrase: &str, nonce: u8) -> Vec<u8> {
115        let bytes = PrivateKey::from_seed(seed_phrase, nonce)
116            .expect("failed to get private ket from seed phrase")
117            .bytes();
118        println!("{}", Base58::encode(&bytes.to_vec(), false));
119        Crypto::get_public_key(&bytes)
120    }
121
122    #[test]
123    fn test_invalid_bytes_len_for_public_key() -> Result<()> {
124        let public_key = PublicKey::from_bytes(&[]);
125        match public_key {
126            Ok(_) => panic!("expected error"),
127            Err(err) => match err {
128                InvalidBytesLength { .. } => Ok(()),
129                _ => panic!("expected InvalidBytesLength error"),
130            },
131        }
132    }
133
134    #[test]
135    fn test_public_key_from_str() -> Result<()> {
136        let expected_str = "8cj6YzvQPhSHGvnjupNTW8zrADTT8CMAAd2xTuej84gB";
137        let public_key: PublicKey = expected_str.try_into()?;
138        assert_eq!(expected_str, public_key.encoded());
139        Ok(())
140    }
141
142    #[test]
143    fn test_public_key_from_string() -> Result<()> {
144        let expected_string = "8cj6YzvQPhSHGvnjupNTW8zrADTT8CMAAd2xTuej84gB".to_owned();
145        let public_key: PublicKey = expected_string.clone().try_into()?;
146        assert_eq!(expected_string, public_key.encoded());
147        Ok(())
148    }
149
150    #[test]
151    fn test_public_key_std_from_str() -> Result<()> {
152        let expected_string = "8cj6YzvQPhSHGvnjupNTW8zrADTT8CMAAd2xTuej84gB".to_owned();
153        let public_key = PublicKey::from_str(&expected_string)?;
154        assert_eq!(expected_string, public_key.encoded());
155        Ok(())
156    }
157
158    #[test]
159    fn test_byte_string_for_public_key() -> Result<()> {
160        let public_key: PublicKey = "8cj6YzvQPhSHGvnjupNTW8zrADTT8CMAAd2xTuej84gB".try_into()?;
161        let expected_bytes = vec![
162            113, 40, 188, 13, 166, 104, 24, 229, 65, 157, 176, 205, 96, 187, 101, 62, 170, 97, 253,
163            32, 117, 73, 107, 139, 119, 67, 237, 157, 117, 22, 27, 36,
164        ];
165        assert_eq!(expected_bytes, public_key.bytes());
166        assert_eq!(
167            "8cj6YzvQPhSHGvnjupNTW8zrADTT8CMAAd2xTuej84gB",
168            public_key.encoded()
169        );
170        assert_eq!(
171            "base58:8cj6YzvQPhSHGvnjupNTW8zrADTT8CMAAd2xTuej84gB",
172            public_key.encoded_with_prefix()
173        );
174        Ok(())
175    }
176}