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