Skip to main content

bitcoin_key_expression/
bip32.rs

1// SPDX-License-Identifier: CC0-1.0
2
3//! BIP-0032 implementation.
4//!
5//! Implementation of BIP-0032 hierarchical deterministic wallets, as defined
6//! at <https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki>.
7
8use alloc::vec;
9use alloc::vec::Vec;
10use core::ops::Index;
11use core::str::FromStr;
12use core::{fmt, slice};
13
14#[cfg(feature = "arbitrary")]
15use arbitrary::{Arbitrary, Unstructured};
16use crypto::key::{FullPublicKey, Keypair, PrivateKey, XOnlyPublicKey};
17use hashes::{hash160, hash_newtype, sha256, sha512, Hash, HashEngine, Hmac, HmacEngine};
18use internals::array::ArrayExt;
19use network::NetworkKind;
20
21#[rustfmt::skip]                // Keep public re-exports separate.
22#[doc(no_inline)]
23pub use self::error::{
24    DerivationError, IndexOutOfRangeError, InvalidBase58PayloadLengthError,
25    ParseChildNumberError, ParseDerivationPathError, ParseError, InvalidSeedLengthError
26};
27
28/// Version bytes for extended public keys on the Bitcoin network.
29const VERSION_BYTES_MAINNET_PUBLIC: [u8; 4] = [0x04, 0x88, 0xB2, 0x1E];
30/// Version bytes for extended private keys on the Bitcoin network.
31const VERSION_BYTES_MAINNET_PRIVATE: [u8; 4] = [0x04, 0x88, 0xAD, 0xE4];
32/// Version bytes for extended public keys on any of the testnet networks.
33const VERSION_BYTES_TESTNETS_PUBLIC: [u8; 4] = [0x04, 0x35, 0x87, 0xCF];
34/// Version bytes for extended private keys on any of the testnet networks.
35const VERSION_BYTES_TESTNETS_PRIVATE: [u8; 4] = [0x04, 0x35, 0x83, 0x94];
36
37/// The old name for xpub, extended public key.
38#[deprecated(since = "0.31.0", note = "use `Xpub` instead")]
39pub type ExtendedPubKey = Xpub;
40
41/// The old name for xpriv, extended private key.
42#[deprecated(since = "0.31.0", note = "use `Xpriv` instead")]
43pub type ExtendedPrivKey = Xpriv;
44
45/// A chain code
46#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
47pub struct ChainCode([u8; 32]);
48internals::impl_array_newtype!(ChainCode, u8, 32);
49crate::impl_array_newtype_stringify!(ChainCode, 32);
50
51impl ChainCode {
52    fn from_hmac(hmac: Hmac<sha512::Hash>) -> Self {
53        Self(*hmac.as_byte_array().split_array::<32, 32>().1)
54    }
55
56    /// Copies the underlying bytes into a new `Vec`.
57    #[inline]
58    #[deprecated(since = "TBD", note = "use to_vec instead")]
59    pub fn to_bytes(self) -> alloc::vec::Vec<u8> { self.to_vec() }
60}
61
62/// A fingerprint
63#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
64pub struct Fingerprint([u8; 4]);
65internals::impl_array_newtype!(Fingerprint, u8, 4);
66crate::impl_array_newtype_stringify!(Fingerprint, 4);
67
68hash_newtype! {
69    /// Extended key identifier as defined in BIP-0032.
70    pub struct XKeyIdentifier(hash160::Hash);
71}
72
73hashes::impl_hex_for_newtype!(XKeyIdentifier);
74#[cfg(feature = "serde")]
75hashes::impl_serde_for_newtype!(XKeyIdentifier);
76
77crate::transparent_newtype! {
78    /// A master seed validated according to BIP-0032 specifications.
79    ///
80    /// Construct from a fixed-size array reference via [`From`] when the byte length is known at
81    /// compile time, or from an arbitrary slice via [`TryFrom`] which performs the length check.
82    pub struct Bip32Seed([u8]);
83
84    impl Bip32Seed {
85        const fn from_slice_unchecked(bytes: &_) -> &Self;
86    }
87}
88
89impl Bip32Seed {
90    /// Minimum seed length in bytes (128 bits).
91    pub const MIN_LEN: usize = 16;
92    /// Maximum seed length in bytes (512 bits).
93    pub const MAX_LEN: usize = 64;
94
95    /// Returns the seed bytes.
96    pub fn as_bytes(&self) -> &[u8] { &self.0 }
97}
98
99impl AsRef<[u8]> for Bip32Seed {
100    fn as_ref(&self) -> &[u8] { &self.0 }
101}
102
103impl AsRef<Self> for Bip32Seed {
104    fn as_ref(&self) -> &Self { self }
105}
106
107impl<'a> TryFrom<&'a [u8]> for &'a Bip32Seed {
108    type Error = InvalidSeedLengthError;
109
110    fn try_from(bytes: &'a [u8]) -> Result<Self, Self::Error> {
111        let len = bytes.len();
112        if len < Bip32Seed::MIN_LEN || len > Bip32Seed::MAX_LEN {
113            return Err(InvalidSeedLengthError { length: len });
114        }
115        Ok(Bip32Seed::from_slice_unchecked(bytes))
116    }
117}
118
119impl fmt::Debug for Bip32Seed {
120    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
121        let hash = sha256::Hash::hash(self.as_bytes());
122        let id = u32::from_be_bytes(*hash.as_byte_array().sub_array::<0, 4>());
123        write!(f, "Bip32Seed(sha256={:08x})", id)
124    }
125}
126
127impl PartialEq for Bip32Seed {
128    fn eq(&self, other: &Self) -> bool {
129        let a = self.as_bytes();
130        let b = other.as_bytes();
131        a.len() == b.len() && hashes::cmp::fixed_time_eq(a, b)
132    }
133}
134
135impl Eq for Bip32Seed {}
136
137macro_rules! impl_bip32_seed_from_array {
138    ($($n:literal),+ $(,)?) => {
139        $(
140            impl<'a> From<&'a [u8; $n]> for &'a Bip32Seed {
141                fn from(arr: &'a [u8; $n]) -> Self { Bip32Seed::from_slice_unchecked(arr) }
142            }
143
144            impl AsRef<Bip32Seed> for [u8; $n] {
145                fn as_ref(&self) -> &Bip32Seed { self.into() }
146            }
147        )+
148    };
149}
150
151impl_bip32_seed_from_array!(
152    16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
153    40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
154    64,
155);
156
157/// Extended private key
158#[derive(Copy, Clone, PartialEq, Eq)]
159#[cfg_attr(feature = "std", derive(Debug))]
160pub struct Xpriv {
161    /// The network this key is to be used on
162    pub network: NetworkKind,
163    /// How many derivations this key is from the master (which is 0)
164    pub depth: u8,
165    /// Fingerprint of the parent key (0 for master)
166    pub parent_fingerprint: Fingerprint,
167    /// Child number of the key used to derive from parent (0 for master)
168    pub child_number: ChildNumber,
169    /// Private key
170    pub private_key: secp256k1::SecretKey,
171    /// Chain code
172    pub chain_code: ChainCode,
173}
174#[cfg(feature = "serde")]
175internals::serde_string_impl!(Xpriv, "a BIP-0032 extended private key");
176
177#[cfg(not(feature = "std"))]
178impl fmt::Debug for Xpriv {
179    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
180        f.debug_struct("Xpriv")
181            .field("network", &self.network)
182            .field("depth", &self.depth)
183            .field("parent_fingerprint", &self.parent_fingerprint)
184            .field("child_number", &self.child_number)
185            .field("chain_code", &self.chain_code)
186            .field("private_key", &"[SecretKey]")
187            .finish()
188    }
189}
190
191/// Extended public key
192#[derive(Copy, Clone, PartialEq, Eq, Debug, PartialOrd, Ord, Hash)]
193pub struct Xpub {
194    /// The network kind this key is to be used on
195    pub network: NetworkKind,
196    /// How many derivations this key is from the master (which is 0)
197    pub depth: u8,
198    /// Fingerprint of the parent key
199    pub parent_fingerprint: Fingerprint,
200    /// Child number of the key used to derive from parent (0 for master)
201    pub child_number: ChildNumber,
202    /// Public key
203    pub public_key: secp256k1::PublicKey,
204    /// Chain code
205    pub chain_code: ChainCode,
206}
207#[cfg(feature = "serde")]
208internals::serde_string_impl!(Xpub, "a BIP-0032 extended public key");
209
210/// Flag with the hardened bit turned on.
211const HARDENED_FLAG: u32 = 1 << 31;
212
213/// The highest valid child index.
214const MAX_CHILD_INDEX: u32 = HARDENED_FLAG - 1;
215
216/// A child number for a derived key.
217///
218/// The high bit marks whether the index is hardened and the remaining bits
219/// store the actual index.
220#[derive(Copy, Clone, PartialEq, Eq, Debug, PartialOrd, Ord, Hash)]
221pub struct ChildNumber(u32);
222
223impl ChildNumber {
224    /// Normal child number with index 0.
225    pub const ZERO_NORMAL: Self = Self(0);
226
227    /// Normal child number with index 1.
228    pub const ONE_NORMAL: Self = Self(1);
229
230    /// Hardened child number with index 0.
231    pub const ZERO_HARDENED: Self = Self(HARDENED_FLAG);
232
233    /// Hardened child number with index 1.
234    pub const ONE_HARDENED: Self = Self(HARDENED_FLAG | 1);
235
236    /// Constructs a new normal child number from an index.
237    ///
238    /// # Errors
239    ///
240    /// Returns an error if the index is not within [0, 2^31 - 1].
241    pub fn from_normal_idx(index: u32) -> Result<Self, IndexOutOfRangeError> {
242        if index <= MAX_CHILD_INDEX {
243            Ok(Self(index))
244        } else {
245            Err(IndexOutOfRangeError { index })
246        }
247    }
248
249    /// Constructs a new hardened child number from an index.
250    ///
251    /// # Errors
252    ///
253    /// Returns an error if the index is not within [0, 2^31 - 1].
254    pub fn from_hardened_idx(index: u32) -> Result<Self, IndexOutOfRangeError> {
255        if index <= MAX_CHILD_INDEX {
256            Ok(Self(index | HARDENED_FLAG))
257        } else {
258            Err(IndexOutOfRangeError { index })
259        }
260    }
261
262    /// Constructs a child number from its raw BIP-0032 representation.
263    ///
264    /// The raw representation includes the hardened bit. Use [`Self::from_normal_idx`] or
265    /// [`Self::from_hardened_idx`] to construct a child number from an index.
266    pub fn from_raw(raw: u32) -> Self { Self(raw) }
267
268    /// Returns the raw BIP-0032 representation.
269    ///
270    /// The raw representation includes the hardened bit. Use [`Self::index`] to get the child
271    /// index without the hardened bit.
272    pub fn to_raw(self) -> u32 { self.0 }
273
274    /// Returns the child index, without the hardened bit.
275    pub fn index(self) -> u32 { self.0 & MAX_CHILD_INDEX }
276
277    /// Returns `true` if the child number is not hardened.
278    pub fn is_normal(&self) -> bool { !self.is_hardened() }
279
280    /// Returns `true` if the child number is hardened.
281    pub fn is_hardened(&self) -> bool { self.0 & HARDENED_FLAG != 0 }
282
283    /// Returns the child number that is a single increment from this one.
284    ///
285    /// # Errors
286    ///
287    /// Returns an error if the index after incrementing will be outside the range [0, 2^31 - 1].
288    pub fn increment(self) -> Result<Self, IndexOutOfRangeError> {
289        let index = self.index();
290        let next = index.checked_add(1).ok_or(IndexOutOfRangeError { index })?;
291        if self.is_hardened() {
292            Self::from_hardened_idx(next)
293        } else {
294            Self::from_normal_idx(next)
295        }
296    }
297
298    /// Formats the child number using the provided formatting function.
299    ///
300    /// For hardened child numbers appends a `'` or `hardened_alt_suffix`
301    /// depending on the formatter.
302    ///
303    /// # Errors
304    ///
305    /// Returns an error if writing to the formatter fails.
306    fn format_with<F>(
307        self,
308        f: &mut fmt::Formatter,
309        format_fn: F,
310        hardened_alt_suffix: &str,
311    ) -> fmt::Result
312    where
313        F: Fn(&u32, &mut fmt::Formatter) -> fmt::Result,
314    {
315        let index = self.index();
316        if self.is_hardened() {
317            format_fn(&index, f)?;
318            let alt = f.alternate();
319            f.write_str(if alt { hardened_alt_suffix } else { "'" })
320        } else {
321            format_fn(&index, f)
322        }
323    }
324}
325
326impl From<ChildNumber> for u32 {
327    fn from(number: ChildNumber) -> Self { number.to_raw() }
328}
329
330impl From<u32> for ChildNumber {
331    fn from(number: u32) -> Self { Self::from_raw(number) }
332}
333
334impl fmt::Display for ChildNumber {
335    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
336        self.format_with(f, fmt::Display::fmt, "h")
337    }
338}
339
340impl fmt::LowerHex for ChildNumber {
341    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
342        self.format_with(f, fmt::LowerHex::fmt, "h")
343    }
344}
345
346impl fmt::UpperHex for ChildNumber {
347    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
348        self.format_with(f, fmt::UpperHex::fmt, "H")
349    }
350}
351
352impl fmt::Octal for ChildNumber {
353    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
354        self.format_with(f, fmt::Octal::fmt, "h")
355    }
356}
357
358impl fmt::Binary for ChildNumber {
359    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
360        self.format_with(f, fmt::Binary::fmt, "h")
361    }
362}
363
364impl FromStr for ChildNumber {
365    type Err = ParseChildNumberError;
366
367    fn from_str(inp: &str) -> Result<Self, Self::Err> {
368        let is_hardened = inp.chars().last().is_some_and(|l| l == '\'' || l == 'h');
369        Ok(if is_hardened {
370            Self::from_hardened_idx(
371                inp[0..inp.len() - 1].parse().map_err(ParseChildNumberError::ParseInt)?,
372            )
373            .map_err(ParseChildNumberError::IndexOutOfRange)?
374        } else {
375            Self::from_normal_idx(inp.parse().map_err(ParseChildNumberError::ParseInt)?)
376                .map_err(ParseChildNumberError::IndexOutOfRange)?
377        })
378    }
379}
380
381impl AsRef<[Self]> for ChildNumber {
382    fn as_ref(&self) -> &[Self] { slice::from_ref(self) }
383}
384
385#[cfg(feature = "serde")]
386impl<'de> serde::Deserialize<'de> for ChildNumber {
387    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
388    where
389        D: serde::Deserializer<'de>,
390    {
391        u32::deserialize(deserializer).map(Self::from)
392    }
393}
394
395#[cfg(feature = "serde")]
396impl serde::Serialize for ChildNumber {
397    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
398    where
399        S: serde::Serializer,
400    {
401        u32::from(*self).serialize(serializer)
402    }
403}
404
405/// A relative BIP-0032 derivation path.
406#[derive(Default, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
407pub struct RelativeDerivationPath(Vec<ChildNumber>);
408
409#[cfg(feature = "serde")]
410internals::serde_string_impl!(RelativeDerivationPath, "a relative BIP-0032 derivation path");
411
412impl<I> Index<I> for RelativeDerivationPath
413where
414    Vec<ChildNumber>: Index<I>,
415{
416    type Output = <Vec<ChildNumber> as Index<I>>::Output;
417
418    #[inline]
419    fn index(&self, index: I) -> &Self::Output { &self.0[index] }
420}
421
422impl From<Vec<ChildNumber>> for RelativeDerivationPath {
423    fn from(numbers: Vec<ChildNumber>) -> Self { Self(numbers) }
424}
425
426impl From<RelativeDerivationPath> for Vec<ChildNumber> {
427    fn from(path: RelativeDerivationPath) -> Self { path.0 }
428}
429
430impl<'a> From<&'a [ChildNumber]> for RelativeDerivationPath {
431    fn from(numbers: &'a [ChildNumber]) -> Self { Self(numbers.to_vec()) }
432}
433
434impl core::iter::FromIterator<ChildNumber> for RelativeDerivationPath {
435    fn from_iter<T>(iter: T) -> Self
436    where
437        T: IntoIterator<Item = ChildNumber>,
438    {
439        Self(Vec::from_iter(iter))
440    }
441}
442
443#[allow(clippy::into_iter_without_iter)]
444impl<'a> core::iter::IntoIterator for &'a RelativeDerivationPath {
445    type Item = &'a ChildNumber;
446    type IntoIter = slice::Iter<'a, ChildNumber>;
447    fn into_iter(self) -> Self::IntoIter { self.0.iter() }
448}
449
450impl AsRef<[ChildNumber]> for RelativeDerivationPath {
451    fn as_ref(&self) -> &[ChildNumber] { &self.0 }
452}
453
454impl FromStr for RelativeDerivationPath {
455    type Err = ParseDerivationPathError;
456
457    fn from_str(path: &str) -> Result<Self, Self::Err> {
458        if path.is_empty() {
459            return Ok(vec![].into());
460        }
461
462        if path == "m" || path.starts_with("m/") {
463            return Err(ParseDerivationPathError::UnexpectedMasterPrefix);
464        }
465
466        let mut ret = Vec::new();
467        for part in path.split('/') {
468            if part.is_empty() {
469                return Err(ParseDerivationPathError::EmptyChild);
470            }
471            ret.push(part.parse()?);
472        }
473        Ok(Self(ret))
474    }
475}
476
477/// An absolute BIP-0032 derivation path, starting at the master key.
478///
479/// Conversion to [`RelativeDerivationPath`] is available through
480/// [`AbsoluteDerivationPath::as_relative`] or
481/// [`AbsoluteDerivationPath::into_relative`].
482///
483/// The leading `m` in BIP-0032 notation has historically been subtle in this crate:
484/// See [PR #2451] and [PR #2677] for prior discussion on the "m/" notation.
485///
486/// [PR #2451]: https://github.com/rust-bitcoin/rust-bitcoin/pull/2451
487/// [PR #2677]: https://github.com/rust-bitcoin/rust-bitcoin/pull/2677
488#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
489pub struct AbsoluteDerivationPath(RelativeDerivationPath);
490
491#[cfg(feature = "serde")]
492internals::serde_string_impl!(AbsoluteDerivationPath, "an absolute BIP-0032 derivation path");
493
494impl AbsoluteDerivationPath {
495    /// Returns the absolute derivation path for a master key.
496    pub fn master() -> Self { Self(RelativeDerivationPath::default()) }
497
498    /// Returns `true` if this is the master path.
499    pub fn is_master(&self) -> bool { self.0.is_empty() }
500
501    /// Returns the relative path below the master key.
502    pub fn as_relative(&self) -> &RelativeDerivationPath { &self.0 }
503
504    /// Converts this absolute path into the relative path below the master key.
505    pub fn into_relative(self) -> RelativeDerivationPath { self.0 }
506
507    /// Returns length of the relative derivation path below the master key.
508    pub fn len(&self) -> usize { self.0.len() }
509
510    /// Returns `true` if this is the master path.
511    pub fn is_empty(&self) -> bool { self.0.is_empty() }
512
513    /// Returns `true` if the relative path below the master key contains a hardened child number.
514    pub fn contains_hardened_child(&self) -> bool { self.0.contains_hardened_child() }
515
516    /// Joins `self` with `path` and returns the resulting new path.
517    #[must_use]
518    pub fn join<T: AsRef<[ChildNumber]>>(&self, path: T) -> Self { Self(self.0.join(path)) }
519}
520
521impl Default for AbsoluteDerivationPath {
522    fn default() -> Self { Self::master() }
523}
524
525impl FromStr for AbsoluteDerivationPath {
526    type Err = ParseDerivationPathError;
527
528    fn from_str(path: &str) -> Result<Self, Self::Err> {
529        if path == "m" {
530            return Ok(Self::master());
531        }
532
533        let path = path.strip_prefix("m/").ok_or(ParseDerivationPathError::MissingMasterPrefix)?;
534        if path.is_empty() {
535            return Err(ParseDerivationPathError::EmptyChild);
536        }
537
538        Ok(Self(path.parse()?))
539    }
540}
541
542impl fmt::Display for AbsoluteDerivationPath {
543    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
544        f.write_str("m")?;
545        if !self.0.is_empty() {
546            f.write_str("/")?;
547            if f.alternate() {
548                write!(f, "{:#}", self.0)?;
549            } else {
550                write!(f, "{}", self.0)?;
551            }
552        }
553        Ok(())
554    }
555}
556
557impl From<RelativeDerivationPath> for AbsoluteDerivationPath {
558    fn from(path: RelativeDerivationPath) -> Self { Self(path) }
559}
560
561impl From<AbsoluteDerivationPath> for RelativeDerivationPath {
562    fn from(path: AbsoluteDerivationPath) -> Self { path.0 }
563}
564
565/// An iterator over children of a [`RelativeDerivationPath`].
566///
567/// It is returned by the methods [`RelativeDerivationPath::children_from`],
568/// [`RelativeDerivationPath::normal_children`] and [`RelativeDerivationPath::hardened_children`].
569pub struct RelativeDerivationPathIterator<'a> {
570    base: &'a RelativeDerivationPath,
571    next_child: Option<ChildNumber>,
572}
573
574impl<'a> RelativeDerivationPathIterator<'a> {
575    /// Starts a new [`RelativeDerivationPathIterator`] at the given child.
576    pub fn start_from(path: &'a RelativeDerivationPath, start: ChildNumber) -> Self {
577        RelativeDerivationPathIterator { base: path, next_child: Some(start) }
578    }
579}
580
581impl Iterator for RelativeDerivationPathIterator<'_> {
582    type Item = RelativeDerivationPath;
583
584    fn next(&mut self) -> Option<Self::Item> {
585        let ret = self.next_child?;
586        self.next_child = ret.increment().ok();
587        Some(self.base.child(ret))
588    }
589}
590
591impl RelativeDerivationPath {
592    /// Returns length of the derivation path
593    pub fn len(&self) -> usize { self.0.len() }
594
595    /// Returns `true` if the derivation path is empty
596    pub fn is_empty(&self) -> bool { self.0.is_empty() }
597
598    /// Returns `true` if the derivation path contains a hardened child number.
599    pub fn contains_hardened_child(&self) -> bool { self.0.iter().any(ChildNumber::is_hardened) }
600
601    /// Constructs a new [`RelativeDerivationPath`] that is a child of this one.
602    #[must_use]
603    pub fn child(&self, cn: ChildNumber) -> Self {
604        let mut path = self.0.clone();
605        path.push(cn);
606        Self(path)
607    }
608
609    /// Converts into a [`RelativeDerivationPath`] that is a child of this one.
610    #[must_use]
611    pub fn into_child(self, cn: ChildNumber) -> Self {
612        let mut path = self.0;
613        path.push(cn);
614        Self(path)
615    }
616
617    /// Gets an [Iterator] over the children of this [`RelativeDerivationPath`]
618    /// starting with the given [`ChildNumber`].
619    pub fn children_from(&self, cn: ChildNumber) -> RelativeDerivationPathIterator<'_> {
620        RelativeDerivationPathIterator::start_from(self, cn)
621    }
622
623    /// Gets an [Iterator] over the unhardened children of this [`RelativeDerivationPath`].
624    pub fn normal_children(&self) -> RelativeDerivationPathIterator<'_> {
625        RelativeDerivationPathIterator::start_from(self, ChildNumber::ZERO_NORMAL)
626    }
627
628    /// Gets an [Iterator] over the hardened children of this [`RelativeDerivationPath`].
629    pub fn hardened_children(&self) -> RelativeDerivationPathIterator<'_> {
630        RelativeDerivationPathIterator::start_from(self, ChildNumber::ZERO_HARDENED)
631    }
632
633    /// Joins `self` with `path` and returns the resulting new path.
634    ///
635    /// ```
636    /// use bitcoin_key_expression::bip32::{RelativeDerivationPath, ChildNumber};
637    ///
638    /// let base = "42".parse::<RelativeDerivationPath>().unwrap();
639    ///
640    /// let deriv_1 = base.join("0/1".parse::<RelativeDerivationPath>().unwrap());
641    /// let deriv_2 = base.join(&[
642    ///     ChildNumber::ZERO_NORMAL,
643    ///     ChildNumber::ONE_NORMAL
644    /// ]);
645    ///
646    /// assert_eq!(deriv_1, deriv_2);
647    /// ```
648    #[must_use]
649    pub fn join<T: AsRef<[ChildNumber]>>(&self, path: T) -> Self {
650        let mut new_path = self.clone();
651        new_path.0.extend_from_slice(path.as_ref());
652        new_path
653    }
654
655    /// Returns the derivation path as a vector of raw BIP-0032 u32 child numbers.
656    /// Unhardened elements are copied as is.
657    /// 0x80000000 is added to the hardened elements.
658    ///
659    /// ```
660    /// use bitcoin_key_expression::bip32::RelativeDerivationPath;
661    ///
662    /// let path = "84'/0'/0'/0/1".parse::<RelativeDerivationPath>().unwrap();
663    /// const HARDENED: u32 = 0x80000000;
664    /// assert_eq!(path.to_u32_vec(), vec![84 + HARDENED, HARDENED, HARDENED, 0, 1]);
665    /// ```
666    pub fn to_u32_vec(&self) -> Vec<u32> { self.into_iter().map(|&el| el.to_raw()).collect() }
667
668    /// Constructs a new derivation path from a slice of raw BIP-0032 u32 child numbers.
669    /// ```
670    /// use bitcoin_key_expression::bip32::RelativeDerivationPath;
671    ///
672    /// const HARDENED: u32 = 0x80000000;
673    /// let expected = vec![84 + HARDENED, HARDENED, HARDENED, 0, 1];
674    /// let path = RelativeDerivationPath::from_u32_slice(expected.as_slice());
675    /// assert_eq!(path.to_u32_vec(), expected);
676    /// ```
677    pub fn from_u32_slice(numbers: &[u32]) -> Self {
678        numbers.iter().map(|&n| ChildNumber::from_raw(n)).collect()
679    }
680}
681
682impl fmt::Display for RelativeDerivationPath {
683    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
684        let mut iter = self.0.iter();
685        if let Some(first_element) = iter.next() {
686            if f.alternate() {
687                write!(f, "{:#}", first_element)?;
688            } else {
689                write!(f, "{}", first_element)?;
690            }
691        }
692        for cn in iter {
693            f.write_str("/")?;
694            if f.alternate() {
695                write!(f, "{:#}", cn)?;
696            } else {
697                write!(f, "{}", cn)?;
698            }
699        }
700        Ok(())
701    }
702}
703
704impl fmt::Debug for RelativeDerivationPath {
705    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self, f) }
706}
707
708/// Full information on the used extended public key: fingerprint of the
709/// master extended public key and a derivation path from it.
710pub type KeySource = (Fingerprint, RelativeDerivationPath);
711
712impl Xpriv {
713    /// Constructs a new master key from a [`Bip32Seed`].
714    #[allow(clippy::missing_panics_doc)]
715    pub fn new_master(network: impl Into<NetworkKind>, seed: impl AsRef<Bip32Seed>) -> Self {
716        Self::new_master_inner(network.into(), seed.as_ref())
717    }
718
719    fn new_master_inner(network: NetworkKind, seed: &Bip32Seed) -> Self {
720        let mut engine = HmacEngine::<sha512::HashEngine>::new(b"Bitcoin seed");
721        engine.input(seed.as_bytes());
722        let hmac = engine.finalize();
723
724        Self {
725            network,
726            depth: 0,
727            parent_fingerprint: Fingerprint::default(),
728            child_number: ChildNumber::ZERO_NORMAL,
729            private_key: secp256k1::SecretKey::from_secret_bytes(
730                *hmac.as_byte_array().split_array::<32, 32>().0,
731            )
732            .expect("cryptographically unreachable"),
733            chain_code: ChainCode::from_hmac(hmac),
734        }
735    }
736
737    /// Constructs a new ECDSA compressed private key matching internal secret key representation.
738    #[deprecated(since = "TBD", note = "use `to_private_key()` instead")]
739    pub fn to_priv(self) -> PrivateKey { self.to_private_key() }
740
741    /// Constructs a new ECDSA compressed private key matching internal secret key representation.
742    pub fn to_private_key(self) -> PrivateKey { PrivateKey::from_secp(self.private_key) }
743
744    /// Constructs a new extended public key from this extended private key.
745    pub fn to_xpub(self) -> Xpub { Xpub::from_xpriv(&self) }
746
747    /// Constructs a new BIP-0340 keypair for Schnorr signatures and Taproot use matching the internal
748    /// secret key representation.
749    pub fn to_keypair(self) -> Keypair { Keypair::from_private_key(&self.to_private_key()) }
750
751    /// Derives an extended private key from a path.
752    ///
753    /// The `path` argument can be both of type `RelativeDerivationPath` or `Vec<ChildNumber>`.
754    ///
755    /// # Errors
756    ///
757    /// See [`derive_xpriv`].
758    ///
759    /// [`derive_xpriv`]: Xpriv::derive_xpriv
760    #[deprecated(since = "TBD", note = "use `derive_xpriv()` instead")]
761    pub fn derive_priv<P: AsRef<[ChildNumber]>>(&self, path: P) -> Result<Self, DerivationError> {
762        self.derive_xpriv(path)
763    }
764
765    /// Derives an extended private key from a path.
766    ///
767    /// The `path` argument can be both of type `RelativeDerivationPath` or `Vec<ChildNumber>`.
768    ///
769    /// # Errors
770    ///
771    /// Returns an error if the derived key exceeds the maximum key depth.
772    pub fn derive_xpriv<P: AsRef<[ChildNumber]>>(&self, path: P) -> Result<Self, DerivationError> {
773        let mut sk: Self = *self;
774        for cnum in path.as_ref() {
775            sk = sk.ckd_priv(*cnum)?;
776        }
777        Ok(sk)
778    }
779
780    /// Private->Private child key derivation
781    fn ckd_priv(&self, i: ChildNumber) -> Result<Self, DerivationError> {
782        let mut engine = HmacEngine::<sha512::HashEngine>::new(&self.chain_code[..]);
783        if i.is_normal() {
784            // Non-hardened key: compute public data and use that.
785            engine.input(&secp256k1::PublicKey::from_secret_key(&self.private_key).serialize()[..]);
786        } else {
787            // Hardened key: use only secret data to prevent public derivation.
788            engine.input(&[0u8]);
789            engine.input(&self.private_key[..]);
790        }
791
792        engine.input(&u32::from(i).to_be_bytes());
793        let hmac: Hmac<sha512::Hash> = engine.finalize();
794        let sk = secp256k1::SecretKey::from_secret_bytes(
795            *hmac.as_byte_array().split_array::<32, 32>().0,
796        )
797        .expect("statistically impossible to hit");
798        let tweaked =
799            sk.add_tweak(&self.private_key.into()).expect("statistically impossible to hit");
800
801        Ok(Self {
802            network: self.network,
803            depth: self.depth.checked_add(1).ok_or(DerivationError::MaximumDepthExceeded)?,
804            parent_fingerprint: self.fingerprint(),
805            child_number: i,
806            private_key: tweaked,
807            chain_code: ChainCode::from_hmac(hmac),
808        })
809    }
810
811    /// Decoding extended private key from binary data according to BIP-0032
812    ///
813    /// # Errors
814    ///
815    /// * [`ParseError::UnknownVersion`] if the decoded network value is not main or testnet.
816    /// * [`ParseError::InvalidPrivateKeyPrefix`] if the private key bytes don't start with zero.
817    /// * [`ParseError::Secp256k1`] if the private key bytes are not a valid secp secret key.
818    /// * [`ParseError::WrongExtendedKeyLength`] if the data is not the correct length.
819    /// * [`ParseError::NonZeroParentFingerprintForMasterKey`] if the depth is 0 and the master key
820    ///   fingerprint is non-zero.
821    /// * [`ParseError::NonZeroChildNumberForMasterKey`] if the depth is 0 and the child number is
822    ///   non-zero.
823    pub fn decode(data: &[u8]) -> Result<Self, ParseError> {
824        let Common { network, depth, parent_fingerprint, child_number, chain_code, key } =
825            Common::decode(data)?;
826
827        let network = match network {
828            VERSION_BYTES_MAINNET_PRIVATE => NetworkKind::Main,
829            VERSION_BYTES_TESTNETS_PRIVATE => NetworkKind::Test,
830            unknown => return Err(ParseError::UnknownVersion(unknown)),
831        };
832
833        let (&zero, private_key) = key.split_first();
834        if zero != 0 {
835            return Err(ParseError::InvalidPrivateKeyPrefix);
836        }
837
838        Ok(Self {
839            network,
840            depth,
841            parent_fingerprint,
842            child_number,
843            chain_code,
844            private_key: secp256k1::SecretKey::from_secret_bytes(*private_key)?,
845        })
846    }
847
848    /// Extended private key binary encoding according to BIP-0032
849    pub fn encode(&self) -> [u8; 78] {
850        let mut ret = [0; 78];
851        ret[0..4].copy_from_slice(&match self.network {
852            NetworkKind::Main => VERSION_BYTES_MAINNET_PRIVATE,
853            NetworkKind::Test => VERSION_BYTES_TESTNETS_PRIVATE,
854        });
855        ret[4] = self.depth;
856        ret[5..9].copy_from_slice(&self.parent_fingerprint[..]);
857        ret[9..13].copy_from_slice(&u32::from(self.child_number).to_be_bytes());
858        ret[13..45].copy_from_slice(&self.chain_code[..]);
859        ret[45] = 0;
860        ret[46..78].copy_from_slice(&self.private_key[..]);
861        ret
862    }
863
864    /// Returns the HASH160 of the public key belonging to the xpriv
865    pub fn identifier(&self) -> XKeyIdentifier { Xpub::from_xpriv(self).identifier() }
866
867    /// Returns the first four bytes of the identifier
868    pub fn fingerprint(&self) -> Fingerprint {
869        self.identifier().as_byte_array().sub_array::<0, 4>().into()
870    }
871}
872
873impl Xpub {
874    /// Constructs a new extended public key from an extended private key.
875    #[deprecated(since = "TBD", note = "use `from_xpriv()` instead")]
876    pub fn from_priv(sk: &Xpriv) -> Self { Self::from_xpriv(sk) }
877
878    /// Constructs a new extended public key from an extended private key.
879    pub fn from_xpriv(xpriv: &Xpriv) -> Self {
880        Self {
881            network: xpriv.network,
882            depth: xpriv.depth,
883            parent_fingerprint: xpriv.parent_fingerprint,
884            child_number: xpriv.child_number,
885            public_key: secp256k1::PublicKey::from_secret_key(&xpriv.private_key),
886            chain_code: xpriv.chain_code,
887        }
888    }
889
890    /// Constructs a new ECDSA compressed public key matching internal public key representation.
891    #[deprecated(since = "TBD", note = "use `to_public_key()` instead")]
892    pub fn to_pub(self) -> FullPublicKey { self.to_public_key() }
893
894    /// Constructs a new ECDSA compressed public key matching internal public key representation.
895    pub fn to_public_key(self) -> FullPublicKey { FullPublicKey::from_secp(self.public_key) }
896
897    /// Constructs a new BIP-0340 x-only public key for BIP-0340 signatures and Taproot use matching
898    /// the internal public key representation.
899    #[deprecated(since = "TBD", note = "use `to_x_only_public_key()` instead")]
900    pub fn to_x_only_pub(self) -> XOnlyPublicKey { self.to_x_only_public_key() }
901
902    /// Constructs a new BIP-0340 x-only public key for BIP-0340 signatures and Taproot use matching
903    /// the internal public key representation.
904    pub fn to_x_only_public_key(self) -> XOnlyPublicKey { XOnlyPublicKey::from(self.public_key) }
905
906    /// Attempts to derive an extended public key from a path.
907    ///
908    /// The `path` argument can be any type implementing `AsRef<[ChildNumber]>`, such as `RelativeDerivationPath`, for instance.
909    ///
910    /// # Errors
911    ///
912    /// See [`derive_xpub`].
913    ///
914    /// [`derive_xpub`]: Xpub::derive_xpub
915    #[deprecated(since = "TBD", note = "use `derive_xpub()` instead")]
916    pub fn derive_pub<P: AsRef<[ChildNumber]>>(&self, path: P) -> Result<Self, DerivationError> {
917        self.derive_xpub(path)
918    }
919
920    /// Attempts to derive an extended public key from a path.
921    ///
922    /// The `path` argument can be any type implementing `AsRef<[ChildNumber]>`, such as
923    /// `RelativeDerivationPath`, for instance.
924    ///
925    /// # Errors
926    ///
927    /// Returns an error if any of the [`ChildNumber`]s are hardened.
928    pub fn derive_xpub<P: AsRef<[ChildNumber]>>(&self, path: P) -> Result<Self, DerivationError> {
929        let mut pk: Self = *self;
930        for cnum in path.as_ref() {
931            pk = pk.ckd_pub(*cnum)?;
932        }
933        Ok(pk)
934    }
935
936    /// Computes the scalar tweak added to this key to get a child key
937    ///
938    /// # Errors
939    ///
940    /// Returns an error if the given [`ChildNumber`] is hardened.
941    #[allow(clippy::missing_panics_doc)]
942    pub fn ckd_pub_tweak(
943        &self,
944        i: ChildNumber,
945    ) -> Result<(secp256k1::SecretKey, ChainCode), DerivationError> {
946        if i.is_hardened() {
947            return Err(DerivationError::CannotDeriveHardenedChild);
948        }
949
950        let mut engine = HmacEngine::<sha512::HashEngine>::new(&self.chain_code[..]);
951        engine.input(&self.public_key.serialize()[..]);
952        engine.input(&i.index().to_be_bytes());
953
954        let hmac = engine.finalize();
955        let private_key = secp256k1::SecretKey::from_secret_bytes(
956            *hmac.as_byte_array().split_array::<32, 32>().0,
957        )
958        .expect("cryptographically unreachable");
959        let chain_code = ChainCode::from_hmac(hmac);
960        Ok((private_key, chain_code))
961    }
962
963    /// Public->Public child key derivation
964    ///
965    /// # Errors
966    ///
967    /// Returns an error if the given [`ChildNumber`] is hardened, or if next key exceeds
968    /// the maximum derivation depth.
969    #[allow(clippy::missing_panics_doc)]
970    pub fn ckd_pub(&self, i: ChildNumber) -> Result<Self, DerivationError> {
971        let (sk, chain_code) = self.ckd_pub_tweak(i)?;
972        let tweaked =
973            self.public_key.add_exp_tweak(&sk.into()).expect("cryptographically unreachable");
974
975        Ok(Self {
976            network: self.network,
977            depth: self.depth.checked_add(1).ok_or(DerivationError::MaximumDepthExceeded)?,
978            parent_fingerprint: self.fingerprint(),
979            child_number: i,
980            public_key: tweaked,
981            chain_code,
982        })
983    }
984
985    /// Decoding extended public key from binary data according to BIP-0032
986    ///
987    /// # Errors
988    ///
989    /// * [`ParseError::UnknownVersion`] if the decoded network value is not main or testnet.
990    /// * [`ParseError::Secp256k1`] if the public key bytes are not a valid secp public key.
991    /// * [`ParseError::WrongExtendedKeyLength`] if the data is not the correct length.
992    /// * [`ParseError::NonZeroParentFingerprintForMasterKey`] if the depth is 0 and the master key
993    ///   fingerprint is non-zero.
994    /// * [`ParseError::NonZeroChildNumberForMasterKey`] if the depth is 0 and the child number is
995    ///   non-zero.
996    pub fn decode(data: &[u8]) -> Result<Self, ParseError> {
997        let Common { network, depth, parent_fingerprint, child_number, chain_code, key } =
998            Common::decode(data)?;
999
1000        let network = match network {
1001            VERSION_BYTES_MAINNET_PUBLIC => NetworkKind::Main,
1002            VERSION_BYTES_TESTNETS_PUBLIC => NetworkKind::Test,
1003            unknown => return Err(ParseError::UnknownVersion(unknown)),
1004        };
1005
1006        Ok(Self {
1007            network,
1008            depth,
1009            parent_fingerprint,
1010            child_number,
1011            chain_code,
1012            public_key: secp256k1::PublicKey::from_slice(&key)?,
1013        })
1014    }
1015
1016    /// Extended public key binary encoding according to BIP-0032
1017    pub fn encode(&self) -> [u8; 78] {
1018        let mut ret = [0; 78];
1019        ret[0..4].copy_from_slice(&match self.network {
1020            NetworkKind::Main => VERSION_BYTES_MAINNET_PUBLIC,
1021            NetworkKind::Test => VERSION_BYTES_TESTNETS_PUBLIC,
1022        });
1023        ret[4] = self.depth;
1024        ret[5..9].copy_from_slice(&self.parent_fingerprint[..]);
1025        ret[9..13].copy_from_slice(&u32::from(self.child_number).to_be_bytes());
1026        ret[13..45].copy_from_slice(&self.chain_code[..]);
1027        ret[45..78].copy_from_slice(&self.public_key.serialize()[..]);
1028        ret
1029    }
1030
1031    /// Returns the HASH160 of the public key component of the xpub
1032    pub fn identifier(&self) -> XKeyIdentifier {
1033        XKeyIdentifier(hash160::Hash::hash(&self.public_key.serialize()))
1034    }
1035
1036    /// Returns the first four bytes of the identifier
1037    pub fn fingerprint(&self) -> Fingerprint {
1038        self.identifier().as_byte_array().sub_array::<0, 4>().into()
1039    }
1040}
1041
1042impl fmt::Display for Xpriv {
1043    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1044        base58::encode_check_to_fmt(fmt, &self.encode()[..])
1045    }
1046}
1047
1048impl FromStr for Xpriv {
1049    type Err = ParseError;
1050
1051    fn from_str(inp: &str) -> Result<Self, ParseError> {
1052        let data = base58::decode_check(inp)?;
1053
1054        if data.len() != 78 {
1055            return Err(InvalidBase58PayloadLengthError { length: data.len() }.into());
1056        }
1057
1058        Self::decode(&data)
1059    }
1060}
1061
1062impl fmt::Display for Xpub {
1063    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1064        base58::encode_check_to_fmt(fmt, &self.encode()[..])
1065    }
1066}
1067
1068impl FromStr for Xpub {
1069    type Err = ParseError;
1070
1071    fn from_str(inp: &str) -> Result<Self, ParseError> {
1072        let data = base58::decode_check(inp)?;
1073
1074        if data.len() != 78 {
1075            return Err(InvalidBase58PayloadLengthError { length: data.len() }.into());
1076        }
1077
1078        Self::decode(&data)
1079    }
1080}
1081
1082impl From<Xpub> for XKeyIdentifier {
1083    fn from(key: Xpub) -> Self { key.identifier() }
1084}
1085
1086impl From<&Xpub> for XKeyIdentifier {
1087    fn from(key: &Xpub) -> Self { key.identifier() }
1088}
1089
1090// Helps unify decoding
1091struct Common {
1092    network: [u8; 4],
1093    depth: u8,
1094    parent_fingerprint: Fingerprint,
1095    child_number: ChildNumber,
1096    chain_code: ChainCode,
1097    // public key (compressed) or 0 byte followed by a private key
1098    key: [u8; 33],
1099}
1100
1101impl Common {
1102    /// Decodes common fields for [`Xpriv`] and [`Xpub`].
1103    ///
1104    /// # Errors
1105    ///
1106    /// * [`ParseError::WrongExtendedKeyLength`] if the data is not the correct length.
1107    /// * [`ParseError::NonZeroParentFingerprintForMasterKey`] if the depth is 0 and the master key
1108    ///   fingerprint is non-zero.
1109    /// * [`ParseError::NonZeroChildNumberForMasterKey`] if the depth is 0 and the child number is
1110    ///   non-zero.
1111    fn decode(data: &[u8]) -> Result<Self, ParseError> {
1112        let data: &[u8; 78] =
1113            data.try_into().map_err(|_| ParseError::WrongExtendedKeyLength(data.len()))?;
1114
1115        let (&network, data) = data.split_array::<4, 74>();
1116        let (&depth, data) = data.split_first::<73>();
1117        let (&parent_fingerprint, data) = data.split_array::<4, 69>();
1118        let (&child_number, data) = data.split_array::<4, 65>();
1119        let (&chain_code, &key) = data.split_array::<32, 33>();
1120
1121        if depth == 0 {
1122            if parent_fingerprint != [0u8; 4] {
1123                return Err(ParseError::NonZeroParentFingerprintForMasterKey);
1124            }
1125
1126            if child_number != [0u8; 4] {
1127                return Err(ParseError::NonZeroChildNumberForMasterKey);
1128            }
1129        }
1130
1131        Ok(Self {
1132            network,
1133            depth,
1134            parent_fingerprint: parent_fingerprint.into(),
1135            child_number: u32::from_be_bytes(child_number).into(),
1136            chain_code: chain_code.into(),
1137            key,
1138        })
1139    }
1140}
1141
1142/// Error types for BIP-0032 operations
1143pub mod error {
1144    use core::convert::Infallible;
1145    use core::fmt;
1146
1147    use internals::write_err;
1148
1149    /// A BIP-0032 error
1150    #[derive(Debug, Clone, PartialEq, Eq)]
1151    #[non_exhaustive]
1152    pub enum ParseError {
1153        /// A secp256k1 error occurred
1154        Secp256k1(secp256k1::Error),
1155        /// Unknown version magic bytes
1156        UnknownVersion([u8; 4]),
1157        /// Encoded extended key data has wrong length
1158        WrongExtendedKeyLength(usize),
1159        /// Base58 encoding error
1160        Base58(base58::Error),
1161        /// Base58 decoded data was an invalid length.
1162        InvalidBase58PayloadLength(InvalidBase58PayloadLengthError),
1163        /// Invalid private key prefix (byte 45 must be 0)
1164        InvalidPrivateKeyPrefix,
1165        /// Non-zero parent fingerprint for a master key (depth 0)
1166        NonZeroParentFingerprintForMasterKey,
1167        /// Non-zero child number for a master key (depth 0)
1168        NonZeroChildNumberForMasterKey,
1169    }
1170
1171    impl From<Infallible> for ParseError {
1172        fn from(never: Infallible) -> Self { match never {} }
1173    }
1174
1175    impl fmt::Display for ParseError {
1176        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1177            match self {
1178                Self::Secp256k1(ref e) => write_err!(f, "secp256k1 error"; e),
1179                Self::UnknownVersion(ref bytes) =>
1180                    write!(f, "unknown version magic bytes: {:?}", bytes),
1181                Self::WrongExtendedKeyLength(ref len) =>
1182                    write!(f, "encoded extended key data has wrong length {}", len),
1183                Self::Base58(ref e) => write_err!(f, "base58 encoding error"; e),
1184                Self::InvalidBase58PayloadLength(ref e) => write_err!(f, "base58 payload"; e),
1185                Self::InvalidPrivateKeyPrefix => f.write_str(
1186                    "invalid private key prefix, byte 45 must be 0 as required by BIP-0032",
1187                ),
1188                Self::NonZeroParentFingerprintForMasterKey =>
1189                    f.write_str("non-zero parent fingerprint in master key"),
1190                Self::NonZeroChildNumberForMasterKey =>
1191                    f.write_str("non-zero child number in master key"),
1192            }
1193        }
1194    }
1195
1196    #[cfg(feature = "std")]
1197    impl std::error::Error for ParseError {
1198        fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
1199            match self {
1200                Self::Secp256k1(ref e) => Some(e),
1201                Self::Base58(ref e) => Some(e),
1202                Self::InvalidBase58PayloadLength(ref e) => Some(e),
1203                Self::UnknownVersion(_) | Self::WrongExtendedKeyLength(_) => None,
1204                Self::InvalidPrivateKeyPrefix => None,
1205                Self::NonZeroParentFingerprintForMasterKey => None,
1206                Self::NonZeroChildNumberForMasterKey => None,
1207            }
1208        }
1209    }
1210
1211    impl From<secp256k1::Error> for ParseError {
1212        fn from(e: secp256k1::Error) -> Self { Self::Secp256k1(e) }
1213    }
1214
1215    impl From<base58::Error> for ParseError {
1216        fn from(err: base58::Error) -> Self { Self::Base58(err) }
1217    }
1218
1219    impl From<InvalidBase58PayloadLengthError> for ParseError {
1220        fn from(e: InvalidBase58PayloadLengthError) -> Self { Self::InvalidBase58PayloadLength(e) }
1221    }
1222
1223    /// A BIP-0032 error
1224    #[derive(Debug, Clone, PartialEq, Eq)]
1225    #[non_exhaustive]
1226    pub enum DerivationError {
1227        /// Attempted to derive a hardened child from an xpub.
1228        ///
1229        /// You can only derive hardened children from xprivs.
1230        CannotDeriveHardenedChild,
1231        /// Attempted to derive a child of depth 256 or higher.
1232        ///
1233        /// There is no way to encode such xkeys.
1234        MaximumDepthExceeded,
1235    }
1236
1237    impl From<Infallible> for DerivationError {
1238        fn from(never: Infallible) -> Self { match never {} }
1239    }
1240
1241    #[cfg(feature = "std")]
1242    impl std::error::Error for DerivationError {
1243        fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
1244            match self {
1245                Self::CannotDeriveHardenedChild => None,
1246                Self::MaximumDepthExceeded => None,
1247            }
1248        }
1249    }
1250
1251    impl fmt::Display for DerivationError {
1252        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1253            match *self {
1254                Self::CannotDeriveHardenedChild =>
1255                    f.write_str("cannot derive hardened child of public key"),
1256                Self::MaximumDepthExceeded =>
1257                    f.write_str("cannot derive child of depth 256 or higher"),
1258            }
1259        }
1260    }
1261
1262    /// Out-of-range index when constructing a child number.
1263    ///
1264    /// *Indices* are always in the range [0, 2^31 - 1]. Normal child numbers have the
1265    /// same range, while hardened child numbers lie in the range [2^31, 2^32 - 1].
1266    #[derive(Debug, Clone, PartialEq, Eq)]
1267    #[non_exhaustive]
1268    pub struct IndexOutOfRangeError {
1269        /// The index that was out of range for a child number.
1270        pub index: u32,
1271    }
1272
1273    impl From<Infallible> for IndexOutOfRangeError {
1274        fn from(never: Infallible) -> Self { match never {} }
1275    }
1276
1277    impl fmt::Display for IndexOutOfRangeError {
1278        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1279            write!(f, "index {} out of range [0, 2^31 - 1] (do you have a hardened child number, rather than an index?)", self.index)
1280        }
1281    }
1282
1283    #[cfg(feature = "std")]
1284    impl std::error::Error for IndexOutOfRangeError {
1285        fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
1286            let Self { index: _ } = self;
1287            None
1288        }
1289    }
1290
1291    /// Error parsing a child number.
1292    #[derive(Debug, Clone, PartialEq, Eq)]
1293    pub enum ParseChildNumberError {
1294        /// Parsed the child number as an integer, but the integer was out of range.
1295        IndexOutOfRange(IndexOutOfRangeError),
1296        /// Failed to parse the child number as an integer.
1297        ParseInt(core::num::ParseIntError),
1298    }
1299
1300    impl From<Infallible> for ParseChildNumberError {
1301        fn from(never: Infallible) -> Self { match never {} }
1302    }
1303
1304    impl fmt::Display for ParseChildNumberError {
1305        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1306            match *self {
1307                Self::IndexOutOfRange(ref e) => e.fmt(f),
1308                Self::ParseInt(ref e) => e.fmt(f),
1309            }
1310        }
1311    }
1312
1313    #[cfg(feature = "std")]
1314    impl std::error::Error for ParseChildNumberError {
1315        fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
1316            match *self {
1317                Self::IndexOutOfRange(ref e) => Some(e),
1318                Self::ParseInt(ref e) => Some(e),
1319            }
1320        }
1321    }
1322
1323    /// Error parsing a derivation path.
1324    #[derive(Debug, Clone, PartialEq, Eq)]
1325    pub enum ParseDerivationPathError {
1326        /// Failed to parse a child number.
1327        Child(ParseChildNumberError),
1328        /// The path contained an empty child number.
1329        EmptyChild,
1330        /// The absolute path was missing the `m` master prefix.
1331        MissingMasterPrefix,
1332        /// The relative path unexpectedly contained the `m` master prefix.
1333        UnexpectedMasterPrefix,
1334    }
1335
1336    impl From<Infallible> for ParseDerivationPathError {
1337        fn from(never: Infallible) -> Self { match never {} }
1338    }
1339
1340    impl fmt::Display for ParseDerivationPathError {
1341        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1342            match *self {
1343                Self::Child(ref e) => write_err!(f, "failed to parse child number"; e),
1344                Self::EmptyChild => f.write_str("derivation path contains an empty child number"),
1345                Self::MissingMasterPrefix =>
1346                    f.write_str("absolute derivation path is missing master prefix `m`"),
1347                Self::UnexpectedMasterPrefix =>
1348                    f.write_str("relative derivation path contains unexpected master prefix `m`"),
1349            }
1350        }
1351    }
1352
1353    #[cfg(feature = "std")]
1354    impl std::error::Error for ParseDerivationPathError {
1355        fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
1356            match *self {
1357                Self::Child(ref e) => Some(e),
1358                Self::EmptyChild | Self::MissingMasterPrefix | Self::UnexpectedMasterPrefix => None,
1359            }
1360        }
1361    }
1362
1363    impl From<ParseChildNumberError> for ParseDerivationPathError {
1364        fn from(e: ParseChildNumberError) -> Self { Self::Child(e) }
1365    }
1366
1367    /// Decoded base58 data was an invalid length.
1368    #[derive(Debug, Clone, PartialEq, Eq)]
1369    pub struct InvalidBase58PayloadLengthError {
1370        /// The base58 payload length we got after decoding xpriv/xpub string.
1371        pub(crate) length: usize,
1372    }
1373
1374    impl InvalidBase58PayloadLengthError {
1375        /// Returns the invalid payload length.
1376        pub fn invalid_base58_payload_length(&self) -> usize { self.length }
1377    }
1378
1379    impl From<Infallible> for InvalidBase58PayloadLengthError {
1380        fn from(never: Infallible) -> Self { match never {} }
1381    }
1382
1383    impl fmt::Display for InvalidBase58PayloadLengthError {
1384        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1385            write!(
1386                f,
1387                "decoded base58 xpriv/xpub data was an invalid length: {} (expected 78)",
1388                self.length
1389            )
1390        }
1391    }
1392
1393    #[cfg(feature = "std")]
1394    impl std::error::Error for InvalidBase58PayloadLengthError {
1395        fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
1396            let Self { length: _ } = self;
1397            None
1398        }
1399    }
1400
1401    /// Master seed had an invalid length.
1402    #[derive(Debug, Copy, Clone, PartialEq, Eq)]
1403    pub struct InvalidSeedLengthError {
1404        pub(crate) length: usize,
1405    }
1406
1407    impl InvalidSeedLengthError {
1408        /// Returns the invalid seed length.
1409        pub fn invalid_seed_length(&self) -> usize { self.length }
1410    }
1411
1412    impl From<Infallible> for InvalidSeedLengthError {
1413        fn from(never: Infallible) -> Self { match never {} }
1414    }
1415
1416    impl fmt::Display for InvalidSeedLengthError {
1417        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1418            write!(
1419                f,
1420                "invalid BIP-0032 master seed length: {} (expected 16 to 64 inclusive)",
1421                self.length
1422            )
1423        }
1424    }
1425
1426    #[cfg(feature = "std")]
1427    impl std::error::Error for InvalidSeedLengthError {
1428        fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
1429            let Self { length: _ } = self;
1430            None
1431        }
1432    }
1433}
1434
1435#[cfg(feature = "arbitrary")]
1436impl<'a> Arbitrary<'a> for RelativeDerivationPath {
1437    fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
1438        let bytes = Vec::<u32>::arbitrary(u)?;
1439        Ok(Self::from_u32_slice(bytes.as_slice()))
1440    }
1441}
1442
1443#[cfg(feature = "arbitrary")]
1444impl<'a> Arbitrary<'a> for AbsoluteDerivationPath {
1445    fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
1446        Ok(Self(RelativeDerivationPath::arbitrary(u)?))
1447    }
1448}
1449
1450#[cfg(feature = "arbitrary")]
1451impl<'a> Arbitrary<'a> for Fingerprint {
1452    fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
1453        Ok(Self::from_byte_array(u.arbitrary()?))
1454    }
1455}
1456
1457#[cfg(feature = "arbitrary")]
1458impl<'a> Arbitrary<'a> for ChainCode {
1459    fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
1460        Ok(Self::from_byte_array(u.arbitrary()?))
1461    }
1462}
1463
1464#[cfg(feature = "arbitrary")]
1465impl<'a> Arbitrary<'a> for ChildNumber {
1466    fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
1467        Ok(Self::from_raw(u.arbitrary()?))
1468    }
1469}
1470
1471#[cfg(feature = "arbitrary")]
1472impl<'a> Arbitrary<'a> for Xpub {
1473    fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
1474        Ok(Self {
1475            network: u.arbitrary()?,
1476            depth: u.arbitrary()?,
1477            parent_fingerprint: u.arbitrary()?,
1478            child_number: u.arbitrary()?,
1479            public_key: u.arbitrary()?,
1480            chain_code: u.arbitrary()?,
1481        })
1482    }
1483}
1484
1485#[cfg(feature = "arbitrary")]
1486impl<'a> Arbitrary<'a> for Xpriv {
1487    fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
1488        let depth = u.arbitrary()?;
1489        let (parent_fingerprint, child_number) = match depth {
1490            0 => (Fingerprint::default(), ChildNumber::ZERO_NORMAL),
1491            _ => (u.arbitrary()?, u.arbitrary()?),
1492        };
1493
1494        Ok(Self {
1495            network: u.arbitrary()?,
1496            depth,
1497            parent_fingerprint,
1498            child_number,
1499            private_key: u.arbitrary()?,
1500            chain_code: u.arbitrary()?,
1501        })
1502    }
1503}
1504
1505#[cfg(test)]
1506mod tests {
1507    use alloc::format;
1508    use alloc::string::ToString;
1509
1510    use hex::hex;
1511
1512    use super::*;
1513
1514    #[test]
1515    fn parse_derivation_path_invalid_format() {
1516        for path in ["n/0'/0", "4/m/5", "0h/0x"] {
1517            assert!(matches!(
1518                path.parse::<RelativeDerivationPath>(),
1519                Err(ParseDerivationPathError::Child(ParseChildNumberError::ParseInt(..))),
1520            ));
1521        }
1522        assert_eq!(
1523            "//3/0'".parse::<RelativeDerivationPath>(),
1524            Err(ParseDerivationPathError::EmptyChild)
1525        );
1526    }
1527
1528    #[test]
1529    fn test_derivation_path_display() {
1530        let path = RelativeDerivationPath::from_str("84'/0'/0'/0/0").unwrap();
1531        assert_eq!(format!("{}", path), "84'/0'/0'/0/0");
1532        assert_eq!(format!("{:#}", path), "84h/0h/0h/0/0");
1533    }
1534
1535    #[test]
1536    fn test_lowerhex_formatting() {
1537        let normal = ChildNumber::from_normal_idx(42).unwrap();
1538        let hardened = ChildNumber::from_hardened_idx(42).unwrap();
1539
1540        assert_eq!(format!("{:x}", normal), "2a");
1541        assert_eq!(format!("{:#x}", normal), "0x2a");
1542
1543        assert_eq!(format!("{:x}", hardened), "2a'");
1544        assert_eq!(format!("{:#x}", hardened), "0x2ah");
1545    }
1546
1547    #[test]
1548    fn test_upperhex_formatting() {
1549        let normal = ChildNumber::from_normal_idx(42).unwrap();
1550        let hardened = ChildNumber::from_hardened_idx(42).unwrap();
1551
1552        assert_eq!(format!("{:X}", normal), "2A");
1553        assert_eq!(format!("{:#X}", normal), "0x2A");
1554
1555        assert_eq!(format!("{:X}", hardened), "2A'");
1556        assert_eq!(format!("{:#X}", hardened), "0x2AH");
1557    }
1558
1559    #[test]
1560    fn test_octal_formatting() {
1561        let normal = ChildNumber::from_normal_idx(42).unwrap();
1562        let hardened = ChildNumber::from_hardened_idx(42).unwrap();
1563
1564        assert_eq!(format!("{:o}", normal), "52");
1565        assert_eq!(format!("{:#o}", normal), "0o52");
1566
1567        assert_eq!(format!("{:o}", hardened), "52'");
1568        assert_eq!(format!("{:#o}", hardened), "0o52h");
1569    }
1570
1571    #[test]
1572    fn test_binary_formatting() {
1573        let normal = ChildNumber::from_normal_idx(42).unwrap();
1574        let hardened = ChildNumber::from_hardened_idx(42).unwrap();
1575
1576        assert_eq!(format!("{:b}", normal), "101010");
1577        assert_eq!(format!("{:#b}", normal), "0b101010");
1578
1579        assert_eq!(format!("{:b}", hardened), "101010'");
1580        assert_eq!(format!("{:#b}", hardened), "0b101010h");
1581    }
1582
1583    #[test]
1584    fn parse_derivation_path_out_of_range() {
1585        let invalid_path = "2147483648";
1586        assert_eq!(
1587            invalid_path.parse::<RelativeDerivationPath>(),
1588            Err(ParseDerivationPathError::Child(ParseChildNumberError::IndexOutOfRange(
1589                IndexOutOfRangeError { index: 2_147_483_648 }
1590            ))),
1591        );
1592    }
1593
1594    #[test]
1595    fn parse_derivation_path_valid_empty() {
1596        // Sanity checks.
1597        assert_eq!(RelativeDerivationPath::default(), RelativeDerivationPath(vec![]));
1598        assert_eq!(
1599            RelativeDerivationPath::default(),
1600            "".parse::<RelativeDerivationPath>().unwrap()
1601        );
1602
1603        // A relative path is empty without an `m`.
1604        assert_eq!("".parse::<RelativeDerivationPath>().unwrap(), RelativeDerivationPath(vec![]));
1605        assert_eq!(
1606            "m".parse::<RelativeDerivationPath>(),
1607            Err(ParseDerivationPathError::UnexpectedMasterPrefix)
1608        );
1609        assert_eq!(
1610            "m/".parse::<RelativeDerivationPath>(),
1611            Err(ParseDerivationPathError::UnexpectedMasterPrefix)
1612        );
1613    }
1614
1615    #[test]
1616    fn parse_derivation_path_valid() {
1617        let valid_paths = [
1618            ("0'", vec![ChildNumber::ZERO_HARDENED]),
1619            ("0'/1", vec![ChildNumber::ZERO_HARDENED, ChildNumber::ONE_NORMAL]),
1620            (
1621                "0h/1/2'",
1622                vec![
1623                    ChildNumber::ZERO_HARDENED,
1624                    ChildNumber::ONE_NORMAL,
1625                    ChildNumber::from_hardened_idx(2).unwrap(),
1626                ],
1627            ),
1628            (
1629                "0'/1/2h/2",
1630                vec![
1631                    ChildNumber::ZERO_HARDENED,
1632                    ChildNumber::ONE_NORMAL,
1633                    ChildNumber::from_hardened_idx(2).unwrap(),
1634                    ChildNumber::from_normal_idx(2).unwrap(),
1635                ],
1636            ),
1637            (
1638                "0'/1/2'/2/1000000000",
1639                vec![
1640                    ChildNumber::ZERO_HARDENED,
1641                    ChildNumber::ONE_NORMAL,
1642                    ChildNumber::from_hardened_idx(2).unwrap(),
1643                    ChildNumber::from_normal_idx(2).unwrap(),
1644                    ChildNumber::from_normal_idx(1_000_000_000).unwrap(),
1645                ],
1646            ),
1647        ];
1648        for (path, expected) in valid_paths {
1649            // Access the inner private field so we don't have to clone expected.
1650            assert_eq!(path.parse::<RelativeDerivationPath>().unwrap().0, expected);
1651        }
1652    }
1653
1654    #[test]
1655    fn parse_absolute_derivation_path() {
1656        let master = "m".parse::<AbsoluteDerivationPath>().unwrap();
1657        assert_eq!(master, AbsoluteDerivationPath::master());
1658        assert_eq!(master.to_string(), "m");
1659        assert!(!master.contains_hardened_child());
1660
1661        let path = "m/0'/1".parse::<AbsoluteDerivationPath>().unwrap();
1662        assert_eq!(path.as_relative(), &"0'/1".parse::<RelativeDerivationPath>().unwrap());
1663        assert_eq!(path.to_string(), "m/0'/1");
1664        assert_eq!(format!("{:#}", path), "m/0h/1");
1665        assert!(path.contains_hardened_child());
1666
1667        assert_eq!(
1668            "".parse::<AbsoluteDerivationPath>(),
1669            Err(ParseDerivationPathError::MissingMasterPrefix)
1670        );
1671        assert_eq!(
1672            "0/1".parse::<AbsoluteDerivationPath>(),
1673            Err(ParseDerivationPathError::MissingMasterPrefix)
1674        );
1675        assert_eq!(
1676            "m/".parse::<AbsoluteDerivationPath>(),
1677            Err(ParseDerivationPathError::EmptyChild)
1678        );
1679    }
1680
1681    #[test]
1682    fn derivation_path_contains_hardened_child() {
1683        assert!(!"".parse::<RelativeDerivationPath>().unwrap().contains_hardened_child());
1684        assert!(!"0/1".parse::<RelativeDerivationPath>().unwrap().contains_hardened_child());
1685        assert!("0'/1".parse::<RelativeDerivationPath>().unwrap().contains_hardened_child());
1686    }
1687
1688    #[test]
1689    fn derivation_path_conversion_index() {
1690        let path = "0h/1/2'".parse::<RelativeDerivationPath>().unwrap();
1691        let numbers: Vec<ChildNumber> = path.clone().into();
1692        let path2: RelativeDerivationPath = numbers.into();
1693        assert_eq!(path, path2);
1694        assert_eq!(&path[..2], &[ChildNumber::ZERO_HARDENED, ChildNumber::ONE_NORMAL]);
1695        let indexed: RelativeDerivationPath = path[..2].into();
1696        assert_eq!(indexed, "0h/1".parse::<RelativeDerivationPath>().unwrap());
1697        assert_eq!(indexed.child(ChildNumber::from_hardened_idx(2).unwrap()), path);
1698    }
1699
1700    #[test]
1701    fn child_number_raw_conversion() {
1702        let normal = ChildNumber::from_normal_idx(42).unwrap();
1703        assert_eq!(normal.to_raw(), 42);
1704        assert_eq!(normal.index(), 42);
1705        assert!(normal.is_normal());
1706        assert!(!normal.is_hardened());
1707        assert_eq!(ChildNumber::from_raw(42), normal);
1708
1709        let hardened = ChildNumber::from_hardened_idx(42).unwrap();
1710        assert_eq!(hardened.to_raw(), HARDENED_FLAG | 42);
1711        assert_eq!(hardened.index(), 42);
1712        assert!(!hardened.is_normal());
1713        assert!(hardened.is_hardened());
1714        assert_eq!(ChildNumber::from_raw(HARDENED_FLAG | 42), hardened);
1715    }
1716
1717    #[test]
1718    fn child_number_index_boundaries() {
1719        let max = HARDENED_FLAG - 1;
1720
1721        assert_eq!(ChildNumber::from_normal_idx(max).unwrap().index(), max);
1722        assert_eq!(ChildNumber::from_hardened_idx(max).unwrap().index(), max);
1723
1724        assert_eq!(
1725            ChildNumber::from_normal_idx(HARDENED_FLAG),
1726            Err(IndexOutOfRangeError { index: HARDENED_FLAG })
1727        );
1728        assert_eq!(
1729            ChildNumber::from_hardened_idx(HARDENED_FLAG),
1730            Err(IndexOutOfRangeError { index: HARDENED_FLAG })
1731        );
1732    }
1733
1734    fn test_path(
1735        network: NetworkKind,
1736        seed: &[u8],
1737        path: &AbsoluteDerivationPath,
1738        expected_sk: &str,
1739        expected_pk: &str,
1740    ) {
1741        let seed = <&Bip32Seed>::try_from(seed).unwrap();
1742        let mut sk = Xpriv::new_master(network, seed);
1743        let mut pk = Xpub::from_xpriv(&sk);
1744        let path = path.as_relative();
1745
1746        // Check derivation convenience method for Xpriv
1747        assert_eq!(&sk.derive_xpriv(path).unwrap().to_string()[..], expected_sk);
1748
1749        // Check derivation convenience method for Xpub, should error
1750        // appropriately if any ChildNumber is hardened
1751        if path.contains_hardened_child() {
1752            assert_eq!(pk.derive_xpub(path), Err(DerivationError::CannotDeriveHardenedChild));
1753        } else {
1754            assert_eq!(&pk.derive_xpub(path).unwrap().to_string()[..], expected_pk);
1755        }
1756
1757        // Derive keys, checking hardened and non-hardened derivation one-by-one
1758        for &num in &path.0 {
1759            sk = sk.ckd_priv(num).unwrap();
1760            if num.is_normal() {
1761                let pk2 = pk.ckd_pub(num).unwrap();
1762                pk = Xpub::from_xpriv(&sk);
1763                assert_eq!(pk, pk2);
1764            } else {
1765                assert_eq!(pk.ckd_pub(num), Err(DerivationError::CannotDeriveHardenedChild));
1766                pk = Xpub::from_xpriv(&sk);
1767            }
1768        }
1769
1770        // Check result against expected base58
1771        assert_eq!(&sk.to_string()[..], expected_sk);
1772        assert_eq!(&pk.to_string()[..], expected_pk);
1773        // Check decoded base58 against result
1774        let decoded_sk = expected_sk.parse::<Xpriv>();
1775        let decoded_pk = expected_pk.parse::<Xpub>();
1776        assert_eq!(Ok(sk), decoded_sk);
1777        assert_eq!(Ok(pk), decoded_pk);
1778    }
1779
1780    #[test]
1781    fn increment() {
1782        let idx = 9_345_497; // randomly generated, I promise
1783        let cn = ChildNumber::from_normal_idx(idx).unwrap();
1784        assert_eq!(cn.increment().ok(), Some(ChildNumber::from_normal_idx(idx + 1).unwrap()));
1785        let cn = ChildNumber::from_hardened_idx(idx).unwrap();
1786        assert_eq!(cn.increment().ok(), Some(ChildNumber::from_hardened_idx(idx + 1).unwrap()));
1787
1788        let max = (1 << 31) - 1;
1789        let cn = ChildNumber::from_normal_idx(max).unwrap();
1790        assert_eq!(cn.increment(), Err(IndexOutOfRangeError { index: 1 << 31 }),);
1791        let cn = ChildNumber::from_hardened_idx(max).unwrap();
1792        assert_eq!(cn.increment(), Err(IndexOutOfRangeError { index: 1 << 31 }),);
1793
1794        let cn = ChildNumber::from_normal_idx(350).unwrap();
1795        let path = "42'".parse::<RelativeDerivationPath>().unwrap();
1796        let mut iter = path.children_from(cn);
1797        assert_eq!(iter.next(), Some("42'/350".parse().unwrap()));
1798        assert_eq!(iter.next(), Some("42'/351".parse().unwrap()));
1799
1800        let path = "42'/350'".parse::<RelativeDerivationPath>().unwrap();
1801        let mut iter = path.normal_children();
1802        assert_eq!(iter.next(), Some("42'/350'/0".parse().unwrap()));
1803        assert_eq!(iter.next(), Some("42'/350'/1".parse().unwrap()));
1804
1805        let path = "42'/350'".parse::<RelativeDerivationPath>().unwrap();
1806        let mut iter = path.hardened_children();
1807        assert_eq!(iter.next(), Some("42'/350'/0'".parse().unwrap()));
1808        assert_eq!(iter.next(), Some("42'/350'/1'".parse().unwrap()));
1809
1810        let cn = ChildNumber::from_hardened_idx(42350).unwrap();
1811        let path = "42'".parse::<RelativeDerivationPath>().unwrap();
1812        let mut iter = path.children_from(cn);
1813        assert_eq!(iter.next(), Some("42'/42350'".parse().unwrap()));
1814        assert_eq!(iter.next(), Some("42'/42351'".parse().unwrap()));
1815
1816        let cn = ChildNumber::from_hardened_idx(max).unwrap();
1817        let path = "42'".parse::<RelativeDerivationPath>().unwrap();
1818        let mut iter = path.children_from(cn);
1819        assert!(iter.next().is_some());
1820        assert!(iter.next().is_none());
1821    }
1822
1823    #[test]
1824    fn vector_1() {
1825        let seed = hex!("000102030405060708090a0b0c0d0e0f");
1826
1827        // m
1828        test_path(NetworkKind::Main, &seed, &"m".parse().unwrap(),
1829                  "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi",
1830                  "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8");
1831
1832        // m/0h
1833        test_path(NetworkKind::Main, &seed, &"m/0h".parse().unwrap(),
1834                  "xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7",
1835                  "xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw");
1836
1837        // m/0h/1
1838        test_path(NetworkKind::Main, &seed, &"m/0h/1".parse().unwrap(),
1839                   "xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs",
1840                   "xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ");
1841
1842        // m/0h/1/2h
1843        test_path(NetworkKind::Main, &seed, &"m/0h/1/2h".parse().unwrap(),
1844                  "xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM",
1845                  "xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5");
1846
1847        // m/0h/1/2h/2
1848        test_path(NetworkKind::Main, &seed, &"m/0h/1/2h/2".parse().unwrap(),
1849                  "xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334",
1850                  "xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV");
1851
1852        // m/0h/1/2h/2/1000000000
1853        test_path(NetworkKind::Main, &seed, &"m/0h/1/2h/2/1000000000".parse().unwrap(),
1854                  "xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76",
1855                  "xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy");
1856    }
1857
1858    #[test]
1859    fn vector_2() {
1860        let seed = hex!("fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542");
1861
1862        // m
1863        test_path(NetworkKind::Main, &seed, &"m".parse().unwrap(),
1864                  "xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U",
1865                  "xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB");
1866
1867        // m/0
1868        test_path(NetworkKind::Main, &seed, &"m/0".parse().unwrap(),
1869                  "xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt",
1870                  "xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH");
1871
1872        // m/0/2147483647h
1873        test_path(NetworkKind::Main, &seed, &"m/0/2147483647h".parse().unwrap(),
1874                  "xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9",
1875                  "xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ85ySDhKiLDBrQSARLq1uNRts8RuJiHjaDMBU4Zn9h8LZNnBC5y4a");
1876
1877        // m/0/2147483647h/1
1878        test_path(NetworkKind::Main, &seed, &"m/0/2147483647h/1".parse().unwrap(),
1879                  "xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef",
1880                  "xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon");
1881
1882        // m/0/2147483647h/1/2147483646h
1883        test_path(NetworkKind::Main, &seed, &"m/0/2147483647h/1/2147483646h".parse().unwrap(),
1884                  "xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc",
1885                  "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL");
1886
1887        // m/0/2147483647h/1/2147483646h/2
1888        test_path(NetworkKind::Main, &seed, &"m/0/2147483647h/1/2147483646h/2".parse().unwrap(),
1889                  "xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j",
1890                  "xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt");
1891    }
1892
1893    #[test]
1894    fn vector_3() {
1895        let seed = hex!("4b381541583be4423346c643850da4b320e46a87ae3d2a4e6da11eba819cd4acba45d239319ac14f863b8d5ab5a0d0c64d2e8a1e7d1457df2e5a3c51c73235be");
1896
1897        // m
1898        test_path(NetworkKind::Main, &seed, &"m".parse().unwrap(),
1899                  "xprv9s21ZrQH143K25QhxbucbDDuQ4naNntJRi4KUfWT7xo4EKsHt2QJDu7KXp1A3u7Bi1j8ph3EGsZ9Xvz9dGuVrtHHs7pXeTzjuxBrCmmhgC6",
1900                  "xpub661MyMwAqRbcEZVB4dScxMAdx6d4nFc9nvyvH3v4gJL378CSRZiYmhRoP7mBy6gSPSCYk6SzXPTf3ND1cZAceL7SfJ1Z3GC8vBgp2epUt13");
1901
1902        // m/0h
1903        test_path(NetworkKind::Main, &seed, &"m/0h".parse().unwrap(),
1904                  "xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L",
1905                  "xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y");
1906    }
1907
1908    #[test]
1909    fn test_reject_xpriv_with_non_zero_byte_at_index_45() {
1910        let mut xpriv = base58::decode_check("xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9").unwrap();
1911
1912        // Modify byte at index 45 to be non-zero (e.g., 1)
1913        xpriv[45] = 1;
1914
1915        let result = Xpriv::decode(&xpriv);
1916        assert!(result.is_err());
1917
1918        match result {
1919            Err(ParseError::InvalidPrivateKeyPrefix) => {}
1920            _ => panic!("Expected InvalidPrivateKeyPrefix error, got {:?}", result),
1921        }
1922    }
1923
1924    #[test]
1925    fn test_reject_xpriv_with_zero_depth_and_non_zero_index() {
1926        let result = "xprv9s21ZrQH4r4TsiLvyLXqM9P7k1K3EYhA1kkD6xuquB5i39AU8KF42acDyL3qsDbU9NmZn6MsGSUYZEsuoePmjzsB3eFKSUEh3Gu1N3cqVUN".parse::<Xpriv>();
1927        assert!(result.is_err());
1928
1929        match result {
1930            Err(ParseError::NonZeroChildNumberForMasterKey) => {}
1931            _ => panic!("Expected NonZeroChildNumberForMasterKey error, got {:?}", result),
1932        }
1933    }
1934
1935    #[test]
1936    fn test_reject_xpriv_with_zero_depth_and_non_zero_parent_fingerprint() {
1937        let result = "xprv9s2SPatNQ9Vc6GTbVMFPFo7jsaZySyzk7L8n2uqKXJen3KUmvQNTuLh3fhZMBoG3G4ZW1N2kZuHEPY53qmbZzCHshoQnNf4GvELZfqTUrcv".parse::<Xpriv>();
1938        assert!(result.is_err());
1939
1940        match result {
1941            Err(ParseError::NonZeroParentFingerprintForMasterKey) => {}
1942            _ => panic!("Expected NonZeroParentFingerprintForMasterKey error, got {:?}", result),
1943        }
1944    }
1945
1946    /// Does round trip test to/from serde value.
1947    #[cfg(feature = "serde")]
1948    macro_rules! serde_round_trip (
1949        ($var:expr) => ({
1950            let encoded = serde_json::to_value(&$var).expect("serde_json failed to encode");
1951            let decoded = serde_json::from_value(encoded).expect("serde_json failed to decode");
1952            assert_eq!($var, decoded);
1953
1954            let encoded = bincode::serialize(&$var).expect("bincode failed to encode");
1955            let decoded = bincode::deserialize(&encoded).expect("bincode failed to decode");
1956            assert_eq!($var, decoded);
1957        })
1958    );
1959
1960    #[test]
1961    #[cfg(feature = "serde")]
1962    pub fn encode_decode_childnumber() {
1963        serde_round_trip!(ChildNumber::ZERO_NORMAL);
1964        serde_round_trip!(ChildNumber::ONE_NORMAL);
1965        serde_round_trip!(ChildNumber::from_normal_idx((1 << 31) - 1).unwrap());
1966        serde_round_trip!(ChildNumber::ZERO_HARDENED);
1967        serde_round_trip!(ChildNumber::ONE_HARDENED);
1968        serde_round_trip!(ChildNumber::from_hardened_idx((1 << 31) - 1).unwrap());
1969    }
1970
1971    #[test]
1972    #[cfg(feature = "serde")]
1973    pub fn encode_decode_derivation_paths() {
1974        serde_round_trip!("0'/1".parse::<RelativeDerivationPath>().unwrap());
1975        serde_round_trip!("m/0'/1".parse::<AbsoluteDerivationPath>().unwrap());
1976    }
1977
1978    #[test]
1979    #[cfg(feature = "serde")]
1980    pub fn encode_fingerprint_chaincode() {
1981        use serde_json;
1982        let fp = Fingerprint::from([1u8, 2, 3, 42]);
1983        #[rustfmt::skip]
1984        let cc = ChainCode::from(
1985            [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]
1986        );
1987
1988        serde_round_trip!(fp);
1989        serde_round_trip!(cc);
1990
1991        assert_eq!("\"0102032a\"", serde_json::to_string(&fp).unwrap());
1992        assert_eq!(
1993            "\"0102030405060708090001020304050607080900010203040506070809000102\"",
1994            serde_json::to_string(&cc).unwrap()
1995        );
1996        assert_eq!("0102032a", fp.to_string());
1997        assert_eq!(
1998            "0102030405060708090001020304050607080900010203040506070809000102",
1999            cc.to_string()
2000        );
2001    }
2002
2003    #[test]
2004    fn fmt_child_number() {
2005        assert_eq!("000005h", &format!("{:#06}", ChildNumber::from_hardened_idx(5).unwrap()));
2006        assert_eq!("5h", &format!("{:#}", ChildNumber::from_hardened_idx(5).unwrap()));
2007        assert_eq!("000005'", &format!("{:06}", ChildNumber::from_hardened_idx(5).unwrap()));
2008        assert_eq!("5'", &format!("{}", ChildNumber::from_hardened_idx(5).unwrap()));
2009        assert_eq!("42", &format!("{}", ChildNumber::from_normal_idx(42).unwrap()));
2010        assert_eq!("000042", &format!("{:06}", ChildNumber::from_normal_idx(42).unwrap()));
2011    }
2012
2013    #[test]
2014    #[should_panic(expected = "Secp256k1(InvalidSecretKey)")]
2015    fn schnorr_broken_privkey_zeros() {
2016        /* this is how we generate key:
2017        let mut sk = secp256k1::key::ONE_KEY;
2018
2019        let zeros = [0u8; 32];
2020        unsafe {
2021            sk.as_mut_ptr().copy_from(zeros.as_ptr(), 32);
2022        }
2023
2024        let xpriv = Xpriv {
2025            network: NetworkKind::Main,
2026            depth: 0,
2027            parent_fingerprint: Default::default(),
2028            child_number: ChildNumber::ZERO_NORMAL,
2029            private_key: sk,
2030            chain_code: ChainCode::from([0u8; 32])
2031        };
2032
2033        println!("{}", xpriv);
2034         */
2035
2036        // Xpriv having secret key set to all zeros
2037        let xpriv_str = "xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzF93Y5wvzdUayhgkkFoicQZcP3y52uPPxFnfoLZB21Teqt1VvEHx";
2038        xpriv_str.parse::<Xpriv>().unwrap();
2039    }
2040
2041    #[test]
2042    #[should_panic(expected = "Secp256k1(InvalidSecretKey)")]
2043    fn schnorr_broken_privkey_ffs() {
2044        // Xpriv having secret key set to all 0xFF's
2045        let xpriv_str = "xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzFAzHGBP2UuGCqWLTAPLcMtD9y5gkZ6Eq3Rjuahrv17fENZ3QzxW";
2046        xpriv_str.parse::<Xpriv>().unwrap();
2047    }
2048
2049    #[test]
2050    fn official_vectors_5() {
2051        let invalid_keys = [
2052            "xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6LBpB85b3D2yc8sfvZU521AAwdZafEz7mnzBBsz4wKY5fTtTQBm",
2053            "xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzFGTQQD3dC4H2D5GBj7vWvSQaaBv5cxi9gafk7NF3pnBju6dwKvH",
2054            "xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6Txnt3siSujt9RCVYsx4qHZGc62TG4McvMGcAUjeuwZdduYEvFn",
2055            "xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzFGpWnsj83BHtEy5Zt8CcDr1UiRXuWCmTQLxEK9vbz5gPstX92JQ",
2056            "xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6N8ZMMXctdiCjxTNq964yKkwrkBJJwpzZS4HS2fxvyYUA4q2Xe4",
2057            "xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzFAzHGBP2UuGCqWLTAPLcMtD9y5gkZ6Eq3Rjuahrv17fEQ3Qen6J",
2058            "xprv9s2SPatNQ9Vc6GTbVMFPFo7jsaZySyzk7L8n2uqKXJen3KUmvQNTuLh3fhZMBoG3G4ZW1N2kZuHEPY53qmbZzCHshoQnNf4GvELZfqTUrcv",
2059            "xpub661no6RGEX3uJkY4bNnPcw4URcQTrSibUZ4NqJEw5eBkv7ovTwgiT91XX27VbEXGENhYRCf7hyEbWrR3FewATdCEebj6znwMfQkhRYHRLpJ",
2060            "xprv9s21ZrQH4r4TsiLvyLXqM9P7k1K3EYhA1kkD6xuquB5i39AU8KF42acDyL3qsDbU9NmZn6MsGSUYZEsuoePmjzsB3eFKSUEh3Gu1N3cqVUN",
2061            "xpub661MyMwAuDcm6CRQ5N4qiHKrJ39Xe1R1NyfouMKTTWcguwVcfrZJaNvhpebzGerh7gucBvzEQWRugZDuDXjNDRmXzSZe4c7mnTK97pTvGS8",
2062            "DMwo58pR1QLEFihHiXPVykYB6fJmsTeHvyTp7hRThAtCX8CvYzgPcn8XnmdfHGMQzT7ayAmfo4z3gY5KfbrZWZ6St24UVf2Qgo6oujFktLHdHY4",
2063            "DMwo58pR1QLEFihHiXPVykYB6fJmsTeHvyTp7hRThAtCX8CvYzgPcn8XnmdfHPmHJiEDXkTiJTVV9rHEBUem2mwVbbNfvT2MTcAqj3nesx8uBf9",
2064            "xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzF93Y5wvzdUayhgkkFoicQZcP3y52uPPxFnfoLZB21Teqt1VvEHx",
2065            "xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzFAzHGBP2UuGCqWLTAPLcMtD5SDKr24z3aiUvKr9bJpdrcLg1y3G",
2066            "xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6Q5JXayek4PRsn35jii4veMimro1xefsM58PgBMrvdYre8QyULY",
2067            "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHL",
2068        ];
2069        for key in invalid_keys {
2070            if key.starts_with("xpub") {
2071                key.parse::<Xpub>().unwrap_err();
2072            } else {
2073                key.parse::<Xpriv>().unwrap_err();
2074            }
2075        }
2076    }
2077
2078    #[test]
2079    fn bip32_seed_rejects_out_of_range_length() {
2080        for len in [0usize, 1, 15, 65, 128, 1024] {
2081            let bytes = vec![0u8; len];
2082            assert_eq!(
2083                <&Bip32Seed>::try_from(bytes.as_slice()),
2084                Err(InvalidSeedLengthError { length: len }),
2085            );
2086        }
2087    }
2088
2089    #[test]
2090    fn bip32_seed_accepts_in_range_length() {
2091        for len in [16usize, 17, 32, 63, 64] {
2092            let bytes = vec![0u8; len];
2093            let seed = <&Bip32Seed>::try_from(bytes.as_slice()).unwrap();
2094            assert_eq!(seed.as_bytes().len(), len);
2095        }
2096
2097        let arr32 = [7u8; 32];
2098        assert_eq!(<&Bip32Seed>::from(&arr32).as_bytes(), &arr32[..]);
2099
2100        let arr64 = [9u8; 64];
2101        assert_eq!(<&Bip32Seed>::from(&arr64).as_bytes(), &arr64[..]);
2102    }
2103
2104    #[test]
2105    fn bip32_seed_debug_redacts_bytes() {
2106        let arr = [0xABu8; 32];
2107        let seed: &Bip32Seed = (&arr).into();
2108        let rendered = alloc::format!("{:?}", seed);
2109        assert_eq!(rendered, "Bip32Seed(sha256=9a2db2e2)");
2110    }
2111}