1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
use crate::{mnemonic, MasterSecret, OfflineContext, Result};
use rand::Rng;
use serde::{Deserialize, Serialize};
use structopt::StructOpt;
#[derive(StructOpt, Debug, Serialize, Deserialize, Clone)]
#[structopt(name = "random")]
pub struct RandomOptions {
#[structopt(short, long)]
pub key_name: String,
}
impl OfflineContext {
pub fn create_key(&self, opt: &RandomOptions) -> Result<MasterSecret> {
let sec = rand::thread_rng().gen::<[u8; 32]>();
let mnemonic = mnemonic::Mnemonic::new(&sec)?;
let master_key = MasterSecret::new(self.network, mnemonic, &opt.key_name)?;
self.write_keys(&master_key)?;
Ok(master_key)
}
}
#[cfg(test)]
mod tests {
use crate::common::context::tests::TestContext;
use crate::common::tests::rnd_string;
use crate::offline::random::RandomOptions;
use miniscript::descriptor::DescriptorSecretKey;
use std::str::FromStr;
impl RandomOptions {
pub fn new_random() -> Self {
let key_name = rnd_string();
RandomOptions { key_name }
}
}
#[test]
fn test_random() {
let rand_opts_1 = RandomOptions::new_random();
let context = TestContext::default();
let key_1 = context.create_key(&rand_opts_1).unwrap();
let result = context.create_key(&rand_opts_1);
assert!(result.is_err(), "Overwrite a key");
assert!(result.unwrap_err().to_string().contains("Cannot overwrite"));
let key_2 = context.create_key(&RandomOptions::new_random()).unwrap();
assert_ne!(key_1, key_2);
}
#[test]
fn test_descriptor_key() {
let xpub = "[a15f432e/48'/1'/0']tpubDDoLq7YG6qr18Paph1uJ8F2ncVuSh2DjkixS6CX37nCiJusecE82JXvFmfZh8hp86Bm7sv7Pkprv5phMXn1r49TU6YrDidGmemFAL1PNWXi/0/*";
assert!(miniscript::DescriptorPublicKey::from_str(&xpub).is_ok());
let xpub = "tpubDDoLq7YG6qr18Paph1uJ8F2ncVuSh2DjkixS6CX37nCiJusecE82JXvFmfZh8hp86Bm7sv7Pkprv5phMXn1r49TU6YrDidGmemFAL1PNWXi";
assert!(miniscript::DescriptorPublicKey::from_str(&xpub).is_ok());
let xpub = "[a15f432e/48'/1'/0']tpubDDoLq7YG6qr18Paph1uJ8F2ncVuSh2DjkixS6CX37nCiJusecE82JXvFmfZh8hp86Bm7sv7Pkprv5phMXn1r49TU6YrDidGmemFAL1PNWXi";
assert!(miniscript::DescriptorPublicKey::from_str(&xpub).is_ok());
assert!(DescriptorSecretKey::from_str("xprv9s21ZrQH143K3yGb6gtghzHH4MPaEHGPN48sxoyYd4EdrQcaSVP2dxZS2vRwoKny1KRS5xMMyGunA3WkToah7ZmJ2fFtGK8vBBBiBkVFmTM").is_ok());
}
}