diff --git a/bitcoin/examples/bip32.rs b/bitcoin/examples/bip32.rs index fee45dfd8..ff95e7b6a 100644 --- a/bitcoin/examples/bip32.rs +++ b/bitcoin/examples/bip32.rs @@ -48,7 +48,7 @@ fn main() { // generate first receiving address at m/0/0 // manually creating indexes this time - let zero = ChildNumber::from_normal_idx(0).unwrap(); + let zero = ChildNumber::ZERO_NORMAL; let public_key = xpub.derive_pub(&secp, &[zero, zero]).unwrap().public_key; let address = Address::p2wpkh(CompressedPublicKey(public_key), KnownHrp::Mainnet); println!("First receiving address: {}", address); diff --git a/bitcoin/examples/ecdsa-psbt-simple.rs b/bitcoin/examples/ecdsa-psbt-simple.rs index af6708caf..5211cc511 100644 --- a/bitcoin/examples/ecdsa-psbt-simple.rs +++ b/bitcoin/examples/ecdsa-psbt-simple.rs @@ -61,7 +61,7 @@ fn get_external_address_xpriv( let derivation_path = BIP84_DERIVATION_PATH.into_derivation_path().expect("valid derivation path"); let child_xpriv = master_xpriv.derive_priv(secp, &derivation_path); - let external_index = ChildNumber::from_normal_idx(0).unwrap(); + let external_index = ChildNumber::ZERO_NORMAL; let idx = ChildNumber::from_normal_idx(index).expect("valid index number"); child_xpriv.derive_priv(secp, &[external_index, idx]) @@ -76,7 +76,7 @@ fn get_internal_address_xpriv( let derivation_path = BIP84_DERIVATION_PATH.into_derivation_path().expect("valid derivation path"); let child_xpriv = master_xpriv.derive_priv(secp, &derivation_path); - let internal_index = ChildNumber::from_normal_idx(1).unwrap(); + let internal_index = ChildNumber::ONE_NORMAL; let idx = ChildNumber::from_normal_idx(index).expect("valid index number"); child_xpriv.derive_priv(secp, &[internal_index, idx]) diff --git a/bitcoin/examples/ecdsa-psbt.rs b/bitcoin/examples/ecdsa-psbt.rs index bc842bdbe..b09121f16 100644 --- a/bitcoin/examples/ecdsa-psbt.rs +++ b/bitcoin/examples/ecdsa-psbt.rs @@ -255,7 +255,7 @@ impl WatchOnly { &self, secp: &Secp256k1, ) -> Result<(CompressedPublicKey, Address, DerivationPath)> { - let path = [ChildNumber::from_normal_idx(1)?, ChildNumber::from_normal_idx(0)?]; + let path = [ChildNumber::ONE_NORMAL, ChildNumber::ZERO_NORMAL]; let derived = self.account_0_xpub.derive_pub(secp, &path)?; let pk = derived.to_pub(); diff --git a/bitcoin/examples/taproot-psbt-simple.rs b/bitcoin/examples/taproot-psbt-simple.rs index 7ea13d443..3a3003200 100644 --- a/bitcoin/examples/taproot-psbt-simple.rs +++ b/bitcoin/examples/taproot-psbt-simple.rs @@ -60,7 +60,7 @@ fn get_external_address_xpriv( let derivation_path = BIP86_DERIVATION_PATH.into_derivation_path().expect("valid derivation path"); let child_xpriv = master_xpriv.derive_priv(secp, &derivation_path); - let external_index = ChildNumber::from_normal_idx(0).unwrap(); + let external_index = ChildNumber::ZERO_NORMAL; let idx = ChildNumber::from_normal_idx(index).expect("valid index number"); child_xpriv.derive_priv(secp, &[external_index, idx]) @@ -75,7 +75,7 @@ fn get_internal_address_xpriv( let derivation_path = BIP86_DERIVATION_PATH.into_derivation_path().expect("valid derivation path"); let child_xpriv = master_xpriv.derive_priv(secp, &derivation_path); - let internal_index = ChildNumber::from_normal_idx(1).unwrap(); + let internal_index = ChildNumber::ONE_NORMAL; let idx = ChildNumber::from_normal_idx(index).expect("valid index number"); child_xpriv.derive_priv(secp, &[internal_index, idx]) diff --git a/bitcoin/examples/taproot-psbt.rs b/bitcoin/examples/taproot-psbt.rs index 49ea6ec45..1c5b4d411 100644 --- a/bitcoin/examples/taproot-psbt.rs +++ b/bitcoin/examples/taproot-psbt.rs @@ -360,7 +360,7 @@ impl BenefactorWallet { current_spend_info: None, next_psbt: None, secp: Secp256k1::new(), - next: ChildNumber::from_normal_idx(0).expect("Zero is a valid child number"), + next: ChildNumber::ZERO_NORMAL, }) } diff --git a/bitcoin/src/bip32.rs b/bitcoin/src/bip32.rs index 6199b3a34..6ace63289 100644 --- a/bitcoin/src/bip32.rs +++ b/bitcoin/src/bip32.rs @@ -126,8 +126,19 @@ pub enum ChildNumber { index: u32, }, } - impl ChildNumber { + /// Normal child number with index 0. + pub const ZERO_NORMAL: Self = ChildNumber::Normal { index: 0 }; + + /// Normal child number with index 1. + pub const ONE_NORMAL: Self = ChildNumber::Normal { index: 1 }; + + /// Hardened child number with index 0. + pub const ZERO_HARDENED: Self = ChildNumber::Hardened { index: 0 }; + + /// Hardened child number with index 1. + pub const ONE_HARDENED: Self = ChildNumber::Hardened { index: 1 }; + /// Create a [`Normal`] from an index, returns an error if the index is not within /// [0, 2^31 - 1]. /// @@ -417,8 +428,8 @@ impl DerivationPath { /// /// let deriv_1 = base.extend(DerivationPath::from_str("0/1").unwrap()); /// let deriv_2 = base.extend(&[ - /// ChildNumber::from_normal_idx(0).unwrap(), - /// ChildNumber::from_normal_idx(1).unwrap() + /// ChildNumber::ZERO_NORMAL, + /// ChildNumber::ONE_NORMAL /// ]); /// /// assert_eq!(deriv_1, deriv_2); @@ -564,7 +575,7 @@ impl Xpriv { network: network.into(), depth: 0, parent_fingerprint: Default::default(), - child_number: ChildNumber::from_normal_idx(0)?, + child_number: ChildNumber::ZERO_NORMAL, private_key: secp256k1::SecretKey::from_slice(&hmac_result.as_ref()[..32])?, chain_code: ChainCode::from_hmac(hmac_result), }) @@ -919,23 +930,16 @@ mod tests { assert_eq!(DerivationPath::from_str("m/").unwrap(), DerivationPath(vec![])); assert_eq!(DerivationPath::from_str("").unwrap(), DerivationPath(vec![])); - assert_eq!( - DerivationPath::from_str("0'"), - Ok(vec![ChildNumber::from_hardened_idx(0).unwrap()].into()) - ); + assert_eq!(DerivationPath::from_str("0'"), Ok(vec![ChildNumber::ZERO_HARDENED].into())); assert_eq!( DerivationPath::from_str("0'/1"), - Ok(vec![ - ChildNumber::from_hardened_idx(0).unwrap(), - ChildNumber::from_normal_idx(1).unwrap() - ] - .into()) + Ok(vec![ChildNumber::ZERO_HARDENED, ChildNumber::ONE_NORMAL].into()) ); assert_eq!( DerivationPath::from_str("0h/1/2'"), Ok(vec![ - ChildNumber::from_hardened_idx(0).unwrap(), - ChildNumber::from_normal_idx(1).unwrap(), + ChildNumber::ZERO_HARDENED, + ChildNumber::ONE_NORMAL, ChildNumber::from_hardened_idx(2).unwrap(), ] .into()) @@ -943,16 +947,16 @@ mod tests { assert_eq!( DerivationPath::from_str("0'/1/2h/2"), Ok(vec![ - ChildNumber::from_hardened_idx(0).unwrap(), - ChildNumber::from_normal_idx(1).unwrap(), + ChildNumber::ZERO_HARDENED, + ChildNumber::ONE_NORMAL, ChildNumber::from_hardened_idx(2).unwrap(), ChildNumber::from_normal_idx(2).unwrap(), ] .into()) ); let want = DerivationPath::from(vec![ - ChildNumber::from_hardened_idx(0).unwrap(), - ChildNumber::from_normal_idx(1).unwrap(), + ChildNumber::ZERO_HARDENED, + ChildNumber::ONE_NORMAL, ChildNumber::from_hardened_idx(2).unwrap(), ChildNumber::from_normal_idx(2).unwrap(), ChildNumber::from_normal_idx(1000000000).unwrap(), @@ -975,10 +979,7 @@ mod tests { let numbers: Vec = path.clone().into(); let path2: DerivationPath = numbers.into(); assert_eq!(path, path2); - assert_eq!( - &path[..2], - &[ChildNumber::from_hardened_idx(0).unwrap(), ChildNumber::from_normal_idx(1).unwrap()] - ); + assert_eq!(&path[..2], &[ChildNumber::ZERO_HARDENED, ChildNumber::ONE_NORMAL]); let indexed: DerivationPath = path[..2].into(); assert_eq!(indexed, DerivationPath::from_str("0h/1").unwrap()); assert_eq!(indexed.child(ChildNumber::from_hardened_idx(2).unwrap()), path); @@ -1166,11 +1167,11 @@ mod tests { #[test] #[cfg(feature = "serde")] pub fn encode_decode_childnumber() { - serde_round_trip!(ChildNumber::from_normal_idx(0).unwrap()); - serde_round_trip!(ChildNumber::from_normal_idx(1).unwrap()); + serde_round_trip!(ChildNumber::ZERO_NORMAL); + serde_round_trip!(ChildNumber::ONE_NORMAL); serde_round_trip!(ChildNumber::from_normal_idx((1 << 31) - 1).unwrap()); - serde_round_trip!(ChildNumber::from_hardened_idx(0).unwrap()); - serde_round_trip!(ChildNumber::from_hardened_idx(1).unwrap()); + serde_round_trip!(ChildNumber::ZERO_HARDENED); + serde_round_trip!(ChildNumber::ONE_HARDENED); serde_round_trip!(ChildNumber::from_hardened_idx((1 << 31) - 1).unwrap()); } diff --git a/bitcoin/src/psbt/mod.rs b/bitcoin/src/psbt/mod.rs index f8cc1a084..fa50fde65 100644 --- a/bitcoin/src/psbt/mod.rs +++ b/bitcoin/src/psbt/mod.rs @@ -1356,8 +1356,8 @@ mod tests { let fprint = sk.fingerprint(secp); let dpath: Vec = vec![ - ChildNumber::from_normal_idx(0).unwrap(), - ChildNumber::from_normal_idx(1).unwrap(), + ChildNumber::ZERO_NORMAL, + ChildNumber::ONE_NORMAL, ChildNumber::from_normal_idx(2).unwrap(), ChildNumber::from_normal_idx(4).unwrap(), ChildNumber::from_normal_idx(42).unwrap(),