1use 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] #[doc(no_inline)]
23pub use self::error::{
24 DerivationError, IndexOutOfRangeError, InvalidBase58PayloadLengthError,
25 ParseChildNumberError, ParseDerivationPathError, ParseError, InvalidSeedLengthError
26};
27
28const VERSION_BYTES_MAINNET_PUBLIC: [u8; 4] = [0x04, 0x88, 0xB2, 0x1E];
30const VERSION_BYTES_MAINNET_PRIVATE: [u8; 4] = [0x04, 0x88, 0xAD, 0xE4];
32const VERSION_BYTES_TESTNETS_PUBLIC: [u8; 4] = [0x04, 0x35, 0x87, 0xCF];
34const VERSION_BYTES_TESTNETS_PRIVATE: [u8; 4] = [0x04, 0x35, 0x83, 0x94];
36
37#[deprecated(since = "0.31.0", note = "use `Xpub` instead")]
39pub type ExtendedPubKey = Xpub;
40
41#[deprecated(since = "0.31.0", note = "use `Xpriv` instead")]
43pub type ExtendedPrivKey = Xpriv;
44
45#[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 #[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#[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 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 pub struct Bip32Seed([u8]);
83
84 impl Bip32Seed {
85 const fn from_slice_unchecked(bytes: &_) -> &Self;
86 }
87}
88
89impl Bip32Seed {
90 pub const MIN_LEN: usize = 16;
92 pub const MAX_LEN: usize = 64;
94
95 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#[derive(Copy, Clone, PartialEq, Eq)]
159#[cfg_attr(feature = "std", derive(Debug))]
160pub struct Xpriv {
161 pub network: NetworkKind,
163 pub depth: u8,
165 pub parent_fingerprint: Fingerprint,
167 pub child_number: ChildNumber,
169 pub private_key: secp256k1::SecretKey,
171 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#[derive(Copy, Clone, PartialEq, Eq, Debug, PartialOrd, Ord, Hash)]
193pub struct Xpub {
194 pub network: NetworkKind,
196 pub depth: u8,
198 pub parent_fingerprint: Fingerprint,
200 pub child_number: ChildNumber,
202 pub public_key: secp256k1::PublicKey,
204 pub chain_code: ChainCode,
206}
207#[cfg(feature = "serde")]
208internals::serde_string_impl!(Xpub, "a BIP-0032 extended public key");
209
210const HARDENED_FLAG: u32 = 1 << 31;
212
213const MAX_CHILD_INDEX: u32 = HARDENED_FLAG - 1;
215
216#[derive(Copy, Clone, PartialEq, Eq, Debug, PartialOrd, Ord, Hash)]
221pub struct ChildNumber(u32);
222
223impl ChildNumber {
224 pub const ZERO_NORMAL: Self = Self(0);
226
227 pub const ONE_NORMAL: Self = Self(1);
229
230 pub const ZERO_HARDENED: Self = Self(HARDENED_FLAG);
232
233 pub const ONE_HARDENED: Self = Self(HARDENED_FLAG | 1);
235
236 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 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 pub fn from_raw(raw: u32) -> Self { Self(raw) }
267
268 pub fn to_raw(self) -> u32 { self.0 }
273
274 pub fn index(self) -> u32 { self.0 & MAX_CHILD_INDEX }
276
277 pub fn is_normal(&self) -> bool { !self.is_hardened() }
279
280 pub fn is_hardened(&self) -> bool { self.0 & HARDENED_FLAG != 0 }
282
283 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 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#[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#[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 pub fn master() -> Self { Self(RelativeDerivationPath::default()) }
497
498 pub fn is_master(&self) -> bool { self.0.is_empty() }
500
501 pub fn as_relative(&self) -> &RelativeDerivationPath { &self.0 }
503
504 pub fn into_relative(self) -> RelativeDerivationPath { self.0 }
506
507 pub fn len(&self) -> usize { self.0.len() }
509
510 pub fn is_empty(&self) -> bool { self.0.is_empty() }
512
513 pub fn contains_hardened_child(&self) -> bool { self.0.contains_hardened_child() }
515
516 #[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
565pub struct RelativeDerivationPathIterator<'a> {
570 base: &'a RelativeDerivationPath,
571 next_child: Option<ChildNumber>,
572}
573
574impl<'a> RelativeDerivationPathIterator<'a> {
575 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 pub fn len(&self) -> usize { self.0.len() }
594
595 pub fn is_empty(&self) -> bool { self.0.is_empty() }
597
598 pub fn contains_hardened_child(&self) -> bool { self.0.iter().any(ChildNumber::is_hardened) }
600
601 #[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 #[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 pub fn children_from(&self, cn: ChildNumber) -> RelativeDerivationPathIterator<'_> {
620 RelativeDerivationPathIterator::start_from(self, cn)
621 }
622
623 pub fn normal_children(&self) -> RelativeDerivationPathIterator<'_> {
625 RelativeDerivationPathIterator::start_from(self, ChildNumber::ZERO_NORMAL)
626 }
627
628 pub fn hardened_children(&self) -> RelativeDerivationPathIterator<'_> {
630 RelativeDerivationPathIterator::start_from(self, ChildNumber::ZERO_HARDENED)
631 }
632
633 #[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 pub fn to_u32_vec(&self) -> Vec<u32> { self.into_iter().map(|&el| el.to_raw()).collect() }
667
668 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
708pub type KeySource = (Fingerprint, RelativeDerivationPath);
711
712impl Xpriv {
713 #[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 #[deprecated(since = "TBD", note = "use `to_private_key()` instead")]
739 pub fn to_priv(self) -> PrivateKey { self.to_private_key() }
740
741 pub fn to_private_key(self) -> PrivateKey { PrivateKey::from_secp(self.private_key) }
743
744 pub fn to_xpub(self) -> Xpub { Xpub::from_xpriv(&self) }
746
747 pub fn to_keypair(self) -> Keypair { Keypair::from_private_key(&self.to_private_key()) }
750
751 #[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 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 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 engine.input(&secp256k1::PublicKey::from_secret_key(&self.private_key).serialize()[..]);
786 } else {
787 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 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 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 pub fn identifier(&self) -> XKeyIdentifier { Xpub::from_xpriv(self).identifier() }
866
867 pub fn fingerprint(&self) -> Fingerprint {
869 self.identifier().as_byte_array().sub_array::<0, 4>().into()
870 }
871}
872
873impl Xpub {
874 #[deprecated(since = "TBD", note = "use `from_xpriv()` instead")]
876 pub fn from_priv(sk: &Xpriv) -> Self { Self::from_xpriv(sk) }
877
878 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 #[deprecated(since = "TBD", note = "use `to_public_key()` instead")]
892 pub fn to_pub(self) -> FullPublicKey { self.to_public_key() }
893
894 pub fn to_public_key(self) -> FullPublicKey { FullPublicKey::from_secp(self.public_key) }
896
897 #[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 pub fn to_x_only_public_key(self) -> XOnlyPublicKey { XOnlyPublicKey::from(self.public_key) }
905
906 #[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 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 #[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 #[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 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 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 pub fn identifier(&self) -> XKeyIdentifier {
1033 XKeyIdentifier(hash160::Hash::hash(&self.public_key.serialize()))
1034 }
1035
1036 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
1090struct Common {
1092 network: [u8; 4],
1093 depth: u8,
1094 parent_fingerprint: Fingerprint,
1095 child_number: ChildNumber,
1096 chain_code: ChainCode,
1097 key: [u8; 33],
1099}
1100
1101impl Common {
1102 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
1142pub mod error {
1144 use core::convert::Infallible;
1145 use core::fmt;
1146
1147 use internals::write_err;
1148
1149 #[derive(Debug, Clone, PartialEq, Eq)]
1151 #[non_exhaustive]
1152 pub enum ParseError {
1153 Secp256k1(secp256k1::Error),
1155 UnknownVersion([u8; 4]),
1157 WrongExtendedKeyLength(usize),
1159 Base58(base58::Error),
1161 InvalidBase58PayloadLength(InvalidBase58PayloadLengthError),
1163 InvalidPrivateKeyPrefix,
1165 NonZeroParentFingerprintForMasterKey,
1167 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 #[derive(Debug, Clone, PartialEq, Eq)]
1225 #[non_exhaustive]
1226 pub enum DerivationError {
1227 CannotDeriveHardenedChild,
1231 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 #[derive(Debug, Clone, PartialEq, Eq)]
1267 #[non_exhaustive]
1268 pub struct IndexOutOfRangeError {
1269 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 #[derive(Debug, Clone, PartialEq, Eq)]
1293 pub enum ParseChildNumberError {
1294 IndexOutOfRange(IndexOutOfRangeError),
1296 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 #[derive(Debug, Clone, PartialEq, Eq)]
1325 pub enum ParseDerivationPathError {
1326 Child(ParseChildNumberError),
1328 EmptyChild,
1330 MissingMasterPrefix,
1332 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 #[derive(Debug, Clone, PartialEq, Eq)]
1369 pub struct InvalidBase58PayloadLengthError {
1370 pub(crate) length: usize,
1372 }
1373
1374 impl InvalidBase58PayloadLengthError {
1375 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 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
1403 pub struct InvalidSeedLengthError {
1404 pub(crate) length: usize,
1405 }
1406
1407 impl InvalidSeedLengthError {
1408 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 assert_eq!(RelativeDerivationPath::default(), RelativeDerivationPath(vec![]));
1598 assert_eq!(
1599 RelativeDerivationPath::default(),
1600 "".parse::<RelativeDerivationPath>().unwrap()
1601 );
1602
1603 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 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 assert_eq!(&sk.derive_xpriv(path).unwrap().to_string()[..], expected_sk);
1748
1749 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 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 assert_eq!(&sk.to_string()[..], expected_sk);
1772 assert_eq!(&pk.to_string()[..], expected_pk);
1773 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; 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 test_path(NetworkKind::Main, &seed, &"m".parse().unwrap(),
1829 "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi",
1830 "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8");
1831
1832 test_path(NetworkKind::Main, &seed, &"m/0h".parse().unwrap(),
1834 "xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7",
1835 "xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw");
1836
1837 test_path(NetworkKind::Main, &seed, &"m/0h/1".parse().unwrap(),
1839 "xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs",
1840 "xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ");
1841
1842 test_path(NetworkKind::Main, &seed, &"m/0h/1/2h".parse().unwrap(),
1844 "xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM",
1845 "xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5");
1846
1847 test_path(NetworkKind::Main, &seed, &"m/0h/1/2h/2".parse().unwrap(),
1849 "xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334",
1850 "xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV");
1851
1852 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 test_path(NetworkKind::Main, &seed, &"m".parse().unwrap(),
1864 "xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U",
1865 "xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB");
1866
1867 test_path(NetworkKind::Main, &seed, &"m/0".parse().unwrap(),
1869 "xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt",
1870 "xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH");
1871
1872 test_path(NetworkKind::Main, &seed, &"m/0/2147483647h".parse().unwrap(),
1874 "xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9",
1875 "xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ85ySDhKiLDBrQSARLq1uNRts8RuJiHjaDMBU4Zn9h8LZNnBC5y4a");
1876
1877 test_path(NetworkKind::Main, &seed, &"m/0/2147483647h/1".parse().unwrap(),
1879 "xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef",
1880 "xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon");
1881
1882 test_path(NetworkKind::Main, &seed, &"m/0/2147483647h/1/2147483646h".parse().unwrap(),
1884 "xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc",
1885 "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL");
1886
1887 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 test_path(NetworkKind::Main, &seed, &"m".parse().unwrap(),
1899 "xprv9s21ZrQH143K25QhxbucbDDuQ4naNntJRi4KUfWT7xo4EKsHt2QJDu7KXp1A3u7Bi1j8ph3EGsZ9Xvz9dGuVrtHHs7pXeTzjuxBrCmmhgC6",
1900 "xpub661MyMwAqRbcEZVB4dScxMAdx6d4nFc9nvyvH3v4gJL378CSRZiYmhRoP7mBy6gSPSCYk6SzXPTf3ND1cZAceL7SfJ1Z3GC8vBgp2epUt13");
1901
1902 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 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 #[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 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 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}