1use std::{convert::TryFrom, str::FromStr};
5
6use super::{KeyInfo, KeyStore, errors::Error, wallet_helpers};
7use crate::shim::{address::Address, crypto::SignatureType};
8use serde::{Deserialize, Serialize};
9
10#[cfg(test)]
11use {
12 crate::shim::crypto::Signature,
13 ahash::{HashMap, HashMapExt as _},
14};
15
16#[derive(Clone, PartialEq, Debug, Eq, Serialize, Deserialize)]
18pub struct Key {
19 pub key_info: KeyInfo,
20 pub public_key: Vec<u8>,
22 pub address: Address,
23}
24
25impl TryFrom<KeyInfo> for Key {
26 type Error = crate::key_management::errors::Error;
27
28 fn try_from(key_info: KeyInfo) -> Result<Self, Self::Error> {
29 let public_key = wallet_helpers::to_public(*key_info.key_type(), key_info.private_key())?;
30 let address = wallet_helpers::new_address(*key_info.key_type(), &public_key)?;
31 Ok(Key {
32 key_info,
33 public_key,
34 address,
35 })
36 }
37}
38
39#[cfg(test)]
45#[derive(Clone, PartialEq, Debug, Eq)]
46pub struct Wallet {
47 keys: HashMap<Address, Key>,
48 keystore: KeyStore,
49}
50
51#[cfg(test)]
52impl Wallet {
53 pub fn new(keystore: KeyStore) -> Self {
55 Wallet {
56 keys: HashMap::new(),
57 keystore,
58 }
59 }
60
61 pub fn new_from_keys(keystore: KeyStore, key_vec: impl IntoIterator<Item = Key>) -> Self {
63 let mut keys: HashMap<Address, Key> = HashMap::new();
64 for item in key_vec.into_iter() {
65 keys.insert(item.address, item);
66 }
67 Wallet { keys, keystore }
68 }
69
70 pub fn find_key(&mut self, addr: &Address) -> Result<Key, Error> {
74 if let Some(k) = self.keys.get(addr) {
75 return Ok(k.clone());
76 }
77 let key_string = format!("wallet-{addr}");
78 let key_info = match self.keystore.get(&key_string) {
79 Ok(k) => k,
80 Err(_) => {
81 self.keystore
83 .get(&format!("wallet-t{}", &addr.to_string()[1..]))?
84 }
85 };
86 let new_key = Key::try_from(key_info)?;
87 self.keys.insert(*addr, new_key.clone());
88 Ok(new_key)
89 }
90
91 pub fn sign(&mut self, addr: &Address, msg: &[u8]) -> Result<Signature, Error> {
93 let key = self.find_key(addr).map_err(|_| Error::KeyNotExists)?;
96 wallet_helpers::sign(*key.key_info.key_type(), key.key_info.private_key(), msg)
97 }
98
99 pub fn export(&mut self, addr: &Address) -> Result<KeyInfo, Error> {
101 let k = self.find_key(addr)?;
102 Ok(k.key_info)
103 }
104
105 pub fn import(&mut self, key_info: KeyInfo) -> Result<Address, Error> {
108 let k = Key::try_from(key_info)?;
109 let addr = format!("wallet-{}", k.address);
110 self.keystore.put(&addr, k.key_info)?;
111 Ok(k.address)
112 }
113
114 pub fn list_addrs(&self) -> Result<Vec<Address>, Error> {
117 list_addrs(&self.keystore)
118 }
119
120 pub fn get_default(&self) -> Result<Address, Error> {
122 let key_info = self.keystore.get("default")?;
123 let k = Key::try_from(key_info)?;
124 Ok(k.address)
125 }
126
127 pub fn set_default(&mut self, addr: Address) -> anyhow::Result<()> {
129 let addr_string = format!("wallet-{addr}");
130 let key_info = self.keystore.get(&addr_string)?;
131 if self.keystore.get("default").is_ok() {
132 self.keystore.remove("default")?; }
137 self.keystore.put("default", key_info)?;
138 Ok(())
139 }
140
141 pub fn generate_addr(&mut self, typ: SignatureType) -> anyhow::Result<Address> {
144 let key = generate_key(typ)?;
145 let addr = format!("wallet-{}", key.address);
146 self.keystore.put(&addr, key.key_info.clone())?;
147 self.keys.insert(key.address, key.clone());
148 let value = self.keystore.get("default");
149 if value.is_err() {
150 self.keystore
151 .put("default", key.key_info.clone())
152 .map_err(|err| Error::Other(err.to_string()))?;
153 }
154
155 Ok(key.address)
156 }
157
158 pub fn has_key(&mut self, addr: &Address) -> bool {
161 self.find_key(addr).is_ok()
162 }
163}
164
165pub fn get_default(keystore: &KeyStore) -> Result<Option<Address>, Error> {
167 if let Ok(key_info) = keystore.get("default") {
168 let k = Key::try_from(key_info)?;
169 Ok(Some(k.address))
170 } else {
171 Ok(None)
172 }
173}
174
175pub fn list_addrs(keystore: &KeyStore) -> Result<Vec<Address>, Error> {
178 let mut all = keystore.list();
179 all.sort();
180 let mut out = Vec::new();
181 for i in all {
182 if let Some(addr_str) = i.strip_prefix("wallet-")
183 && let Ok(addr) = crate::shim::address::StrictAddress::from_str(addr_str)
184 {
185 out.push(addr.into());
186 }
187 }
188 Ok(out)
189}
190
191pub fn find_key(addr: &Address, keystore: &KeyStore) -> Result<Key, Error> {
193 let key_string = format!("wallet-{addr}");
194 let key_info = keystore.get(&key_string)?;
195 let new_key = Key::try_from(key_info)?;
196 Ok(new_key)
197}
198
199pub fn remove_key(addr: &Address, keystore: &mut KeyStore) -> Result<(), Error> {
201 let key_string = format!("wallet-{addr}");
202 let deleted_keyinfo = keystore
203 .remove(&key_string)
204 .map_err(|_| Error::KeyNotExists)?;
205 if let Ok(default_keyinfo) = keystore.get("default")
206 && default_keyinfo == deleted_keyinfo
207 {
208 keystore
209 .remove("default")
210 .map_err(|_| Error::KeyNotExists)?;
211 }
212 println!("wallet {addr} deleted");
213 Ok(())
214}
215
216pub fn try_find(addr: &Address, keystore: &mut KeyStore) -> Result<KeyInfo, Error> {
217 let key_string = format!("wallet-{addr}");
218 match keystore.get(&key_string) {
219 Ok(k) => Ok(k),
220 Err(_) => {
221 let mut new_addr = addr.to_string();
222 if new_addr.len() < 2 {
223 return Err(Error::Other(format!("Invalid addr {new_addr}")));
224 }
225 new_addr.replace_range(0..1, "t");
228 let key_string = format!("wallet-{new_addr}");
229 let key_info = match keystore.get(&key_string) {
230 Ok(k) => k,
231 #[allow(clippy::indexing_slicing)]
232 Err(_) => keystore.get(&format!("wallet-f{}", &new_addr[1..]))?,
233 };
234 Ok(key_info)
235 }
236 }
237}
238
239pub fn export_key_info(addr: &Address, keystore: &KeyStore) -> Result<KeyInfo, Error> {
241 let key = find_key(addr, keystore)?;
242 Ok(key.key_info)
243}
244
245pub fn generate_key(typ: SignatureType) -> Result<Key, Error> {
247 let private_key = wallet_helpers::generate(typ)?;
248 let key_info = KeyInfo::new(typ, private_key);
249 Key::try_from(key_info)
250}
251
252#[cfg(test)]
253mod tests {
254 use crate::utils::encoding::{blake2b_256, keccak_256};
255 use bls_signatures::{PrivateKey as BlsPrivate, Serialize};
256 use libsecp256k1::{Message as SecpMessage, SecretKey as SecpPrivate};
257
258 use super::*;
259 use crate::key_management::{KeyStoreConfig, generate};
260
261 fn construct_priv_keys() -> Vec<Key> {
262 let mut secp_keys = Vec::new();
263 let mut bls_keys = Vec::new();
264 let mut delegated_keys = Vec::new();
265 for _ in 1..5 {
266 let secp_priv_key = generate(SignatureType::Secp256k1).unwrap();
267 let secp_key_info = KeyInfo::new(SignatureType::Secp256k1, secp_priv_key);
268 let secp_key = Key::try_from(secp_key_info).unwrap();
269 secp_keys.push(secp_key);
270
271 let bls_priv_key = generate(SignatureType::Bls).unwrap();
272 let bls_key_info = KeyInfo::new(SignatureType::Bls, bls_priv_key);
273 let bls_key = Key::try_from(bls_key_info).unwrap();
274 bls_keys.push(bls_key);
275
276 let delegated_priv_key = generate(SignatureType::Delegated).unwrap();
277 let delegated_key_info = KeyInfo::new(SignatureType::Delegated, delegated_priv_key);
278 let delegated_key = Key::try_from(delegated_key_info).unwrap();
279 delegated_keys.push(delegated_key);
280 }
281
282 secp_keys.append(bls_keys.as_mut());
283 secp_keys.append(delegated_keys.as_mut());
284 secp_keys
285 }
286
287 fn generate_wallet() -> Wallet {
288 let key_vec = construct_priv_keys();
289 Wallet::new_from_keys(KeyStore::new(KeyStoreConfig::Memory).unwrap(), key_vec)
290 }
291
292 #[test]
293 fn contains_key() {
294 let key_vec = construct_priv_keys();
295 let found_key = key_vec[0].clone();
296 let addr = key_vec[0].address;
297
298 let mut wallet =
299 Wallet::new_from_keys(KeyStore::new(KeyStoreConfig::Memory).unwrap(), key_vec);
300
301 assert_eq!(wallet.find_key(&addr).unwrap(), found_key);
303 assert!(wallet.has_key(&addr));
305
306 let new_priv_key = generate(SignatureType::Bls).unwrap();
307 let pub_key =
308 wallet_helpers::to_public(SignatureType::Bls, new_priv_key.as_slice()).unwrap();
309 let address = Address::new_bls(pub_key.as_slice()).unwrap();
310
311 assert!(!wallet.has_key(&address));
313 assert!(matches!(
316 wallet.find_key(&address).unwrap_err(),
317 Error::KeyInfo
318 ));
319 assert!(!wallet.has_key(&address));
321 }
322
323 #[test]
324 fn secp_sign() {
325 let key_vec = construct_priv_keys();
326 let priv_key_bytes = key_vec[2].key_info.private_key().clone();
327 let addr = key_vec[2].address;
328
329 let keystore = KeyStore::new(KeyStoreConfig::Memory).unwrap();
330 let mut wallet = Wallet::new_from_keys(keystore, key_vec);
331 let msg = [0u8; 64];
332
333 let msg_sig = wallet.sign(&addr, &msg).unwrap();
334
335 let msg_complete = blake2b_256(&msg);
336 let message = SecpMessage::parse(&msg_complete);
337 let priv_key = SecpPrivate::parse_slice(&priv_key_bytes).unwrap();
338 let (sig, recovery_id) = libsecp256k1::sign(&message, &priv_key);
339 let mut new_bytes = [0; 65];
340 new_bytes[..64].copy_from_slice(&sig.serialize());
341 new_bytes[64] = recovery_id.serialize();
342 let actual = Signature::new_secp256k1(new_bytes.to_vec());
343 assert_eq!(msg_sig, actual)
344 }
345
346 #[test]
347 fn bls_sign() {
348 let key_vec = construct_priv_keys();
349 let priv_key_bytes = key_vec[4].key_info.private_key().clone();
350 let addr = key_vec[4].address;
351 let mut wallet =
352 Wallet::new_from_keys(KeyStore::new(KeyStoreConfig::Memory).unwrap(), key_vec);
353
354 let msg = [0u8; 64];
355 let msg_sign = wallet.sign(&addr, &msg).unwrap();
356
357 let priv_key = BlsPrivate::from_bytes(&priv_key_bytes).unwrap();
358 let sig = priv_key.sign(msg);
359 let actual = Signature::new_bls(sig.as_bytes());
360 assert_eq!(msg_sign, actual);
361 }
362
363 #[test]
364 fn delegated_sign() {
365 let key_vec = construct_priv_keys();
366 let priv_key_bytes = key_vec[9].key_info.private_key().clone();
367 let addr = key_vec[9].address;
368
369 let keystore = KeyStore::new(KeyStoreConfig::Memory).unwrap();
370 let mut wallet = Wallet::new_from_keys(keystore, key_vec);
371 let msg = [0u8; 64];
372
373 let msg_sig = wallet.sign(&addr, &msg).unwrap();
374
375 let msg_complete = keccak_256(&msg);
376 let message = SecpMessage::parse(&msg_complete);
377 let priv_key = SecpPrivate::parse_slice(&priv_key_bytes).unwrap();
378 let (sig, recovery_id) = libsecp256k1::sign(&message, &priv_key);
379 let mut new_bytes = [0; 65];
380 new_bytes[..64].copy_from_slice(&sig.serialize());
381 new_bytes[64] = recovery_id.serialize();
382 let actual = Signature::new_delegated(new_bytes.to_vec());
383 assert_eq!(msg_sig, actual)
384 }
385
386 #[test]
387 fn import_export() {
388 let key_vec = construct_priv_keys();
389 let key = key_vec[0].clone();
390 let keystore = KeyStore::new(KeyStoreConfig::Memory).unwrap();
391 let mut wallet = Wallet::new_from_keys(keystore, key_vec);
392
393 let key_info = wallet.export(&key.address).unwrap();
394 assert_eq!(key_info, key.key_info);
396
397 let new_priv_key = generate(SignatureType::Secp256k1).unwrap();
398 let pub_key =
399 wallet_helpers::to_public(SignatureType::Secp256k1, new_priv_key.as_slice()).unwrap();
400 let test_addr = Address::new_secp256k1(pub_key.as_slice()).unwrap();
401 let key_info_err = wallet.export(&test_addr).unwrap_err();
402 assert!(matches!(key_info_err, Error::KeyInfo));
404
405 let test_key_info = KeyInfo::new(SignatureType::Secp256k1, new_priv_key);
406 assert!(wallet.import(test_key_info.clone()).is_ok());
408
409 let duplicate_error = wallet.import(test_key_info).unwrap_err();
410 assert!(matches!(duplicate_error, Error::KeyExists));
413 }
414
415 #[test]
416 fn list_addr() {
417 let key_vec = construct_priv_keys();
418 let mut addr_string_vec = Vec::new();
419
420 let mut key_store = KeyStore::new(KeyStoreConfig::Memory).unwrap();
421
422 for i in &key_vec {
423 addr_string_vec.push(i.address.to_string());
424
425 let addr_string = format!("wallet-{}", i.address);
426 key_store.put(&addr_string, i.key_info.clone()).unwrap();
427 }
428
429 addr_string_vec.sort();
430
431 let mut addr_vec = Vec::new();
432
433 for addr in addr_string_vec {
434 addr_vec.push(Address::from_str(addr.as_str()).unwrap())
435 }
436
437 let wallet = Wallet::new(key_store);
438
439 let test_addr_vec = wallet.list_addrs().unwrap();
440
441 assert_eq!(test_addr_vec, addr_vec);
444 }
445
446 #[test]
447 fn generate_new_key() {
448 let mut wallet = generate_wallet();
449 let addr = wallet.generate_addr(SignatureType::Bls).unwrap();
450 let key = wallet.keystore.get("default").unwrap();
451 assert_eq!(&SignatureType::Bls, key.key_type());
454
455 let address = format!("wallet-{addr}");
456
457 let key_info = wallet.keystore.get(&address).unwrap();
458 let key = wallet.keys.get(&addr).unwrap();
459
460 assert_eq!(key_info.key_type(), &SignatureType::Bls);
463 assert_eq!(key.address, addr);
464 }
465
466 #[test]
467 fn get_set_default() {
468 let key_store = KeyStore::new(KeyStoreConfig::Memory).unwrap();
469 let mut wallet = Wallet::new(key_store);
470 assert!(matches!(wallet.get_default().unwrap_err(), Error::KeyInfo));
472
473 let new_priv_key = generate(SignatureType::Secp256k1).unwrap();
474 let pub_key =
475 wallet_helpers::to_public(SignatureType::Secp256k1, new_priv_key.as_slice()).unwrap();
476 let test_addr = Address::new_secp256k1(pub_key.as_slice()).unwrap();
477
478 let key_info = KeyInfo::new(SignatureType::Secp256k1, new_priv_key);
479 let test_addr_string = format!("wallet-{test_addr}");
480
481 wallet.keystore.put(&test_addr_string, key_info).unwrap();
482
483 assert!(wallet.set_default(test_addr).is_ok());
485
486 assert_eq!(wallet.get_default().unwrap(), test_addr);
489 }
490
491 #[test]
492 fn secp_verify() {
493 let secp_priv_key = generate(SignatureType::Secp256k1).unwrap();
494 let secp_key_info = KeyInfo::new(SignatureType::Secp256k1, secp_priv_key);
495 let secp_key = Key::try_from(secp_key_info).unwrap();
496 let addr = secp_key.address;
497 let key_store = KeyStore::new(KeyStoreConfig::Memory).unwrap();
498 let mut wallet = Wallet::new_from_keys(key_store, vec![secp_key]);
499
500 let msg = [0u8; 64];
501
502 let sig = wallet.sign(&addr, &msg).unwrap();
503 sig.verify(&msg, &addr).unwrap();
504
505 let invalid_addr = wallet.generate_addr(SignatureType::Secp256k1).unwrap();
507 assert!(sig.verify(&msg, &invalid_addr).is_err())
508 }
509
510 #[test]
511 fn bls_verify_test() {
512 let bls_priv_key = generate(SignatureType::Bls).unwrap();
513 let bls_key_info = KeyInfo::new(SignatureType::Bls, bls_priv_key);
514 let bls_key = Key::try_from(bls_key_info).unwrap();
515 let addr = bls_key.address;
516 let key_store = KeyStore::new(KeyStoreConfig::Memory).unwrap();
517 let mut wallet = Wallet::new_from_keys(key_store, vec![bls_key]);
518
519 let msg = [0u8; 64];
520
521 let sig = wallet.sign(&addr, &msg).unwrap();
522 sig.verify(&msg, &addr).unwrap();
523
524 let invalid_addr = wallet.generate_addr(SignatureType::Bls).unwrap();
526 assert!(sig.verify(&msg, &invalid_addr).is_err())
527 }
528
529 #[test]
530 fn delegated_verify() {
531 let delegated_priv_key = generate(SignatureType::Delegated).unwrap();
532 let delegated_key_info = KeyInfo::new(SignatureType::Delegated, delegated_priv_key);
533 let delegated_key = Key::try_from(delegated_key_info).unwrap();
534 let addr = delegated_key.address;
535
536 let key_store = KeyStore::new(KeyStoreConfig::Memory).unwrap();
537 let mut wallet = Wallet::new_from_keys(key_store, vec![delegated_key]);
538
539 let msg = [0u8; 64];
540
541 let sig = wallet.sign(&addr, &msg).unwrap();
542 sig.verify(&msg, &addr).unwrap();
543
544 let invalid_addr = wallet.generate_addr(SignatureType::Delegated).unwrap();
546 assert!(sig.verify(&msg, &invalid_addr).is_err())
547 }
548}