Skip to main content

digibyte/util/
bip32.rs

1// Rust Bitcoin Library
2// Written in 2014 by
3//     Andrew Poelstra <apoelstra@wpsoftware.net>
4// To the extent possible under law, the author(s) have dedicated all
5// copyright and related and neighboring rights to this software to
6// the public domain worldwide. This software is distributed without
7// any warranty.
8//
9// You should have received a copy of the CC0 Public Domain Dedication
10// along with this software.
11// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
12//
13
14//! BIP32 Implementation
15//!
16//! Implementation of BIP32 hierarchical deterministic wallets, as defined
17//! at https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki
18
19use std::default::Default;
20use std::{error, fmt};
21use std::str::FromStr;
22#[cfg(feature = "serde")] use serde;
23
24use hash_types::XpubIdentifier;
25use hashes::{sha512, Hash, HashEngine, Hmac, HmacEngine};
26use secp256k1::{self, Secp256k1};
27
28use network::constants::Network;
29use util::{base58, endian};
30use util::key::{self, PublicKey, PrivateKey};
31
32/// A chain code
33#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
34pub struct ChainCode([u8; 32]);
35impl_array_newtype!(ChainCode, u8, 32);
36impl_bytes_newtype!(ChainCode, 32);
37
38/// A fingerprint
39#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
40pub struct Fingerprint([u8; 4]);
41impl_array_newtype!(Fingerprint, u8, 4);
42impl_bytes_newtype!(Fingerprint, 4);
43
44impl Default for Fingerprint {
45    fn default() -> Fingerprint { Fingerprint([0; 4]) }
46}
47
48/// Extended private key
49#[derive(Copy, Clone, PartialEq, Eq, Debug)]
50pub struct ExtendedPrivKey {
51    /// The network this key is to be used on
52    pub network: Network,
53    /// How many derivations this key is from the master (which is 0)
54    pub depth: u8,
55    /// Fingerprint of the parent key (0 for master)
56    pub parent_fingerprint: Fingerprint,
57    /// Child number of the key used to derive from parent (0 for master)
58    pub child_number: ChildNumber,
59    /// Private key
60    pub private_key: PrivateKey,
61    /// Chain code
62    pub chain_code: ChainCode
63}
64serde_string_impl!(ExtendedPrivKey, "a BIP-32 extended private key");
65
66/// Extended public key
67#[derive(Copy, Clone, PartialEq, Eq, Debug, PartialOrd, Ord, Hash)]
68pub struct ExtendedPubKey {
69    /// The network this key is to be used on
70    pub network: Network,
71    /// How many derivations this key is from the master (which is 0)
72    pub depth: u8,
73    /// Fingerprint of the parent key
74    pub parent_fingerprint: Fingerprint,
75    /// Child number of the key used to derive from parent (0 for master)
76    pub child_number: ChildNumber,
77    /// Public key
78    pub public_key: PublicKey,
79    /// Chain code
80    pub chain_code: ChainCode
81}
82serde_string_impl!(ExtendedPubKey, "a BIP-32 extended public key");
83
84/// A child number for a derived key
85#[derive(Copy, Clone, PartialEq, Eq, Debug, PartialOrd, Ord, Hash)]
86pub enum ChildNumber {
87    /// Non-hardened key
88    Normal {
89        /// Key index, within [0, 2^31 - 1]
90        index: u32
91    },
92    /// Hardened key
93    Hardened {
94        /// Key index, within [0, 2^31 - 1]
95        index: u32
96    },
97}
98
99impl ChildNumber {
100    /// Create a [`Normal`] from an index, returns an error if the index is not within
101    /// [0, 2^31 - 1].
102    ///
103    /// [`Normal`]: #variant.Normal
104    pub fn from_normal_idx(index: u32) -> Result<Self, Error> {
105        if index & (1 << 31) == 0 {
106            Ok(ChildNumber::Normal { index: index })
107        } else {
108            Err(Error::InvalidChildNumber(index))
109        }
110    }
111
112    /// Create a [`Hardened`] from an index, returns an error if the index is not within
113    /// [0, 2^31 - 1].
114    ///
115    /// [`Hardened`]: #variant.Hardened
116    pub fn from_hardened_idx(index: u32) -> Result<Self, Error> {
117        if index & (1 << 31) == 0 {
118            Ok(ChildNumber::Hardened { index: index })
119        } else {
120            Err(Error::InvalidChildNumber(index))
121        }
122    }
123
124    /// Returns `true` if the child number is a [`Normal`] value.
125    ///
126    /// [`Normal`]: #variant.Normal
127    pub fn is_normal(&self) -> bool {
128        !self.is_hardened()
129    }
130
131    /// Returns `true` if the child number is a [`Hardened`] value.
132    ///
133    /// [`Hardened`]: #variant.Hardened
134    pub fn is_hardened(&self) -> bool {
135        match self {
136            ChildNumber::Hardened {..} => true,
137            ChildNumber::Normal {..} => false,
138        }
139    }
140
141    /// Returns the child number that is a single increment from this one.
142    pub fn increment(self) -> Result<ChildNumber, Error> {
143        match self {
144            ChildNumber::Normal{ index: idx } => ChildNumber::from_normal_idx(idx+1),
145            ChildNumber::Hardened{ index: idx } => ChildNumber::from_hardened_idx(idx+1),
146        }
147    }
148}
149
150impl From<u32> for ChildNumber {
151    fn from(number: u32) -> Self {
152        if number & (1 << 31) != 0 {
153            ChildNumber::Hardened { index: number ^ (1 << 31) }
154        } else {
155            ChildNumber::Normal { index: number }
156        }
157    }
158}
159
160impl From<ChildNumber> for u32 {
161    fn from(cnum: ChildNumber) -> Self {
162        match cnum {
163            ChildNumber::Normal { index } => index,
164            ChildNumber::Hardened { index } => index | (1 << 31),
165        }
166    }
167}
168
169impl fmt::Display for ChildNumber {
170    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
171        match *self {
172            ChildNumber::Hardened { index } => {
173                fmt::Display::fmt(&index, f)?;
174                let alt = f.alternate();
175                f.write_str(if alt { "'" } else { "h" })
176            },
177            ChildNumber::Normal { index } => fmt::Display::fmt(&index, f),
178        }
179    }
180}
181
182impl FromStr for ChildNumber {
183    type Err = Error;
184
185    fn from_str(inp: &str) -> Result<ChildNumber, Error> {
186        let is_hardened = inp.chars().last().map_or(false, |l| l == '\'' || l == 'h');
187        Ok(if is_hardened {
188            ChildNumber::from_hardened_idx(inp[0..inp.len() - 1].parse().map_err(|_| Error::InvalidChildNumberFormat)?)?
189        } else {
190            ChildNumber::from_normal_idx(inp.parse().map_err(|_| Error::InvalidChildNumberFormat)?)?
191        })
192    }
193}
194
195#[cfg(feature = "serde")]
196impl<'de> serde::Deserialize<'de> for ChildNumber {
197    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
198    where
199        D: serde::Deserializer<'de>,
200    {
201        u32::deserialize(deserializer).map(ChildNumber::from)
202    }
203}
204
205#[cfg(feature = "serde")]
206impl serde::Serialize for ChildNumber {
207    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
208    where
209        S: serde::Serializer,
210    {
211        u32::from(*self).serialize(serializer)
212    }
213}
214
215/// Trait that allows possibly failable conversion from a type into a
216/// derivation path
217pub trait IntoDerivationPath {
218    /// Convers a given type into a [`DerivationPath`] with possible error
219    fn into_derivation_path(self) -> Result<DerivationPath, Error>;
220}
221
222/// A BIP-32 derivation path.
223#[derive(Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
224pub struct DerivationPath(Vec<ChildNumber>);
225impl_index_newtype!(DerivationPath, ChildNumber);
226serde_string_impl!(DerivationPath, "a BIP-32 derivation path");
227
228impl Default for DerivationPath {
229    fn default() -> DerivationPath {
230        DerivationPath::master()
231    }
232}
233
234impl<T> IntoDerivationPath for T where T: Into<DerivationPath> {
235    fn into_derivation_path(self) -> Result<DerivationPath, Error> {
236        Ok(self.into())
237    }
238}
239
240impl IntoDerivationPath for String {
241    fn into_derivation_path(self) -> Result<DerivationPath, Error> {
242        self.parse()
243    }
244}
245
246impl<'a> IntoDerivationPath for &'a str {
247    fn into_derivation_path(self) -> Result<DerivationPath, Error> {
248        self.parse()
249    }
250}
251
252impl From<Vec<ChildNumber>> for DerivationPath {
253    fn from(numbers: Vec<ChildNumber>) -> Self {
254        DerivationPath(numbers)
255    }
256}
257
258impl Into<Vec<ChildNumber>> for DerivationPath {
259    fn into(self) -> Vec<ChildNumber> {
260        self.0
261    }
262}
263
264impl<'a> From<&'a [ChildNumber]> for DerivationPath {
265    fn from(numbers: &'a [ChildNumber]) -> Self {
266        DerivationPath(numbers.to_vec())
267    }
268}
269
270impl ::std::iter::FromIterator<ChildNumber> for DerivationPath {
271    fn from_iter<T>(iter: T) -> Self where T: IntoIterator<Item = ChildNumber> {
272        DerivationPath(Vec::from_iter(iter))
273    }
274}
275
276impl<'a> ::std::iter::IntoIterator for &'a DerivationPath {
277    type Item = &'a ChildNumber;
278    type IntoIter = ::std::slice::Iter<'a, ChildNumber>;
279    fn into_iter(self) -> Self::IntoIter {
280        self.0.iter()
281    }
282}
283
284impl AsRef<[ChildNumber]> for DerivationPath {
285    fn as_ref(&self) -> &[ChildNumber] {
286        &self.0
287    }
288}
289
290impl FromStr for DerivationPath {
291    type Err = Error;
292
293    fn from_str(path: &str) -> Result<DerivationPath, Error> {
294        let mut parts = path.split('/');
295        // First parts must be `m`.
296        if parts.next().unwrap() != "m" {
297            return Err(Error::InvalidDerivationPathFormat);
298        }
299
300        let ret: Result<Vec<ChildNumber>, Error> = parts.map(str::parse).collect();
301        Ok(DerivationPath(ret?))
302    }
303}
304
305/// An iterator over children of a [DerivationPath].
306///
307/// It is returned by the methods [DerivationPath::children_since],
308/// [DerivationPath::normal_children] and [DerivationPath::hardened_children].
309pub struct DerivationPathIterator<'a> {
310    base: &'a DerivationPath,
311    next_child: Option<ChildNumber>,
312}
313
314impl<'a> DerivationPathIterator<'a> {
315    /// Start a new [DerivationPathIterator] at the given child.
316    pub fn start_from(path: &'a DerivationPath, start: ChildNumber) -> DerivationPathIterator<'a> {
317        DerivationPathIterator {
318            base: path,
319            next_child: Some(start),
320        }
321    }
322}
323
324impl<'a> Iterator for DerivationPathIterator<'a> {
325    type Item = DerivationPath;
326
327    fn next(&mut self) -> Option<Self::Item> {
328        let ret = self.next_child?;
329        self.next_child = ret.increment().ok();
330        Some(self.base.child(ret))
331    }
332}
333
334impl DerivationPath {
335    /// Returns length of the derivation path
336    pub fn len(&self) -> usize {
337        self.0.len()
338    }
339
340    /// Returns derivation path for a master key (i.e. empty derivation path)
341    pub fn master() -> DerivationPath {
342        DerivationPath(vec![])
343    }
344
345    /// Returns whether derivation path represents master key (i.e. it's length
346    /// is empty). True for `m` path.
347    pub fn is_master(&self) -> bool {
348        self.0.is_empty()
349    }
350
351    /// Create a new [DerivationPath] that is a child of this one.
352    pub fn child(&self, cn: ChildNumber) -> DerivationPath {
353        let mut path = self.0.clone();
354        path.push(cn);
355        DerivationPath(path)
356    }
357
358    /// Convert into a [DerivationPath] that is a child of this one.
359    pub fn into_child(self, cn: ChildNumber) -> DerivationPath {
360        let mut path = self.0;
361        path.push(cn);
362        DerivationPath(path)
363    }
364
365    /// Get an [Iterator] over the children of this [DerivationPath]
366    /// starting with the given [ChildNumber].
367    pub fn children_from(&self, cn: ChildNumber) -> DerivationPathIterator {
368        DerivationPathIterator::start_from(&self, cn)
369    }
370
371    /// Get an [Iterator] over the unhardened children of this [DerivationPath].
372    pub fn normal_children(&self) -> DerivationPathIterator {
373        DerivationPathIterator::start_from(&self, ChildNumber::Normal{ index: 0 })
374    }
375
376    /// Get an [Iterator] over the hardened children of this [DerivationPath].
377    pub fn hardened_children(&self) -> DerivationPathIterator {
378        DerivationPathIterator::start_from(&self, ChildNumber::Hardened{ index: 0 })
379    }
380
381    /// Concatenate `self` with `path` and return the resulting new path.
382    ///
383    /// ```
384    /// use bitcoin::util::bip32::{DerivationPath, ChildNumber};
385    /// use std::str::FromStr;
386    ///
387    /// let base = DerivationPath::from_str("m/42").unwrap();
388    ///
389    /// let deriv_1 = base.extend(DerivationPath::from_str("m/0/1").unwrap());
390    /// let deriv_2 = base.extend(&[
391    ///     ChildNumber::from_normal_idx(0).unwrap(),
392    ///     ChildNumber::from_normal_idx(1).unwrap()
393    /// ]);
394    ///
395    /// assert_eq!(deriv_1, deriv_2);
396    /// ```
397    pub fn extend<T: AsRef<[ChildNumber]>>(&self, path: T) -> DerivationPath {
398        let mut new_path = self.clone();
399        new_path.0.extend_from_slice(path.as_ref());
400        new_path
401    }
402}
403
404impl fmt::Display for DerivationPath {
405    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
406        f.write_str("m")?;
407        for cn in self.0.iter() {
408            f.write_str("/")?;
409            fmt::Display::fmt(cn, f)?;
410        }
411        Ok(())
412    }
413}
414
415impl fmt::Debug for DerivationPath {
416    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
417        fmt::Display::fmt(&self, f)
418    }
419}
420
421/// Full information on the used extended public key: fingerprint of the
422/// master extended public key and a derivation path from it.
423pub type KeySource = (Fingerprint, DerivationPath);
424
425/// A BIP32 error
426#[derive(Clone, PartialEq, Eq, Debug)]
427pub enum Error {
428    /// A pk->pk derivation was attempted on a hardened key
429    CannotDeriveFromHardenedKey,
430    /// A secp256k1 error occurred
431    Ecdsa(secp256k1::Error),
432    /// A child number was provided that was out of range
433    InvalidChildNumber(u32),
434    /// Error creating a master seed --- for application use
435    RngError(String),
436    /// Invalid childnumber format.
437    InvalidChildNumberFormat,
438    /// Invalid derivation path format.
439    InvalidDerivationPathFormat,
440    /// Unknown version magic bytes
441    UnknownVersion([u8; 4]),
442    /// Encoded extended key data has wrong length
443    WrongExtendedKeyLength(usize),
444    /// Base58 encoding error
445    Base58(base58::Error)
446}
447
448impl fmt::Display for Error {
449    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
450        match *self {
451            Error::CannotDeriveFromHardenedKey => f.write_str("cannot derive hardened key from public key"),
452            Error::Ecdsa(ref e) => fmt::Display::fmt(e, f),
453            Error::InvalidChildNumber(ref n) => write!(f, "child number {} is invalid (not within [0, 2^31 - 1])", n),
454            Error::RngError(ref s) => write!(f, "rng error {}", s),
455            Error::InvalidChildNumberFormat => f.write_str("invalid child number format"),
456            Error::InvalidDerivationPathFormat => f.write_str("invalid derivation path format"),
457            Error::UnknownVersion(ref bytes) => write!(f, "unknown version magic bytes: {:?}", bytes),
458            Error::WrongExtendedKeyLength(ref len) => write!(f, "encoded extended key data has wrong length {}", len),
459            Error::Base58(ref err) => write!(f, "base58 encoding error: {}", err),
460        }
461    }
462}
463
464impl error::Error for Error {
465    fn cause(&self) -> Option<&dyn error::Error> {
466       if let Error::Ecdsa(ref e) = *self {
467           Some(e)
468       } else {
469           None
470       }
471    }
472}
473
474impl From<key::Error> for Error {
475    fn from(err: key::Error) -> Self {
476        match err {
477            key::Error::Base58(e) => Error::Base58(e),
478            key::Error::Secp256k1(e) => Error::Ecdsa(e),
479        }
480    }
481}
482
483impl From<secp256k1::Error> for Error {
484    fn from(e: secp256k1::Error) -> Error { Error::Ecdsa(e) }
485}
486
487impl From<base58::Error> for Error {
488    fn from(err: base58::Error) -> Self {
489        Error::Base58(err)
490    }
491}
492
493impl ExtendedPrivKey {
494    /// Construct a new master key from a seed value
495    pub fn new_master(network: Network, seed: &[u8]) -> Result<ExtendedPrivKey, Error> {
496        let mut hmac_engine: HmacEngine<sha512::Hash> = HmacEngine::new(b"Digibyte seed");
497        hmac_engine.input(seed);
498        let hmac_result: Hmac<sha512::Hash> = Hmac::from_engine(hmac_engine);
499
500        Ok(ExtendedPrivKey {
501            network: network,
502            depth: 0,
503            parent_fingerprint: Default::default(),
504            child_number: ChildNumber::from_normal_idx(0)?,
505            private_key: PrivateKey {
506                compressed: true,
507                network: network,
508                key: secp256k1::SecretKey::from_slice(
509                    &hmac_result[..32]
510                ).map_err(Error::Ecdsa)?,
511            },
512            chain_code: ChainCode::from(&hmac_result[32..]),
513        })
514    }
515
516    /// Attempts to derive an extended private key from a path.
517    ///
518    /// The `path` argument can be both of type `DerivationPath` or `Vec<ChildNumber>`.
519    pub fn derive_priv<C: secp256k1::Signing, P: AsRef<[ChildNumber]>>(
520        &self,
521        secp: &Secp256k1<C>,
522        path: &P,
523    ) -> Result<ExtendedPrivKey, Error> {
524        let mut sk: ExtendedPrivKey = *self;
525        for cnum in path.as_ref() {
526            sk = sk.ckd_priv(secp, *cnum)?;
527        }
528        Ok(sk)
529    }
530
531    /// Private->Private child key derivation
532    pub fn ckd_priv<C: secp256k1::Signing>(&self, secp: &Secp256k1<C>, i: ChildNumber) -> Result<ExtendedPrivKey, Error> {
533        let mut hmac_engine: HmacEngine<sha512::Hash> = HmacEngine::new(&self.chain_code[..]);
534        match i {
535            ChildNumber::Normal { .. } => {
536                // Non-hardened key: compute public data and use that
537                hmac_engine.input(&PublicKey::from_private_key(secp, &self.private_key).key.serialize()[..]);
538            }
539            ChildNumber::Hardened { .. } => {
540                // Hardened key: use only secret data to prevent public derivation
541                hmac_engine.input(&[0u8]);
542                hmac_engine.input(&self.private_key[..]);
543            }
544        }
545
546        hmac_engine.input(&endian::u32_to_array_be(u32::from(i)));
547        let hmac_result: Hmac<sha512::Hash> = Hmac::from_engine(hmac_engine);
548        let mut sk = PrivateKey {
549            compressed: true,
550            network: self.network,
551            key: secp256k1::SecretKey::from_slice(&hmac_result[..32]).map_err(Error::Ecdsa)?,
552        };
553        sk.key.add_assign(&self.private_key[..]).map_err(Error::Ecdsa)?;
554
555        Ok(ExtendedPrivKey {
556            network: self.network,
557            depth: self.depth + 1,
558            parent_fingerprint: self.fingerprint(secp),
559            child_number: i,
560            private_key: sk,
561            chain_code: ChainCode::from(&hmac_result[32..])
562        })
563    }
564
565    /// Decoding extended private key from binary data according to BIP 32
566    pub fn decode(data: &[u8]) -> Result<ExtendedPrivKey, Error> {
567        if data.len() != 78 {
568            return Err(Error::WrongExtendedKeyLength(data.len()))
569        }
570
571        let network = if data[0..4] == [0x04u8, 0x88, 0xAD, 0xE4] {
572            Network::Digibyte
573        } else if data[0..4] == [0x04u8, 0x35, 0x83, 0x94] {
574            Network::Testnet
575        } else {
576            let mut ver = [0u8; 4];
577            ver.copy_from_slice(&data[0..4]);
578            return Err(Error::UnknownVersion(ver));
579        };
580
581        Ok(ExtendedPrivKey {
582            network: network,
583            depth: data[4],
584            parent_fingerprint: Fingerprint::from(&data[5..9]),
585            child_number: endian::slice_to_u32_be(&data[9..13]).into(),
586            chain_code: ChainCode::from(&data[13..45]),
587            private_key: PrivateKey {
588                compressed: true,
589                network: network,
590                key: secp256k1::SecretKey::from_slice(
591                    &data[46..78]
592                ).map_err(Error::Ecdsa)?,
593            },
594        })
595    }
596
597    /// Extended private key binary encoding according to BIP 32
598    pub fn encode(&self) -> [u8; 78] {
599        let mut ret = [0; 78];
600        ret[0..4].copy_from_slice(&match self.network {
601            Network::Digibyte => [0x04, 0x88, 0xAD, 0xE4],
602            Network::Testnet | Network::Signet | Network::Regtest => [0x04, 0x35, 0x83, 0x94],
603        }[..]);
604        ret[4] = self.depth as u8;
605        ret[5..9].copy_from_slice(&self.parent_fingerprint[..]);
606        ret[9..13].copy_from_slice(&endian::u32_to_array_be(u32::from(self.child_number)));
607        ret[13..45].copy_from_slice(&self.chain_code[..]);
608        ret[45] = 0;
609        ret[46..78].copy_from_slice(&self.private_key[..]);
610        ret
611    }
612
613    /// Returns the HASH160 of the public key belonging to the xpriv
614    pub fn identifier<C: secp256k1::Signing>(&self, secp: &Secp256k1<C>) -> XpubIdentifier {
615        ExtendedPubKey::from_private(secp, self).identifier()
616    }
617
618    /// Returns the first four bytes of the identifier
619    pub fn fingerprint<C: secp256k1::Signing>(&self, secp: &Secp256k1<C>) -> Fingerprint {
620        Fingerprint::from(&self.identifier(secp)[0..4])
621    }
622}
623
624impl ExtendedPubKey {
625    /// Derives a public key from a private key
626    pub fn from_private<C: secp256k1::Signing>(secp: &Secp256k1<C>, sk: &ExtendedPrivKey) -> ExtendedPubKey {
627        ExtendedPubKey {
628            network: sk.network,
629            depth: sk.depth,
630            parent_fingerprint: sk.parent_fingerprint,
631            child_number: sk.child_number,
632            public_key: PublicKey::from_private_key(secp, &sk.private_key),
633            chain_code: sk.chain_code
634        }
635    }
636
637    /// Attempts to derive an extended public key from a path.
638    ///
639    /// The `path` argument can be both of type `DerivationPath` or `Vec<ChildNumber>`.
640    pub fn derive_pub<C: secp256k1::Verification, P: AsRef<[ChildNumber]>>(
641        &self,
642        secp: &Secp256k1<C>,
643        path: &P,
644    ) -> Result<ExtendedPubKey, Error> {
645        let mut pk: ExtendedPubKey = *self;
646        for cnum in path.as_ref() {
647            pk = pk.ckd_pub(secp, *cnum)?
648        }
649        Ok(pk)
650    }
651
652    /// Compute the scalar tweak added to this key to get a child key
653    pub fn ckd_pub_tweak(&self, i: ChildNumber) -> Result<(PrivateKey, ChainCode), Error> {
654        match i {
655            ChildNumber::Hardened { .. } => {
656                Err(Error::CannotDeriveFromHardenedKey)
657            }
658            ChildNumber::Normal { index: n } => {
659                let mut hmac_engine: HmacEngine<sha512::Hash> = HmacEngine::new(&self.chain_code[..]);
660                hmac_engine.input(&self.public_key.key.serialize()[..]);
661                hmac_engine.input(&endian::u32_to_array_be(n));
662
663                let hmac_result: Hmac<sha512::Hash> = Hmac::from_engine(hmac_engine);
664
665                let private_key = PrivateKey {
666                    compressed: true,
667                    network: self.network,
668                    key: secp256k1::SecretKey::from_slice(&hmac_result[..32])?,
669                };
670                let chain_code = ChainCode::from(&hmac_result[32..]);
671                Ok((private_key, chain_code))
672            }
673        }
674    }
675
676    /// Public->Public child key derivation
677    pub fn ckd_pub<C: secp256k1::Verification>(
678        &self,
679        secp: &Secp256k1<C>,
680        i: ChildNumber,
681    ) -> Result<ExtendedPubKey, Error> {
682        let (sk, chain_code) = self.ckd_pub_tweak(i)?;
683        let mut pk = self.public_key;
684        pk.key.add_exp_assign(secp, &sk[..]).map_err(Error::Ecdsa)?;
685
686        Ok(ExtendedPubKey {
687            network: self.network,
688            depth: self.depth + 1,
689            parent_fingerprint: self.fingerprint(),
690            child_number: i,
691            public_key: pk,
692            chain_code: chain_code
693        })
694    }
695
696    /// Decoding extended public key from binary data according to BIP 32
697    pub fn decode(data: &[u8]) -> Result<ExtendedPubKey, Error> {
698        if data.len() != 78 {
699            return Err(Error::WrongExtendedKeyLength(data.len()))
700        }
701
702        Ok(ExtendedPubKey {
703            network: if data[0..4] == [0x04u8, 0x88, 0xB2, 0x1E] {
704                Network::Digibyte
705            } else if data[0..4] == [0x04u8, 0x35, 0x87, 0xCF] {
706                Network::Testnet
707            } else {
708                let mut ver = [0u8; 4];
709                ver.copy_from_slice(&data[0..4]);
710                return Err(Error::UnknownVersion(ver));
711            },
712            depth: data[4],
713            parent_fingerprint: Fingerprint::from(&data[5..9]),
714            child_number: endian::slice_to_u32_be(&data[9..13]).into(),
715            chain_code: ChainCode::from(&data[13..45]),
716            public_key: PublicKey::from_slice(&data[45..78])?,
717        })
718    }
719
720    /// Extended public key binary encoding according to BIP 32
721    pub fn encode(&self) -> [u8; 78] {
722        let mut ret = [0; 78];
723        ret[0..4].copy_from_slice(&match self.network {
724            Network::Digibyte => [0x04u8, 0x88, 0xB2, 0x1E],
725            Network::Testnet | Network::Signet | Network::Regtest => [0x04u8, 0x35, 0x87, 0xCF],
726        }[..]);
727        ret[4] = self.depth as u8;
728        ret[5..9].copy_from_slice(&self.parent_fingerprint[..]);
729        ret[9..13].copy_from_slice(&endian::u32_to_array_be(u32::from(self.child_number)));
730        ret[13..45].copy_from_slice(&self.chain_code[..]);
731        ret[45..78].copy_from_slice(&self.public_key.key.serialize()[..]);
732        ret
733    }
734
735    /// Returns the HASH160 of the chaincode
736    pub fn identifier(&self) -> XpubIdentifier {
737        let mut engine = XpubIdentifier::engine();
738        self.public_key.write_into(&mut engine).expect("engines don't error");
739        XpubIdentifier::from_engine(engine)
740    }
741
742    /// Returns the first four bytes of the identifier
743    pub fn fingerprint(&self) -> Fingerprint {
744        Fingerprint::from(&self.identifier()[0..4])
745    }
746}
747
748impl fmt::Display for ExtendedPrivKey {
749    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
750        base58::check_encode_slice_to_fmt(fmt, &self.encode()[..])
751    }
752}
753
754impl FromStr for ExtendedPrivKey {
755    type Err = Error;
756
757    fn from_str(inp: &str) -> Result<ExtendedPrivKey, Error> {
758        let data = base58::from_check(inp)?;
759
760        if data.len() != 78 {
761            return Err(base58::Error::InvalidLength(data.len()).into());
762        }
763
764        Ok(ExtendedPrivKey::decode(&data[..])?)
765    }
766}
767
768impl fmt::Display for ExtendedPubKey {
769    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
770        base58::check_encode_slice_to_fmt(fmt, &self.encode()[..])
771    }
772}
773
774impl FromStr for ExtendedPubKey {
775    type Err = Error;
776
777    fn from_str(inp: &str) -> Result<ExtendedPubKey, Error> {
778        let data = base58::from_check(inp)?;
779
780        if data.len() != 78 {
781            return Err(base58::Error::InvalidLength(data.len()).into());
782        }
783
784        Ok(ExtendedPubKey::decode(&data[..])?)
785    }
786}
787
788#[cfg(test)]
789mod tests {
790    use super::*;
791    use super::ChildNumber::{Hardened, Normal};
792
793    use std::str::FromStr;
794    use std::string::ToString;
795
796    use secp256k1::{self, Secp256k1};
797    use hashes::hex::FromHex;
798
799    use network::constants::Network::{self, Digibyte};
800
801    #[test]
802    fn test_parse_derivation_path() {
803        assert_eq!(DerivationPath::from_str("42"), Err(Error::InvalidDerivationPathFormat));
804        assert_eq!(DerivationPath::from_str("n/0'/0"), Err(Error::InvalidDerivationPathFormat));
805        assert_eq!(DerivationPath::from_str("4/m/5"), Err(Error::InvalidDerivationPathFormat));
806        assert_eq!(DerivationPath::from_str("m//3/0'"), Err(Error::InvalidChildNumberFormat));
807        assert_eq!(DerivationPath::from_str("m/0h/0x"), Err(Error::InvalidChildNumberFormat));
808        assert_eq!(DerivationPath::from_str("m/2147483648"), Err(Error::InvalidChildNumber(2147483648)));
809
810        assert_eq!(DerivationPath::master(), DerivationPath::from_str("m").unwrap());
811        assert_eq!(DerivationPath::master(), DerivationPath::default());
812        assert_eq!(DerivationPath::from_str("m"), Ok(vec![].into()));
813        assert_eq!(
814            DerivationPath::from_str("m/0'"),
815            Ok(vec![ChildNumber::from_hardened_idx(0).unwrap()].into())
816        );
817        assert_eq!(
818            DerivationPath::from_str("m/0'/1"),
819            Ok(vec![ChildNumber::from_hardened_idx(0).unwrap(), ChildNumber::from_normal_idx(1).unwrap()].into())
820        );
821        assert_eq!(
822            DerivationPath::from_str("m/0h/1/2'"),
823            Ok(vec![
824                ChildNumber::from_hardened_idx(0).unwrap(),
825                ChildNumber::from_normal_idx(1).unwrap(),
826                ChildNumber::from_hardened_idx(2).unwrap(),
827            ].into())
828        );
829        assert_eq!(
830            DerivationPath::from_str("m/0'/1/2h/2"),
831            Ok(vec![
832                ChildNumber::from_hardened_idx(0).unwrap(),
833                ChildNumber::from_normal_idx(1).unwrap(),
834                ChildNumber::from_hardened_idx(2).unwrap(),
835                ChildNumber::from_normal_idx(2).unwrap(),
836            ].into())
837        );
838        assert_eq!(
839            DerivationPath::from_str("m/0'/1/2'/2/1000000000"),
840            Ok(vec![
841                ChildNumber::from_hardened_idx(0).unwrap(),
842                ChildNumber::from_normal_idx(1).unwrap(),
843                ChildNumber::from_hardened_idx(2).unwrap(),
844                ChildNumber::from_normal_idx(2).unwrap(),
845                ChildNumber::from_normal_idx(1000000000).unwrap(),
846            ].into())
847        );
848        let s = "m/0'/50/3'/5/545456";
849        assert_eq!(DerivationPath::from_str(s), s.into_derivation_path());
850        assert_eq!(DerivationPath::from_str(s), s.to_string().into_derivation_path());
851    }
852
853    #[test]
854    fn test_derivation_path_conversion_index() {
855        let path = DerivationPath::from_str("m/0h/1/2'").unwrap();
856        let numbers: Vec<ChildNumber> = path.clone().into();
857        let path2: DerivationPath = numbers.into();
858        assert_eq!(path, path2);
859        assert_eq!(&path[..2], &[ChildNumber::from_hardened_idx(0).unwrap(), ChildNumber::from_normal_idx(1).unwrap()]);
860        let indexed: DerivationPath = path[..2].into();
861        assert_eq!(indexed, DerivationPath::from_str("m/0h/1").unwrap());
862        assert_eq!(indexed.child(ChildNumber::from_hardened_idx(2).unwrap()), path);
863    }
864
865    fn test_path<C: secp256k1::Signing + secp256k1::Verification>(secp: &Secp256k1<C>,
866                 network: Network,
867                 seed: &[u8],
868                 path: DerivationPath,
869                 expected_sk: &str,
870                 expected_pk: &str) {
871
872        let mut sk = ExtendedPrivKey::new_master(network, seed).unwrap();
873        let mut pk = ExtendedPubKey::from_private(secp, &sk);
874
875        // Check derivation convenience method for ExtendedPrivKey
876        assert_eq!(
877            &sk.derive_priv(secp, &path).unwrap().to_string()[..],
878            expected_sk
879        );
880
881        // Check derivation convenience method for ExtendedPubKey, should error
882        // appropriately if any ChildNumber is hardened
883        if path.0.iter().any(|cnum| cnum.is_hardened()) {
884            assert_eq!(
885                pk.derive_pub(secp, &path),
886                Err(Error::CannotDeriveFromHardenedKey)
887            );
888        } else {
889            assert_eq!(
890                &pk.derive_pub(secp, &path).unwrap().to_string()[..],
891                expected_pk
892            );
893        }
894
895        // Derive keys, checking hardened and non-hardened derivation one-by-one
896        for &num in path.0.iter() {
897            sk = sk.ckd_priv(secp, num).unwrap();
898            match num {
899                Normal {..} => {
900                    let pk2 = pk.ckd_pub(secp, num).unwrap();
901                    pk = ExtendedPubKey::from_private(secp, &sk);
902                    assert_eq!(pk, pk2);
903                }
904                Hardened {..} => {
905                    assert_eq!(
906                        pk.ckd_pub(secp, num),
907                        Err(Error::CannotDeriveFromHardenedKey)
908                    );
909                    pk = ExtendedPubKey::from_private(secp, &sk);
910                }
911            }
912        }
913
914        // Check result against expected base58
915        assert_eq!(&sk.to_string()[..], expected_sk);
916        assert_eq!(&pk.to_string()[..], expected_pk);
917        // Check decoded base58 against result
918        let decoded_sk = ExtendedPrivKey::from_str(expected_sk);
919        let decoded_pk = ExtendedPubKey::from_str(expected_pk);
920        assert_eq!(Ok(sk), decoded_sk);
921        assert_eq!(Ok(pk), decoded_pk);
922    }
923
924    #[test]
925    fn test_increment() {
926        let idx = 9345497; // randomly generated, I promise
927        let cn = ChildNumber::from_normal_idx(idx).unwrap();
928        assert_eq!(cn.increment().ok(), Some(ChildNumber::from_normal_idx(idx+1).unwrap()));
929        let cn = ChildNumber::from_hardened_idx(idx).unwrap();
930        assert_eq!(cn.increment().ok(), Some(ChildNumber::from_hardened_idx(idx+1).unwrap()));
931
932        let max = (1<<31)-1;
933        let cn = ChildNumber::from_normal_idx(max).unwrap();
934        assert_eq!(cn.increment().err(), Some(Error::InvalidChildNumber(1<<31)));
935        let cn = ChildNumber::from_hardened_idx(max).unwrap();
936        assert_eq!(cn.increment().err(), Some(Error::InvalidChildNumber(1<<31)));
937
938        let cn = ChildNumber::from_normal_idx(350).unwrap();
939        let path = DerivationPath::from_str("m/42'").unwrap();
940        let mut iter = path.children_from(cn);
941        assert_eq!(iter.next(), Some("m/42'/350".parse().unwrap()));
942        assert_eq!(iter.next(), Some("m/42'/351".parse().unwrap()));
943
944        let path = DerivationPath::from_str("m/42'/350'").unwrap();
945        let mut iter = path.normal_children();
946        assert_eq!(iter.next(), Some("m/42'/350'/0".parse().unwrap()));
947        assert_eq!(iter.next(), Some("m/42'/350'/1".parse().unwrap()));
948
949        let path = DerivationPath::from_str("m/42'/350'").unwrap();
950        let mut iter = path.hardened_children();
951        assert_eq!(iter.next(), Some("m/42'/350'/0'".parse().unwrap()));
952        assert_eq!(iter.next(), Some("m/42'/350'/1'".parse().unwrap()));
953
954        let cn = ChildNumber::from_hardened_idx(42350).unwrap();
955        let path = DerivationPath::from_str("m/42'").unwrap();
956        let mut iter = path.children_from(cn);
957        assert_eq!(iter.next(), Some("m/42'/42350'".parse().unwrap()));
958        assert_eq!(iter.next(), Some("m/42'/42351'".parse().unwrap()));
959
960        let cn = ChildNumber::from_hardened_idx(max).unwrap();
961        let path = DerivationPath::from_str("m/42'").unwrap();
962        let mut iter = path.children_from(cn);
963        assert!(iter.next().is_some());
964        assert!(iter.next().is_none());
965    }
966
967    #[test]
968    fn test_vector_1() {
969        let secp = Secp256k1::new();
970        let seed = Vec::from_hex("000102030405060708090a0b0c0d0e0f").unwrap();
971
972        // m
973        test_path(&secp, Digibyte, &seed, "m".parse().unwrap(),
974                  "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi",
975                  "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8");
976
977        // m/0h
978        test_path(&secp, Digibyte, &seed, "m/0h".parse().unwrap(),
979                  "xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7",
980                  "xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw");
981
982        // m/0h/1
983        test_path(&secp, Digibyte, &seed, "m/0h/1".parse().unwrap(),
984                   "xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs",
985                   "xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ");
986
987        // m/0h/1/2h
988        test_path(&secp, Digibyte, &seed, "m/0h/1/2h".parse().unwrap(),
989                  "xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM",
990                  "xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5");
991
992        // m/0h/1/2h/2
993        test_path(&secp, Digibyte, &seed, "m/0h/1/2h/2".parse().unwrap(),
994                  "xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334",
995                  "xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV");
996
997        // m/0h/1/2h/2/1000000000
998        test_path(&secp, Digibyte, &seed, "m/0h/1/2h/2/1000000000".parse().unwrap(),
999                  "xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76",
1000                  "xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy");
1001    }
1002
1003    #[test]
1004    fn test_vector_2() {
1005        let secp = Secp256k1::new();
1006        let seed = Vec::from_hex("fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542").unwrap();
1007
1008        // m
1009        test_path(&secp, Digibyte, &seed, "m".parse().unwrap(),
1010                  "xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U",
1011                  "xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB");
1012
1013        // m/0
1014        test_path(&secp, Digibyte, &seed, "m/0".parse().unwrap(),
1015                  "xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt",
1016                  "xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH");
1017
1018        // m/0/2147483647h
1019        test_path(&secp, Digibyte, &seed, "m/0/2147483647h".parse().unwrap(),
1020                  "xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9",
1021                  "xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ85ySDhKiLDBrQSARLq1uNRts8RuJiHjaDMBU4Zn9h8LZNnBC5y4a");
1022
1023        // m/0/2147483647h/1
1024        test_path(&secp, Digibyte, &seed, "m/0/2147483647h/1".parse().unwrap(),
1025                  "xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef",
1026                  "xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon");
1027
1028        // m/0/2147483647h/1/2147483646h
1029        test_path(&secp, Digibyte, &seed, "m/0/2147483647h/1/2147483646h".parse().unwrap(),
1030                  "xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc",
1031                  "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL");
1032
1033        // m/0/2147483647h/1/2147483646h/2
1034        test_path(&secp, Digibyte, &seed, "m/0/2147483647h/1/2147483646h/2".parse().unwrap(),
1035                  "xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j",
1036                  "xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt");
1037    }
1038
1039    #[test]
1040    fn test_vector_3() {
1041        let secp = Secp256k1::new();
1042        let seed = Vec::from_hex("4b381541583be4423346c643850da4b320e46a87ae3d2a4e6da11eba819cd4acba45d239319ac14f863b8d5ab5a0d0c64d2e8a1e7d1457df2e5a3c51c73235be").unwrap();
1043
1044        // m
1045        test_path(&secp, Digibyte, &seed, "m".parse().unwrap(),
1046                  "xprv9s21ZrQH143K25QhxbucbDDuQ4naNntJRi4KUfWT7xo4EKsHt2QJDu7KXp1A3u7Bi1j8ph3EGsZ9Xvz9dGuVrtHHs7pXeTzjuxBrCmmhgC6",
1047                  "xpub661MyMwAqRbcEZVB4dScxMAdx6d4nFc9nvyvH3v4gJL378CSRZiYmhRoP7mBy6gSPSCYk6SzXPTf3ND1cZAceL7SfJ1Z3GC8vBgp2epUt13");
1048
1049        // m/0h
1050        test_path(&secp, Digibyte, &seed, "m/0h".parse().unwrap(),
1051                  "xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L",
1052                  "xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y");
1053
1054    }
1055
1056    #[test]
1057    #[cfg(feature = "serde")]
1058    pub fn encode_decode_childnumber() {
1059        serde_round_trip!(ChildNumber::from_normal_idx(0).unwrap());
1060        serde_round_trip!(ChildNumber::from_normal_idx(1).unwrap());
1061        serde_round_trip!(ChildNumber::from_normal_idx((1 << 31) - 1).unwrap());
1062        serde_round_trip!(ChildNumber::from_hardened_idx(0).unwrap());
1063        serde_round_trip!(ChildNumber::from_hardened_idx(1).unwrap());
1064        serde_round_trip!(ChildNumber::from_hardened_idx((1 << 31) - 1).unwrap());
1065    }
1066
1067    #[test]
1068    #[cfg(feature = "serde")]
1069    pub fn encode_fingerprint_chaincode() {
1070        use serde_json;
1071        let fp = Fingerprint::from(&[1u8,2,3,42][..]);
1072        let cc = ChainCode::from(
1073            &[1u8,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2][..]
1074        );
1075
1076        serde_round_trip!(fp);
1077        serde_round_trip!(cc);
1078
1079        assert_eq!("\"0102032a\"", serde_json::to_string(&fp).unwrap());
1080        assert_eq!(
1081            "\"0102030405060708090001020304050607080900010203040506070809000102\"",
1082            serde_json::to_string(&cc).unwrap()
1083        );
1084        assert_eq!("0102032a", fp.to_string());
1085        assert_eq!(
1086            "0102030405060708090001020304050607080900010203040506070809000102",
1087            cc.to_string()
1088        );
1089    }
1090
1091    #[test]
1092    fn fmt_child_number() {
1093        assert_eq!("000005'", &format!("{:#06}", ChildNumber::from_hardened_idx(5).unwrap()));
1094        assert_eq!("5'", &format!("{:#}", ChildNumber::from_hardened_idx(5).unwrap()));
1095        assert_eq!("000005h", &format!("{:06}", ChildNumber::from_hardened_idx(5).unwrap()));
1096        assert_eq!("5h", &format!("{}", ChildNumber::from_hardened_idx(5).unwrap()));
1097        assert_eq!("42", &format!("{}", ChildNumber::from_normal_idx(42).unwrap()));
1098        assert_eq!("000042", &format!("{:06}", ChildNumber::from_normal_idx(42).unwrap()));
1099    }
1100}
1101