derivation32/
lib.rs

1//! **Implementation of [bip-0032](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki)
2//!  in rust for use on command line interface.**
3//!
4//! ## Advantages
5//!
6//! * **Freedom**
7//!
8//!     This tool don't have the restrictions that almost all others have. It's capable of derive
9//!  any child in any path that you want, any time you want. But remember: *with great power comes
10//!  great responsibility*.
11//!
12//! ## Disclaimer
13//!
14//! * **Don't trust, verify**
15//!
16//!     Compare the results of this tool with others. Verify the implementation (and the tests).
17//!
18//!     If encryption is used, test [decryption](https://crates.io/crates/encrypt38) until you are
19//!  convinced that the passphrase you *used* was the one you *wanted*.
20//!
21//!     **Use at your won risk.**
22//!
23//! ## Example
24//!
25//! ```console
26//! $ derivation32 ypub6ZXGqDMx4DsojFChRekQJdW5w1UW5JaLUrSN7wXUcoDf2egC21Ycq1ostNik2wz9nd48pyEL6n6CxBNap6B56iMyHEBv3ytGugKRUCj9LSP
27//! ypub6ZXGqDMx4DsojFChRekQJdW5w1UW5JaLUrSN7wXUcoDf2egC21Ycq1ostNik2wz9nd48pyEL6n6CxBNap6B56iMyHEBv3ytGugKRUCj9LSP
28//! m/0 | 3AvgNg5V1TkMU7yZZCPTdohzySmBX3Wsnt | 03ea2d750dab0388662ecc142eec8379d52a3fb2c3d03c5a64555a85dff3b34497
29//! m/1 | 3511m3xxtmKjiBJYcKZGyxVSJ7jwNBwAPK | 024940543af2b30e68762feaad32457dc7f0711f01d20e1097bafb7eee47f257d5
30//! m/2 | 3FSwvaEECxQHJgWA6fQeYoYYEAauk7cJSg | 036e7cee3e0e0a951178716fa5e5e7bfb26b7f073fc5daca26ff528c0846cabbb4
31//! m/3 | 33QM6BAorebmxpB35S1Kuo5edwMy7QrhHC | 036c6b4e86ef104fe72725de3508bd041a797728ac83631e927679163ff0fc8c19
32//! m/4 | 35tf6DpuS7iZ2nXH8C6DNawFXz4Br9mqie | 03d93e0c9ab1a4442d73707053a9fa4b56dd14f3d2f79e73d6f181d1ad8783a0e6
33//! m/5 | 3PuaDPqBkHnwHWAufm78UdozMPzj2Ap5qo | 0300e46b582e78f38abb219cb3eb22b386789b1988b829a30b563a9e69b95dce2d
34//! m/6 | 3HmBbbDfgKTxGAGfxy1n1okKudgphwVgym | 025b841819bc7f849d55942392e404899affc1a0b76b9575b3e2dbf0f76cdb5b86
35//! m/7 | 3FdEm4dakmMs4ScSmDmyUbBK3THRWkBBFk | 03cbbfb8922148d2af520a680bbcba42add58f7dc6c403308aedce957a994ff6b2
36//! m/8 | 3Nn995qzzzUwz8mKyjfAozBKb6xX68GBgt | 0255c327c5c4507cb76b961b518d985db340f9b1c19add118171d0ef98254c1964
37//! m/9 | 3EES1qCEGAzXbSNtXcpCZBe5G2u4p9pEC5 | 02b9ca0ff5e63fb59a464ab146612e9d79f8b21bbb2f606283fcbcf7c2f5bb06d1
38//! ```
39//!
40//! ## Features
41//!
42//! * **Address**
43//!
44//!     Insert an address to show information about it.
45//!
46//!     Inform hexadecimal entropy or wif private key to generate address.
47//!
48//!     This tool show the respective address of a derived child in the legacy, segwit-nested and
49//!  segwit-native formats according to the version prefix of the informed extended private key.
50//!
51//! * **Custom separator**
52//!
53//!     Customization of the default separator of information when deriving an extended key.
54//!
55//! * **Derivation**
56//!
57//!     Receives an extended key and show the derivation on default path (according to version
58//! prefix).
59//!
60//! * **Encryption**
61//!
62//!     Optional encryption of resulting private keys with bip-0038 standard.
63//!
64//! * **Extended keys**
65//!
66//!     Show the private and public extended keys of the derived path.
67//!
68//! * **Path specification**
69//!
70//!     Specify a custom path used to derive the extended key.
71//!
72//! * **Range of result**
73//!
74//!     This tool optionally receives a range of child numbers to be showed (including hardened
75//!  ones when possible).
76//!
77//! ## Help
78//!
79//! ```shell
80//! Inform extended key and optional path and/or range to show derivation. Insert
81//! address, hexadecimal entropy or wif private key to show information about it.
82//! Optional range is closed (include start and end). Optionally encrypts private
83//! keys. Default separator of results can be customized.
84//!
85//! Usage: derivation32 [OPTIONS] <DATA>
86//!
87//! Arguments:
88//!   <DATA>  Address, hexadecimal entropy, extended key or wif key
89//!
90//! Options:
91//!   -e <passphrase>      Encrypt resulting private keys (bip-0038)
92//!   -p <path>            Path used to derive the extended private key
93//!   -r <range>           Closed range in the form of (1..9h) used on derivation
94//!   -s <separator>       Specify a character (or string) to separate results
95//!   -h, --help           Print help
96//!   -V, --version        Print version
97//! derivation32 1.1.3
98//! Inform extended key and optional path and/or range to show derivation. Insert
99//! address, hexadecimal entropy or wif private key to show information about it.
100//! Optional range is closed (include start and end). Optionally encrypts private
101//! keys. Default separator of results can be customized.
102//!
103//! USAGE:
104//!     derivation32 [OPTIONS] <DATA>
105//!
106//! FLAGS:
107//!     -h, --help       Prints help information
108//!     -V, --version    Prints version information
109//!
110//! OPTIONS:
111//!     -e <passphrase>        Encrypt resulting private keys (bip-0038)
112//!     -p <path>              Path used to derive the extended private key
113//!     -r <range>             Closed range in the form of (1..9h) used on derivation
114//!     -s <separator>         Specify a character (or string) to separate results
115//!
116//! ARGS:
117//!     <DATA>    Address, hexadecimal entropy, extended key or wif key
118//! ```
119//!
120//! ## Installation
121//!
122//! You have to install [rust](https://www.rust-lang.org/tools/install) and a
123//!  [linker](https://gcc.gnu.org/wiki/InstallingGCC) if you don't already have them.
124//!
125//! ```shell
126//! $ cargo install derivation32
127//! ```
128//!
129//! ## Recommendation
130//!
131//! * **Generation of extended root keys**
132//!
133//!     If you don't have a mnemonic and the corresponding extended root keys consider using
134//!  [mnemonic39](https://crates.io/crates/mnemonic39).
135
136use bip38::Encrypt;
137use bitcoin_bech32::constants::Network;
138use bitcoin_bech32::{u5, WitnessProgram};
139use clap::{
140    builder::OsStringValueParser, builder::TypedValueParser, crate_version, Arg, ArgMatches,
141    Command,
142};
143use hmac::{Hmac, Mac};
144use ripemd::Ripemd160;
145use secp256k1::{PublicKey, Scalar, Secp256k1, SecretKey};
146use sha2::Digest;
147use std::ffi::OsString;
148
149/// Head of user information.
150const ABOUT: &str = "Inform extended key and optional path and/or range to show derivation. Insert
151address, hexadecimal entropy or wif private key to show information about it.
152Optional range is closed (include start and end). Optionally encrypts private
153keys. Default separator of results can be customized.";
154
155/// Default range of 'children' used in derivation if none is specified.
156const DEF_RNG: (u32, u32) = (0, 9);
157
158/// Default separator used between results if no other is specified.
159const DEF_SEP: &str = " | ";
160
161/// First index of a hardened derivation (first hardened child: 0h).
162const HARD_NB: u32 = 0x80000000;
163
164/// Character that denotes a hardened child in the derivation path.
165const HARD_CHAR: char = 'h';
166
167/// Minimal number of characters in data argument
168const LEN_ARG_MIN: usize = 27;
169
170/// Number of base 58 characters that represent an extended key.
171const LEN_XKEY: usize = 111;
172
173/// Maximum base 58 characters in legacy and nested tipe of address (1,3)
174const LEN_LEG_MAX: usize = 35;
175
176/// Minimum base 58 characters in legacy and nested tipe of address (1,3).
177const LEN_LEG_MIN: usize = 27;
178
179/// Number of characters present in native segwit address.
180const LEN_SEGWIT: usize = 42;
181
182/// Number of characters in wif compressed secret key.
183const LEN_WIF_C: usize = 52;
184
185/// Number of characters in wif uncompressed secret key.
186const LEN_WIF_U: usize = 51;
187
188/// Number of bytes of a public key compressed.
189const NBBY_PUBC: usize = 33;
190
191/// Number of bytes of a public key uncompressed.
192const NBBY_PUBU: usize = 65;
193
194/// Number of bytes (payload only) contained a decoded wif compressed key.
195const NBBY_WIFC: usize = 34;
196
197/// Number of bytes (payload only) contained a decoded wif uncompressed key.
198const NBBY_WIFU: usize = 33;
199
200/// Number of bytes of a root key (payload only).
201const NBBY_XKEY: usize = 78;
202
203/// Byte of 'OP_0' in the Script language.
204const OP_0: u8 = 0x00;
205
206/// Byte to push the next 20 bytes in the Script language.
207const OP_PUSH20: u8 = 0x14;
208
209/// First character of all paths.
210const PATH_START: &str = "m";
211
212/// Valid prefixes of main net address.
213const PRE_ADDR: &str = "13bc";
214
215/// Prefix of all p2wpkh-p2sh address in main net.
216const PRE_P2WPKH_P2SH_B: u8 = 0x05;
217
218/// First two possible characters of wif compressed.
219const PRE_WIF_C: &str = "KL";
220
221/// First byte of all wif encoded secret keys.
222const PRE_WIF_B: u8 = 0x80;
223
224/// First character of wif uncompressed.
225const PRE_WIF_U: &str = "5";
226
227/// All valid versions in string representation of private extended keys.
228const PRE_PRV_KEY: [&str; 6] = ["tprv", "uprv", "vprv", "xprv", "yprv", "zprv"];
229
230/// All valid versions in string representation of public extended keys.
231const PRE_PUB_KEY: [&str; 6] = ["tpub", "upub", "vpub", "xpub", "ypub", "zpub"];
232
233/// String used as separator on derivation paths.
234const SEP_PATH: char = '/';
235
236/// String used as separator of range.
237const SEP_RANGE: &str = "..";
238
239/// Test net version of bip-0032 extended private keys.
240const TPRV: [u8; 4] = [0x04, 0x35, 0x83, 0x94];
241
242/// Test net version of bip-0032 extended public keys.
243const TPUB: [u8; 4] = [0x04, 0x35, 0x87, 0xcf];
244
245/// Test net version of bip-0049 extended private keys.
246const UPRV: [u8; 4] = [0x04, 0x4a, 0x4e, 0x28];
247
248/// Test net version of bip-0049 extended public keys.
249const UPUB: [u8; 4] = [0x04, 0x4a, 0x52, 0x62];
250
251/// Test net version of bip-0084 extended private keys.
252const VPRV: [u8; 4] = [0x04, 0x5f, 0x18, 0xbc];
253
254/// Test net version of bip-0084 extended public keys.
255const VPUB: [u8; 4] = [0x04, 0x5f, 0x1c, 0xf6];
256
257/// Main net version of bip-0032 extended private keys.
258const XPRV: [u8; 4] = [0x04, 0x88, 0xad, 0xe4];
259
260/// Main net version of bip-0032 extended public keys.
261const XPUB: [u8; 4] = [0x04, 0x88, 0xb2, 0x1e];
262
263/// Main net version of bip-0049 extended private keys.
264const YPRV: [u8; 4] = [0x04, 0x9d, 0x78, 0x78];
265
266/// Main net version of bip-0049 extended public keys.
267const YPUB: [u8; 4] = [0x04, 0x9d, 0x7c, 0xb2];
268
269/// Main net version of bip-0084 extended private keys.
270const ZPRV: [u8; 4] = [0x04, 0xb2, 0x43, 0x0c];
271
272/// Main net version of bip-0084 extended public keys.
273const ZPUB: [u8; 4] = [0x04, 0xb2, 0x47, 0x46];
274
275/// Error types of 'derivation' project.
276#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd)]
277#[doc(hidden)]
278pub enum Error {
279    /// Invalid address is received.
280    Address,
281    /// Invalid argument length.
282    Argument(String),
283    /// Invalid base 58 string encountered.
284    Base58,
285    /// Invalid bech32 data is found.
286    Bech32,
287    /// Wrapper for errors of 'bip38' dependency.
288    Bip38(bip38::Error),
289    /// Invalid checksum encountered.
290    Checksum,
291    /// Found invalid option in the current context.
292    Context(String),
293    /// Invalid attempt to derive a hardened child from extended public key.
294    FromHard,
295    /// Invalid hexadecimal value represented in string.
296    HexStr,
297    /// Invalid input in hmac function.
298    Hmac,
299    /// Key with invalid length found.
300    KeyLen,
301    /// Invalid key version (as prefix) found.
302    KeyVer,
303    /// Invalid number of public key bytes.
304    NbPubB(usize),
305    /// Not found data to process
306    NotFound,
307    /// Invalid derivation path string.
308    Path(String),
309    /// Invalid private data found.
310    PrvData,
311    /// Invalid public data found.
312    PubData,
313    /// Invalid range was found.
314    Range(String),
315    /// Invalid secret entropy found (could not generate address).
316    SecEnt,
317    /// Invalid wif secret key.
318    WifKey,
319}
320
321/// Structure to represent a extended private key.
322#[derive(Clone, Copy, Debug, PartialEq)]
323struct ExtPrvKey {
324    pub version: [u8; 4],
325    pub depth: u8,
326    pub parentf: [u8; 4],
327    pub childnb: u32,
328    pub chaincd: [u8; 32],
329    pub prvdata: [u8; 32], // ignores '0x00' prefix of all private data
330    pub purpose: u32,
331}
332
333/// Structure to represent a extended public key.
334#[derive(Clone, Copy, Debug, PartialEq)]
335struct ExtPubKey {
336    pub version: [u8; 4],
337    pub depth: u8,
338    pub parentf: [u8; 4],
339    pub childnb: u32,
340    pub chaincd: [u8; 32],
341    pub pubdata: [u8; 33],
342    pub purpose: u32,
343}
344
345/// Functions to manipulate data in form of arbitrary number of bytes [u8].
346trait BytesManipulation {
347    /// Encode informed data in base 58 check.
348    fn encode_base58ck(&self) -> String;
349
350    /// Sha256 and ripemd160 in sequence.
351    fn hash160(&self) -> [u8; 20];
352
353    /// Receives an arbitrary number of bytes and return 32 bytes of a double sha256 hash.
354    fn hash256(&self) -> [u8; 32];
355
356    /// Receives bytes and return string of hexadecimal characters.
357    fn hex_string(&self) -> String;
358
359    /// Create an p2wpkh address according to inserted public key bytes.
360    fn p2wpkh(&self) -> Result<String, Error>;
361}
362
363/// Function to manipulate derivation path in form of [u32].
364trait PathManipulation {
365    /// Transform a path in a form of u32 values into a string of type 'm/0...'
366    fn encode_path(&self) -> String;
367}
368
369/// Functions to manipulate private keys in 32 bytes.
370trait PrivateKeyManipulation {
371    /// Generate a secret key represented in wif format.
372    fn encode_wif(&self, compress: bool) -> Result<String, Error>;
373
374    /// Generate secp256k1 point based on target secret key.
375    fn public_key(&self, compress: bool) -> Result<Vec<u8>, Error>;
376}
377
378/// Functions to manipulate compressed public keys (33 bytes).
379trait PublicKeyCompressedManipulation {
380    /// Generate an segwit address of a compressed public key.
381    fn segwit_p2wpkh(&self) -> Result<String, Error>;
382
383    /// Generate an segwit address according to informed compressed public key.
384    fn segwit_p2wpkh_p2sh(&self) -> Result<String, Error>;
385}
386
387/// Functions to manipulate strings in various occasions.
388trait StringManipulation {
389    /// Decode an address into bytes (payload only).
390    fn decode_address(&self) -> Result<Vec<u8>, Error>;
391
392    /// Decode target base 58 string into bytes (payload only).
393    fn decode_base58ck(&self) -> Result<Vec<u8>, Error>;
394
395    /// Decode a secret key encoded in base 58 and return bytes compression.
396    fn decode_wif(&self) -> Result<([u8; 32], bool), Error>;
397
398    /// Transform string of hexadecimal characters into a vector of bytes.
399    fn hex_bytes(&self) -> Result<Vec<u8>, Error>;
400
401    /// Show information about target secret hexadecimal entropy.
402    fn info_entropy(&self, pass: &str, separator: &str) -> Result<(), Error>;
403
404    /// Show information about informed wif secret key.
405    fn info_wif(&self, pass: &str, separator: &str) -> Result<(), Error>;
406
407    /// Test if an string of arbitrary length contains only hexadecimal chars.
408    fn is_hex(&self) -> bool;
409
410    /// Transform a path string into u32 vector of corresponding values.
411    fn decode_path(&self, public: bool) -> Result<Vec<u32>, Error>;
412
413    /// Transform a range of the type '0..9' into values (inclusive).
414    fn decode_range(&self) -> Result<(u32, u32), Error>;
415}
416
417impl core::fmt::Display for Error {
418    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
419        match self {
420            Error::Address => write!(f, "invalid address"),
421            Error::Argument(a) => write!(f, "invalid argument: '\x1b[33m{}\x1b[m'", a),
422            Error::Base58 => write!(f, "invalid base 58 string"),
423            Error::Bech32 => write!(f, "invalid bech32 string"),
424            Error::Bip38(err) => write!(f, "{}", err),
425            Error::Checksum => write!(f, "invalid checksum"),
426            Error::Context(o) => write!(
427                f,
428                "option '\x1b[33m{}\x1b[m' invalid in this context (aborted)",
429                o
430            ),
431            Error::FromHard => write!(f, "cannot derive hardened from public"),
432            Error::HexStr => write!(f, "invalid hexadecimal string"),
433            Error::Hmac => write!(f, "invalid input in hmac"),
434            Error::KeyLen => write!(f, "invalid key length"),
435            Error::KeyVer => write!(f, "invalid key version (prefix)"),
436            Error::NbPubB(nb) => write!(
437                f,
438                "invalid number of bytes in the public key: '\x1b[33m{}\x1b[m'",
439                nb
440            ),
441            Error::NotFound => write!(f, "data to process not found"),
442            Error::Path(v) => write!(f, "invalid path value: '\x1b[33m{}\x1b[m'", v),
443            Error::PrvData => write!(f, "invalid private data"),
444            Error::PubData => write!(f, "invalid public data"),
445            Error::Range(r) => write!(f, "invalid range value: '\x1b[33m{}\x1b[m'", r),
446            Error::SecEnt => write!(f, "invalid secret entropy"),
447            Error::WifKey => write!(f, "invalid wif secret key"),
448        }
449    }
450}
451
452impl From<bip38::Error> for Error {
453    fn from(err: bip38::Error) -> Self {
454        Error::Bip38(err)
455    }
456}
457
458/// Implementation of trait BytesManipulation.
459impl BytesManipulation for [u8] {
460    #[inline]
461    fn encode_base58ck(&self) -> String {
462        let mut decoded: Vec<u8> = self.to_vec();
463        decoded.append(&mut decoded.hash256()[..4].to_vec());
464        bs58::encode(decoded).into_string()
465    }
466
467    #[inline]
468    fn hash160(&self) -> [u8; 20] {
469        let mut result = [0x00; 20];
470        result[..].copy_from_slice(&Ripemd160::digest(&sha2::Sha256::digest(self)));
471        result
472    }
473
474    #[inline]
475    fn hash256(&self) -> [u8; 32] {
476        let mut result = [0x00; 32];
477        result[..].copy_from_slice(&sha2::Sha256::digest(&sha2::Sha256::digest(self)));
478        result
479    }
480
481    #[inline]
482    fn hex_string(&self) -> String {
483        let mut result = String::new();
484        for byte in self {
485            result = format!("{}{:02x}", result, byte);
486        }
487        result
488    }
489
490    #[inline]
491    fn p2wpkh(&self) -> Result<String, Error> {
492        if self.len() != NBBY_PUBC && self.len() != NBBY_PUBU {
493            return Err(Error::NbPubB(self.len()));
494        }
495        let mut address_bytes = vec![0x00]; // version prefix
496        address_bytes.append(&mut self.hash160().to_vec());
497        Ok(address_bytes.encode_base58ck())
498    }
499}
500
501/// Implementation of enum Error.
502impl Error {
503    /// Retrieve the status code to be showed when exiting because of an error.
504    #[doc(hidden)]
505    pub fn status(&self) -> i32 {
506        match self {
507            Error::Address => 1,
508            Error::Argument(_) => 2,
509            Error::Base58 => 3,
510            Error::Bech32 => 4,
511            Error::Bip38(_) => 5,
512            Error::Checksum => 6,
513            Error::Context(_) => 7,
514            Error::FromHard => 8,
515            Error::HexStr => 9,
516            Error::Hmac => 10,
517            Error::KeyLen => 11,
518            Error::KeyVer => 12,
519            Error::NbPubB(_) => 13,
520            Error::NotFound => 14,
521            Error::Path(_) => 15,
522            Error::PrvData => 16,
523            Error::PubData => 17,
524            Error::Range(_) => 18,
525            Error::SecEnt => 19,
526            Error::WifKey => 20,
527        }
528    }
529}
530
531/// Implementation of the structure ExtPrvKey.
532impl ExtPrvKey {
533    /// Return the extended private key as base 58 check string representation.
534    fn as_bs58ck_prv(&self) -> String {
535        let mut result = [0x00; 82];
536        result[..NBBY_XKEY].copy_from_slice(&self.bytes_prv());
537        result[NBBY_XKEY..].copy_from_slice(&self.bytes_prv().hash256()[..4]);
538        bs58::encode(result).into_string()
539    }
540
541    /// Return the extended private key as bytes.
542    fn bytes_prv(&self) -> [u8; 78] {
543        let mut result = [0x00; 78];
544        result[..4].copy_from_slice(&self.version);
545        result[4] = self.depth;
546        result[5..9].copy_from_slice(&self.parentf);
547        result[9..13].copy_from_slice(&self.childnb.to_be_bytes());
548        result[13..45].copy_from_slice(&self.chaincd);
549        result[45] = 0x00;
550        result[46..].copy_from_slice(&self.prvdata);
551        result
552    }
553
554    /// Private to private child key derivation.
555    fn ckd_prv(&self, childnb: &u32) -> Result<ExtPrvKey, Error> {
556        let mut hmac =
557            Hmac::<sha2::Sha512>::new_from_slice(&self.chaincd).map_err(|_| Error::Hmac)?;
558
559        if childnb >= &HARD_NB {
560            hmac.update(&[0x00]); // zeroed first byte of all private data
561            hmac.update(&self.prvdata);
562        } else {
563            hmac.update(&self.prvdata.public_key(true)?);
564        }
565
566        hmac.update(&childnb.to_be_bytes());
567
568        let r_hmac = hmac.finalize().into_bytes();
569        let mut sk = SecretKey::from_slice(&r_hmac[..32]).map_err(|_| Error::SecEnt)?;
570
571        sk = sk
572            .add_tweak(&Scalar::from_be_bytes(self.prvdata).map_err(|_| Error::SecEnt)?)
573            .map_err(|_| Error::SecEnt)?;
574
575        let (mut parentf, mut chaincd, mut prvdata) = ([0x00; 4], [0x00; 32], [0x00; 32]);
576
577        parentf[..].copy_from_slice(&self.prvdata.public_key(true)?.hash160()[..4]);
578        chaincd[..].copy_from_slice(&r_hmac[32..]);
579        prvdata[..].copy_from_slice(&sk[..]);
580
581        Ok(Self {
582            version: self.version,
583            depth: self.depth + 1,
584            parentf,
585            childnb: *childnb,
586            chaincd,
587            prvdata,
588            purpose: self.purpose,
589        })
590    }
591
592    /// Derive the extended private key according to informed path.
593    fn derive_prv(&self, path: &[u32]) -> Result<ExtPrvKey, Error> {
594        let mut derived = *self;
595        for cnb in path {
596            derived = derived.ckd_prv(cnb)?;
597        }
598        Ok(derived)
599    }
600
601    /// Transform a crude vector of bytes in the structure ExtPrvKey (checked).
602    fn from_bs58_prv(prvk: &str) -> Result<Self, Error> {
603        if prvk.len() < 4 || !prvk.is_char_boundary(4) || !PRE_PRV_KEY.contains(&(&prvk[..4])) {
604            return Err(Error::KeyVer);
605        } else if prvk.len() != LEN_XKEY {
606            return Err(Error::KeyLen);
607        }
608        let prvk = prvk.decode_base58ck()?;
609
610        if prvk.len() != NBBY_XKEY {
611            return Err(Error::KeyLen);
612        }
613        if prvk[45] != 0 {
614            return Err(Error::PrvData);
615        }
616
617        let (mut version, mut parentf, mut childnb, mut chaincd, mut prvdata) =
618            ([0x00; 4], [0x00; 4], [0x00; 4], [0x00; 32], [0x00; 32]);
619        version[..].copy_from_slice(&prvk[..4]);
620        parentf[..].copy_from_slice(&prvk[5..9]);
621        childnb[..].copy_from_slice(&prvk[9..13]);
622        chaincd[..].copy_from_slice(&prvk[13..45]);
623        prvdata[..].copy_from_slice(&prvk[46..]);
624
625        Ok(Self {
626            version,
627            depth: prvk[4],
628            parentf,
629            childnb: u32::from_be_bytes(childnb),
630            chaincd,
631            prvdata,
632            purpose: if prvk[..4] == TPRV || prvk[..4] == XPRV {
633                44
634            } else if prvk[..4] == UPRV || prvk[..4] == YPRV {
635                49
636            } else {
637                // trusts in the first if
638                84
639            },
640        })
641    }
642
643    /// Show derivation of the extended private key in command line interface.
644    fn show_prv(
645        &self,
646        path: &[u32],
647        range: (u32, u32),
648        pass: &str,
649        separator: &str,
650    ) -> Result<(), Error> {
651        let base_path_str = path.encode_path();
652        let parent = self.derive_prv(path)?;
653
654        println!(
655            "{}\n{}",
656            parent.as_bs58ck_prv(),
657            ExtPubKey::from_prv(&parent)?.as_bs58ck_pub()
658        );
659
660        let encrypt = !pass.is_empty();
661
662        // + 1 to reach possible last child and be close range maintaining u32
663        for child_nb in range.0..range.1 + 1 {
664            let child_prv = parent.derive_prv(&[child_nb])?;
665            let child_pub = ExtPubKey::from_prv(&child_prv)?;
666            let address = match child_prv.purpose {
667                44 => child_pub.pubdata.p2wpkh()?,
668                49 => child_pub.pubdata.segwit_p2wpkh_p2sh()?,
669                84 => child_pub.pubdata.segwit_p2wpkh()?,
670                _ => String::from("please, don't"),
671            };
672            let prv_str = if encrypt {
673                child_prv.prvdata.encrypt(pass, true)?
674            } else {
675                child_prv.prvdata.encode_wif(true)?
676            };
677            println!(
678                "{}/{}{}{}{}{}{}{}",
679                base_path_str,
680                child_nb,
681                separator,
682                address,
683                separator,
684                child_pub.pubdata.hex_string(),
685                separator,
686                prv_str
687            );
688        }
689        Ok(())
690    }
691}
692
693/// Implementation of the structure ExtPubKey.
694impl ExtPubKey {
695    /// Return the extended public key represented as a base 58 check string.
696    fn as_bs58ck_pub(&self) -> String {
697        let mut result = [0x00; 82];
698        result[..NBBY_XKEY].copy_from_slice(&self.bytes_pub());
699        result[NBBY_XKEY..].copy_from_slice(&self.bytes_pub().hash256()[..4]);
700        bs58::encode(result).into_string()
701    }
702
703    /// Return the extended public key as bytes.
704    fn bytes_pub(&self) -> [u8; 78] {
705        let mut result = [0x00; 78];
706        result[..4].copy_from_slice(&self.version);
707        result[4] = self.depth;
708        result[5..9].copy_from_slice(&self.parentf);
709        result[9..13].copy_from_slice(&self.childnb.to_be_bytes());
710        result[13..45].copy_from_slice(&self.chaincd);
711        result[45..].copy_from_slice(&self.pubdata);
712        result
713    }
714
715    /// Public to public key derivation.
716    fn ckd_pub(&self, childnb: &u32) -> Result<ExtPubKey, Error> {
717        if childnb >= &HARD_NB {
718            return Err(Error::FromHard);
719        }
720
721        let mut hmac =
722            Hmac::<sha2::Sha512>::new_from_slice(&self.chaincd).map_err(|_| Error::Hmac)?;
723
724        hmac.update(&self.pubdata);
725        hmac.update(&childnb.to_be_bytes());
726
727        let r_hmac = hmac.finalize().into_bytes();
728        let mut pubk = PublicKey::from_slice(&self.pubdata).map_err(|_| Error::PubData)?;
729
730        pubk = pubk
731            .add_exp_tweak(
732                &Secp256k1::new(),
733                &Scalar::from(SecretKey::from_slice(&r_hmac[..32]).map_err(|_| Error::SecEnt)?),
734            )
735            .map_err(|_| Error::SecEnt)?;
736
737        let (mut parentf, mut chaincd) = ([0x00; 4], [0x00; 32]);
738        parentf[..].copy_from_slice(&self.pubdata.hash160()[..4]);
739        chaincd[..].copy_from_slice(&r_hmac[32..]);
740
741        Ok(Self {
742            version: self.version,
743            depth: self.depth + 1,
744            parentf,
745            childnb: *childnb,
746            chaincd,
747            pubdata: pubk.serialize(),
748            purpose: self.purpose,
749        })
750    }
751
752    /// Derive the extended public key according to valid informed path.
753    fn derive_pub(&self, path: &[u32]) -> Result<ExtPubKey, Error> {
754        let mut derived = *self;
755        for child_nb in path {
756            derived = derived.ckd_pub(child_nb)?;
757        }
758        Ok(derived)
759    }
760
761    /// Transform a crude vector of bytes in the structure ExtPubKey (checked).
762    fn from_bs58_pub(pubk: &str) -> Result<Self, Error> {
763        if pubk.len() < 4 || !pubk.is_char_boundary(4) || !PRE_PUB_KEY.contains(&(&pubk[..4])) {
764            return Err(Error::KeyVer);
765        } else if pubk.len() != LEN_XKEY {
766            return Err(Error::KeyLen);
767        }
768        let pubk = pubk.decode_base58ck()?;
769        if pubk.len() != NBBY_XKEY {
770            return Err(Error::KeyLen);
771        }
772
773        let (mut version, mut parentf, mut childnb, mut chaincd, mut pubdata) = (
774            [0x00; 4],
775            [0x00; 4],
776            [0x00; 4],
777            [0x00; 32],
778            [0x00; NBBY_PUBC],
779        );
780        version[..].copy_from_slice(&pubk[..4]);
781        parentf[..].copy_from_slice(&pubk[5..9]);
782        childnb[..].copy_from_slice(&pubk[9..13]);
783        chaincd[..].copy_from_slice(&pubk[13..45]);
784        pubdata[..].copy_from_slice(&pubk[45..]);
785
786        Ok(Self {
787            version,
788            depth: pubk[4],
789            parentf,
790            childnb: u32::from_be_bytes(childnb),
791            chaincd,
792            pubdata,
793            purpose: if pubk[..4] == TPUB || pubk[..4] == XPUB {
794                44
795            } else if pubk[..4] == UPUB || pubk[..4] == YPUB {
796                49
797            } else {
798                // trusts in the first if
799                84
800            },
801        })
802    }
803
804    /// Derive a extended public key from a private one.
805    fn from_prv(prv: &ExtPrvKey) -> Result<ExtPubKey, Error> {
806        let mut pubdata = [0x00; NBBY_PUBC];
807        pubdata[..].copy_from_slice(&prv.prvdata.public_key(true)?);
808        Ok(ExtPubKey {
809            version: match prv.version {
810                TPRV => TPUB,
811                UPRV => UPUB,
812                VPRV => VPUB,
813                XPRV => XPUB,
814                YPRV => YPUB,
815                ZPRV => ZPUB,
816                _ => XPUB,
817            },
818            depth: prv.depth,
819            parentf: prv.parentf,
820            childnb: prv.childnb,
821            chaincd: prv.chaincd,
822            pubdata,
823            purpose: prv.purpose,
824        })
825    }
826
827    /// Show derivation of the extended public key based on path and range.
828    fn show_pub(&self, path: &[u32], range: (u32, u32), separator: &str) -> Result<(), Error> {
829        if range.0 >= HARD_NB || range.1 >= HARD_NB {
830            return Err(Error::FromHard);
831        }
832        let base_path_str = path.encode_path();
833        let parent = self.derive_pub(path)?;
834        println!("{}", parent.as_bs58ck_pub());
835        for child_nb in range.0..range.1 + 1 {
836            let child = parent.derive_pub(&[child_nb])?;
837            let address = match child.purpose {
838                44 => child.pubdata.p2wpkh()?,
839                49 => child.pubdata.segwit_p2wpkh_p2sh()?,
840                84 => child.pubdata.segwit_p2wpkh()?,
841                _ => String::from("please, don't"),
842            };
843
844            println!(
845                "{}/{}{}{}{}{}",
846                base_path_str,
847                child_nb,
848                separator,
849                address,
850                separator,
851                child.pubdata.hex_string()
852            );
853        }
854        Ok(())
855    }
856}
857
858/// Implementation of trait PathManipulation.
859impl PathManipulation for [u32] {
860    #[inline]
861    fn encode_path(&self) -> String {
862        if self.is_empty() {
863            return String::from(PATH_START);
864        }
865        let mut encoded_path = String::from(PATH_START);
866        for value in self {
867            let child = if value < &HARD_NB {
868                format!("{}", value)
869            } else {
870                format!("{}{}", value - HARD_NB, HARD_CHAR)
871            };
872            encoded_path += &format!("{}{}", SEP_PATH, child);
873        }
874        encoded_path
875    }
876}
877
878/// Implementation of trait PrivateKeyManipulation.
879impl PrivateKeyManipulation for [u8; 32] {
880    #[inline]
881    fn encode_wif(&self, compress: bool) -> Result<String, Error> {
882        let mut decoded: Vec<u8> = vec![PRE_WIF_B];
883        decoded.append(&mut self.to_vec());
884        if compress {
885            decoded.push(0x01);
886        }
887        Ok(decoded.encode_base58ck())
888    }
889
890    #[inline]
891    fn public_key(&self, compress: bool) -> Result<Vec<u8>, Error> {
892        let secp_pub = PublicKey::from_secret_key(
893            &Secp256k1::new(),
894            &SecretKey::from_slice(self).map_err(|_| Error::SecEnt)?,
895        );
896        if compress {
897            Ok(secp_pub.serialize().to_vec())
898        } else {
899            Ok(secp_pub.serialize_uncompressed().to_vec())
900        }
901    }
902}
903
904/// Implementation of trait PublicKeyCompressedManipulation.
905impl PublicKeyCompressedManipulation for [u8; NBBY_PUBC] {
906    #[inline]
907    fn segwit_p2wpkh(&self) -> Result<String, Error> {
908        // segwit version has to be inserted as 5 bit unsigned integer
909        let witness_program = WitnessProgram::new(
910            u5::try_from_u8(0).map_err(|_| Error::Bech32)?,
911            self.hash160().to_vec(),
912            Network::Bitcoin,
913        )
914        .map_err(|_| Error::Bech32)?;
915        Ok(witness_program.to_address())
916    }
917
918    #[inline]
919    fn segwit_p2wpkh_p2sh(&self) -> Result<String, Error> {
920        let mut redeem_script = vec![OP_0, OP_PUSH20];
921        redeem_script.append(&mut self.hash160().to_vec());
922        let mut address_bytes = vec![PRE_P2WPKH_P2SH_B];
923        address_bytes.append(&mut redeem_script.hash160().to_vec());
924        Ok(address_bytes.encode_base58ck())
925    }
926}
927
928/// Implementation of trait StringManipulation.
929impl StringManipulation for str {
930    #[inline]
931    fn decode_address(&self) -> Result<Vec<u8>, Error> {
932        if self.len() == LEN_SEGWIT && self.starts_with("bc") {
933            let decoded = WitnessProgram::from_address(&self)
934                .map_err(|_| Error::Bech32)?
935                .program()
936                .to_vec();
937            Ok(decoded)
938        } else if (self.starts_with('1') || self.starts_with('3'))
939            && self.len() >= LEN_LEG_MIN
940            && self.len() <= LEN_LEG_MAX
941        {
942            let decoded = &self.decode_base58ck()?[1..]; // remove version
943            Ok(decoded.to_vec())
944        } else {
945            Err(Error::Address)
946        }
947    }
948
949    #[inline]
950    fn decode_base58ck(&self) -> Result<Vec<u8>, Error> {
951        if self.len() < LEN_ARG_MIN {
952            // to protect posterior slicing
953            return Err(Error::Argument(String::from(self)));
954        }
955        let raw = bs58::decode(self).into_vec().map_err(|_| Error::Base58)?;
956        if raw[raw.len() - 4..] == raw[..raw.len() - 4].hash256()[..4] {
957            Ok(raw[..(raw.len() - 4)].to_vec())
958        } else {
959            Err(Error::Checksum)
960        }
961    }
962
963    #[inline]
964    fn decode_wif(&self) -> Result<([u8; 32], bool), Error> {
965        if (!self.is_char_boundary(1) || !PRE_WIF_C.contains(&self[..1]) || self.len() != LEN_WIF_C)
966            && (!self.starts_with(PRE_WIF_U) || self.len() != LEN_WIF_U)
967        {
968            return Err(Error::WifKey);
969        }
970        let raw_bytes = self.decode_base58ck()?;
971        if (raw_bytes.len() != NBBY_WIFC && raw_bytes.len() != NBBY_WIFU)
972            || raw_bytes[0] != PRE_WIF_B
973        {
974            return Err(Error::WifKey);
975        }
976        let mut payload = [0x00; 32];
977        payload[..].copy_from_slice(&raw_bytes[1..33]);
978        Ok((payload, raw_bytes.len() == NBBY_WIFC))
979    }
980
981    #[inline]
982    fn hex_bytes(&self) -> Result<Vec<u8>, Error> {
983        let mut out = Vec::new();
984        for index in (0..self.len()).step_by(2) {
985            out.push(u8::from_str_radix(&self[index..index + 2], 16).map_err(|_| Error::HexStr)?);
986        }
987        Ok(out)
988    }
989
990    #[inline]
991    fn info_entropy(&self, pass: &str, separator: &str) -> Result<(), Error> {
992        if self.len() != 64 {
993            return Err(Error::SecEnt);
994        }
995        let mut secret = [0x00; 32];
996        secret[..].copy_from_slice(&self.hex_bytes()?);
997        let mut pubc = [0x00; NBBY_PUBC];
998        pubc[..].copy_from_slice(&secret.public_key(true)?);
999        let pubu = secret.public_key(false)?;
1000        let hex_pubc = pubc.hex_string();
1001        let secret_str = if pass.is_empty() {
1002            secret.encode_wif(true)?
1003        } else {
1004            secret.encrypt(pass, true)?
1005        };
1006
1007        if separator == DEF_SEP {
1008            println!(
1009                "{:42}{}{}{}{}\n{:42}{}{}{}{}\n{}{}{}{}{}",
1010                pubc.p2wpkh()?,
1011                separator,
1012                hex_pubc,
1013                separator,
1014                secret_str,
1015                pubc.segwit_p2wpkh_p2sh()?,
1016                separator,
1017                hex_pubc,
1018                separator,
1019                secret_str,
1020                pubc.segwit_p2wpkh()?,
1021                separator,
1022                hex_pubc,
1023                separator,
1024                secret_str
1025            );
1026        } else {
1027            println!(
1028                "{}{}{}{}{}\n{}{}{}{}{}\n{}{}{}{}{}",
1029                pubc.p2wpkh()?,
1030                separator,
1031                hex_pubc,
1032                separator,
1033                secret_str,
1034                pubc.segwit_p2wpkh_p2sh()?,
1035                separator,
1036                hex_pubc,
1037                separator,
1038                secret_str,
1039                pubc.segwit_p2wpkh()?,
1040                separator,
1041                hex_pubc,
1042                separator,
1043                secret_str
1044            );
1045        }
1046
1047        println!(
1048            "{}{}{}{}{}",
1049            pubu.p2wpkh()?,
1050            separator,
1051            pubu.hex_string(),
1052            separator,
1053            if pass.is_empty() {
1054                secret.encode_wif(false)?
1055            } else {
1056                secret.encrypt(pass, false)?
1057            }
1058        );
1059        Ok(())
1060    }
1061
1062    #[inline]
1063    fn info_wif(&self, pass: &str, separator: &str) -> Result<(), Error> {
1064        let (secret, compress) = self.decode_wif()?;
1065        let public = secret.public_key(compress)?;
1066        let secret = if !pass.is_empty() {
1067            secret.encrypt(pass, compress)?
1068        } else {
1069            String::from(self)
1070        };
1071
1072        if compress {
1073            let hex_pubc = public.hex_string();
1074            let mut public_comp = [0x00; NBBY_PUBC];
1075            public_comp[..].copy_from_slice(&public);
1076            if separator == DEF_SEP {
1077                println!(
1078                    "{:42}{}{}{}{}\n{:42}{}{}{}{}\n{}{}{}{}{}",
1079                    public_comp.p2wpkh()?,
1080                    separator,
1081                    hex_pubc,
1082                    separator,
1083                    secret,
1084                    public_comp.segwit_p2wpkh_p2sh()?,
1085                    separator,
1086                    hex_pubc,
1087                    separator,
1088                    secret,
1089                    public_comp.segwit_p2wpkh()?,
1090                    separator,
1091                    hex_pubc,
1092                    separator,
1093                    secret
1094                );
1095            } else {
1096                println!(
1097                    "{}{}{}{}{}\n{}{}{}{}{}\n{}{}{}{}{}",
1098                    public_comp.p2wpkh()?,
1099                    separator,
1100                    hex_pubc,
1101                    separator,
1102                    secret,
1103                    public_comp.segwit_p2wpkh_p2sh()?,
1104                    separator,
1105                    hex_pubc,
1106                    separator,
1107                    secret,
1108                    public_comp.segwit_p2wpkh()?,
1109                    separator,
1110                    hex_pubc,
1111                    separator,
1112                    secret
1113                );
1114            };
1115        } else {
1116            println!(
1117                "{}{}{}{}{}",
1118                public.p2wpkh()?,
1119                separator,
1120                public.hex_string(),
1121                separator,
1122                secret
1123            );
1124        }
1125        Ok(())
1126    }
1127
1128    #[inline]
1129    fn is_hex(&self) -> bool {
1130        for c in self.chars() {
1131            if !c.is_ascii_hexdigit() {
1132                return false;
1133            }
1134        }
1135        true
1136    }
1137
1138    #[inline]
1139    fn decode_path(&self, public: bool) -> Result<Vec<u32>, Error> {
1140        if self.is_empty() || !self.starts_with(PATH_START) {
1141            return Err(Error::Path(String::from(self)));
1142        } else if public && self.contains(HARD_CHAR) {
1143            return Err(Error::FromHard);
1144        }
1145
1146        let mut result: Vec<u32> = Vec::new();
1147        let mut first_m = true; // used to prevent 'm' in the middle of path
1148
1149        for cnb in self.split_terminator(SEP_PATH) {
1150            let mut total: u32 = 0;
1151
1152            if cnb.is_empty() {
1153                return Err(Error::Path(String::from("//")));
1154            } else if cnb == PATH_START && first_m {
1155                first_m = false;
1156                continue;
1157            } else if cnb.ends_with(HARD_CHAR) {
1158                total += match cnb.trim_end_matches(HARD_CHAR).parse::<u32>() {
1159                    Ok(value) => {
1160                        if value < HARD_NB {
1161                            HARD_NB + value //accepts 0 as value
1162                        } else {
1163                            return Err(Error::Path(String::from(cnb)));
1164                        }
1165                    }
1166                    Err(_) => return Err(Error::Path(String::from(cnb))),
1167                };
1168            } else {
1169                total = match cnb.parse::<u32>() {
1170                    Ok(value) => {
1171                        if value < HARD_NB {
1172                            // prevent unwanted hardened child
1173                            value
1174                        } else {
1175                            return Err(Error::Path(String::from(cnb)));
1176                        }
1177                    }
1178                    Err(_) => return Err(Error::Path(String::from(cnb))),
1179                };
1180            }
1181            result.push(total);
1182        }
1183        Ok(result)
1184    }
1185
1186    #[inline]
1187    fn decode_range(&self) -> Result<(u32, u32), Error> {
1188        if !self.contains(SEP_RANGE) {
1189            match self.trim_end_matches(HARD_CHAR).parse::<u32>() {
1190                Ok(value) => {
1191                    if self.ends_with(HARD_CHAR) {
1192                        return Ok((value + HARD_NB, value + HARD_NB));
1193                    } else {
1194                        return Ok((value, value));
1195                    }
1196                }
1197                Err(_) => return Err(Error::Range(String::from(self))),
1198            }
1199        }
1200
1201        let (start, stop) = self
1202            .split_once(SEP_RANGE)
1203            .ok_or_else(|| Error::Range(String::from(self)))?;
1204
1205        if start.ends_with(HARD_CHAR) && !stop.is_empty() && !stop.ends_with(HARD_CHAR) {
1206            return Err(Error::Range(String::from(stop)));
1207        }
1208
1209        let start = match start.parse::<u32>() {
1210            Ok(value) => {
1211                if value < HARD_NB {
1212                    value
1213                } else {
1214                    return Err(Error::Range(String::from(start)));
1215                }
1216            }
1217            Err(_) => {
1218                if start.is_empty() {
1219                    0
1220                } else if start.ends_with(HARD_CHAR) {
1221                    match start.trim_end_matches(HARD_CHAR).parse::<u32>() {
1222                        Ok(value) => {
1223                            if value < HARD_NB {
1224                                value + HARD_NB
1225                            } else {
1226                                return Err(Error::Range(String::from(start)));
1227                            }
1228                        }
1229                        Err(_) => return Err(Error::Range(String::from(start))),
1230                    }
1231                } else {
1232                    return Err(Error::Range(String::from(start)));
1233                }
1234            }
1235        };
1236
1237        let stop = match stop.parse::<u32>() {
1238            Ok(value) => {
1239                if value < HARD_NB {
1240                    value
1241                } else {
1242                    return Err(Error::Range(String::from(stop)));
1243                }
1244            }
1245            Err(_) => {
1246                if stop.is_empty() && start < HARD_NB {
1247                    HARD_NB - 1
1248                } else if stop.is_empty() && start >= HARD_NB {
1249                    u32::MAX
1250                } else if stop.ends_with(HARD_CHAR) {
1251                    match stop.trim_end_matches(HARD_CHAR).parse::<u32>() {
1252                        Ok(value) => {
1253                            if value < HARD_NB {
1254                                value + HARD_NB
1255                            } else {
1256                                return Err(Error::Range(String::from(stop)));
1257                            }
1258                        }
1259                        Err(_) => return Err(Error::Range(String::from(stop))),
1260                    }
1261                } else {
1262                    return Err(Error::Range(String::from(stop)));
1263                }
1264            }
1265        };
1266
1267        if start >= stop {
1268            Err(Error::Range(String::from(self)))
1269        } else {
1270            Ok((start, stop))
1271        }
1272    }
1273}
1274
1275/// Evaluate arguments and execute actions accordingly.
1276#[doc(hidden)]
1277pub fn handle_arguments(matches: ArgMatches) -> Result<(), Error> {
1278    let nothing = "".to_string();
1279    let def_sep = DEF_SEP.to_string();
1280    let data = matches.get_one::<String>("DATA").ok_or(Error::NotFound)?;
1281    let passphrase = matches.get_one::<String>("passphrase").unwrap_or(&nothing);
1282    let path = matches.get_one::<String>("path").unwrap_or(&nothing);
1283    let range = matches.get_one::<String>("range").unwrap_or(&nothing);
1284    let rng_t = if range.is_empty() {
1285        DEF_RNG
1286    } else {
1287        range.decode_range()?
1288    };
1289    let separator = matches.get_one::<String>("separator").unwrap_or(&def_sep);
1290
1291    if PRE_WIF_C.contains(&data[..1]) || data.starts_with(PRE_WIF_U) {
1292        if !path.is_empty() {
1293            return Err(Error::Context(String::from("p")));
1294        } else if !range.is_empty() {
1295            return Err(Error::Context(String::from("r")));
1296        }
1297        data.info_wif(passphrase, separator)?;
1298    } else if data.is_hex() && data.len() == 64 {
1299        if !path.is_empty() {
1300            return Err(Error::Context(String::from("p")));
1301        } else if !range.is_empty() {
1302            return Err(Error::Context(String::from("r")));
1303        }
1304        data.info_entropy(passphrase, separator)?;
1305    } else if PRE_ADDR.contains(&data[..1]) || PRE_ADDR.contains(&data[..2]) {
1306        if matches.contains_id("passphrase") {
1307            // protects from empty passphrase
1308            return Err(Error::Context(String::from("e")));
1309        } else if !path.is_empty() {
1310            return Err(Error::Context(String::from("p")));
1311        } else if !range.is_empty() {
1312            return Err(Error::Context(String::from("r")));
1313        } else if matches.contains_id("separator") {
1314            // protects from " | "
1315            return Err(Error::Context(String::from("s")));
1316        }
1317        println!("{}", data.decode_address()?.hex_string());
1318    } else if PRE_PRV_KEY.contains(&(&data[..4])) {
1319        let parent = ExtPrvKey::from_bs58_prv(data)?;
1320        parent.show_prv(
1321            &if path.is_empty() {
1322                // decisive, default path and flag 'false'
1323                vec![parent.purpose + HARD_NB, HARD_NB, HARD_NB, 0]
1324            } else {
1325                path.decode_path(false)?
1326            },
1327            rng_t,
1328            passphrase,
1329            separator,
1330        )?;
1331    } else if PRE_PUB_KEY.contains(&(&data[..4])) {
1332        if matches.contains_id("passphrase") {
1333            return Err(Error::Context(String::from("e")));
1334        }
1335        ExtPubKey::from_bs58_pub(data)?.show_pub(
1336            &if path.is_empty() {
1337                // decisive too
1338                vec![]
1339            } else {
1340                path.decode_path(true)?
1341            },
1342            rng_t,
1343            separator,
1344        )?;
1345    } else {
1346        return Err(Error::Argument(String::from(data)));
1347    }
1348    Ok(())
1349}
1350
1351/// Create the default clap app for the project
1352#[doc(hidden)]
1353pub fn init_clap() -> Command {
1354    Command::new("derivation32")
1355        .about(ABOUT)
1356        .version(crate_version!())
1357        .arg(
1358            Arg::new("DATA")
1359                .help("Address, hexadecimal entropy, extended key or wif key")
1360                .required(true)
1361                .value_parser(OsStringValueParser::new().try_map(validate_data)),
1362        )
1363        .arg(
1364            Arg::new("passphrase")
1365                .help("Encrypt resulting private keys (bip-0038)")
1366                .short('e'),
1367        )
1368        .arg(
1369            Arg::new("path")
1370                .help("Path used to derive the extended private key")
1371                .short('p')
1372                .value_parser(OsStringValueParser::new().try_map(validate_path)),
1373        )
1374        .arg(
1375            Arg::new("range")
1376                .help("Closed range in the form of (1..9h) used on derivation")
1377                .short('r')
1378                .value_parser(OsStringValueParser::new().try_map(validate_range)),
1379        )
1380        .arg(
1381            Arg::new("separator")
1382                .help("Specify a character (or string) to separate results")
1383                .short('s'),
1384        )
1385}
1386
1387/// Used in clap to validate the argument 'data'
1388fn validate_data(data_os: OsString) -> Result<String, &'static str> {
1389    let data = data_os.to_str().unwrap_or("");
1390    if data.len() >= LEN_ARG_MIN && (data.len() == LEN_WIF_C &&
1391        data.is_char_boundary(1) && PRE_WIF_C.contains(&data[..1])) ||
1392        (data.len() == LEN_WIF_U && data.starts_with(PRE_WIF_U)) || // wif key
1393        data.len() == 64 && data.is_hex() || // hexadecimal entropy
1394        (data.len() >= LEN_LEG_MIN && data.len() <= LEN_LEG_MAX &&
1395        data.is_char_boundary(1) && PRE_ADDR.contains(&data[..1])) ||
1396        (data.len() == LEN_SEGWIT && data.is_char_boundary(2) &&
1397        PRE_ADDR.contains(&data[..2])) || // address
1398        data.is_char_boundary(4) && (PRE_PRV_KEY.contains(&(&data[..4]))
1399        || PRE_PUB_KEY.contains(&(&data[..4]))) && data.len() == LEN_XKEY
1400    {
1401        Ok(data.to_string()) // last but not least: extended key
1402    } else {
1403        Err("not a hexadecimal entropy, extended key or wif key")
1404    }
1405}
1406
1407/// Used in clap to validate the option 'path'
1408fn validate_path(path_os: OsString) -> Result<String, &'static str> {
1409    let path = path_os.to_str().unwrap_or("");
1410    if path.decode_path(false).is_ok() {
1411        Ok(path.to_string())
1412    } else {
1413        Err("path error")
1414    }
1415}
1416
1417/// Used in clap to validate the option 'range'
1418fn validate_range(range_os: OsString) -> Result<String, &'static str> {
1419    let range = range_os.to_str().unwrap_or("");
1420    if range.decode_range().is_ok() {
1421        Ok(range.to_string())
1422    } else {
1423        Err("range error")
1424    }
1425}
1426
1427/// Tests of the project
1428#[cfg(test)]
1429mod tests {
1430    use super::*;
1431
1432    /// Result of a double sha256 in 32 '0xff' bytes.
1433    const DS256_F: [u8; 32] = [
1434        0x71, 0xca, 0x50, 0x49, 0x66, 0x1b, 0x67, 0xd2, 0xba, 0xba, 0xf3, 0x06, 0xcd, 0x9b, 0xc8,
1435        0x09, 0x0a, 0x93, 0x32, 0x4c, 0x2d, 0x4f, 0xf1, 0xbb, 0x12, 0xa3, 0x71, 0xa0, 0x2c, 0xc2,
1436        0x3e, 0xb8,
1437    ];
1438
1439    /// Result of a double sha256 in 32 '0x69' bytes.
1440    const DS256_L: [u8; 32] = [
1441        0xc1, 0x61, 0xd0, 0x98, 0x17, 0x97, 0x65, 0xc7, 0x6b, 0x8a, 0x2e, 0xae, 0xbd, 0xd1, 0xcc,
1442        0x27, 0x6c, 0xfa, 0x02, 0x72, 0x18, 0xe6, 0x9c, 0x09, 0xb7, 0xa0, 0x94, 0x7e, 0x81, 0xc7,
1443        0x60, 0x85,
1444    ];
1445
1446    /// Result of a double sha256 in a '0x00' byte.
1447    const DS256_Z: [u8; 32] = [
1448        0x14, 0x06, 0xe0, 0x58, 0x81, 0xe2, 0x99, 0x36, 0x77, 0x66, 0xd3, 0x13, 0xe2, 0x6c, 0x05,
1449        0x56, 0x4e, 0xc9, 0x1b, 0xf7, 0x21, 0xd3, 0x17, 0x26, 0xbd, 0x6e, 0x46, 0xe6, 0x06, 0x89,
1450        0x53, 0x9a,
1451    ];
1452
1453    /// Result from 33 bytes '0x11' inserted in sha256 and after in ripemd160.
1454    const H160_33_1: [u8; 20] = [
1455        0x8e, 0xc4, 0xcf, 0x3e, 0xe1, 0x60, 0xb0, 0x54, 0xe0, 0xab, 0xb6, 0xf5, 0xc8, 0x17, 0x7b,
1456        0x9e, 0xe5, 0x6f, 0xa5, 0x1e,
1457    ];
1458
1459    /// Result from 33 bytes '0x69' inserted in sha256 and after in ripemd160.
1460    const H160_33_L: [u8; 20] = [
1461        0x05, 0x88, 0xa4, 0x7e, 0x70, 0xb0, 0x2d, 0x64, 0x6a, 0xb0, 0x65, 0x80, 0x50, 0x74, 0x66,
1462        0x25, 0xb0, 0x51, 0x03, 0xc8,
1463    ];
1464
1465    /// 64 zeros hexadecimal number represented in str format.
1466    const HEX_STR_0: &str = "0000000000000000000000000000000000000000000000000000000000000000";
1467
1468    /// 64 ones hexadecimal number represented in str format.
1469    const HEX_STR_1: &str = "1111111111111111111111111111111111111111111111111111111111111111";
1470
1471    /// 2 ^ 256 - 1 represented in a str of hexadecimal characters.
1472    const HEX_STR_F: &str = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
1473
1474    /// Interesting hexadecimal number represented in str format.
1475    const HEX_STR_L: &str = "6969696969696969696969696969696969696969696969696969696969696969";
1476
1477    /// Compressed address with secret key of all bytes '0x11'
1478    const P2WPKH_C_1: &str = "1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9";
1479
1480    /// Compressed address that generated with 'secret' entropy.
1481    const P2WPKH_C_A: &str = "16JrGhLx5bcBSA34kew9V6Mufa4aXhFe9X";
1482
1483    /// Compressed address with secret key of all bytes '0x69'.
1484    const P2WPKH_C_L: &str = "1N7qxowv8SnfdBYhmvpxZxyjsYQDPd88ES";
1485
1486    /// Segwit p2wpkh-p2sh address with all secret bytes '0x11'.
1487    const P2WPKH_P2SH_1: &str = "3PFpzMLrKWsphFtc8BesF3MGPnimKMuF4x";
1488
1489    /// Segwit p2wpkh-p2sh address with 'secret' entropy.
1490    const P2WPKH_P2SH_A: &str = "34N3tf5m5rdNhW5zpTXNEJucHviFEa8KEq";
1491
1492    /// Segwit p2wpkh-p2sh address with all secret bytes '0x69'.
1493    const P2WPKH_P2SH_L: &str = "35E9BxrEWjgHDFWucazLK5VVxH5oGLRj4g";
1494
1495    /// Uncompressed address generated with entropy of 32 '0x11' bytes.
1496    const P2WPKH_U_1: &str = "1MsHWS1BnwMc3tLE8G35UXsS58fKipzB7a";
1497
1498    /// Uncompressed address generated with 'secret' entropy.
1499    const P2WPKH_U_A: &str = "19P1LctLQmH6tuHCRkv8QznNBGBvFCyKxi";
1500
1501    /// Uncompressed address generated with entropy of 32 '0x69' bytes.
1502    const P2WPKH_U_L: &str = "17iS4e5ib2t2Bj2UFjPbxSDdmecHNnCAwy";
1503
1504    /// m/0 address from extended public key 'XPUB_Z'.
1505    const P2WPKH_Z_0: &str = "1LqBGSKuX5yYUonjxT5qGfpUsXKYYWeabA";
1506
1507    /// m/44h/0h/0h/0/19 address from master root key with zeroed entropy.
1508    const P2WPKH_Z_19: &str = "19hp5PzFjsD6z1hwMucUbLHAYeYDWdvB1B";
1509
1510    /// 'Secret' entropy to generate address.
1511    const P2WPKH_B: [u8; 32] = [
1512        0xa9, 0x66, 0xeb, 0x60, 0x58, 0xf8, 0xec, 0x9f, 0x47, 0x07, 0x4a, 0x2f, 0xaa, 0xdd, 0x3d,
1513        0xab, 0x42, 0xe2, 0xc6, 0x0e, 0xd0, 0x5b, 0xc3, 0x4d, 0x39, 0xd6, 0xc0, 0xe1, 0xd3, 0x2b,
1514        0x8b, 0xdf,
1515    ];
1516
1517    /// Bytes of compressed public key generated with 'P2PKG_B' secret.
1518    const PUB_C_A: [u8; NBBY_PUBC] = [
1519        0x02, 0x3c, 0xba, 0x1f, 0x4d, 0x12, 0xd1, 0xce, 0x0b, 0xce, 0xd7, 0x25, 0x37, 0x37, 0x69,
1520        0xb2, 0x26, 0x2c, 0x6d, 0xaa, 0x97, 0xbe, 0x6a, 0x05, 0x88, 0xcf, 0xec, 0x8c, 0xe1, 0xa5,
1521        0xf0, 0xbd, 0x09,
1522    ];
1523
1524    /// Bytes of compressed public key generated with all bytes '0x11'.
1525    const PUB_C_1: [u8; NBBY_PUBC] = [
1526        0x03, 0x4f, 0x35, 0x5b, 0xdc, 0xb7, 0xcc, 0x0a, 0xf7, 0x28, 0xef, 0x3c, 0xce, 0xb9, 0x61,
1527        0x5d, 0x90, 0x68, 0x4b, 0xb5, 0xb2, 0xca, 0x5f, 0x85, 0x9a, 0xb0, 0xf0, 0xb7, 0x04, 0x07,
1528        0x58, 0x71, 0xaa,
1529    ];
1530
1531    /// Bytes of compressed public key generated with all bytes '0x69'.
1532    const PUB_C_L: [u8; NBBY_PUBC] = [
1533        0x02, 0x66, 0x6b, 0xdf, 0x20, 0x25, 0xe3, 0x2f, 0x41, 0x08, 0x88, 0x99, 0xf2, 0xbc, 0xb4,
1534        0xbf, 0x69, 0x83, 0x18, 0x7f, 0x38, 0x0e, 0x72, 0xfc, 0x7d, 0xee, 0x11, 0x5b, 0x1f, 0x99,
1535        0x57, 0xcc, 0x72,
1536    ];
1537
1538    /// Bytes of uncompressed public key generated with all bytes '0x11'.
1539    const PUB_U_1: [u8; NBBY_PUBU] = [
1540        0x04, 0x4f, 0x35, 0x5b, 0xdc, 0xb7, 0xcc, 0x0a, 0xf7, 0x28, 0xef, 0x3c, 0xce, 0xb9, 0x61,
1541        0x5d, 0x90, 0x68, 0x4b, 0xb5, 0xb2, 0xca, 0x5f, 0x85, 0x9a, 0xb0, 0xf0, 0xb7, 0x04, 0x07,
1542        0x58, 0x71, 0xaa, 0x38, 0x5b, 0x6b, 0x1b, 0x8e, 0xad, 0x80, 0x9c, 0xa6, 0x74, 0x54, 0xd9,
1543        0x68, 0x3f, 0xcf, 0x2b, 0xa0, 0x34, 0x56, 0xd6, 0xfe, 0x2c, 0x4a, 0xbe, 0x2b, 0x07, 0xf0,
1544        0xfb, 0xdb, 0xb2, 0xf1, 0xc1,
1545    ];
1546
1547    /// Bytes of uncompressed public key generated with 'P2PKG_B' secret.
1548    const PUB_U_A: [u8; NBBY_PUBU] = [
1549        0x04, 0x3c, 0xba, 0x1f, 0x4d, 0x12, 0xd1, 0xce, 0x0b, 0xce, 0xd7, 0x25, 0x37, 0x37, 0x69,
1550        0xb2, 0x26, 0x2c, 0x6d, 0xaa, 0x97, 0xbe, 0x6a, 0x05, 0x88, 0xcf, 0xec, 0x8c, 0xe1, 0xa5,
1551        0xf0, 0xbd, 0x09, 0x2f, 0x56, 0xb5, 0x49, 0x2a, 0xdb, 0xfc, 0x57, 0x0b, 0x15, 0x64, 0x4c,
1552        0x74, 0xcc, 0x8a, 0x48, 0x74, 0xed, 0x20, 0xdf, 0xe4, 0x7e, 0x5d, 0xce, 0x2e, 0x08, 0x60,
1553        0x1d, 0x6f, 0x11, 0xf5, 0xa4,
1554    ];
1555
1556    /// Bytes of uncompressed public key generated with all bytes '0x69'.
1557    const PUB_U_L: [u8; NBBY_PUBU] = [
1558        0x04, 0x66, 0x6b, 0xdf, 0x20, 0x25, 0xe3, 0x2f, 0x41, 0x08, 0x88, 0x99, 0xf2, 0xbc, 0xb4,
1559        0xbf, 0x69, 0x83, 0x18, 0x7f, 0x38, 0x0e, 0x72, 0xfc, 0x7d, 0xee, 0x11, 0x5b, 0x1f, 0x99,
1560        0x57, 0xcc, 0x72, 0x9d, 0xd9, 0x76, 0x13, 0x1c, 0x4c, 0x8e, 0x12, 0xab, 0x10, 0x83, 0xca,
1561        0x06, 0x54, 0xca, 0x5f, 0xdb, 0xca, 0xc8, 0xd3, 0x19, 0x8d, 0xaf, 0x90, 0xf5, 0x81, 0xb5,
1562        0x91, 0xd5, 0x63, 0x79, 0xca,
1563    ];
1564
1565    /// Segwit address generated with secret of all bytes '0x11'
1566    const SEGW_1: &str = "bc1ql3e9pgs3mmwuwrh95fecme0s0qtn2880lsvsd5";
1567
1568    /// Segwit address generated with 'secret' number.
1569    const SEGW_A: &str = "bc1q8gudgnt2pjxshwzwqgevccet0eyvwtswt03nuy";
1570
1571    /// Segwit address generated with secret of all bytes '0x69'
1572    const SEGW_L: &str = "bc1qu7nqysur9dr49e4vd9xvguwh5ewzft597d8mc7";
1573
1574    /// Decoded segwit address generated with secret of all bytes '0x11'
1575    const SEGW_DEC_1: [u8; 20] = [
1576        0xfc, 0x72, 0x50, 0xa2, 0x11, 0xde, 0xdd, 0xc7, 0x0e, 0xe5, 0xa2, 0x73, 0x8d, 0xe5, 0xf0,
1577        0x78, 0x17, 0x35, 0x1c, 0xef,
1578    ];
1579
1580    /// Decoded segwit address generated with 'secret' number.
1581    const SEGW_DEC_A: [u8; 20] = [
1582        0x3a, 0x38, 0xd4, 0x4d, 0x6a, 0x0c, 0x8d, 0x0b, 0xb8, 0x4e, 0x02, 0x32, 0xcc, 0x63, 0x2b,
1583        0x7e, 0x48, 0xc7, 0x2e, 0x0e,
1584    ];
1585
1586    /// Decoded segwit address generated with secret of all bytes '0x69'
1587    const SEGW_DEC_L: [u8; 20] = [
1588        0xe7, 0xa6, 0x02, 0x43, 0x83, 0x2b, 0x47, 0x52, 0xe6, 0xac, 0x69, 0x4c, 0xc4, 0x71, 0xd7,
1589        0xa6, 0x5c, 0x24, 0xae, 0x85,
1590    ];
1591
1592    /// Paths of first test vector of bip-0032.
1593    const TV_32_01_PATH: [&str; 6] = [
1594        "m",
1595        "m/0h",
1596        "m/0h/1",
1597        "m/0h/1/2h",
1598        "m/0h/1/2h/2",
1599        "m/0h/1/2h/2/1000000000",
1600    ];
1601
1602    /// Paths of second test vector of bip-0032.
1603    const TV_32_02_PATH: [&str; 6] = [
1604        "m",
1605        "m/0",
1606        "m/0/2147483647h",
1607        "m/0/2147483647h/1",
1608        "m/0/2147483647h/1/2147483646h",
1609        "m/0/2147483647h/1/2147483646h/2",
1610    ];
1611
1612    /// Paths of third test vector of bip-0032.
1613    const TV_32_03_PATH: [&str; 2] = ["m", "m/0h"];
1614
1615    /// Private extended keys of first test vector of bip-0032.
1616    const TV_32_01_XPRV: [[&str; 2]; 6] = [
1617        [
1618            "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kej",
1619            "MRNNU3TGtRBeJgk33yuGBxrMPHi",
1620        ],
1621        [
1622            "xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT",
1623            "11eZG7XnxHrnYeSvkzY7d2bhkJ7",
1624        ],
1625        [
1626            "xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg",
1627            "8MSY3H2EU4pWcQDnRnrVA1xe8fs",
1628        ],
1629        [
1630            "xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewR",
1631            "iNMjANTtpgP4mLTj34bhnZX7UiM",
1632        ],
1633        [
1634            "xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqs",
1635            "unu5Mm3wDvUAKRHSC34sJ7in334",
1636        ],
1637        [
1638            "xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rF",
1639            "SruoUihUZREPSL39UNdE3BBDu76",
1640        ],
1641    ];
1642
1643    /// Private extended keys of second test vector of bip-0032.
1644    const TV_32_02_XPRV: [[&str; 2]; 6] = [
1645        [
1646            "xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNq",
1647            "Pqm55Qn3LqFtT2emdEXVYsCzC2U",
1648        ],
1649        [
1650            "xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1e",
1651            "x8G81dwSM1fwqWpWkeS3v86pgKt",
1652        ],
1653        [
1654            "xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kR",
1655            "gVsFawNzmjuHc2YmYRmagcEPdU9",
1656        ],
1657        [
1658            "xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXa",
1659            "jPPdbRCHuWS6T8XA2ECKADdw4Ef",
1660        ],
1661        [
1662            "xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcx",
1663            "FLJ8HFsTjSyQbLYnMpCqE2VbFWc",
1664        ],
1665        [
1666            "xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWT",
1667            "yefMLEcBYJUuekgW4BYPJcr9E7j",
1668        ],
1669    ];
1670
1671    /// Private extended keys of third test vector of bip-0032.
1672    const TV_32_03_XPRV: [[&str; 2]; 2] = [
1673        [
1674            "xprv9s21ZrQH143K25QhxbucbDDuQ4naNntJRi4KUfWT7xo4EKsHt2QJDu7KXp1A3u7Bi1j8ph3EGsZ9Xvz9",
1675            "dGuVrtHHs7pXeTzjuxBrCmmhgC6",
1676        ],
1677        [
1678            "xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJ",
1679            "CVVFceUvJFjaPdGZ2y9WACViL4L",
1680        ],
1681    ];
1682
1683    /// Public extended keys of first test vector of bip-0032.
1684    const TV_32_01_XPUB: [[&str; 2]; 6] = [
1685        [
1686            "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqs",
1687            "efD265TMg7usUDFdp6W1EGMcet8",
1688        ],
1689        [
1690            "xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1",
1691            "bgwQ9xv5ski8PX9rL2dZXvgGDnw",
1692        ],
1693        [
1694            "xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq",
1695            "527Hqck2AxYysAA7xmALppuCkwQ",
1696        ],
1697        [
1698            "xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7",
1699            "n7epu4trkrX7x7DogT5Uv6fcLW5",
1700        ],
1701        [
1702            "xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37",
1703            "sR62cfN7fe5JnJ7dh8zL4fiyLHV",
1704        ],
1705        [
1706            "xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8",
1707            "yGasTvXEYBVPamhGW6cFJodrTHy",
1708        ],
1709    ];
1710
1711    /// Public extended keys of second test vector of bip-0032.
1712    const TV_32_02_XPUB: [[&str; 2]; 6] = [
1713        [
1714            "xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6",
1715            "mr8BDzTJY47LJhkJ8UB7WEGuduB",
1716        ],
1717        [
1718            "xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDzn",
1719            "ezpbZb7ap6r1D3tgFxHmwMkQTPH",
1720        ],
1721        [
1722            "xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ85ySDhKiLDBrQSARLq1uNRts8",
1723            "RuJiHjaDMBU4Zn9h8LZNnBC5y4a",
1724        ],
1725        [
1726            "xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89",
1727            "LojfZ537wTfunKau47EL2dhHKon",
1728        ],
1729        [
1730            "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY",
1731            "2grBGRjaDMzQLcgJvLJuZZvRcEL",
1732        ],
1733        [
1734            "xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2",
1735            "rnY5agb9rXpVGyy3bdW6EEgAtqt",
1736        ],
1737    ];
1738
1739    /// Public extended keys of third test vector of bip-0032.
1740    const TV_32_03_XPUB: [[&str; 2]; 2] = [
1741        [
1742            "xpub661MyMwAqRbcEZVB4dScxMAdx6d4nFc9nvyvH3v4gJL378CSRZiYmhRoP7mBy6gSPSCYk6SzXPTf3ND1",
1743            "cZAceL7SfJ1Z3GC8vBgp2epUt13",
1744        ],
1745        [
1746            "xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9M",
1747            "Yo6oDaPPLPxSb7gwQN3ih19Zm4Y",
1748        ],
1749    ];
1750
1751    /// WIF secret key with payload of all bytes '0x11'.
1752    const WIF_1: &str = "5HwoXVkHoRM8sL2KmNRS217n1g8mPPBomrY7yehCuXC1115WWsh";
1753
1754    /// WIF secret key with payload of 'secret' entropy.
1755    const WIF_A: &str = "5K6tjEYPunJtSHRbWLSWtYGXmeFW4UJStKb3RUo5VUqQtksHkze";
1756
1757    /// WIF secret key with payload of all bytes '0x69'.
1758    const WIF_L: &str = "5JciBbkdYdjKKE9rwZ7c1XscwwcLBbv9aJyeZeWQi2gZnHeiX57";
1759
1760    /// WIF compressed secret key with all bytes '0x11'.
1761    const WIC_1: &str = "KwntMbt59tTsj8xqpqYqRRWufyjGunvhSyeMo3NTYpFYzZbXJ5Hp";
1762
1763    /// WIF compressed secret key of 'secret' entropy.
1764    const WIC_A: &str = "L2u1KQma7xyx2bVZJUocvV1Yp3R1GKW1FX3Fh3gNphrgTDVqp1sG";
1765
1766    /// WIF compressed secret key with all bytes '0x69'.
1767    const WIC_L: &str = "KzkcmnPaJd7mqT47Rnk9XMGRfW2wfo7ar2M2o6Yoe6Rdgbg2bHM9";
1768
1769    ///army van defense carry jealous true garbage claim echo media make crunch
1770    const XPRV_A: [&str; 2] = [
1771        "xprv9s21ZrQH143K3t4UZrNgeA3w861fwjYLaGwmPtQyPMmzshV2owVpfBSd2Q7YsHZ9j6i6ddYjb5PLtUdMZn8L",
1772        "hvuCVhGcQntq5rn7JVMqnie",
1773    ];
1774
1775    /// Root key generated randomly.
1776    const XPRV_R: [&str; 2] = [
1777        "xprv9s21ZrQH143K2maNNY6YGXJZ4yGBEae4Jc4s6pfR6haWQEjLbCa2gBzUyYJS5cQuxPNjTtfBqUC9DPPyXfJV",
1778        "UgMn6qqmUUDJBtTzqa6rY2w",
1779    ];
1780
1781    /// m/1h/2/3h/4/5h/6/7h/8/9' derivation of root key generated randomly.
1782    const XPRV_R_D: [&str; 2] = [
1783        "xprvAAVaDKt9qqGMFfrRPXWyL9SVkSsq7QozvfmVh1e9g1A9XZUuYwewdx84fw9iL8YkyzycjB4STWQf9bFuzATG",
1784        "yZTR7PUB1CLpGRaLUAiGgxH",
1785    ];
1786
1787    /// 'XPRV_R' with a non zero value at byte index 45 (invalid in private).
1788    const XPRV_R_NZ: [&str; 2] = [
1789        "xprv9s21ZrQH143K2maNNY6YGXJZ4yGBEae4Jc4s6pfR6haWQEjLbCa2gBzV34QbbxYGS4PWd2gF2LN4N4MHgdxt",
1790        "jcqiixH56CSRZhAiexotiHQ",
1791    ];
1792
1793    /// Root key generated with zeroed entropy.
1794    const XPRV_Z: [&str; 2] = [
1795        "xprv9s21ZrQH143K3GJpoapnV8SFfukcVBSfeCficPSGfubmSFDxo1kuHnLisriDvSnRRuL2Qrg5ggqHKNVpxR86",
1796        "QEC8w35uxmGoggxtQTPvfUu",
1797    ];
1798
1799    /// Extended public key of 'XPRV_A' with path m/44h/0h/0h/0.
1800    const XPUB_A: [&str; 2] = [
1801        "xpub6EdHrjLe1JdwRR6W5romAvmVzk7bfXQWV2N9SuTWP1ebszkLVQMev6KWTNtb2D9mQpocUfAsPQGkE6wtVe8K",
1802        "ug3dYyA9yCJTnHRPJAbgEAF",
1803    ];
1804
1805    /// Extended public key of 'XPRV_R' with path m/44h/0h/0h/0.
1806    const XPUB_R: [&str; 2] = [
1807        "xpub6EBARkwLtwz68GAfCSJ8AAqn6gxR2Lw6mJfK23rqDya64GvRT2LHYwDmBVdG5Cazs1Q59gPXj1MNmmL24Vi4",
1808        "Ce7nmjizMude8mGYqzSbMB8",
1809    ];
1810
1811    /// Extended public key of 'XPRV_Z' with path m/44h/0h/0h/0.
1812    const XPUB_Z: [&str; 2] = [
1813        "xpub6ELHKXNimKbxMCytPh7EdC2QXx46T9qLDJWGnTraz1H9kMMFdcduoU69wh9cxP12wDxqAAfbaESWGYt5rREs",
1814        "X1J8iR2TEunvzvddduAPYcY",
1815    ];
1816
1817    /// Bytes representation of the private extended key 'army van defense...'
1818    const XPRV_A_B: [u8; NBBY_XKEY] = [
1819        0x04, 0x88, 0xad, 0xe4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb7, 0x0d,
1820        0x67, 0x53, 0x23, 0xc4, 0x0e, 0xc4, 0x61, 0xe0, 0xa6, 0xaf, 0x60, 0x3b, 0x1f, 0x13, 0x5f,
1821        0xb2, 0xaf, 0x9a, 0xe7, 0x53, 0xee, 0xff, 0x18, 0x92, 0x27, 0x32, 0xa7, 0x3b, 0x0f, 0x05,
1822        0x00, 0xb2, 0xa0, 0xd5, 0x76, 0xb8, 0x28, 0xb5, 0x37, 0x68, 0x8b, 0x56, 0x1f, 0x2c, 0xfa,
1823        0x8d, 0xac, 0x36, 0x02, 0xd5, 0x4c, 0x62, 0xbd, 0xe6, 0x19, 0xad, 0x53, 0x31, 0xe6, 0xc2,
1824        0x35, 0xee, 0x26,
1825    ];
1826
1827    /// Bytes representation of the private extended key generated randomly.
1828    const XPRV_R_B: [u8; NBBY_XKEY] = [
1829        0x04, 0x88, 0xad, 0xe4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x61,
1830        0x89, 0xa3, 0xed, 0x99, 0xca, 0xf4, 0x0f, 0x7c, 0x9b, 0x88, 0xf1, 0x6d, 0x80, 0x58, 0x92,
1831        0xc9, 0x26, 0xb7, 0xbf, 0x8e, 0xcf, 0x7b, 0xff, 0x63, 0x2d, 0x7d, 0x40, 0x42, 0xbd, 0x4d,
1832        0x00, 0xd1, 0x95, 0x7c, 0xc8, 0x92, 0xb0, 0xd4, 0xf0, 0x48, 0x35, 0x65, 0xc4, 0x5c, 0x8c,
1833        0x4f, 0x2a, 0xe9, 0x46, 0x1c, 0x65, 0xb6, 0x1e, 0x33, 0x76, 0xb5, 0x05, 0xbe, 0x15, 0x6e,
1834        0xce, 0x5e, 0x3c,
1835    ];
1836
1837    /// Bytes representation of the private extended key with zeroed entropy.
1838    const XPRV_Z_B: [u8; NBBY_XKEY] = [
1839        0x04, 0x88, 0xad, 0xe4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x23,
1840        0x40, 0x8d, 0xad, 0xd3, 0xc7, 0xb5, 0x6e, 0xed, 0x15, 0x56, 0x77, 0x07, 0xae, 0x5e, 0x5d,
1841        0xca, 0x08, 0x9d, 0xe9, 0x72, 0xe0, 0x7f, 0x3b, 0x86, 0x04, 0x50, 0xe2, 0xa3, 0xb7, 0x0e,
1842        0x00, 0x18, 0x37, 0xc1, 0xbe, 0x8e, 0x29, 0x95, 0xec, 0x11, 0xcd, 0xa2, 0xb0, 0x66, 0x15,
1843        0x1b, 0xe2, 0xcf, 0xb4, 0x8a, 0xdf, 0x9e, 0x47, 0xb1, 0x51, 0xd4, 0x6a, 0xda, 0xb3, 0xa2,
1844        0x1c, 0xdf, 0x67,
1845    ];
1846
1847    /// Bytes representation of the extended public key 'XPUB_A'.
1848    const XPUB_A_B: [u8; NBBY_XKEY] = [
1849        0x04, 0x88, 0xb2, 0x1e, 0x04, 0x94, 0xb0, 0x09, 0xed, 0x00, 0x00, 0x00, 0x00, 0xca, 0x1a,
1850        0xc2, 0x0b, 0x6c, 0xbf, 0x6e, 0x45, 0xc3, 0xcf, 0xc2, 0xf2, 0x39, 0x9a, 0x5f, 0xd8, 0x91,
1851        0xa9, 0x2f, 0xff, 0x52, 0x21, 0xcd, 0xe0, 0x8a, 0x73, 0x98, 0xb5, 0x2d, 0x58, 0x1f, 0xd0,
1852        0x03, 0x86, 0x36, 0x98, 0x82, 0x77, 0x1a, 0x91, 0xbe, 0xc8, 0xb1, 0xc9, 0xd5, 0x0c, 0x54,
1853        0x66, 0xfe, 0x04, 0x44, 0xff, 0x76, 0x3e, 0xe0, 0xf7, 0x3b, 0xa0, 0x60, 0xc4, 0x7c, 0x63,
1854        0x53, 0xbd, 0xf7,
1855    ];
1856
1857    /// Bytes representation of the extended public key 'XPUB_R'.
1858    const XPUB_R_B: [u8; NBBY_XKEY] = [
1859        0x04, 0x88, 0xb2, 0x1e, 0x04, 0x57, 0x66, 0x12, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x83, 0x59,
1860        0xda, 0xd5, 0x56, 0xc1, 0xf4, 0x3c, 0x23, 0x3f, 0xb4, 0xba, 0x56, 0x55, 0xc1, 0xd6, 0x89,
1861        0x3b, 0x1f, 0x9d, 0x6d, 0x42, 0x52, 0xdb, 0x18, 0xd3, 0x0f, 0xc7, 0xfe, 0x3c, 0x44, 0xd6,
1862        0x02, 0xbb, 0xb6, 0xd2, 0x7b, 0x71, 0xb2, 0x6b, 0xf9, 0x23, 0xf9, 0xce, 0xcb, 0x31, 0x3f,
1863        0x1c, 0xb3, 0x48, 0xda, 0x6a, 0x92, 0xe8, 0xba, 0x7c, 0xa1, 0x70, 0x25, 0x61, 0xb4, 0x62,
1864        0x00, 0xc0, 0x67,
1865    ];
1866
1867    /// Bytes representation of the extended public key 'XPUB_Z'.
1868    const XPUB_Z_B: [u8; NBBY_XKEY] = [
1869        0x04, 0x88, 0xb2, 0x1e, 0x04, 0x6c, 0xc9, 0xf2, 0x52, 0x00, 0x00, 0x00, 0x00, 0xbc, 0xe8,
1870        0x0d, 0xd5, 0x80, 0x79, 0x2c, 0xd1, 0x8a, 0xf5, 0x42, 0x79, 0x0e, 0x56, 0xaa, 0x81, 0x31,
1871        0x78, 0xdc, 0x28, 0x64, 0x4b, 0xb5, 0xf0, 0x3d, 0xbd, 0x44, 0xc8, 0x5f, 0x2d, 0x2e, 0x7a,
1872        0x03, 0x86, 0xb8, 0x65, 0xb5, 0x2b, 0x75, 0x3d, 0x0a, 0x84, 0xd0, 0x9b, 0xc2, 0x00, 0x63,
1873        0xfa, 0xb5, 0xd8, 0x45, 0x3e, 0xc3, 0x3c, 0x21, 0x5d, 0x40, 0x19, 0xa5, 0x80, 0x1c, 0x9c,
1874        0x64, 0x38, 0xb9,
1875    ];
1876
1877    #[test]
1878    fn test_as_bs58ck_prv() {
1879        assert_eq!(
1880            ExtPrvKey::from_bs58_prv(&XPRV_A.concat())
1881                .unwrap()
1882                .as_bs58ck_prv(),
1883            XPRV_A.concat()
1884        );
1885        assert_eq!(
1886            ExtPrvKey::from_bs58_prv(&XPRV_R.concat())
1887                .unwrap()
1888                .as_bs58ck_prv(),
1889            XPRV_R.concat()
1890        );
1891        assert_eq!(
1892            ExtPrvKey::from_bs58_prv(&XPRV_Z.concat())
1893                .unwrap()
1894                .as_bs58ck_prv(),
1895            XPRV_Z.concat()
1896        );
1897        assert_eq!(
1898            ExtPrvKey::from_bs58_prv(&XPRV_R.concat())
1899                .unwrap()
1900                .derive_prv(&"m/1h/2/3h/4/5h/6/7h/8/9h".decode_path(false).unwrap())
1901                .unwrap()
1902                .as_bs58ck_prv(),
1903            XPRV_R_D.concat()
1904        );
1905        assert_ne!(
1906            ExtPrvKey::from_bs58_prv(&XPRV_Z.concat())
1907                .unwrap()
1908                .as_bs58ck_prv(),
1909            "error"
1910        );
1911    }
1912
1913    #[test]
1914    fn test_as_bs58ck_pub() {
1915        assert_eq!(
1916            ExtPubKey::from_bs58_pub(&XPUB_A.concat())
1917                .unwrap()
1918                .as_bs58ck_pub(),
1919            XPUB_A.concat()
1920        );
1921        assert_eq!(
1922            ExtPubKey::from_bs58_pub(&XPUB_R.concat())
1923                .unwrap()
1924                .as_bs58ck_pub(),
1925            XPUB_R.concat()
1926        );
1927        assert_eq!(
1928            ExtPubKey::from_bs58_pub(&XPUB_Z.concat())
1929                .unwrap()
1930                .as_bs58ck_pub(),
1931            XPUB_Z.concat()
1932        );
1933        assert_ne!(
1934            ExtPubKey::from_bs58_pub(&XPUB_Z.concat())
1935                .unwrap()
1936                .as_bs58ck_pub(),
1937            "error"
1938        );
1939    }
1940
1941    #[test]
1942    fn test_bytes_prv() {
1943        assert_eq!(
1944            ExtPrvKey::from_bs58_prv(&XPRV_A.concat())
1945                .unwrap()
1946                .bytes_prv(),
1947            XPRV_A_B[..NBBY_XKEY]
1948        );
1949        assert_eq!(
1950            ExtPrvKey::from_bs58_prv(&XPRV_R.concat())
1951                .unwrap()
1952                .bytes_prv(),
1953            XPRV_R_B[..NBBY_XKEY]
1954        );
1955        assert_eq!(
1956            ExtPrvKey::from_bs58_prv(&XPRV_Z.concat())
1957                .unwrap()
1958                .bytes_prv(),
1959            XPRV_Z_B[..NBBY_XKEY]
1960        );
1961    }
1962
1963    #[test]
1964    fn test_bytes_pub() {
1965        assert_eq!(
1966            ExtPubKey::from_bs58_pub(&XPUB_A.concat())
1967                .unwrap()
1968                .bytes_pub(),
1969            XPUB_A_B[..NBBY_XKEY]
1970        );
1971        assert_eq!(
1972            ExtPubKey::from_bs58_pub(&XPUB_R.concat())
1973                .unwrap()
1974                .bytes_pub(),
1975            XPUB_R_B[..NBBY_XKEY]
1976        );
1977        assert_eq!(
1978            ExtPubKey::from_bs58_pub(&XPUB_Z.concat())
1979                .unwrap()
1980                .bytes_pub(),
1981            XPUB_Z_B[..NBBY_XKEY]
1982        );
1983    }
1984
1985    #[test]
1986    fn test_ckd_prv() {
1987        assert!(ExtPrvKey::from_bs58_prv(&XPRV_A.concat())
1988            .unwrap()
1989            .ckd_prv(&0)
1990            .is_ok());
1991        assert!(ExtPrvKey::from_bs58_prv(&XPRV_R.concat())
1992            .unwrap()
1993            .ckd_prv(&0)
1994            .is_ok());
1995        assert!(ExtPrvKey::from_bs58_prv(&XPRV_Z.concat())
1996            .unwrap()
1997            .ckd_prv(&0)
1998            .is_ok());
1999        let mut to_test = ExtPrvKey::from_bs58_prv(&XPRV_A.concat()).unwrap();
2000        to_test.prvdata = [0xff; 32];
2001        assert_eq!(to_test.ckd_prv(&0).unwrap_err(), Error::SecEnt);
2002        to_test.prvdata = [0x00; 32];
2003        assert_eq!(to_test.ckd_prv(&0).unwrap_err(), Error::SecEnt);
2004    }
2005
2006    #[test]
2007    fn test_ckd_pub() {
2008        assert!(ExtPubKey::from_bs58_pub(&XPUB_A.concat())
2009            .unwrap()
2010            .ckd_pub(&0)
2011            .is_ok());
2012        assert!(ExtPubKey::from_bs58_pub(&XPUB_R.concat())
2013            .unwrap()
2014            .ckd_pub(&0)
2015            .is_ok());
2016        assert!(ExtPubKey::from_bs58_pub(&XPUB_Z.concat())
2017            .unwrap()
2018            .ckd_pub(&0)
2019            .is_ok());
2020        let mut to_test = ExtPubKey::from_bs58_pub(&XPUB_A.concat()).unwrap();
2021        to_test.pubdata = [0xff; 33];
2022        assert_eq!(to_test.ckd_pub(&0).unwrap_err(), Error::PubData);
2023        to_test.pubdata = [0x00; 33];
2024        assert_eq!(to_test.ckd_pub(&0).unwrap_err(), Error::PubData);
2025    }
2026
2027    #[test]
2028    fn test_decode_address() {
2029        assert!(P2WPKH_C_1.decode_address().is_ok());
2030        assert!(P2WPKH_C_A.decode_address().is_ok());
2031        assert!(P2WPKH_C_L.decode_address().is_ok());
2032        assert!(P2WPKH_P2SH_1.decode_address().is_ok());
2033        assert!(P2WPKH_P2SH_L.decode_address().is_ok());
2034        assert!(P2WPKH_U_1.decode_address().is_ok());
2035        assert!(P2WPKH_U_A.decode_address().is_ok());
2036        assert!(P2WPKH_U_L.decode_address().is_ok());
2037        assert_eq!(SEGW_1.decode_address().unwrap(), SEGW_DEC_1);
2038        assert_eq!(SEGW_A.decode_address().unwrap(), SEGW_DEC_A);
2039        assert_eq!(SEGW_L.decode_address().unwrap(), SEGW_DEC_L);
2040        assert_eq!("invalid".decode_address().unwrap_err(), Error::Address);
2041        assert_eq!("1_invalid".decode_address().unwrap_err(), Error::Address);
2042        assert_eq!("3_invalid".decode_address().unwrap_err(), Error::Address);
2043        assert_eq!("bc_invalid".decode_address().unwrap_err(), Error::Address);
2044        assert_eq!(SEGW_1[..41].decode_address().unwrap_err(), Error::Address);
2045    }
2046
2047    #[test]
2048    fn test_decode_base58ck() {
2049        assert_eq!(XPRV_A.concat().decode_base58ck().unwrap(), XPRV_A_B);
2050        assert_eq!(XPRV_R.concat().decode_base58ck().unwrap(), XPRV_R_B);
2051        assert_eq!(XPRV_Z.concat().decode_base58ck().unwrap(), XPRV_Z_B);
2052        assert_eq!(
2053            ["!"; LEN_ARG_MIN].concat().decode_base58ck().unwrap_err(),
2054            Error::Base58
2055        );
2056        assert_eq!(
2057            ["a"; LEN_ARG_MIN - 1]
2058                .concat()
2059                .decode_base58ck()
2060                .unwrap_err(),
2061            Error::Argument(String::from(["a"; LEN_ARG_MIN - 1].concat()))
2062        );
2063        assert_eq!(
2064            XPRV_A
2065                .concat()
2066                .replace("a", "A")
2067                .decode_base58ck()
2068                .unwrap_err(),
2069            Error::Checksum
2070        );
2071    }
2072
2073    #[test]
2074    fn test_decode_path() {
2075        assert!(PATH_START.decode_path(false).is_ok());
2076        assert!("m/0h/0".decode_path(true).is_err());
2077        assert!("m/0/1h/9/2147483647h/0/32h/69/96/0h/1"
2078            .decode_path(false)
2079            .is_ok());
2080        assert!("m/0/1h/9/2147483647h/0/32h/69/96/0h/1/"
2081            .decode_path(false)
2082            .is_ok());
2083        assert!("m/0/1h/9/4294967295/0/32h/69/96/0h/1/"
2084            .decode_path(false)
2085            .is_err());
2086        assert!("M".decode_path(false).is_err());
2087        assert!("n".decode_path(false).is_err());
2088        assert!("/0h/mh".decode_path(false).is_err());
2089        assert!("0h/mh".decode_path(false).is_err());
2090        assert!("0/mh".decode_path(false).is_err());
2091        assert!("m/0h/ah".decode_path(false).is_err());
2092        assert_eq!(PATH_START.decode_path(false).unwrap(), []);
2093        assert_eq!("m/0h/1".decode_path(false).unwrap(), [HARD_NB, 1]);
2094        assert_eq!("m/1/10h".decode_path(false).unwrap(), [1, 0x8000000a]);
2095        assert_eq!("m/0/1/2/3/4/".decode_path(false).unwrap(), [0, 1, 2, 3, 4]);
2096        assert_eq!(
2097            "m/0/1h/9/2147483647h/m/32".decode_path(false).unwrap_err(),
2098            Error::Path(String::from("m"))
2099        );
2100        assert_eq!(
2101            "m/0/1h/9/2147483648/0/32".decode_path(false).unwrap_err(),
2102            Error::Path(String::from("2147483648"))
2103        );
2104        assert_eq!(
2105            "m/0/1h/9/2147483648/0/32".decode_path(false).unwrap_err(),
2106            Error::Path(String::from("2147483648"))
2107        );
2108        assert_eq!(
2109            "m/0/1h/9/4294967295/0/32".decode_path(false).unwrap_err(),
2110            Error::Path(String::from("4294967295"))
2111        );
2112    }
2113
2114    #[test]
2115    fn test_decode_range() {
2116        assert_eq!("1".decode_range().unwrap(), (1, 1));
2117        assert_eq!("1h".decode_range().unwrap(), (0x80000001, 0x80000001));
2118        assert_eq!("..1".decode_range().unwrap(), (0, 1));
2119        assert_eq!("..1h".decode_range().unwrap(), (0, 0x80000001));
2120        assert_eq!("1..".decode_range().unwrap(), (1, 0x7fffffff));
2121        assert_eq!("1h..".decode_range().unwrap(), (0x80000001, 0xffffffff));
2122        assert_eq!("0..9".decode_range().unwrap(), (0, 9));
2123        assert_eq!("0..9h".decode_range().unwrap(), (0, 0x80000009));
2124        assert_eq!("0h..9h".decode_range().unwrap(), (0x80000000, 0x80000009));
2125        assert_eq!("6232..6233".decode_range().unwrap(), (6232, 6233));
2126        assert_eq!(
2127            "1h..0".decode_range().unwrap_err(),
2128            Error::Range(String::from("0"))
2129        );
2130        assert_eq!(
2131            "0:9".decode_range().unwrap_err(),
2132            Error::Range(String::from("0:9"))
2133        );
2134        assert_eq!(
2135            "9..9".decode_range().unwrap_err(),
2136            Error::Range(String::from("9..9"))
2137        );
2138        assert_eq!(
2139            "9..0".decode_range().unwrap_err(),
2140            Error::Range(String::from("9..0"))
2141        );
2142        assert_eq!(
2143            "-9..0".decode_range().unwrap_err(),
2144            Error::Range(String::from("-9"))
2145        );
2146        assert_eq!(
2147            "-1..".decode_range().unwrap_err(),
2148            Error::Range(String::from("-1"))
2149        );
2150        assert_eq!(
2151            "..-1".decode_range().unwrap_err(),
2152            Error::Range(String::from("-1"))
2153        );
2154        assert_eq!(
2155            "0..2147483649".decode_range().unwrap_err(),
2156            Error::Range(String::from("2147483649"))
2157        );
2158    }
2159
2160    #[test]
2161    fn test_decode_wif() {
2162        assert_eq!(WIC_1.decode_wif().unwrap(), ([0x11; 32], true));
2163        assert_eq!(WIC_L.decode_wif().unwrap(), ([0x69; 32], true));
2164        assert_eq!(WIF_1.decode_wif().unwrap(), ([0x11; 32], false));
2165        assert_eq!(WIF_L.decode_wif().unwrap(), ([0x69; 32], false));
2166        assert_eq!(
2167            [WIF_L, "a"].concat().decode_wif().unwrap_err(),
2168            Error::WifKey
2169        );
2170        assert_eq!(
2171            WIC_L.replace("dgbg", "dgdg").decode_wif().unwrap_err(),
2172            Error::Checksum
2173        );
2174        assert_eq!(
2175            ["a"; LEN_WIF_U].concat().decode_wif().unwrap_err(),
2176            Error::WifKey
2177        );
2178        assert_eq!(
2179            ["a"; LEN_WIF_C].concat().decode_wif().unwrap_err(),
2180            Error::WifKey
2181        );
2182    }
2183
2184    #[test]
2185    fn test_derive_prv() {
2186        for (idx, xprv) in TV_32_01_XPRV.iter().enumerate() {
2187            assert_eq!(
2188                ExtPrvKey::from_bs58_prv(&TV_32_01_XPRV[0].concat())
2189                    .unwrap()
2190                    .derive_prv(&TV_32_01_PATH[idx].decode_path(false).unwrap())
2191                    .unwrap()
2192                    .as_bs58ck_prv(),
2193                xprv.concat()
2194            );
2195        }
2196        for (idx, xprv) in TV_32_02_XPRV.iter().enumerate() {
2197            assert_eq!(
2198                ExtPrvKey::from_bs58_prv(&TV_32_02_XPRV[0].concat())
2199                    .unwrap()
2200                    .derive_prv(&TV_32_02_PATH[idx].decode_path(false).unwrap())
2201                    .unwrap()
2202                    .as_bs58ck_prv(),
2203                xprv.concat()
2204            );
2205        }
2206        for (idx, xprv) in TV_32_03_XPRV.iter().enumerate() {
2207            assert_eq!(
2208                ExtPrvKey::from_bs58_prv(&TV_32_03_XPRV[0].concat())
2209                    .unwrap()
2210                    .derive_prv(&TV_32_03_PATH[idx].decode_path(false).unwrap())
2211                    .unwrap()
2212                    .as_bs58ck_prv(),
2213                xprv.concat()
2214            );
2215        }
2216        let to_test = ExtPrvKey::from_bs58_prv(&XPRV_R.concat()).unwrap();
2217        assert!(to_test.derive_prv(&"m".decode_path(false).unwrap()).is_ok());
2218        assert!(to_test
2219            .derive_prv(
2220                &"m/0/1h/9/2147483647h/0/32h/69/96/0h/1"
2221                    .decode_path(false)
2222                    .unwrap()
2223            )
2224            .is_ok());
2225        let pub_key = ExtPrvKey::from_bs58_prv(&XPRV_Z.concat())
2226            .unwrap()
2227            .derive_prv(&"m/44h/0h/0h/0/19".decode_path(false).unwrap())
2228            .unwrap()
2229            .prvdata
2230            .public_key(true)
2231            .unwrap();
2232        assert_eq!(pub_key.p2wpkh().unwrap(), P2WPKH_Z_19);
2233    }
2234
2235    #[test]
2236    fn test_derive_pub() {
2237        let to_test = ExtPubKey::from_bs58_pub(&XPUB_R.concat()).unwrap();
2238        assert!(to_test.derive_pub(&"m".decode_path(true).unwrap()).is_ok());
2239        assert!(to_test
2240            .derive_pub(&"m/0/9/2147483647/0/32/69/96/0/1".decode_path(true).unwrap())
2241            .is_ok());
2242        assert!(to_test
2243            .derive_pub(
2244                // false let pass hardened value
2245                &"m/0/9/0h/0/32/69/96/0/1".decode_path(false).unwrap()
2246            )
2247            .is_err());
2248        assert_eq!(
2249            ExtPubKey::from_bs58_pub(&XPUB_Z.concat())
2250                .unwrap()
2251                .derive_pub(&"m/0".decode_path(true).unwrap())
2252                .unwrap()
2253                .pubdata
2254                .p2wpkh()
2255                .unwrap(),
2256            P2WPKH_Z_0
2257        );
2258    }
2259
2260    #[test]
2261    fn test_encode_base58ck() {
2262        assert_eq!("a".as_bytes().encode_base58ck(), "C2dGTwc");
2263        assert_eq!("abc".as_bytes().encode_base58ck(), "4h3c6RH52R");
2264    }
2265
2266    #[test]
2267    fn test_encode_path() {
2268        assert_eq!("m".decode_path(false).unwrap().encode_path(), "m");
2269        assert_eq!(
2270            "m/00000000h/1".decode_path(false).unwrap().encode_path(),
2271            "m/0h/1"
2272        );
2273        assert_eq!(
2274            "m/000001/10h".decode_path(false).unwrap().encode_path(),
2275            "m/1/10h"
2276        );
2277        assert_eq!([0u32; 0].encode_path(), "m");
2278        assert_eq!([1u32, 2, 3, 4, 5, HARD_NB].encode_path(), "m/1/2/3/4/5/0h");
2279    }
2280
2281    #[test]
2282    fn test_encode_wif() {
2283        assert_eq!(&[0x11; 32].encode_wif(true).unwrap(), WIC_1);
2284        assert_eq!(&P2WPKH_B.encode_wif(true).unwrap(), WIC_A);
2285        assert_eq!(&[0x69; 32].encode_wif(true).unwrap(), WIC_L);
2286        assert_eq!(&[0x11; 32].encode_wif(false).unwrap(), WIF_1);
2287        assert_eq!(&P2WPKH_B.encode_wif(false).unwrap(), WIF_A);
2288        assert_eq!(&[0x69; 32].encode_wif(false).unwrap(), WIF_L);
2289    }
2290
2291    #[test]
2292    fn test_from_bs58_prv() {
2293        assert_eq!(
2294            ExtPrvKey::from_bs58_prv(&XPRV_A.concat())
2295                .unwrap()
2296                .bytes_prv(),
2297            XPRV_A_B[..NBBY_XKEY]
2298        );
2299        assert_eq!(
2300            ExtPrvKey::from_bs58_prv(&XPRV_R.concat())
2301                .unwrap()
2302                .bytes_prv(),
2303            XPRV_R_B[..NBBY_XKEY]
2304        );
2305        assert_eq!(
2306            ExtPrvKey::from_bs58_prv(&XPRV_Z.concat())
2307                .unwrap()
2308                .bytes_prv(),
2309            XPRV_Z_B[..NBBY_XKEY]
2310        );
2311        assert_eq!(
2312            ExtPrvKey::from_bs58_prv(&XPUB_Z.concat()).unwrap_err(), // xpub
2313            Error::KeyVer
2314        );
2315        assert_eq!(
2316            ExtPrvKey::from_bs58_prv(&XPRV_Z.concat().replace("a", "A")).unwrap_err(),
2317            Error::Checksum
2318        );
2319        assert_eq!(
2320            ExtPrvKey::from_bs58_prv(&XPRV_Z.concat()[..100]).unwrap_err(),
2321            Error::KeyLen
2322        );
2323        assert_eq!(
2324            ExtPrvKey::from_bs58_prv(&[&XPRV_Z.concat(), "aaaaa"].concat()).unwrap_err(),
2325            Error::KeyLen
2326        );
2327        assert_eq!(
2328            ExtPrvKey::from_bs58_prv(&XPRV_R_NZ.concat()).unwrap_err(), //non 0
2329            Error::PrvData
2330        );
2331    }
2332
2333    #[test]
2334    fn test_from_bs58_pub() {
2335        assert_eq!(
2336            ExtPubKey::from_bs58_pub(&XPUB_A.concat())
2337                .unwrap()
2338                .bytes_pub(),
2339            XPUB_A_B[..NBBY_XKEY]
2340        );
2341        assert_eq!(
2342            ExtPubKey::from_bs58_pub(&XPUB_R.concat())
2343                .unwrap()
2344                .bytes_pub(),
2345            XPUB_R_B[..NBBY_XKEY]
2346        );
2347        assert_eq!(
2348            ExtPubKey::from_bs58_pub(&XPUB_Z.concat())
2349                .unwrap()
2350                .bytes_pub(),
2351            XPUB_Z_B[..NBBY_XKEY]
2352        );
2353        assert_eq!(
2354            ExtPubKey::from_bs58_pub(&XPRV_Z.concat()).unwrap_err(), // xprv
2355            Error::KeyVer
2356        );
2357        assert_eq!(
2358            ExtPubKey::from_bs58_pub(&XPUB_Z.concat()[..100]).unwrap_err(),
2359            Error::KeyLen
2360        );
2361        assert_eq!(
2362            ExtPubKey::from_bs58_pub(&[&XPUB_Z.concat(), "aaaaa"].concat()).unwrap_err(),
2363            Error::KeyLen
2364        );
2365        assert_eq!(
2366            ExtPubKey::from_bs58_pub(&XPUB_Z.concat().replace("a", "A")).unwrap_err(),
2367            Error::Checksum
2368        );
2369    }
2370
2371    #[test]
2372    fn test_from_prv() {
2373        for (idx, xpub) in TV_32_01_XPUB.iter().enumerate() {
2374            assert_eq!(
2375                ExtPubKey::from_prv(
2376                    &ExtPrvKey::from_bs58_prv(&TV_32_01_XPRV[0].concat())
2377                        .unwrap()
2378                        .derive_prv(&TV_32_01_PATH[idx].decode_path(false).unwrap())
2379                        .unwrap()
2380                )
2381                .unwrap()
2382                .as_bs58ck_pub(),
2383                xpub.concat()
2384            );
2385        }
2386        for (idx, xpub) in TV_32_02_XPUB.iter().enumerate() {
2387            assert_eq!(
2388                ExtPubKey::from_prv(
2389                    &ExtPrvKey::from_bs58_prv(&TV_32_02_XPRV[0].concat())
2390                        .unwrap()
2391                        .derive_prv(&TV_32_02_PATH[idx].decode_path(false).unwrap())
2392                        .unwrap()
2393                )
2394                .unwrap()
2395                .as_bs58ck_pub(),
2396                xpub.concat()
2397            );
2398        }
2399        for (idx, xpub) in TV_32_03_XPUB.iter().enumerate() {
2400            assert_eq!(
2401                ExtPubKey::from_prv(
2402                    &ExtPrvKey::from_bs58_prv(&TV_32_03_XPRV[0].concat())
2403                        .unwrap()
2404                        .derive_prv(&TV_32_03_PATH[idx].decode_path(false).unwrap())
2405                        .unwrap()
2406                )
2407                .unwrap()
2408                .as_bs58ck_pub(),
2409                xpub.concat()
2410            );
2411        }
2412        assert_eq!(
2413            ExtPubKey::from_prv(
2414                &ExtPrvKey::from_bs58_prv(&XPRV_A.concat())
2415                    .unwrap()
2416                    .derive_prv(&"m/44h/0h/0h/0".decode_path(false).unwrap())
2417                    .unwrap()
2418            )
2419            .unwrap()
2420            .as_bs58ck_pub(),
2421            XPUB_A.concat()
2422        );
2423        assert_eq!(
2424            ExtPubKey::from_prv(
2425                &ExtPrvKey::from_bs58_prv(&XPRV_R.concat())
2426                    .unwrap()
2427                    .derive_prv(&"m/44h/0h/0h/0".decode_path(false).unwrap())
2428                    .unwrap()
2429            )
2430            .unwrap()
2431            .as_bs58ck_pub(),
2432            XPUB_R.concat()
2433        );
2434        assert_eq!(
2435            ExtPubKey::from_prv(
2436                &ExtPrvKey::from_bs58_prv(&XPRV_Z.concat())
2437                    .unwrap()
2438                    .derive_prv(&"m/44h/0h/0h/0".decode_path(false).unwrap())
2439                    .unwrap()
2440            )
2441            .unwrap()
2442            .as_bs58ck_pub(),
2443            XPUB_Z.concat()
2444        );
2445    }
2446
2447    #[test]
2448    fn test_handle_arguments() {
2449        let inputs = [
2450            &XPRV_A.concat(),
2451            &XPRV_R.concat(),
2452            &XPRV_Z.concat(),
2453            HEX_STR_1,
2454            HEX_STR_L,
2455            WIF_1,
2456            WIF_L,
2457            WIC_1,
2458            WIC_L,
2459            &P2WPKH_B.hex_string(),
2460            P2WPKH_C_1,
2461            P2WPKH_C_A,
2462            P2WPKH_C_L,
2463            P2WPKH_P2SH_1,
2464            P2WPKH_P2SH_L,
2465            P2WPKH_U_1,
2466            P2WPKH_U_A,
2467            P2WPKH_U_L,
2468            SEGW_1,
2469            SEGW_A,
2470            SEGW_L,
2471        ];
2472        for input in &inputs {
2473            assert!(handle_arguments(init_clap().get_matches_from(vec!["", input])).is_ok());
2474        }
2475        assert!(handle_arguments(init_clap().get_matches_from(vec![
2476            "",
2477            &XPRV_R.concat(),
2478            "-e",
2479            "バンドメイド",
2480            "-p",
2481            "m/0h",
2482            "-r",
2483            "0h..11h"
2484        ]))
2485        .is_ok());
2486    }
2487
2488    #[test]
2489    fn test_hash160() {
2490        assert_eq!([0x11; 33].hash160(), H160_33_1);
2491        assert_eq!([0x69; 33].hash160(), H160_33_L);
2492    }
2493
2494    #[test]
2495    fn test_hash256() {
2496        // created with dual 'echo HEX_NB | xxd -r -p | openssl sha256'
2497        assert_eq!([0x00].hash256(), DS256_Z);
2498        assert_eq!([0x69; 32].hash256(), DS256_L);
2499        assert_eq!([0xff; 32].hash256(), DS256_F);
2500    }
2501
2502    #[test]
2503    fn test_hex_bytes() {
2504        assert_eq!("0488ade4".hex_bytes().unwrap(), XPRV);
2505        assert_eq!("BABACA".hex_bytes().unwrap(), [0xba, 0xba, 0xca]);
2506    }
2507
2508    #[test]
2509    fn test_hex_string() {
2510        assert_eq!(XPRV.hex_string(), String::from("0488ade4"));
2511        assert_eq!([0xba, 0xba, 0xca].hex_string(), String::from("babaca"));
2512    }
2513
2514    #[test]
2515    fn test_info_entropy() {
2516        assert!(HEX_STR_1.info_entropy("", DEF_SEP).is_ok());
2517        assert!(HEX_STR_L.info_entropy("", DEF_SEP).is_ok());
2518        assert!(HEX_STR_1.info_entropy("pass", DEF_SEP).is_ok());
2519        assert_eq!(
2520            HEX_STR_0.info_entropy("", DEF_SEP).unwrap_err(),
2521            Error::SecEnt
2522        );
2523        assert_eq!(
2524            HEX_STR_F.info_entropy("", DEF_SEP).unwrap_err(),
2525            Error::SecEnt
2526        );
2527        assert_eq!(
2528            ["a"; 63].concat().info_entropy("", DEF_SEP).unwrap_err(),
2529            Error::SecEnt
2530        );
2531        assert_eq!(
2532            ["?"; 64].concat().info_entropy("", DEF_SEP).unwrap_err(),
2533            Error::HexStr
2534        );
2535    }
2536
2537    #[test]
2538    fn test_info_wif() {
2539        assert!(WIF_1.info_wif("", DEF_SEP).is_ok());
2540        assert!(WIF_L.info_wif("", DEF_SEP).is_ok());
2541        assert!(WIF_1.info_wif("superpass", DEF_SEP).is_ok());
2542        assert!(WIC_1.info_wif("", DEF_SEP).is_ok());
2543        assert!(WIC_L.info_wif("", DEF_SEP).is_ok());
2544        assert!(WIC_1.info_wif("superduperpass", DEF_SEP).is_ok());
2545        assert_eq!(
2546            WIC_1.replace("H", "h").info_wif("", DEF_SEP).unwrap_err(),
2547            Error::Checksum
2548        );
2549        assert_eq!(
2550            WIF_1.replace("W", "w").info_wif("", DEF_SEP).unwrap_err(),
2551            Error::Checksum
2552        );
2553        assert_eq!(
2554            "something_wrong".info_wif("", DEF_SEP).unwrap_err(),
2555            Error::WifKey
2556        );
2557    }
2558
2559    #[test]
2560    fn test_init_clap() {
2561        let inputs = [
2562            &XPRV_A.concat(),
2563            &XPRV_R.concat(),
2564            &XPRV_Z.concat(),
2565            HEX_STR_1,
2566            HEX_STR_L,
2567            WIF_1,
2568            WIF_L,
2569            WIC_1,
2570            WIC_L,
2571            &P2WPKH_B.hex_string(),
2572            P2WPKH_C_1,
2573            P2WPKH_C_A,
2574            P2WPKH_C_L,
2575            P2WPKH_P2SH_1,
2576            P2WPKH_P2SH_L,
2577            P2WPKH_U_1,
2578            P2WPKH_U_A,
2579            P2WPKH_U_L,
2580            SEGW_1,
2581            SEGW_A,
2582            SEGW_L,
2583        ];
2584        for input in &inputs {
2585            assert!(init_clap().try_get_matches_from(vec!["", input]).is_ok());
2586        }
2587        assert!(init_clap()
2588            .try_get_matches_from(vec![
2589                "",
2590                &XPRV_A.concat(),
2591                "-e",
2592                "ultrasecretpass",
2593                "-p",
2594                "m/10h/20",
2595                "-r",
2596                "..7"
2597            ])
2598            .is_ok());
2599        assert!(init_clap()
2600            .try_get_matches_from(vec!["only_binary_name"])
2601            .is_err());
2602        assert!(init_clap()
2603            .try_get_matches_from(vec!["", &["a"; LEN_ARG_MIN - 1].concat()])
2604            .is_err());
2605        assert!(init_clap()
2606            .try_get_matches_from(vec!["", "wrong_data"])
2607            .is_err());
2608        assert!(init_clap()
2609            .try_get_matches_from(vec!["", &XPRV_A.concat(), "-e"])
2610            .is_err());
2611        assert!(init_clap()
2612            .try_get_matches_from(vec!["", &XPRV_A.concat(), "-p"])
2613            .is_err());
2614        assert!(init_clap()
2615            .try_get_matches_from(vec!["", &XPRV_A.concat(), "-r"])
2616            .is_err());
2617        assert!(init_clap()
2618            .try_get_matches_from(vec!["", &XPRV_A.concat(), "-x"])
2619            .is_err());
2620        assert!(init_clap()
2621            .try_get_matches_from(vec!["", "double", "data"])
2622            .is_err());
2623    }
2624
2625    #[test]
2626    fn test_is_hex() {
2627        assert!("0123456789abcdf".is_hex());
2628        assert!("ABCDEF".is_hex());
2629        assert!(!"ghijkl".is_hex());
2630        assert!(!"'!@#$%&*;:><?".is_hex());
2631    }
2632
2633    #[test]
2634    fn test_p2wpkh() {
2635        assert_eq!(PUB_C_1.p2wpkh().unwrap(), P2WPKH_C_1);
2636        assert_eq!(PUB_C_A.p2wpkh().unwrap(), P2WPKH_C_A);
2637        assert_eq!(PUB_C_L.p2wpkh().unwrap(), P2WPKH_C_L);
2638        assert_eq!(PUB_U_1.p2wpkh().unwrap(), P2WPKH_U_1);
2639        assert_eq!(PUB_U_A.p2wpkh().unwrap(), P2WPKH_U_A);
2640        assert_eq!(PUB_U_L.p2wpkh().unwrap(), P2WPKH_U_L);
2641        assert_eq!(PUB_C_L[1..].p2wpkh().unwrap_err(), Error::NbPubB(32));
2642        assert_eq!(PUB_U_L[1..].p2wpkh().unwrap_err(), Error::NbPubB(64));
2643    }
2644
2645    #[test]
2646    fn test_public_key() {
2647        assert_eq!(P2WPKH_B.public_key(true).unwrap(), PUB_C_A);
2648        assert_eq!([0x11; 32].public_key(true).unwrap(), PUB_C_1);
2649        assert_eq!([0x69; 32].public_key(true).unwrap(), PUB_C_L);
2650        assert_eq!(P2WPKH_B.public_key(false).unwrap(), PUB_U_A);
2651        assert_eq!([0x11; 32].public_key(false).unwrap(), PUB_U_1);
2652        assert_eq!([0x69; 32].public_key(false).unwrap(), PUB_U_L);
2653    }
2654
2655    #[test]
2656    fn test_segwit_p2wpkh() {
2657        assert_eq!(PUB_C_1.segwit_p2wpkh().unwrap(), SEGW_1);
2658        assert_eq!(PUB_C_A.segwit_p2wpkh().unwrap(), SEGW_A);
2659        assert_eq!(PUB_C_L.segwit_p2wpkh().unwrap(), SEGW_L);
2660    }
2661
2662    #[test]
2663    fn test_segwit_p2wpkh_p2sh() {
2664        assert_eq!(PUB_C_1.segwit_p2wpkh_p2sh().unwrap(), P2WPKH_P2SH_1);
2665        assert_eq!(PUB_C_A.segwit_p2wpkh_p2sh().unwrap(), P2WPKH_P2SH_A);
2666        assert_eq!(PUB_C_L.segwit_p2wpkh_p2sh().unwrap(), P2WPKH_P2SH_L);
2667    }
2668
2669    #[test]
2670    fn test_show_prv() {
2671        assert!(&ExtPrvKey::from_bs58_prv(&XPRV_A.concat())
2672            .unwrap()
2673            .show_prv(&vec![], (0, 1), "", DEF_SEP)
2674            .is_ok());
2675        assert!(ExtPrvKey::from_bs58_prv(&XPRV_R.concat())
2676            .unwrap()
2677            .show_prv(&vec![], (0, 1), "", DEF_SEP)
2678            .is_ok());
2679        assert!(ExtPrvKey::from_bs58_prv(&XPRV_Z.concat())
2680            .unwrap()
2681            .show_prv(&vec![], (0, 1), "", DEF_SEP)
2682            .is_ok());
2683    }
2684
2685    #[test]
2686    fn test_show_pub() {
2687        assert!(ExtPubKey::from_bs58_pub(&XPUB_A.concat())
2688            .unwrap()
2689            .show_pub(&vec![], (0, 1), DEF_SEP)
2690            .is_ok());
2691        assert!(ExtPubKey::from_bs58_pub(&XPUB_R.concat())
2692            .unwrap()
2693            .show_pub(&vec![], (0, 1), DEF_SEP)
2694            .is_ok());
2695        assert!(ExtPubKey::from_bs58_pub(&XPUB_Z.concat())
2696            .unwrap()
2697            .show_pub(&vec![], (0, 1), DEF_SEP)
2698            .is_ok());
2699        assert_eq!(
2700            ExtPubKey::from_bs58_pub(&XPUB_Z.concat())
2701                .unwrap()
2702                .show_pub(&vec![], (0x7fffffff, HARD_NB), DEF_SEP)
2703                .unwrap_err(),
2704            Error::FromHard
2705        );
2706    }
2707
2708    #[test]
2709    fn test_validate_data() {
2710        let inputs = [
2711            &XPRV_A.concat(),
2712            &XPRV_R.concat(),
2713            &XPRV_Z.concat(),
2714            HEX_STR_1,
2715            HEX_STR_L,
2716            WIF_1,
2717            WIF_L,
2718            WIC_1,
2719            WIC_L,
2720            &P2WPKH_B.hex_string(),
2721            P2WPKH_C_1,
2722            P2WPKH_C_A,
2723            P2WPKH_C_L,
2724            P2WPKH_P2SH_1,
2725            P2WPKH_P2SH_L,
2726            P2WPKH_U_1,
2727            P2WPKH_U_A,
2728            P2WPKH_U_L,
2729            SEGW_1,
2730            SEGW_A,
2731            SEGW_L,
2732        ];
2733        for input in &inputs {
2734            assert!(validate_data(OsString::from(*input)).is_ok());
2735        }
2736        assert!(validate_data(OsString::from(&XPRV_A.concat()[..LEN_XKEY - 1])).is_err());
2737        assert!(validate_data(OsString::from(format!("{}a", XPRV_A.concat()))).is_err());
2738        assert!(validate_data(OsString::from(&HEX_STR_1[1..])).is_err());
2739        assert!(validate_data(OsString::from(format!("{}a", HEX_STR_1))).is_err());
2740        assert!(validate_data(OsString::from(&WIF_L[..LEN_WIF_U - 1])).is_err());
2741        assert!(validate_data(OsString::from(format!("{}a", WIF_L))).is_err());
2742        assert!(validate_data(OsString::from(&WIC_L[..LEN_WIF_C - 1])).is_err());
2743        assert!(validate_data(OsString::from(format!("{}a", WIC_L))).is_err());
2744        assert!(validate_data(OsString::from(&P2WPKH_C_A[..LEN_LEG_MIN - 1])).is_err());
2745        assert!(validate_data(OsString::from(format!("{}ab", P2WPKH_C_A))).is_err());
2746        assert!(validate_data(OsString::from(&P2WPKH_P2SH_L[..LEN_LEG_MIN - 1])).is_err());
2747        assert!(validate_data(OsString::from(format!("{}ab", P2WPKH_P2SH_L))).is_err());
2748        assert!(validate_data(OsString::from(&SEGW_A[..LEN_SEGWIT - 1])).is_err());
2749        assert!(validate_data(OsString::from(format!("{}a", SEGW_A))).is_err());
2750    }
2751
2752    #[test]
2753    fn test_validate_path() {
2754        assert!(validate_path(OsString::from("m/0h/1")).is_ok());
2755        assert!(validate_path(OsString::from("m/h/1")).is_err());
2756        // to see more go to 'test_decode_path'
2757    }
2758
2759    #[test]
2760    fn test_validate_range() {
2761        assert!(validate_range(OsString::from("1..9")).is_ok());
2762        assert!(validate_range(OsString::from("9..1")).is_err());
2763        // to see more go to 'test_decode_range'
2764    }
2765}