From d0e0e9462046a49f8f8efba4f120b6613bc27c03 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sun, 30 Jul 2023 16:59:09 +0200 Subject: [PATCH] bip32: fix FromStr implementations --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- std/src/index.rs | 19 +++++++++++-------- std/src/path.rs | 8 ++++---- std/src/xpub.rs | 18 +++++++++++++++--- 5 files changed, 33 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index db3d1f1..8962c88 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "amplify" -version = "4.0.0" +version = "4.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26966af46e0d200e8bf2b7f16230997c1c3f2d141bc27ccc091c012ed527b58" +checksum = "4707ab08f19a25ba492cbf61713591b7f022b54ee188f35457e6de22f367df4a" dependencies = [ "amplify_apfloat", "amplify_derive", diff --git a/Cargo.toml b/Cargo.toml index 59c11f3..a342ef4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ edition = "2021" license = "Apache-2.0" [workspace.dependencies] -amplify = "4.0.0" +amplify = "4.0.1" bitcoin_hashes = "0.12.0" bech32 = "0.9.1" bp-primitives = "0.10.6" diff --git a/std/src/index.rs b/std/src/index.rs index f947edd..e251882 100644 --- a/std/src/index.rs +++ b/std/src/index.rs @@ -363,13 +363,13 @@ impl Idx for HardenedIndex { const MAX: Self = Self(u32::MAX); #[inline] - fn from_child_number(index: impl Into) -> Self { Self(index.into() as u32) } + fn from_child_number(child_no: impl Into) -> Self { Self(child_no.into() as u32) } #[inline] - fn try_from_child_number(index: impl Into) -> Result { - let index = index.into(); + fn try_from_child_number(child_no: impl Into) -> Result { + let index = child_no.into(); if index < HARDENED_INDEX_BOUNDARY { - Ok(Self(index - HARDENED_INDEX_BOUNDARY)) + Ok(Self(index)) } else { Err(IndexError { what: "child number", @@ -386,10 +386,13 @@ impl Idx for HardenedIndex { fn child_number(&self) -> u32 { self.0 } #[inline] - fn try_from_index(value: u32) -> Result { - Self::try_from_child_number(value - HARDENED_INDEX_BOUNDARY).map_err(|_| IndexError { + fn try_from_index(child_no: u32) -> Result { + if child_no < HARDENED_INDEX_BOUNDARY { + return Ok(Self(child_no)); + } + Self::try_from_child_number(child_no - HARDENED_INDEX_BOUNDARY).map_err(|_| IndexError { what: "index", - invalid: value, + invalid: child_no, start: HARDENED_INDEX_BOUNDARY, end: u32::MAX, }) @@ -448,7 +451,7 @@ impl DerivationIndex { pub fn from_index(value: u32) -> Self { match value { 0..=0x0FFFFFFF => NormalIndex(value).into(), - _ => HardenedIndex(value).into(), + _ => HardenedIndex(value - HARDENED_INDEX_BOUNDARY).into(), } } diff --git a/std/src/path.rs b/std/src/path.rs index 5439e13..cf7e6f8 100644 --- a/std/src/path.rs +++ b/std/src/path.rs @@ -65,11 +65,11 @@ where IndexParseError: From<::Err> { type Err = DerivationParseError; - fn from_str(s: &str) -> Result { - if !s.starts_with('/') { - return Err(DerivationParseError::InvalidFormat(s.to_owned())); + fn from_str(mut s: &str) -> Result { + if s.starts_with('/') { + s = &s[1..]; } - let inner = s[1..] + let inner = s .split('/') .map(I::from_str) .collect::, I::Err>>() diff --git a/std/src/xpub.rs b/std/src/xpub.rs index 7a59efe..e2337dd 100644 --- a/std/src/xpub.rs +++ b/std/src/xpub.rs @@ -350,13 +350,25 @@ impl FromStr for XpubDescriptor { } if !d.origin.derivation.is_empty() { let network = if d.xpub.testnet { HardenedIndex::ONE } else { HardenedIndex::ZERO }; - if d.origin.derivation.last() != Some(&network.into()) { - return Err(XpubParseError::DepthMismatch); + if d.origin.derivation.get(1) != Some(&network.into()) { + return Err(XpubParseError::NetworkMismatch); } if d.origin.derivation.last() != Some(&d.xpub.meta.child_number) { - return Err(XpubParseError::DepthMismatch); + return Err(XpubParseError::ParentMismatch); } } Ok(d) } } + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn display_from_str() { + let s = "[643a7adc/86h/1h/0h]tpubDCNiWHaiSkgnQjuhsg9kjwaUzaxQjUcmhagvYzqQ3TYJTgFGJstVaqnu4yhtFktBhCVFmBNLQ5sN53qKzZbMksm3XEyGJsEhQPfVZdWmTE2"; + let xpub = XpubDescriptor::from_str(s).unwrap(); + assert_eq!(s, xpub.to_string()); + } +}