From 6d5ef23e61d3a45443df5a71c059df1716a7fd4a Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Fri, 17 Nov 2023 13:21:06 +1100 Subject: [PATCH 1/4] Add NetworkKind Add a new type `NetworkKind` the describes the kind of network we are on, ether mainnet or one of the test nets (testnet, regtest, signet). Do not use the type yet. --- bitcoin/src/lib.rs | 2 +- bitcoin/src/network.rs | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/bitcoin/src/lib.rs b/bitcoin/src/lib.rs index 53b94258..0ebbe5a2 100644 --- a/bitcoin/src/lib.rs +++ b/bitcoin/src/lib.rs @@ -129,7 +129,7 @@ pub use crate::{ crypto::key::{self, PrivateKey, PubkeyHash, PublicKey, CompressedPublicKey, WPubkeyHash, XOnlyPublicKey}, crypto::sighash::{self, LegacySighash, SegwitV0Sighash, TapSighash, TapSighashTag}, merkle_tree::MerkleBlock, - network::Network, + network::{Network, NetworkKind}, pow::{CompactTarget, Target, Work}, psbt::Psbt, sighash::{EcdsaSighashType, TapSighashType}, diff --git a/bitcoin/src/network.rs b/bitcoin/src/network.rs index 32102715..9c76d70f 100644 --- a/bitcoin/src/network.rs +++ b/bitcoin/src/network.rs @@ -31,6 +31,33 @@ use crate::constants::ChainHash; use crate::p2p::Magic; use crate::prelude::{String, ToOwned}; +/// What kind of network we are on. +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum NetworkKind { + /// The Bitcoin mainnet network. + Main, + /// Some kind of testnet network. + Test, +} + +// We explicitly do not provide `is_testnet`, using `!network.is_mainnet()` is less +// ambiguous due to confusion caused by signet/testnet/regtest. +impl NetworkKind { + /// Returns true if this is real mainnet bitcoin. + pub fn is_mainnet(&self) -> bool { *self == NetworkKind::Main } +} + +impl From for NetworkKind { + fn from(n: Network) -> Self { + use Network::*; + + match n { + Bitcoin => NetworkKind::Main, + Testnet | Signet | Regtest => NetworkKind::Test, + } + } +} + /// The cryptocurrency network to act on. #[derive(Copy, PartialEq, Eq, PartialOrd, Ord, Clone, Hash, Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] From d22f3828f6c17dd683aff87accea7fbeff37c985 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Tue, 28 Nov 2023 10:18:53 +1100 Subject: [PATCH 2/4] Use NetworkKind in address module --- bitcoin/src/address/mod.rs | 159 +++++++++++++----------------------- bitcoin/src/sign_message.rs | 9 +- bitcoin/tests/serde.rs | 4 +- 3 files changed, 65 insertions(+), 107 deletions(-) diff --git a/bitcoin/src/address/mod.rs b/bitcoin/src/address/mod.rs index 336f63b3..b1843824 100644 --- a/bitcoin/src/address/mod.rs +++ b/bitcoin/src/address/mod.rs @@ -46,7 +46,7 @@ use crate::blockdata::script::witness_program::WitnessProgram; use crate::blockdata::script::witness_version::WitnessVersion; use crate::blockdata::script::{self, PushBytesBuf, Script, ScriptBuf, ScriptHash}; use crate::crypto::key::{PubkeyHash, PublicKey, CompressedPublicKey, TweakedPublicKey, UntweakedPublicKey}; -use crate::network::Network; +use crate::network::{Network, NetworkKind}; use crate::prelude::*; use crate::taproot::TapNodeHash; @@ -135,8 +135,8 @@ impl NetworkValidation for NetworkUnchecked { /// addresses are used only on the appropriate network. #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] enum AddressInner { - P2pkh { hash: PubkeyHash, prefix: LegacyP2pkhPrefix }, - P2sh { hash: ScriptHash, prefix: LegacyP2shPrefix }, + P2pkh { hash: PubkeyHash, network: NetworkKind }, + P2sh { hash: ScriptHash, network: NetworkKind }, Segwit { program: WitnessProgram, hrp: KnownHrp }, } @@ -145,15 +145,21 @@ impl fmt::Display for AddressInner { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { use AddressInner::*; match self { - P2pkh { hash, prefix } => { + P2pkh { hash, network } => { let mut prefixed = [0; 21]; - prefixed[0] = prefix.to_u8(); + prefixed[0] = match network { + NetworkKind::Main => PUBKEY_ADDRESS_PREFIX_MAIN, + NetworkKind::Test => PUBKEY_ADDRESS_PREFIX_TEST, + }; prefixed[1..].copy_from_slice(&hash[..]); base58::encode_check_to_fmt(fmt, &prefixed[..]) } - P2sh { hash, prefix } => { + P2sh { hash, network } => { let mut prefixed = [0; 21]; - prefixed[0] = prefix.to_u8(); + prefixed[0] = match network { + NetworkKind::Main => SCRIPT_ADDRESS_PREFIX_MAIN, + NetworkKind::Test => SCRIPT_ADDRESS_PREFIX_TEST, + }; prefixed[1..].copy_from_slice(&hash[..]); base58::encode_check_to_fmt(fmt, &prefixed[..]) } @@ -172,64 +178,6 @@ impl fmt::Display for AddressInner { } } -/// Prefix byte used for legacy P2PKH addresses. -#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -enum LegacyP2pkhPrefix { - /// Prefix used for legacy addresses on the main Bitcoin network. - Mainnet, - /// Prefix used for legacy addresses on all other test networks (testnet, signet, regtest). - AllTestnets, -} - -impl LegacyP2pkhPrefix { - /// Creates a legacy prefix from the associated `network`. - fn from_network(network: Network) -> Self { - use Network::*; - - match network { - Bitcoin => Self::Mainnet, - Signet | Testnet | Regtest => Self::AllTestnets, - } - } - - /// Converts this prefix enum to the respective byte value. - fn to_u8(self) -> u8 { - match self { - Self::Mainnet => PUBKEY_ADDRESS_PREFIX_MAIN, - Self::AllTestnets => PUBKEY_ADDRESS_PREFIX_TEST, - } - } -} - -/// Prefix byte used for legacy P2SH addresses. -#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -enum LegacyP2shPrefix { - /// Prefix used for legacy addresses on the main Bitcoin network. - Mainnet, - /// Prefix used for legacy addresses on all other test networks (testnet, signet, regtest). - AllTestnets, -} - -impl LegacyP2shPrefix { - /// Creates a legacy prefix from the associated `network`. - fn from_network(network: Network) -> Self { - use Network::*; - - match network { - Bitcoin => Self::Mainnet, - Signet | Testnet | Regtest => Self::AllTestnets, - } - } - - /// Converts this prefix enum to the respective byte value. - fn to_u8(self) -> u8 { - match self { - Self::Mainnet => SCRIPT_ADDRESS_PREFIX_MAIN, - Self::AllTestnets => SCRIPT_ADDRESS_PREFIX_TEST, - } - } -} - /// Known bech32 human-readable parts. #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[non_exhaustive] @@ -277,6 +225,10 @@ impl KnownHrp { } } +impl From for KnownHrp { + fn from(n: Network) -> Self { Self::from_network(n) } +} + /// A Bitcoin address. /// /// ### Parsing addresses @@ -412,10 +364,9 @@ impl Address { /// /// This is the preferred non-witness type address. #[inline] - pub fn p2pkh(pk: impl Into, network: Network) -> Address { + pub fn p2pkh(pk: impl Into, network: impl Into) -> Address { let hash = pk.into(); - let prefix = LegacyP2pkhPrefix::from_network(network); - Self(AddressInner::P2pkh { hash, prefix }, PhantomData) + Self(AddressInner::P2pkh { hash, network: network.into() }, PhantomData) } /// Creates a pay to script hash P2SH address from a script. @@ -423,7 +374,7 @@ impl Address { /// This address type was introduced with BIP16 and is the popular type to implement multi-sig /// these days. #[inline] - pub fn p2sh(script: &Script, network: Network) -> Result { + pub fn p2sh(script: &Script, network: impl Into) -> Result { if script.len() > MAX_SCRIPT_ELEMENT_SIZE { return Err(Error::ExcessiveScriptSize); } @@ -432,9 +383,8 @@ impl Address { } // This is intentionally not public so we enforce script length checks. - fn p2sh_from_hash(hash: ScriptHash, network: Network) -> Address { - let prefix = LegacyP2shPrefix::from_network(network); - Self(AddressInner::P2sh { hash, prefix }, PhantomData) + fn p2sh_from_hash(hash: ScriptHash, network: impl Into) -> Address { + Self(AddressInner::P2sh { hash, network: network.into() }, PhantomData) } /// Creates a witness pay to public key address from a public key. @@ -453,8 +403,8 @@ impl Address { /// This is a segwit address type that looks familiar (as p2sh) to legacy clients. pub fn p2shwpkh( pk: &CompressedPublicKey, - network: Network, - ) -> Self { + network: impl Into, + ) -> Address { let builder = script::Builder::new().push_int(0).push_slice(pk.wpubkey_hash()); let script_hash = builder.as_script().script_hash(); Address::p2sh_from_hash(script_hash, network) @@ -469,7 +419,7 @@ impl Address { /// Creates a pay to script address that embeds a witness pay to script hash address. /// /// This is a segwit address type that looks familiar (as p2sh) to legacy clients. - pub fn p2shwsh(script: &Script, network: Network) -> Address { + pub fn p2shwsh(script: &Script, network: impl Into) -> Address { let builder = script::Builder::new().push_int(0).push_slice(script.wscript_hash()); let script_hash = builder.as_script().script_hash(); Address::p2sh_from_hash(script_hash, network) @@ -496,6 +446,7 @@ impl Address { /// /// This only exists to support future witness versions. If you are doing normal mainnet things /// then you likely do not need this constructor. + // TODO: This is still arguably wrong, could take a KnownHrp/Hrp instead of Network. pub fn from_witness_program(program: WitnessProgram, network: Network) -> Address { let hrp = KnownHrp::from_network(network); let inner = AddressInner::Segwit { program, hrp }; @@ -530,7 +481,7 @@ impl Address { use AddressInner::*; match self.0 { - P2pkh { ref hash, prefix: _ } => Some(*hash), + P2pkh { ref hash, network: _ } => Some(*hash), _ => None, } } @@ -540,7 +491,7 @@ impl Address { use AddressInner::*; match self.0 { - P2sh { ref hash, prefix: _ } => Some(*hash), + P2sh { ref hash, network: _ } => Some(*hash), _ => None, } } @@ -587,9 +538,13 @@ impl Address { pub fn script_pubkey(&self) -> ScriptBuf { use AddressInner::*; match self.0 { - P2pkh { ref hash, prefix: _ } => ScriptBuf::new_p2pkh(hash), - P2sh { ref hash, prefix: _ } => ScriptBuf::new_p2sh(hash), - Segwit { ref program, hrp: _ } => ScriptBuf::new_witness_program(program), + P2pkh { ref hash, network: _ } => ScriptBuf::new_p2pkh(hash), + P2sh { ref hash, network: _ } => ScriptBuf::new_p2sh(hash), + Segwit { ref program, hrp: _ } => { + let prog = program.program(); + let version = program.version(); + ScriptBuf::new_witness_program_unchecked(version, prog) + } } } @@ -650,9 +605,9 @@ impl Address { pub fn matches_script_pubkey(&self, script: &Script) -> bool { use AddressInner::*; match self.0 { - P2pkh { ref hash, prefix: _ } if script.is_p2pkh() => + P2pkh { ref hash, network: _ } if script.is_p2pkh() => &script.as_bytes()[3..23] == >::as_ref(hash), - P2sh { ref hash, prefix: _ } if script.is_p2sh() => + P2sh { ref hash, network: _ } if script.is_p2sh() => &script.as_bytes()[2..22] == >::as_ref(hash), Segwit { ref program, hrp: _ } if script.is_witness_program() => &script.as_bytes()[2..] == program.program().as_bytes(), @@ -671,8 +626,8 @@ impl Address { fn payload_as_bytes(&self) -> &[u8] { use AddressInner::*; match self.0 { - P2sh { ref hash, prefix: _ } => hash.as_ref(), - P2pkh { ref hash, prefix: _ } => hash.as_ref(), + P2sh { ref hash, network: _ } => hash.as_ref(), + P2pkh { ref hash, network: _ } => hash.as_ref(), Segwit { ref program, hrp: _ } => program.program().as_bytes(), } } @@ -706,12 +661,12 @@ impl Address { /// assert!(address.is_valid_for_network(Network::Bitcoin)); /// assert_eq!(address.is_valid_for_network(Network::Testnet), false); /// ``` - pub fn is_valid_for_network(&self, network: Network) -> bool { + pub fn is_valid_for_network(&self, n: Network) -> bool { use AddressInner::*; match self.0 { - P2pkh { hash: _, ref prefix } => *prefix == LegacyP2pkhPrefix::from_network(network), - P2sh { hash: _, ref prefix } => *prefix == LegacyP2shPrefix::from_network(network), - Segwit { program: _, ref hrp } => *hrp == KnownHrp::from_network(network), + P2pkh { hash: _, ref network } => *network == NetworkKind::from(n), + P2sh { hash: _, ref network } => *network == NetworkKind::from(n), + Segwit { program: _, ref hrp } => *hrp == KnownHrp::from_network(n), } } @@ -739,8 +694,8 @@ impl Address { use AddressInner::*; let inner = match self.0 { - P2pkh { hash, prefix } => P2pkh { hash, prefix }, - P2sh { hash, prefix } => P2sh { hash, prefix }, + P2pkh { hash, network } => P2pkh { hash, network }, + P2sh { hash, network } => P2sh { hash, network }, Segwit { program, hrp } => Segwit { program, hrp }, }; Address(inner, PhantomData) @@ -801,19 +756,19 @@ impl FromStr for Address { let inner = match *prefix { PUBKEY_ADDRESS_PREFIX_MAIN => { let hash = PubkeyHash::from_byte_array(data); - AddressInner::P2pkh { hash, prefix: LegacyP2pkhPrefix::Mainnet } + AddressInner::P2pkh { hash, network: NetworkKind::Main } } PUBKEY_ADDRESS_PREFIX_TEST => { let hash = PubkeyHash::from_byte_array(data); - AddressInner::P2pkh { hash, prefix: LegacyP2pkhPrefix::AllTestnets } + AddressInner::P2pkh { hash, network: NetworkKind::Test } } SCRIPT_ADDRESS_PREFIX_MAIN => { let hash = ScriptHash::from_byte_array(data); - AddressInner::P2sh { hash, prefix: LegacyP2shPrefix::Mainnet } + AddressInner::P2sh { hash, network: NetworkKind::Main } } SCRIPT_ADDRESS_PREFIX_TEST => { let hash = ScriptHash::from_byte_array(data); - AddressInner::P2sh { hash, prefix: LegacyP2shPrefix::AllTestnets } + AddressInner::P2sh { hash, network: NetworkKind::Test } } x => return Err(ParseError::Base58(base58::Error::InvalidAddressVersion(x))), }; @@ -868,7 +823,7 @@ mod tests { #[test] fn test_p2pkh_address_58() { let hash = "162c5ea71c0b23f5b9022ef047c4a86470a5b070".parse::().unwrap(); - let addr = Address::p2pkh(hash, Bitcoin); + let addr = Address::p2pkh(hash, NetworkKind::Main); assert_eq!( addr.script_pubkey(), @@ -882,13 +837,13 @@ mod tests { #[test] fn test_p2pkh_from_key() { let key = "048d5141948c1702e8c95f438815794b87f706a8d4cd2bffad1dc1570971032c9b6042a0431ded2478b5c9cf2d81c124a5e57347a3c63ef0e7716cf54d613ba183".parse::().unwrap(); - let addr = Address::p2pkh(key, Bitcoin); + let addr = Address::p2pkh(key, NetworkKind::Main); assert_eq!(&addr.to_string(), "1QJVDzdqb1VpbDK7uDeyVXy9mR27CJiyhY"); let key = "03df154ebfcf29d29cc10d5c2565018bce2d9edbab267c31d2caf44a63056cf99f" .parse::() .unwrap(); - let addr = Address::p2pkh(key, Testnet); + let addr = Address::p2pkh(key, NetworkKind::Test); assert_eq!(&addr.to_string(), "mqkhEMH6NCeYjFybv7pvFC22MFeaNT9AQC"); assert_eq!(addr.address_type(), Some(AddressType::P2pkh)); roundtrips(&addr, Testnet); @@ -897,7 +852,7 @@ mod tests { #[test] fn test_p2sh_address_58() { let hash = "162c5ea71c0b23f5b9022ef047c4a86470a5b070".parse::().unwrap(); - let addr = Address::p2sh_from_hash(hash, Bitcoin); + let addr = Address::p2sh_from_hash(hash, NetworkKind::Main); assert_eq!( addr.script_pubkey(), @@ -911,7 +866,7 @@ mod tests { #[test] fn test_p2sh_parse() { let script = ScriptBuf::from_hex("552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae").unwrap(); - let addr = Address::p2sh(&script, Testnet).unwrap(); + let addr = Address::p2sh(&script, NetworkKind::Test).unwrap(); assert_eq!(&addr.to_string(), "2N3zXjbwdTcPsJiy8sUK9FhWJhqQCxA8Jjr"); assert_eq!(addr.address_type(), Some(AddressType::P2sh)); roundtrips(&addr, Testnet); @@ -920,7 +875,7 @@ mod tests { #[test] fn test_p2sh_parse_for_large_script() { let script = ScriptBuf::from_hex("552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae12123122313123123ac1231231231231313123131231231231313212313213123123552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae12123122313123123ac1231231231231313123131231231231313212313213123123552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae12123122313123123ac1231231231231313123131231231231313212313213123123").unwrap(); - assert_eq!(Address::p2sh(&script, Testnet), Err(Error::ExcessiveScriptSize)); + assert_eq!(Address::p2sh(&script, NetworkKind::Test), Err(Error::ExcessiveScriptSize)); } #[test] @@ -954,7 +909,7 @@ mod tests { let key = "026c468be64d22761c30cd2f12cbc7de255d592d7904b1bab07236897cc4c2e766" .parse::() .unwrap(); - let addr = Address::p2shwpkh(&key, Bitcoin); + let addr = Address::p2shwpkh(&key, NetworkKind::Main); assert_eq!(&addr.to_string(), "3QBRmWNqqBGme9er7fMkGqtZtp4gjMFxhE"); assert_eq!(addr.address_type(), Some(AddressType::P2sh)); roundtrips(&addr, Bitcoin); @@ -964,7 +919,7 @@ mod tests { fn test_p2shwsh() { // stolen from Bitcoin transaction f9ee2be4df05041d0e0a35d7caa3157495ca4f93b233234c9967b6901dacf7a9 let script = ScriptBuf::from_hex("522103e5529d8eaa3d559903adb2e881eb06c86ac2574ffa503c45f4e942e2a693b33e2102e5f10fcdcdbab211e0af6a481f5532536ec61a5fdbf7183770cf8680fe729d8152ae").unwrap(); - let addr = Address::p2shwsh(&script, Bitcoin); + let addr = Address::p2shwsh(&script, NetworkKind::Main); assert_eq!(&addr.to_string(), "36EqgNnsWW94SreZgBWc1ANC6wpFZwirHr"); assert_eq!(addr.address_type(), Some(AddressType::P2sh)); roundtrips(&addr, Bitcoin); diff --git a/bitcoin/src/sign_message.rs b/bitcoin/src/sign_message.rs index c543c4ff..a7236bf4 100644 --- a/bitcoin/src/sign_message.rs +++ b/bitcoin/src/sign_message.rs @@ -209,6 +209,7 @@ 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() { @@ -243,12 +244,14 @@ mod tests { .try_into() .expect("compressed was set to true"); + let p2pkh = Address::p2pkh(pubkey, NetworkKind::Main); + assert_eq!(signature2.is_signed_by_address(&secp, &p2pkh, msg_hash), Ok(true)); let p2wpkh = Address::p2wpkh(&pubkey, Network::Bitcoin); assert_eq!( signature2.is_signed_by_address(&secp, &p2wpkh, msg_hash), Err(MessageSignatureError::UnsupportedAddressType(AddressType::P2wpkh)) ); - let p2shwpkh = Address::p2shwpkh(&pubkey, Network::Bitcoin); + let p2shwpkh = Address::p2shwpkh(&pubkey, NetworkKind::Main); assert_eq!( signature2.is_signed_by_address(&secp, &p2shwpkh, msg_hash), Err(MessageSignatureError::UnsupportedAddressType(AddressType::P2sh)) @@ -266,7 +269,7 @@ mod tests { use secp256k1; use crate::crypto::key::PublicKey; - use crate::{Address, Network}; + use crate::{Address, NetworkKind}; let secp = secp256k1::Secp256k1::new(); let message = "a different message from what was signed"; @@ -283,7 +286,7 @@ mod tests { PublicKey::from_slice(&BASE64_STANDARD.decode(pubkey_base64).expect("base64 string")) .expect("pubkey slice"); - let p2pkh = Address::p2pkh(pubkey, Network::Bitcoin); + let p2pkh = Address::p2pkh(pubkey, NetworkKind::Main); assert_eq!(signature.is_signed_by_address(&secp, &p2pkh, msg_hash), Ok(false)); } } diff --git a/bitcoin/tests/serde.rs b/bitcoin/tests/serde.rs index 430e9b6c..04686a7c 100644 --- a/bitcoin/tests/serde.rs +++ b/bitcoin/tests/serde.rs @@ -38,7 +38,7 @@ use bitcoin::psbt::{Input, Output, Psbt, PsbtSighashType}; use bitcoin::sighash::{EcdsaSighashType, TapSighashType}; use bitcoin::taproot::{self, ControlBlock, LeafVersion, TapTree, TaprootBuilder}; use bitcoin::{ - ecdsa, transaction, Address, Amount, Block, Network, OutPoint, PrivateKey, PublicKey, + ecdsa, transaction, Address, Amount, Block, NetworkKind, OutPoint, PrivateKey, PublicKey, ScriptBuf, Sequence, Target, Transaction, TxIn, TxOut, Txid, Work, }; @@ -145,7 +145,7 @@ fn serde_regression_witness() { fn serde_regression_address() { let s = include_str!("data/serde/public_key_hex"); let pk = PublicKey::from_str(s.trim()).unwrap(); - let addr = Address::p2pkh(pk, Network::Bitcoin); + let addr = Address::p2pkh(pk, NetworkKind::Main); let got = serialize(&addr).unwrap(); let want = include_bytes!("data/serde/address_bincode") as &[_]; From 35bbfcded7b4a781a70495b9a4c7a6cd65be36bd Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Tue, 28 Nov 2023 10:28:55 +1100 Subject: [PATCH 3/4] Use NetworkKind in PrivateKey We only use the network to serialize and deserialize from WIF. For this we only really need network kind since WIF only differentiates between mainnet and non-mainnet. --- bitcoin/src/bip32.rs | 2 +- bitcoin/src/crypto/key.rs | 42 ++++++++++++++++++++------------------- bitcoin/src/psbt/mod.rs | 3 ++- 3 files changed, 25 insertions(+), 22 deletions(-) diff --git a/bitcoin/src/bip32.rs b/bitcoin/src/bip32.rs index ad4dfcf9..6db12c44 100644 --- a/bitcoin/src/bip32.rs +++ b/bitcoin/src/bip32.rs @@ -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, inner: self.private_key } + PrivateKey { compressed: true, network: self.network.into(), inner: self.private_key } } /// Constructs BIP340 keypair for Schnorr signatures and Taproot use matching the internal diff --git a/bitcoin/src/crypto/key.rs b/bitcoin/src/crypto/key.rs index ba7cf541..97e0014e 100644 --- a/bitcoin/src/crypto/key.rs +++ b/bitcoin/src/crypto/key.rs @@ -16,7 +16,7 @@ use io::{Read, Write}; use crate::crypto::ecdsa; use crate::internal_macros::impl_asref_push_bytes; -use crate::network::Network; +use crate::network::NetworkKind; use crate::prelude::*; use crate::taproot::{TapNodeHash, TapTweakHash}; use crate::{base58, io}; @@ -390,8 +390,8 @@ impl From<&CompressedPublicKey> for WPubkeyHash { pub struct PrivateKey { /// Whether this private key should be serialized as compressed pub compressed: bool, - /// The network on which this key should be used - pub network: Network, + /// The network kind on which this key should be used + pub network: NetworkKind, /// The actual ECDSA key pub inner: secp256k1::SecretKey, } @@ -400,20 +400,23 @@ impl PrivateKey { /// Constructs new compressed ECDSA private key using the secp256k1 algorithm and /// a secure random number generator. #[cfg(feature = "rand-std")] - pub fn generate(network: Network) -> PrivateKey { + pub fn generate(network: impl Into) -> PrivateKey { let secret_key = secp256k1::SecretKey::new(&mut rand::thread_rng()); - PrivateKey::new(secret_key, network) + PrivateKey::new(secret_key, network.into()) } /// Constructs compressed ECDSA private key from the provided generic Secp256k1 private key /// and the specified network - pub fn new(key: secp256k1::SecretKey, network: Network) -> PrivateKey { - PrivateKey { compressed: true, network, inner: key } + pub fn new(key: secp256k1::SecretKey, network: impl Into) -> PrivateKey { + PrivateKey { compressed: true, network: network.into(), inner: key } } /// Constructs uncompressed (legacy) ECDSA private key from the provided generic Secp256k1 /// private key and the specified network - pub fn new_uncompressed(key: secp256k1::SecretKey, network: Network) -> PrivateKey { - PrivateKey { compressed: false, network, inner: key } + pub fn new_uncompressed( + key: secp256k1::SecretKey, + network: impl Into, + ) -> PrivateKey { + PrivateKey { compressed: false, network: network.into(), inner: key } } /// Creates a public key from this private key @@ -428,17 +431,16 @@ impl PrivateKey { pub fn to_bytes(self) -> Vec { self.inner[..].to_vec() } /// Deserialize a private key from a slice - pub fn from_slice(data: &[u8], network: Network) -> Result { + pub fn from_slice(data: &[u8], network: impl Into) -> Result { Ok(PrivateKey::new(secp256k1::SecretKey::from_slice(data)?, network)) } /// Format the private key to WIF format. + #[rustfmt::skip] pub fn fmt_wif(&self, fmt: &mut dyn fmt::Write) -> fmt::Result { let mut ret = [0; 34]; - ret[0] = match self.network { - Network::Bitcoin => 128, - Network::Testnet | Network::Signet | Network::Regtest => 239, - }; + ret[0] = if self.network.is_mainnet() { 128 } else { 239 }; + ret[1..33].copy_from_slice(&self.inner[..]); let privkey = if self.compressed { ret[33] = 1; @@ -470,8 +472,8 @@ impl PrivateKey { }; let network = match data[0] { - 128 => Network::Bitcoin, - 239 => Network::Testnet, + 128 => NetworkKind::Main, + 239 => NetworkKind::Test, x => { return Err(Error::Base58(base58::Error::InvalidAddressVersion(x))); } @@ -953,14 +955,14 @@ mod tests { use super::*; use crate::address::Address; - use crate::network::Network::{Bitcoin, Testnet}; + use crate::network::NetworkKind; #[test] fn test_key_derivation() { // testnet compressed let sk = PrivateKey::from_wif("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy").unwrap(); - assert_eq!(sk.network, Testnet); + assert_eq!(sk.network, NetworkKind::Test); assert!(sk.compressed); assert_eq!(&sk.to_wif(), "cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy"); @@ -977,7 +979,7 @@ mod tests { // mainnet uncompressed let sk = PrivateKey::from_wif("5JYkZjmN7PVMjJUfJWfRFwtuXTGB439XV6faajeHPAM9Z2PT2R3").unwrap(); - assert_eq!(sk.network, Bitcoin); + assert_eq!(sk.network, NetworkKind::Main); assert!(!sk.compressed); assert_eq!(&sk.to_wif(), "5JYkZjmN7PVMjJUfJWfRFwtuXTGB439XV6faajeHPAM9Z2PT2R3"); @@ -1295,7 +1297,7 @@ mod tests { fn private_key_debug_is_obfuscated() { let sk = PrivateKey::from_str("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy").unwrap(); - let want = "PrivateKey { compressed: true, network: Testnet, inner: SecretKey(#32014e414fdce702) }"; + let want = "PrivateKey { compressed: true, network: Test, inner: SecretKey(#32014e414fdce702) }"; let got = format!("{:?}", sk); assert_eq!(got, want) } diff --git a/bitcoin/src/psbt/mod.rs b/bitcoin/src/psbt/mod.rs index 925ea413..a1d2c2a6 100644 --- a/bitcoin/src/psbt/mod.rs +++ b/bitcoin/src/psbt/mod.rs @@ -1015,6 +1015,7 @@ mod tests { 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; use crate::psbt::serialize::{Deserialize, Serialize}; @@ -1926,7 +1927,7 @@ mod tests { let secp = Secp256k1::new(); let sk = SecretKey::new(&mut thread_rng()); - let priv_key = PrivateKey::new(sk, crate::Network::Regtest); + let priv_key = PrivateKey::new(sk, NetworkKind::Test); let pk = PublicKey::from_private_key(&secp, &priv_key); (priv_key, pk, secp) From 4354f37f5183f13f1d7cb1fc57d5d276a4a568ed Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Tue, 28 Nov 2023 10:40:08 +1100 Subject: [PATCH 4/4] 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