From 2424b654d5bc3e3b509f46b5d261353cdd98ae8b Mon Sep 17 00:00:00 2001 From: BinChengZhao Date: Mon, 16 Sep 2024 13:22:22 +0800 Subject: [PATCH] feat: rust-bitcoin supports testnet4 --- bitcoin/src/address/mod.rs | 11 ++-- bitcoin/src/blockdata/block.rs | 4 +- bitcoin/src/blockdata/constants.rs | 77 +++++++++++++++++----- bitcoin/src/blockdata/script/push_bytes.rs | 4 +- bitcoin/src/network/mod.rs | 50 ++++++++------ bitcoin/src/network/params.rs | 62 +++++++++++++---- bitcoin/src/p2p/mod.rs | 9 ++- 7 files changed, 157 insertions(+), 60 deletions(-) diff --git a/bitcoin/src/address/mod.rs b/bitcoin/src/address/mod.rs index 9fa8dd4d3..d05d0cdf3 100644 --- a/bitcoin/src/address/mod.rs +++ b/bitcoin/src/address/mod.rs @@ -194,7 +194,7 @@ impl fmt::Display for AddressInner { pub enum KnownHrp { /// The main Bitcoin network. Mainnet, - /// The test networks, testnet (testnet3), and signet. + /// The test networks, testnet (testnet3), testnet4, and signet. Testnets, /// The regtest network. Regtest, @@ -720,6 +720,7 @@ impl Address { /// /// let address: Address = "32iVBEu4dxkUQk9dJbZUiBiQdmypcEyJRf".parse().unwrap(); /// assert!(address.is_valid_for_network(Network::Bitcoin)); + /// assert_eq!(address.is_valid_for_network(Network::Testnet(TestnetVersion::V4)), false); /// ``` pub fn is_valid_for_network(&self, n: Network) -> bool { use AddressInner::*; @@ -887,8 +888,8 @@ mod tests { use hex_lit::hex; use super::*; - use crate::network::params; use crate::network::Network::{Bitcoin, Testnet}; + use crate::network::{params, TestnetVersion}; use crate::script::ScriptBufExt as _; fn roundtrips(addr: &Address, network: Network) { @@ -941,7 +942,7 @@ mod tests { let addr = Address::p2pkh(key, NetworkKind::Test); assert_eq!(&addr.to_string(), "mqkhEMH6NCeYjFybv7pvFC22MFeaNT9AQC"); assert_eq!(addr.address_type(), Some(AddressType::P2pkh)); - roundtrips(&addr, Testnet(crate::TestnetVersion::V3)); + roundtrips(&addr, Testnet(TestnetVersion::V3)); } #[test] @@ -964,7 +965,7 @@ mod tests { 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(crate::TestnetVersion::V3)); + roundtrips(&addr, Testnet(TestnetVersion::V3)); } #[test] @@ -1281,7 +1282,7 @@ mod tests { let address = address_string .parse::>() .expect("address") - .require_network(Network::Testnet(crate::TestnetVersion::V3)) + .require_network(Network::Testnet(TestnetVersion::V3)) .expect("testnet"); let pubkey_string = "04e96e22004e3db93530de27ccddfdf1463975d2138ac018fc3e7ba1a2e5e0aad8e424d0b55e2436eb1d0dcd5cb2b8bcc6d53412c22f358de57803a6a655fbbd04"; diff --git a/bitcoin/src/blockdata/block.rs b/bitcoin/src/blockdata/block.rs index a093b266c..9b9e8f2d8 100644 --- a/bitcoin/src/blockdata/block.rs +++ b/bitcoin/src/blockdata/block.rs @@ -477,7 +477,7 @@ mod tests { use super::*; use crate::consensus::encode::{deserialize, serialize}; - use crate::Network; + use crate::{Network, TestnetVersion}; #[test] fn test_coinbase_and_bip34() { @@ -546,7 +546,7 @@ mod tests { // Check testnet block 000000000000045e0b1660b6445b5e5c5ab63c9a4f956be7e1e69be04fa4497b #[test] fn segwit_block_test() { - let params = Params::new(Network::Testnet(crate::TestnetVersion::V3)); + let params = Params::new(Network::Testnet(TestnetVersion::V3)); let segwit_block = include_bytes!("../../tests/data/testnet_block_000000000000045e0b1660b6445b5e5c5ab63c9a4f956be7e1e69be04fa4497b.raw").to_vec(); let decode: Result = deserialize(&segwit_block); diff --git a/bitcoin/src/blockdata/constants.rs b/bitcoin/src/blockdata/constants.rs index 8948f96ef..a891ba038 100644 --- a/bitcoin/src/blockdata/constants.rs +++ b/bitcoin/src/blockdata/constants.rs @@ -72,8 +72,11 @@ const GENESIS_OUTPUT_PK: [u8; 65] = [ 0x8a, 0x4c, 0x70, 0x2b, 0x6b, 0xf1, 0x1d, 0x5f ]; +#[rustfmt::skip] +const TESTNET4_GENESIS_OUTPUT_PK: [u8; 33] = [0x00; 33]; + /// Constructs and returns the coinbase (and only) transaction of the Bitcoin genesis block. -fn bitcoin_genesis_tx() -> Transaction { +fn bitcoin_genesis_tx(params: &Params) -> Transaction { // Base let mut ret = Transaction { version: transaction::Version::ONE, @@ -82,21 +85,35 @@ fn bitcoin_genesis_tx() -> Transaction { output: vec![], }; - // Inputs - let in_script = script::Builder::new() - .push_int_unchecked(486604799) - .push_int_non_minimal(4) - .push_slice(b"The Times 03/Jan/2009 Chancellor on brink of second bailout for banks") - .into_script(); + let (in_script, out_script) = { + match params.network { + Network::Testnet(TestnetVersion::V4) => ( + script::Builder::new() + .push_int_unchecked(486604799) + .push_int_non_minimal(4) + .push_slice(b"03/May/2024 000000000000000000001ebd58c244970b3aa9d783bb001011fbe8ea8e98e00e") + .into_script(), + script::Builder::new().push_slice(TESTNET4_GENESIS_OUTPUT_PK).push_opcode(OP_CHECKSIG).into_script(), + + ), + _ => ( + script::Builder::new() + .push_int_unchecked(486604799) + .push_int_non_minimal(4) + .push_slice(b"The Times 03/Jan/2009 Chancellor on brink of second bailout for banks") + .into_script(), + script::Builder::new().push_slice(GENESIS_OUTPUT_PK).push_opcode(OP_CHECKSIG).into_script(), + ), + } + }; + ret.input.push(TxIn { previous_output: OutPoint::COINBASE_PREVOUT, script_sig: in_script, sequence: Sequence::MAX, witness: Witness::default(), }); - // Outputs - let out_script = - script::Builder::new().push_slice(GENESIS_OUTPUT_PK).push_opcode(OP_CHECKSIG).into_script(); + ret.output.push(TxOut { value: Amount::from_sat(50 * 100_000_000), script_pubkey: out_script }); // end @@ -105,12 +122,12 @@ fn bitcoin_genesis_tx() -> Transaction { /// Constructs and returns the genesis block. pub fn genesis_block(params: impl AsRef) -> Block { - let params_ref = params.as_ref(); - let txdata = vec![bitcoin_genesis_tx()]; + let params = params.as_ref(); + let txdata = vec![bitcoin_genesis_tx(params)]; let hash: sha256d::Hash = txdata[0].compute_txid().into(); let merkle_root: crate::TxMerkleNode = hash.into(); - match params_ref.network { + match params.network { Network::Bitcoin => Block { header: block::Header { version: block::Version::ONE, @@ -133,6 +150,17 @@ pub fn genesis_block(params: impl AsRef) -> Block { }, txdata, }, + Network::Testnet(TestnetVersion::V4) => Block { + header: block::Header { + version: block::Version::ONE, + prev_blockhash: BlockHash::GENESIS_PREVIOUS_BLOCK_HASH, + merkle_root, + time: 1714777860, + bits: CompactTarget::from_consensus(0x1d00ffff), + nonce: 393743547, + }, + txdata, + }, Network::Signet => Block { header: block::Header { version: block::Version::ONE, @@ -172,10 +200,21 @@ impl ChainHash { 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, ]); /// `ChainHash` for testnet3 bitcoin. + #[deprecated(since = "0.33.0", note = "Use TESTNET3 instead")] pub const TESTNET: Self = Self([ 67, 73, 127, 215, 248, 38, 149, 113, 8, 244, 163, 15, 217, 206, 195, 174, 186, 121, 151, 32, 132, 233, 14, 173, 1, 234, 51, 9, 0, 0, 0, 0, ]); + /// `ChainHash` for testnet3 bitcoin. + pub const TESTNET3: Self = Self([ + 67, 73, 127, 215, 248, 38, 149, 113, 8, 244, 163, 15, 217, 206, 195, 174, 186, 121, 151, + 32, 132, 233, 14, 173, 1, 234, 51, 9, 0, 0, 0, 0, + ]); + /// `ChainHash` for testnet4 bitcoin. + pub const TESTNET4: Self = Self([ + 67, 240, 139, 218, 176, 80, 227, 91, 86, 124, 134, 75, 145, 244, 127, 80, 174, 114, 90, + 226, 222, 83, 188, 251, 186, 242, 132, 218, 0, 0, 0, 0, + ]); /// `ChainHash` for signet bitcoin. pub const SIGNET: Self = Self([ 246, 30, 238, 59, 99, 163, 128, 164, 119, 160, 99, 175, 50, 178, 187, 201, 124, 159, 249, @@ -194,7 +233,8 @@ impl ChainHash { pub fn using_genesis_block(params: impl AsRef) -> Self { match params.as_ref().network { Network::Bitcoin => Self::BITCOIN, - Network::Testnet(TestnetVersion::V3) => Self::TESTNET, + Network::Testnet(TestnetVersion::V3) => Self::TESTNET3, + Network::Testnet(TestnetVersion::V4) => Self::TESTNET4, Network::Signet => Self::SIGNET, Network::Regtest => Self::REGTEST, } @@ -207,7 +247,8 @@ impl ChainHash { pub const fn using_genesis_block_const(network: Network) -> Self { match network { Network::Bitcoin => Self::BITCOIN, - Network::Testnet(TestnetVersion::V3) => Self::TESTNET, + Network::Testnet(TestnetVersion::V3) => Self::TESTNET3, + Network::Testnet(TestnetVersion::V4) => Self::TESTNET4, Network::Signet => Self::SIGNET, Network::Regtest => Self::REGTEST, } @@ -230,7 +271,7 @@ mod test { #[test] fn bitcoin_genesis_first_transaction() { - let gen = bitcoin_genesis_tx(); + let gen = bitcoin_genesis_tx(&Params::MAINNET); assert_eq!(gen.version, transaction::Version::ONE); assert_eq!(gen.input.len(), 1); @@ -286,7 +327,7 @@ mod test { #[test] fn testnet_genesis_full_block() { - let gen = genesis_block(¶ms::TESTNET); + let gen = genesis_block(¶ms::TESTNET3); assert_eq!(gen.header.version, block::Version::ONE); assert_eq!(gen.header.prev_blockhash, BlockHash::GENESIS_PREVIOUS_BLOCK_HASH); assert_eq!( @@ -341,6 +382,7 @@ mod test { match network { Network::Bitcoin => {}, Network::Testnet(TestnetVersion::V3) => {}, + Network::Testnet(TestnetVersion::V4) => {}, Network::Signet => {}, Network::Regtest => {}, _ => panic!("update ChainHash::using_genesis_block and chain_hash_genesis_block with new variants"), @@ -361,6 +403,7 @@ mod test { chain_hash_genesis_block! { mainnet_chain_hash_genesis_block, Network::Bitcoin; testnet_chain_hash_genesis_block, Network::Testnet(TestnetVersion::V3); + testnet4_chain_hash_genesis_block, Network::Testnet(TestnetVersion::V4); signet_chain_hash_genesis_block, Network::Signet; regtest_chain_hash_genesis_block, Network::Regtest; } diff --git a/bitcoin/src/blockdata/script/push_bytes.rs b/bitcoin/src/blockdata/script/push_bytes.rs index 89cbdc268..654342b14 100644 --- a/bitcoin/src/blockdata/script/push_bytes.rs +++ b/bitcoin/src/blockdata/script/push_bytes.rs @@ -202,12 +202,12 @@ mod primitive { } } - // Sizes up to 73 to support all pubkey and signature sizes + // Sizes up to 76 to support all pubkey and signature sizes from_array! { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, - 71, 72, 73, + 71, 72, 73, 74, 75, 76 } /// Owned, growable counterpart to `PushBytes`. diff --git a/bitcoin/src/network/mod.rs b/bitcoin/src/network/mod.rs index 6db563003..c34ee1c08 100644 --- a/bitcoin/src/network/mod.rs +++ b/bitcoin/src/network/mod.rs @@ -68,6 +68,8 @@ impl From for NetworkKind { pub enum TestnetVersion { /// Testnet version 3. V3, + /// Testnet version 4. + V4, } /// The cryptocurrency network to act on. @@ -163,6 +165,7 @@ impl Network { Network::Bitcoin => "main", // For user-side compatibility, testnet3 is retained as test Network::Testnet(TestnetVersion::V3) => "test", + Network::Testnet(TestnetVersion::V4) => "testnet4", Network::Signet => "signet", Network::Regtest => "regtest", } @@ -183,6 +186,7 @@ impl Network { let network = match core_arg { "main" => Bitcoin, "test" => Testnet(TestnetVersion::V3), + "testnet4" => Testnet(TestnetVersion::V4), "signet" => Signet, "regtest" => Regtest, _ => return Err(ParseNetworkError(core_arg.to_owned())), @@ -221,7 +225,8 @@ impl Network { pub const fn params(self) -> &'static Params { match self { Network::Bitcoin => &Params::BITCOIN, - Network::Testnet(TestnetVersion::V3) => &Params::TESTNET, + Network::Testnet(TestnetVersion::V3) => &Params::TESTNET3, + Network::Testnet(TestnetVersion::V4) => &Params::TESTNET4, Network::Signet => &Params::SIGNET, Network::Regtest => &Params::REGTEST, } @@ -233,6 +238,7 @@ impl Network { match self { Network::Bitcoin => "bitcoin", Network::Testnet(TestnetVersion::V3) => "testnet", + Network::Testnet(TestnetVersion::V4) => "testnet4", Network::Signet => "signet", Network::Regtest => "regtest", } @@ -266,7 +272,7 @@ pub mod as_core_arg { Network::from_core_arg(s).map_err(|_| { E::invalid_value( serde::de::Unexpected::Str(s), - &"bitcoin network encoded as a string (either main, test, signet or regtest)", + &"bitcoin network encoded as a string (either main, test, testnet4, signet or regtest)", ) }) } @@ -274,7 +280,7 @@ pub mod as_core_arg { fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result { write!( formatter, - "bitcoin network encoded as a string (either main, test, signet or regtest)" + "bitcoin network encoded as a string (either main, test, testnet4, signet or regtest)" ) } } @@ -303,16 +309,12 @@ impl FromStr for Network { type Err = ParseNetworkError; #[inline] - /// Parses a string slice into a `Network` enum variant. - /// This function is used internally to convert a string representation - /// of a network type into its corresponding `Network` enum variant. - /// Returns `Ok(Network)` if the string matches a known network type, - /// otherwise returns `Err(ParseNetworkError)`. fn from_str(s: &str) -> Result { match s { "bitcoin" => Ok(Network::Bitcoin), // For user-side compatibility, testnet3 is retained as testnet "testnet" => Ok(Network::Testnet(TestnetVersion::V3)), + "testnet4" => Ok(Network::Testnet(TestnetVersion::V4)), "signet" => Ok(Network::Signet), "regtest" => Ok(Network::Regtest), _ => Err(ParseNetworkError(s.to_owned())), @@ -349,7 +351,8 @@ impl TryFrom for Network { match chain_hash { // Note: any new network entries must be matched against here. ChainHash::BITCOIN => Ok(Network::Bitcoin), - ChainHash::TESTNET => Ok(Network::Testnet(TestnetVersion::V3)), + ChainHash::TESTNET3 => Ok(Network::Testnet(TestnetVersion::V3)), + ChainHash::TESTNET4 => Ok(Network::Testnet(TestnetVersion::V4)), ChainHash::SIGNET => Ok(Network::Signet), ChainHash::REGTEST => Ok(Network::Regtest), _ => Err(UnknownChainHashError(chain_hash)), @@ -359,7 +362,7 @@ impl TryFrom for Network { #[cfg(test)] mod tests { - use super::Network; + use super::{Network, TestnetVersion}; use crate::consensus::encode::{deserialize, serialize}; use crate::p2p::ServiceFlags; @@ -367,16 +370,24 @@ mod tests { fn serialize_test() { assert_eq!(serialize(&Network::Bitcoin.magic()), &[0xf9, 0xbe, 0xb4, 0xd9]); assert_eq!( - serialize(&Network::Testnet(crate::TestnetVersion::V3).magic()), + serialize(&Network::Testnet(TestnetVersion::V3).magic()), &[0x0b, 0x11, 0x09, 0x07] ); + assert_eq!( + serialize(&Network::Testnet(TestnetVersion::V4).magic()), + &[0x1c, 0x16, 0x3f, 0x28] + ); assert_eq!(serialize(&Network::Signet.magic()), &[0x0a, 0x03, 0xcf, 0x40]); assert_eq!(serialize(&Network::Regtest.magic()), &[0xfa, 0xbf, 0xb5, 0xda]); assert_eq!(deserialize(&[0xf9, 0xbe, 0xb4, 0xd9]).ok(), Some(Network::Bitcoin.magic())); assert_eq!( deserialize(&[0x0b, 0x11, 0x09, 0x07]).ok(), - Some(Network::Testnet(crate::TestnetVersion::V3).magic()) + Some(Network::Testnet(TestnetVersion::V3).magic()) + ); + assert_eq!( + deserialize(&[0x1c, 0x16, 0x3f, 0x28]).ok(), + Some(Network::Testnet(TestnetVersion::V4).magic()) ); assert_eq!(deserialize(&[0x0a, 0x03, 0xcf, 0x40]).ok(), Some(Network::Signet.magic())); assert_eq!(deserialize(&[0xfa, 0xbf, 0xb5, 0xda]).ok(), Some(Network::Regtest.magic())); @@ -385,15 +396,14 @@ mod tests { #[test] fn string_test() { assert_eq!(Network::Bitcoin.to_string(), "bitcoin"); - assert_eq!(Network::Testnet(crate::TestnetVersion::V3).to_string(), "testnet"); + assert_eq!(Network::Testnet(TestnetVersion::V3).to_string(), "testnet"); + assert_eq!(Network::Testnet(TestnetVersion::V4).to_string(), "testnet4"); assert_eq!(Network::Regtest.to_string(), "regtest"); assert_eq!(Network::Signet.to_string(), "signet"); assert_eq!("bitcoin".parse::().unwrap(), Network::Bitcoin); - assert_eq!( - "testnet".parse::().unwrap(), - Network::Testnet(crate::TestnetVersion::V3) - ); + assert_eq!("testnet".parse::().unwrap(), Network::Testnet(TestnetVersion::V3)); + assert_eq!("testnet4".parse::().unwrap(), Network::Testnet(TestnetVersion::V4)); assert_eq!("regtest".parse::().unwrap(), Network::Regtest); assert_eq!("signet".parse::().unwrap(), Network::Signet); assert!("fakenet".parse::().is_err()); @@ -446,7 +456,8 @@ mod tests { use Network::*; let tests = vec![ (Bitcoin, "bitcoin"), - (Testnet(crate::TestnetVersion::V3), "testnet"), + (Testnet(TestnetVersion::V3), "testnet"), + (Testnet(TestnetVersion::V4), "testnet4"), (Signet, "signet"), (Regtest, "regtest"), ]; @@ -467,7 +478,8 @@ mod tests { fn from_to_core_arg() { let expected_pairs = [ (Network::Bitcoin, "main"), - (Network::Testnet(crate::TestnetVersion::V3), "test"), + (Network::Testnet(TestnetVersion::V3), "test"), + (Network::Testnet(TestnetVersion::V4), "testnet4"), (Network::Regtest, "regtest"), (Network::Signet, "signet"), ]; diff --git a/bitcoin/src/network/params.rs b/bitcoin/src/network/params.rs index 8414c955c..e17f5bc1c 100644 --- a/bitcoin/src/network/params.rs +++ b/bitcoin/src/network/params.rs @@ -3,7 +3,7 @@ //! Bitcoin consensus parameters. //! //! This module provides a predefined set of parameters for different Bitcoin -//! chains (such as mainnet, testnet). +//! chains (such as mainnet, testnet, testnet4). //! //! # Custom Signets Example //! @@ -128,8 +128,13 @@ pub struct Params { /// /// [using-statics-or-consts]: pub static MAINNET: Params = Params::MAINNET; -/// The testnet parameters. -pub static TESTNET: Params = Params::TESTNET; +/// The testnet3 parameters. +#[deprecated(since = "0.33.0", note = "Use TESTNET3 instead")] +pub static TESTNET: Params = Params::TESTNET3; +/// The testnet3 parameters. +pub static TESTNET3: Params = Params::TESTNET3; +/// The testnet4 parameters. +pub static TESTNET4: Params = Params::TESTNET4; /// The signet parameters. pub static SIGNET: Params = Params::SIGNET; /// The regtest parameters. @@ -157,7 +162,8 @@ impl Params { no_pow_retargeting: false, }; - /// The testnet parameters. + /// The testnet3 parameters. + #[deprecated(since = "0.33.0", note = "Use TESTNET3 instead")] pub const TESTNET: Params = Params { network: Network::Testnet(TestnetVersion::V3), bip16_time: 1333238400, // Apr 1 2012 @@ -174,6 +180,40 @@ impl Params { no_pow_retargeting: false, }; + /// The testnet3 parameters. + pub const TESTNET3: Params = Params { + network: Network::Testnet(TestnetVersion::V3), + bip16_time: 1333238400, // Apr 1 2012 + bip34_height: BlockHeight::from_u32(21111), // 0000000023b3a96d3484e5abb3755c413e7d41500f8e2a5c3f0dd01299cd8ef8 + bip65_height: BlockHeight::from_u32(581885), // 00000000007f6655f22f98e72ed80d8b06dc761d5da09df0fa1dc4be4f861eb6 + bip66_height: BlockHeight::from_u32(330776), // 000000002104c8c45e99a8853285a3b592602a3ccde2b832481da85e9e4ba182 + rule_change_activation_threshold: BlockInterval::from_u32(1512), // 75% + miner_confirmation_window: BlockInterval::from_u32(2016), + pow_limit: Target::MAX_ATTAINABLE_TESTNET, + max_attainable_target: Target::MAX_ATTAINABLE_TESTNET, + pow_target_spacing: 10 * 60, // 10 minutes. + pow_target_timespan: 14 * 24 * 60 * 60, // 2 weeks. + allow_min_difficulty_blocks: true, + no_pow_retargeting: false, + }; + + /// The testnet4 parameters. + pub const TESTNET4: Params = Params { + network: Network::Testnet(TestnetVersion::V4), + bip16_time: 1333238400, // Apr 1 2012 + bip34_height: BlockHeight::from_u32(1), + bip65_height: BlockHeight::from_u32(1), + bip66_height: BlockHeight::from_u32(1), + rule_change_activation_threshold: BlockInterval::from_u32(1512), // 75% + miner_confirmation_window: BlockInterval::from_u32(2016), + pow_limit: Target::MAX_ATTAINABLE_TESTNET, + max_attainable_target: Target::MAX_ATTAINABLE_TESTNET, + pow_target_spacing: 10 * 60, // 10 minutes. + pow_target_timespan: 14 * 24 * 60 * 60, // 2 weeks. + allow_min_difficulty_blocks: true, + no_pow_retargeting: false, + }; + /// The signet parameters. pub const SIGNET: Params = Params { network: Network::Signet, @@ -208,11 +248,12 @@ impl Params { no_pow_retargeting: true, }; - /// Creates parameters set for the given network. /// Creates parameters set for the given network. + /// Creates parameters set for the given network. pub const fn new(network: Network) -> Self { match network { Network::Bitcoin => Params::MAINNET, - Network::Testnet(TestnetVersion::V3) => Params::TESTNET, + Network::Testnet(TestnetVersion::V3) => Params::TESTNET3, + Network::Testnet(TestnetVersion::V4) => Params::TESTNET4, Network::Signet => Params::SIGNET, Network::Regtest => Params::REGTEST, } @@ -245,12 +286,5 @@ impl AsRef for Params { } impl AsRef for Network { - fn as_ref(&self) -> &Params { - match *self { - Network::Bitcoin => &MAINNET, - Network::Testnet(TestnetVersion::V3) => &TESTNET, - Network::Signet => &SIGNET, - Network::Regtest => ®TEST, - } - } + fn as_ref(&self) -> &Params { Self::params(*self) } } diff --git a/bitcoin/src/p2p/mod.rs b/bitcoin/src/p2p/mod.rs index eea926043..f860a9fea 100644 --- a/bitcoin/src/p2p/mod.rs +++ b/bitcoin/src/p2p/mod.rs @@ -217,7 +217,12 @@ impl Magic { /// Bitcoin mainnet network magic bytes. pub const BITCOIN: Self = Self([0xF9, 0xBE, 0xB4, 0xD9]); /// Bitcoin testnet3 network magic bytes. + #[deprecated(since = "0.33.0", note = "Use TESTNET3 instead")] pub const TESTNET: Self = Self([0x0B, 0x11, 0x09, 0x07]); + /// Bitcoin testnet3 network magic bytes. + pub const TESTNET3: Self = Self([0x0B, 0x11, 0x09, 0x07]); + /// Bitcoin testnet4 network magic bytes. + pub const TESTNET4: Self = Self([0x1c, 0x16, 0x3f, 0x28]); /// Bitcoin signet network magic bytes. pub const SIGNET: Self = Self([0x0A, 0x03, 0xCF, 0x40]); /// Bitcoin regtest network magic bytes. @@ -274,7 +279,8 @@ macro_rules! generate_network_magic_conversion { // `Network -> Magic` and `Magic -> Network` generate_network_magic_conversion! { Network::Bitcoin => Magic::BITCOIN, - Network::Testnet(TestnetVersion::V3) => Magic::TESTNET, + Network::Testnet(TestnetVersion::V3) => Magic::TESTNET3, + Network::Testnet(TestnetVersion::V4) => Magic::TESTNET4, Network::Signet => Magic::SIGNET, Network::Regtest => Magic::REGTEST, } @@ -432,6 +438,7 @@ mod tests { let known_network_magic_strs = [ ("f9beb4d9", Network::Bitcoin), ("0b110907", Network::Testnet(TestnetVersion::V3)), + ("1c163f28", Network::Testnet(TestnetVersion::V4)), ("fabfb5da", Network::Regtest), ("0a03cf40", Network::Signet), ];