From 4354f37f5183f13f1d7cb1fc57d5d276a4a568ed Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Tue, 28 Nov 2023 10:40:08 +1100 Subject: [PATCH] Use NetworkKind in bip32 module BIP-32 only differentiates between mainnet and some testnet when encoding and decoding xpubs and xprivs. As such we can use the new `NetworkKind` type instead of `Network` throughout the `bip32` module. --- bitcoin/examples/bip32.rs | 11 +++---- bitcoin/src/bip32.rs | 63 ++++++++++++++++++------------------- bitcoin/src/psbt/mod.rs | 3 +- bitcoin/src/sign_message.rs | 3 +- bitcoin/tests/psbt.rs | 8 ++--- 5 files changed, 40 insertions(+), 48 deletions(-) diff --git a/bitcoin/examples/bip32.rs b/bitcoin/examples/bip32.rs index 98f19673..de027003 100644 --- a/bitcoin/examples/bip32.rs +++ b/bitcoin/examples/bip32.rs @@ -8,7 +8,7 @@ use bitcoin::bip32::{ChildNumber, DerivationPath, Xpriv, Xpub}; use bitcoin::hex::FromHex; use bitcoin::secp256k1::ffi::types::AlignedType; use bitcoin::secp256k1::Secp256k1; -use bitcoin::CompressedPublicKey; +use bitcoin::{Network, NetworkKind, CompressedPublicKey}; fn main() { // This example derives root xprv from a 32-byte seed, @@ -26,10 +26,7 @@ fn main() { let seed_hex = &args[1]; println!("Seed: {}", seed_hex); - - // default network as mainnet - let network = bitcoin::Network::Bitcoin; - println!("Network: {:?}", network); + println!("Using mainnet network"); let seed = Vec::from_hex(seed_hex).unwrap(); @@ -39,7 +36,7 @@ fn main() { let secp = Secp256k1::preallocated_new(buf.as_mut_slice()).unwrap(); // calculate root key from seed - let root = Xpriv::new_master(network, &seed).unwrap(); + let root = Xpriv::new_master(NetworkKind::Main, &seed).unwrap(); println!("Root key: {}", root); // derive child xpub @@ -53,6 +50,6 @@ fn main() { // manually creating indexes this time let zero = ChildNumber::from_normal_idx(0).unwrap(); let public_key = xpub.derive_pub(&secp, &[zero, zero]).unwrap().public_key; - let address = Address::p2wpkh(&CompressedPublicKey(public_key), network); + let address = Address::p2wpkh(&CompressedPublicKey(public_key), Network::Bitcoin); println!("First receiving address: {}", address); } diff --git a/bitcoin/src/bip32.rs b/bitcoin/src/bip32.rs index 6db12c44..5bda3575 100644 --- a/bitcoin/src/bip32.rs +++ b/bitcoin/src/bip32.rs @@ -21,7 +21,7 @@ use serde; use crate::base58; use crate::crypto::key::{self, Keypair, PrivateKey, CompressedPublicKey}; use crate::internal_macros::impl_bytes_newtype; -use crate::network::Network; +use crate::network::NetworkKind; use crate::prelude::*; /// Version bytes for extended public keys on the Bitcoin network. @@ -69,7 +69,7 @@ hash_newtype! { #[cfg_attr(feature = "std", derive(Debug))] pub struct Xpriv { /// The network this key is to be used on - pub network: Network, + pub network: NetworkKind, /// How many derivations this key is from the master (which is 0) pub depth: u8, /// Fingerprint of the parent key (0 for master) @@ -101,8 +101,8 @@ impl fmt::Debug for Xpriv { /// Extended public key #[derive(Copy, Clone, PartialEq, Eq, Debug, PartialOrd, Ord, Hash)] pub struct Xpub { - /// The network this key is to be used on - pub network: Network, + /// The network kind this key is to be used on + pub network: NetworkKind, /// How many derivations this key is from the master (which is 0) pub depth: u8, /// Fingerprint of the parent key @@ -558,13 +558,13 @@ impl From for Error { impl Xpriv { /// Construct a new master key from a seed value - pub fn new_master(network: Network, seed: &[u8]) -> Result { + pub fn new_master(network: impl Into, seed: &[u8]) -> Result { let mut hmac_engine: HmacEngine = HmacEngine::new(b"Bitcoin seed"); hmac_engine.input(seed); let hmac_result: Hmac = Hmac::from_engine(hmac_engine); Ok(Xpriv { - network, + network: network.into(), depth: 0, parent_fingerprint: Default::default(), child_number: ChildNumber::from_normal_idx(0)?, @@ -575,7 +575,7 @@ impl Xpriv { /// Constructs ECDSA compressed private key matching internal secret key representation. pub fn to_priv(self) -> PrivateKey { - PrivateKey { compressed: true, network: self.network.into(), inner: self.private_key } + PrivateKey { compressed: true, network: self.network, inner: self.private_key } } /// Constructs BIP340 keypair for Schnorr signatures and Taproot use matching the internal @@ -645,9 +645,9 @@ impl Xpriv { } let network = if data.starts_with(&VERSION_BYTES_MAINNET_PRIVATE) { - Network::Bitcoin + NetworkKind::Main } else if data.starts_with(&VERSION_BYTES_TESTNETS_PRIVATE) { - Network::Testnet + NetworkKind::Test } else { let (b0, b1, b2, b3) = (data[0], data[1], data[2], data[3]); return Err(Error::UnknownVersion([b0, b1, b2, b3])); @@ -671,8 +671,8 @@ impl Xpriv { pub fn encode(&self) -> [u8; 78] { let mut ret = [0; 78]; ret[0..4].copy_from_slice(&match self.network { - Network::Bitcoin => VERSION_BYTES_MAINNET_PRIVATE, - Network::Testnet | Network::Signet | Network::Regtest => VERSION_BYTES_TESTNETS_PRIVATE, + NetworkKind::Main => VERSION_BYTES_MAINNET_PRIVATE, + NetworkKind::Test => VERSION_BYTES_TESTNETS_PRIVATE, }); ret[4] = self.depth; ret[5..9].copy_from_slice(&self.parent_fingerprint[..]); @@ -777,9 +777,9 @@ impl Xpub { } let network = if data.starts_with(&VERSION_BYTES_MAINNET_PUBLIC) { - Network::Bitcoin + NetworkKind::Main } else if data.starts_with(&VERSION_BYTES_TESTNETS_PUBLIC) { - Network::Testnet + NetworkKind::Test } else { let (b0, b1, b2, b3) = (data[0], data[1], data[2], data[3]); return Err(Error::UnknownVersion([b0, b1, b2, b3])); @@ -803,8 +803,8 @@ impl Xpub { pub fn encode(&self) -> [u8; 78] { let mut ret = [0; 78]; ret[0..4].copy_from_slice(&match self.network { - Network::Bitcoin => VERSION_BYTES_MAINNET_PUBLIC, - Network::Testnet | Network::Signet | Network::Regtest => VERSION_BYTES_TESTNETS_PUBLIC, + NetworkKind::Main => VERSION_BYTES_MAINNET_PUBLIC, + NetworkKind::Test => VERSION_BYTES_TESTNETS_PUBLIC, }); ret[4] = self.depth; ret[5..9].copy_from_slice(&self.parent_fingerprint[..]); @@ -884,7 +884,6 @@ mod tests { use super::ChildNumber::{Hardened, Normal}; use super::*; - use crate::network::Network::{self, Bitcoin}; #[test] fn test_parse_derivation_path() { @@ -965,7 +964,7 @@ mod tests { fn test_path( secp: &Secp256k1, - network: Network, + network: NetworkKind, seed: &[u8], path: DerivationPath, expected_sk: &str, @@ -1060,32 +1059,32 @@ mod tests { let seed = hex!("000102030405060708090a0b0c0d0e0f"); // m - test_path(&secp, Bitcoin, &seed, "m".parse().unwrap(), + test_path(&secp, NetworkKind::Main, &seed, "m".parse().unwrap(), "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi", "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8"); // m/0h - test_path(&secp, Bitcoin, &seed, "m/0h".parse().unwrap(), + test_path(&secp, NetworkKind::Main, &seed, "m/0h".parse().unwrap(), "xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7", "xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw"); // m/0h/1 - test_path(&secp, Bitcoin, &seed, "m/0h/1".parse().unwrap(), + test_path(&secp, NetworkKind::Main, &seed, "m/0h/1".parse().unwrap(), "xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs", "xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ"); // m/0h/1/2h - test_path(&secp, Bitcoin, &seed, "m/0h/1/2h".parse().unwrap(), + test_path(&secp, NetworkKind::Main, &seed, "m/0h/1/2h".parse().unwrap(), "xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM", "xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5"); // m/0h/1/2h/2 - test_path(&secp, Bitcoin, &seed, "m/0h/1/2h/2".parse().unwrap(), + test_path(&secp, NetworkKind::Main, &seed, "m/0h/1/2h/2".parse().unwrap(), "xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334", "xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV"); // m/0h/1/2h/2/1000000000 - test_path(&secp, Bitcoin, &seed, "m/0h/1/2h/2/1000000000".parse().unwrap(), + test_path(&secp, NetworkKind::Main, &seed, "m/0h/1/2h/2/1000000000".parse().unwrap(), "xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76", "xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy"); } @@ -1096,32 +1095,32 @@ mod tests { let seed = hex!("fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542"); // m - test_path(&secp, Bitcoin, &seed, "m".parse().unwrap(), + test_path(&secp, NetworkKind::Main, &seed, "m".parse().unwrap(), "xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U", "xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB"); // m/0 - test_path(&secp, Bitcoin, &seed, "m/0".parse().unwrap(), + test_path(&secp, NetworkKind::Main, &seed, "m/0".parse().unwrap(), "xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt", "xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH"); // m/0/2147483647h - test_path(&secp, Bitcoin, &seed, "m/0/2147483647h".parse().unwrap(), + test_path(&secp, NetworkKind::Main, &seed, "m/0/2147483647h".parse().unwrap(), "xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9", "xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ85ySDhKiLDBrQSARLq1uNRts8RuJiHjaDMBU4Zn9h8LZNnBC5y4a"); // m/0/2147483647h/1 - test_path(&secp, Bitcoin, &seed, "m/0/2147483647h/1".parse().unwrap(), + test_path(&secp, NetworkKind::Main, &seed, "m/0/2147483647h/1".parse().unwrap(), "xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef", "xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon"); // m/0/2147483647h/1/2147483646h - test_path(&secp, Bitcoin, &seed, "m/0/2147483647h/1/2147483646h".parse().unwrap(), + test_path(&secp, NetworkKind::Main, &seed, "m/0/2147483647h/1/2147483646h".parse().unwrap(), "xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc", "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL"); // m/0/2147483647h/1/2147483646h/2 - test_path(&secp, Bitcoin, &seed, "m/0/2147483647h/1/2147483646h/2".parse().unwrap(), + test_path(&secp, NetworkKind::Main, &seed, "m/0/2147483647h/1/2147483646h/2".parse().unwrap(), "xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j", "xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt"); } @@ -1132,12 +1131,12 @@ mod tests { let seed = hex!("4b381541583be4423346c643850da4b320e46a87ae3d2a4e6da11eba819cd4acba45d239319ac14f863b8d5ab5a0d0c64d2e8a1e7d1457df2e5a3c51c73235be"); // m - test_path(&secp, Bitcoin, &seed, "m".parse().unwrap(), + test_path(&secp, NetworkKind::Main, &seed, "m".parse().unwrap(), "xprv9s21ZrQH143K25QhxbucbDDuQ4naNntJRi4KUfWT7xo4EKsHt2QJDu7KXp1A3u7Bi1j8ph3EGsZ9Xvz9dGuVrtHHs7pXeTzjuxBrCmmhgC6", "xpub661MyMwAqRbcEZVB4dScxMAdx6d4nFc9nvyvH3v4gJL378CSRZiYmhRoP7mBy6gSPSCYk6SzXPTf3ND1cZAceL7SfJ1Z3GC8vBgp2epUt13"); // m/0h - test_path(&secp, Bitcoin, &seed, "m/0h".parse().unwrap(), + test_path(&secp, NetworkKind::Main, &seed, "m/0h".parse().unwrap(), "xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L", "xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y"); } @@ -1200,7 +1199,7 @@ mod tests { } let xpriv = Xpriv { - network: Network::Bitcoin, + network: NetworkKind::Main, depth: 0, parent_fingerprint: Default::default(), child_number: ChildNumber::Normal { index: 0 }, diff --git a/bitcoin/src/psbt/mod.rs b/bitcoin/src/psbt/mod.rs index a1d2c2a6..4581e770 100644 --- a/bitcoin/src/psbt/mod.rs +++ b/bitcoin/src/psbt/mod.rs @@ -1014,7 +1014,6 @@ mod tests { use crate::blockdata::script::ScriptBuf; use crate::blockdata::transaction::{self, OutPoint, Sequence, Transaction, TxIn, TxOut}; use crate::blockdata::witness::Witness; - use crate::network::Network::Bitcoin; use crate::network::NetworkKind; use crate::psbt::map::{Input, Output}; use crate::psbt::raw; @@ -1152,7 +1151,7 @@ mod tests { let mut hd_keypaths: BTreeMap = Default::default(); - let mut sk: Xpriv = Xpriv::new_master(Bitcoin, &seed).unwrap(); + let mut sk: Xpriv = Xpriv::new_master(NetworkKind::Main, &seed).unwrap(); let fprint = sk.fingerprint(secp); diff --git a/bitcoin/src/sign_message.rs b/bitcoin/src/sign_message.rs index a7236bf4..c16bc810 100644 --- a/bitcoin/src/sign_message.rs +++ b/bitcoin/src/sign_message.rs @@ -209,7 +209,6 @@ pub fn signed_msg_hash(msg: &str) -> sha256d::Hash { #[cfg(test)] mod tests { use super::*; - use crate::network::NetworkKind; #[test] fn test_signed_msg_hash() { @@ -227,7 +226,7 @@ mod tests { use secp256k1; - use crate::{Address, AddressType, Network}; + use crate::{Address, AddressType, Network, NetworkKind}; let secp = secp256k1::Secp256k1::new(); let message = "rust-bitcoin MessageSignature test"; diff --git a/bitcoin/tests/psbt.rs b/bitcoin/tests/psbt.rs index 7ad4bda5..f8d51b13 100644 --- a/bitcoin/tests/psbt.rs +++ b/bitcoin/tests/psbt.rs @@ -13,12 +13,10 @@ use bitcoin::psbt::{Psbt, PsbtSighashType}; use bitcoin::script::PushBytes; use bitcoin::secp256k1::{self, Secp256k1}; use bitcoin::{ - absolute, Amount, Denomination, Network, OutPoint, PrivateKey, PublicKey, ScriptBuf, Sequence, - Transaction, TxIn, TxOut, Witness, + absolute, Amount, Denomination, NetworkKind, OutPoint, PrivateKey, PublicKey, ScriptBuf, + Sequence, Transaction, TxIn, TxOut, Witness, }; -const NETWORK: Network = Network::Testnet; - #[track_caller] fn hex_psbt(s: &str) -> Psbt { let v: Vec = Vec::from_hex(s).expect("valid hex digits"); @@ -124,7 +122,7 @@ fn build_extended_private_key() -> Xpriv { let xpriv = Xpriv::from_str(extended_private_key).unwrap(); let sk = PrivateKey::from_wif(seed).unwrap(); - let seeded = Xpriv::new_master(NETWORK, &sk.inner.secret_bytes()).unwrap(); + let seeded = Xpriv::new_master(NetworkKind::Test, &sk.inner.secret_bytes()).unwrap(); assert_eq!(xpriv, seeded); xpriv