Introduce TestnetVersion enum with only TestnetV3
This commit is contained in:
parent
e8a3c1f01b
commit
afa91a2030
|
@ -194,7 +194,7 @@ impl fmt::Display for AddressInner {
|
||||||
pub enum KnownHrp {
|
pub enum KnownHrp {
|
||||||
/// The main Bitcoin network.
|
/// The main Bitcoin network.
|
||||||
Mainnet,
|
Mainnet,
|
||||||
/// The test networks, testnet and signet.
|
/// The test networks, testnet (testnet3), and signet.
|
||||||
Testnets,
|
Testnets,
|
||||||
/// The regtest network.
|
/// The regtest network.
|
||||||
Regtest,
|
Regtest,
|
||||||
|
@ -207,7 +207,7 @@ impl KnownHrp {
|
||||||
|
|
||||||
match network {
|
match network {
|
||||||
Bitcoin => Self::Mainnet,
|
Bitcoin => Self::Mainnet,
|
||||||
Testnet | Signet => Self::Testnets,
|
Testnet(_) | Signet => Self::Testnets,
|
||||||
Regtest => Self::Regtest,
|
Regtest => Self::Regtest,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -708,11 +708,11 @@ impl Address<NetworkUnchecked> {
|
||||||
/// network a simple comparison is not enough anymore. Instead this function can be used.
|
/// network a simple comparison is not enough anymore. Instead this function can be used.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use bitcoin::{Address, Network};
|
/// use bitcoin::{Address, Network, TestnetVersion};
|
||||||
/// use bitcoin::address::NetworkUnchecked;
|
/// use bitcoin::address::NetworkUnchecked;
|
||||||
///
|
///
|
||||||
/// let address: Address<NetworkUnchecked> = "2N83imGV3gPwBzKJQvWJ7cRUY2SpUyU6A5e".parse().unwrap();
|
/// let address: Address<NetworkUnchecked> = "2N83imGV3gPwBzKJQvWJ7cRUY2SpUyU6A5e".parse().unwrap();
|
||||||
/// assert!(address.is_valid_for_network(Network::Testnet));
|
/// assert!(address.is_valid_for_network(Network::Testnet(TestnetVersion::V3)));
|
||||||
/// assert!(address.is_valid_for_network(Network::Regtest));
|
/// assert!(address.is_valid_for_network(Network::Regtest));
|
||||||
/// assert!(address.is_valid_for_network(Network::Signet));
|
/// assert!(address.is_valid_for_network(Network::Signet));
|
||||||
///
|
///
|
||||||
|
@ -720,7 +720,6 @@ impl Address<NetworkUnchecked> {
|
||||||
///
|
///
|
||||||
/// let address: Address<NetworkUnchecked> = "32iVBEu4dxkUQk9dJbZUiBiQdmypcEyJRf".parse().unwrap();
|
/// let address: Address<NetworkUnchecked> = "32iVBEu4dxkUQk9dJbZUiBiQdmypcEyJRf".parse().unwrap();
|
||||||
/// assert!(address.is_valid_for_network(Network::Bitcoin));
|
/// 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, n: Network) -> bool {
|
pub fn is_valid_for_network(&self, n: Network) -> bool {
|
||||||
use AddressInner::*;
|
use AddressInner::*;
|
||||||
|
@ -942,7 +941,7 @@ mod tests {
|
||||||
let addr = Address::p2pkh(key, NetworkKind::Test);
|
let addr = Address::p2pkh(key, NetworkKind::Test);
|
||||||
assert_eq!(&addr.to_string(), "mqkhEMH6NCeYjFybv7pvFC22MFeaNT9AQC");
|
assert_eq!(&addr.to_string(), "mqkhEMH6NCeYjFybv7pvFC22MFeaNT9AQC");
|
||||||
assert_eq!(addr.address_type(), Some(AddressType::P2pkh));
|
assert_eq!(addr.address_type(), Some(AddressType::P2pkh));
|
||||||
roundtrips(&addr, Testnet);
|
roundtrips(&addr, Testnet(crate::TestnetVersion::V3));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -965,7 +964,7 @@ mod tests {
|
||||||
let addr = Address::p2sh(&script, NetworkKind::Test).unwrap();
|
let addr = Address::p2sh(&script, NetworkKind::Test).unwrap();
|
||||||
assert_eq!(&addr.to_string(), "2N3zXjbwdTcPsJiy8sUK9FhWJhqQCxA8Jjr");
|
assert_eq!(&addr.to_string(), "2N3zXjbwdTcPsJiy8sUK9FhWJhqQCxA8Jjr");
|
||||||
assert_eq!(addr.address_type(), Some(AddressType::P2sh));
|
assert_eq!(addr.address_type(), Some(AddressType::P2sh));
|
||||||
roundtrips(&addr, Testnet);
|
roundtrips(&addr, Testnet(crate::TestnetVersion::V3));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1282,7 +1281,7 @@ mod tests {
|
||||||
let address = address_string
|
let address = address_string
|
||||||
.parse::<Address<_>>()
|
.parse::<Address<_>>()
|
||||||
.expect("address")
|
.expect("address")
|
||||||
.require_network(Network::Testnet)
|
.require_network(Network::Testnet(crate::TestnetVersion::V3))
|
||||||
.expect("testnet");
|
.expect("testnet");
|
||||||
|
|
||||||
let pubkey_string = "04e96e22004e3db93530de27ccddfdf1463975d2138ac018fc3e7ba1a2e5e0aad8e424d0b55e2436eb1d0dcd5cb2b8bcc6d53412c22f358de57803a6a655fbbd04";
|
let pubkey_string = "04e96e22004e3db93530de27ccddfdf1463975d2138ac018fc3e7ba1a2e5e0aad8e424d0b55e2436eb1d0dcd5cb2b8bcc6d53412c22f358de57803a6a655fbbd04";
|
||||||
|
|
|
@ -546,7 +546,7 @@ mod tests {
|
||||||
// Check testnet block 000000000000045e0b1660b6445b5e5c5ab63c9a4f956be7e1e69be04fa4497b
|
// Check testnet block 000000000000045e0b1660b6445b5e5c5ab63c9a4f956be7e1e69be04fa4497b
|
||||||
#[test]
|
#[test]
|
||||||
fn segwit_block_test() {
|
fn segwit_block_test() {
|
||||||
let params = Params::new(Network::Testnet);
|
let params = Params::new(Network::Testnet(crate::TestnetVersion::V3));
|
||||||
let segwit_block = include_bytes!("../../tests/data/testnet_block_000000000000045e0b1660b6445b5e5c5ab63c9a4f956be7e1e69be04fa4497b.raw").to_vec();
|
let segwit_block = include_bytes!("../../tests/data/testnet_block_000000000000045e0b1660b6445b5e5c5ab63c9a4f956be7e1e69be04fa4497b.raw").to_vec();
|
||||||
|
|
||||||
let decode: Result<Block, _> = deserialize(&segwit_block);
|
let decode: Result<Block, _> = deserialize(&segwit_block);
|
||||||
|
|
|
@ -17,7 +17,7 @@ use crate::opcodes::all::*;
|
||||||
use crate::pow::CompactTarget;
|
use crate::pow::CompactTarget;
|
||||||
use crate::transaction::{self, OutPoint, Transaction, TxIn, TxOut};
|
use crate::transaction::{self, OutPoint, Transaction, TxIn, TxOut};
|
||||||
use crate::witness::Witness;
|
use crate::witness::Witness;
|
||||||
use crate::{script, Amount, BlockHash, Sequence};
|
use crate::{script, Amount, BlockHash, Sequence, TestnetVersion};
|
||||||
|
|
||||||
/// How many seconds between blocks we expect on average.
|
/// How many seconds between blocks we expect on average.
|
||||||
pub const TARGET_BLOCK_SPACING: u32 = 600;
|
pub const TARGET_BLOCK_SPACING: u32 = 600;
|
||||||
|
@ -94,7 +94,6 @@ fn bitcoin_genesis_tx() -> Transaction {
|
||||||
sequence: Sequence::MAX,
|
sequence: Sequence::MAX,
|
||||||
witness: Witness::default(),
|
witness: Witness::default(),
|
||||||
});
|
});
|
||||||
|
|
||||||
// Outputs
|
// Outputs
|
||||||
let out_script =
|
let out_script =
|
||||||
script::Builder::new().push_slice(GENESIS_OUTPUT_PK).push_opcode(OP_CHECKSIG).into_script();
|
script::Builder::new().push_slice(GENESIS_OUTPUT_PK).push_opcode(OP_CHECKSIG).into_script();
|
||||||
|
@ -106,10 +105,12 @@ fn bitcoin_genesis_tx() -> Transaction {
|
||||||
|
|
||||||
/// Constructs and returns the genesis block.
|
/// Constructs and returns the genesis block.
|
||||||
pub fn genesis_block(params: impl AsRef<Params>) -> Block {
|
pub fn genesis_block(params: impl AsRef<Params>) -> Block {
|
||||||
|
let params_ref = params.as_ref();
|
||||||
let txdata = vec![bitcoin_genesis_tx()];
|
let txdata = vec![bitcoin_genesis_tx()];
|
||||||
let hash: sha256d::Hash = txdata[0].compute_txid().into();
|
let hash: sha256d::Hash = txdata[0].compute_txid().into();
|
||||||
let merkle_root = hash.into();
|
let merkle_root: crate::TxMerkleNode = hash.into();
|
||||||
match params.as_ref().network {
|
|
||||||
|
match params_ref.network {
|
||||||
Network::Bitcoin => Block {
|
Network::Bitcoin => Block {
|
||||||
header: block::Header {
|
header: block::Header {
|
||||||
version: block::Version::ONE,
|
version: block::Version::ONE,
|
||||||
|
@ -121,7 +122,7 @@ pub fn genesis_block(params: impl AsRef<Params>) -> Block {
|
||||||
},
|
},
|
||||||
txdata,
|
txdata,
|
||||||
},
|
},
|
||||||
Network::Testnet => Block {
|
Network::Testnet(TestnetVersion::V3) => Block {
|
||||||
header: block::Header {
|
header: block::Header {
|
||||||
version: block::Version::ONE,
|
version: block::Version::ONE,
|
||||||
prev_blockhash: BlockHash::GENESIS_PREVIOUS_BLOCK_HASH,
|
prev_blockhash: BlockHash::GENESIS_PREVIOUS_BLOCK_HASH,
|
||||||
|
@ -170,7 +171,7 @@ impl ChainHash {
|
||||||
111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247, 79, 147, 30, 131,
|
111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247, 79, 147, 30, 131,
|
||||||
101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0,
|
101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0,
|
||||||
]);
|
]);
|
||||||
/// `ChainHash` for testnet bitcoin.
|
/// `ChainHash` for testnet3 bitcoin.
|
||||||
pub const TESTNET: Self = Self([
|
pub const TESTNET: Self = Self([
|
||||||
67, 73, 127, 215, 248, 38, 149, 113, 8, 244, 163, 15, 217, 206, 195, 174, 186, 121, 151,
|
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,
|
32, 132, 233, 14, 173, 1, 234, 51, 9, 0, 0, 0, 0,
|
||||||
|
@ -191,9 +192,12 @@ impl ChainHash {
|
||||||
/// See [BOLT 0](https://github.com/lightning/bolts/blob/ffeece3dab1c52efdb9b53ae476539320fa44938/00-introduction.md#chain_hash)
|
/// See [BOLT 0](https://github.com/lightning/bolts/blob/ffeece3dab1c52efdb9b53ae476539320fa44938/00-introduction.md#chain_hash)
|
||||||
/// for specification.
|
/// for specification.
|
||||||
pub fn using_genesis_block(params: impl AsRef<Params>) -> Self {
|
pub fn using_genesis_block(params: impl AsRef<Params>) -> Self {
|
||||||
let network = params.as_ref().network;
|
match params.as_ref().network {
|
||||||
let hashes = [Self::BITCOIN, Self::TESTNET, Self::SIGNET, Self::REGTEST];
|
Network::Bitcoin => Self::BITCOIN,
|
||||||
hashes[network as usize]
|
Network::Testnet(TestnetVersion::V3) => Self::TESTNET,
|
||||||
|
Network::Signet => Self::SIGNET,
|
||||||
|
Network::Regtest => Self::REGTEST,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the hash of the `network` genesis block for use as a chain hash.
|
/// Returns the hash of the `network` genesis block for use as a chain hash.
|
||||||
|
@ -201,8 +205,12 @@ impl ChainHash {
|
||||||
/// See [BOLT 0](https://github.com/lightning/bolts/blob/ffeece3dab1c52efdb9b53ae476539320fa44938/00-introduction.md#chain_hash)
|
/// See [BOLT 0](https://github.com/lightning/bolts/blob/ffeece3dab1c52efdb9b53ae476539320fa44938/00-introduction.md#chain_hash)
|
||||||
/// for specification.
|
/// for specification.
|
||||||
pub const fn using_genesis_block_const(network: Network) -> Self {
|
pub const fn using_genesis_block_const(network: Network) -> Self {
|
||||||
let hashes = [Self::BITCOIN, Self::TESTNET, Self::SIGNET, Self::REGTEST];
|
match network {
|
||||||
hashes[network as usize]
|
Network::Bitcoin => Self::BITCOIN,
|
||||||
|
Network::Testnet(TestnetVersion::V3) => Self::TESTNET,
|
||||||
|
Network::Signet => Self::SIGNET,
|
||||||
|
Network::Regtest => Self::REGTEST,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts genesis block hash into `ChainHash`.
|
/// Converts genesis block hash into `ChainHash`.
|
||||||
|
@ -332,7 +340,7 @@ mod test {
|
||||||
#[allow(unreachable_patterns)] // This is specifically trying to catch later added variants.
|
#[allow(unreachable_patterns)] // This is specifically trying to catch later added variants.
|
||||||
match network {
|
match network {
|
||||||
Network::Bitcoin => {},
|
Network::Bitcoin => {},
|
||||||
Network::Testnet => {},
|
Network::Testnet(TestnetVersion::V3) => {},
|
||||||
Network::Signet => {},
|
Network::Signet => {},
|
||||||
Network::Regtest => {},
|
Network::Regtest => {},
|
||||||
_ => panic!("update ChainHash::using_genesis_block and chain_hash_genesis_block with new variants"),
|
_ => panic!("update ChainHash::using_genesis_block and chain_hash_genesis_block with new variants"),
|
||||||
|
@ -352,7 +360,7 @@ mod test {
|
||||||
|
|
||||||
chain_hash_genesis_block! {
|
chain_hash_genesis_block! {
|
||||||
mainnet_chain_hash_genesis_block, Network::Bitcoin;
|
mainnet_chain_hash_genesis_block, Network::Bitcoin;
|
||||||
testnet_chain_hash_genesis_block, Network::Testnet;
|
testnet_chain_hash_genesis_block, Network::Testnet(TestnetVersion::V3);
|
||||||
signet_chain_hash_genesis_block, Network::Signet;
|
signet_chain_hash_genesis_block, Network::Signet;
|
||||||
regtest_chain_hash_genesis_block, Network::Regtest;
|
regtest_chain_hash_genesis_block, Network::Regtest;
|
||||||
}
|
}
|
||||||
|
|
|
@ -135,7 +135,7 @@ pub use crate::{
|
||||||
crypto::key::{self, PrivateKey, PubkeyHash, PublicKey, CompressedPublicKey, WPubkeyHash, XOnlyPublicKey},
|
crypto::key::{self, PrivateKey, PubkeyHash, PublicKey, CompressedPublicKey, WPubkeyHash, XOnlyPublicKey},
|
||||||
crypto::sighash::{self, LegacySighash, SegwitV0Sighash, TapSighash, TapSighashTag},
|
crypto::sighash::{self, LegacySighash, SegwitV0Sighash, TapSighash, TapSighashTag},
|
||||||
merkle_tree::{MerkleBlock, TxMerkleNode, WitnessMerkleNode},
|
merkle_tree::{MerkleBlock, TxMerkleNode, WitnessMerkleNode},
|
||||||
network::{Network, NetworkKind},
|
network::{Network, NetworkKind, TestnetVersion},
|
||||||
network::params::{self, Params},
|
network::params::{self, Params},
|
||||||
pow::{CompactTarget, Target, Work},
|
pow::{CompactTarget, Target, Work},
|
||||||
psbt::Psbt,
|
psbt::Psbt,
|
||||||
|
|
|
@ -25,7 +25,7 @@ use core::str::FromStr;
|
||||||
|
|
||||||
use internals::write_err;
|
use internals::write_err;
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{de::Visitor, Deserialize, Deserializer, Serialize, Serializer};
|
||||||
|
|
||||||
use crate::constants::ChainHash;
|
use crate::constants::ChainHash;
|
||||||
use crate::p2p::Magic;
|
use crate::p2p::Magic;
|
||||||
|
@ -57,27 +57,70 @@ impl From<Network> for NetworkKind {
|
||||||
|
|
||||||
match n {
|
match n {
|
||||||
Bitcoin => NetworkKind::Main,
|
Bitcoin => NetworkKind::Main,
|
||||||
Testnet | Signet | Regtest => NetworkKind::Test,
|
Testnet(_) | Signet | Regtest => NetworkKind::Test,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The testnet version to act on.
|
||||||
|
#[derive(Copy, PartialEq, Eq, PartialOrd, Ord, Clone, Hash, Debug)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
pub enum TestnetVersion {
|
||||||
|
/// Testnet version 3.
|
||||||
|
V3,
|
||||||
|
}
|
||||||
|
|
||||||
/// The cryptocurrency network to act on.
|
/// The cryptocurrency network to act on.
|
||||||
#[derive(Copy, PartialEq, Eq, PartialOrd, Ord, Clone, Hash, Debug)]
|
#[derive(Copy, PartialEq, Eq, PartialOrd, Ord, Clone, Hash, Debug)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
|
||||||
#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
pub enum Network {
|
pub enum Network {
|
||||||
/// Mainnet Bitcoin.
|
/// Mainnet Bitcoin.
|
||||||
Bitcoin,
|
Bitcoin,
|
||||||
/// Bitcoin's testnet network.
|
/// Bitcoin's testnet network.
|
||||||
Testnet,
|
Testnet(TestnetVersion),
|
||||||
/// Bitcoin's signet network.
|
/// Bitcoin's signet network.
|
||||||
Signet,
|
Signet,
|
||||||
/// Bitcoin's regtest network.
|
/// Bitcoin's regtest network.
|
||||||
Regtest,
|
Regtest,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
|
impl Serialize for Network {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
serializer.serialize_str(self.as_display_str())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
|
impl<'de> Deserialize<'de> for Network {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
struct NetworkVisitor;
|
||||||
|
|
||||||
|
impl<'de> Visitor<'de> for NetworkVisitor {
|
||||||
|
type Value = Network;
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
formatter.write_str("a valid network identifier")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_str<E>(self, value: &str) -> Result<Network, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error,
|
||||||
|
{
|
||||||
|
Network::from_str(value).map_err(E::custom)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deserializer.deserialize_str(NetworkVisitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Network {
|
impl Network {
|
||||||
/// Creates a `Network` from the magic bytes.
|
/// Creates a `Network` from the magic bytes.
|
||||||
///
|
///
|
||||||
|
@ -118,7 +161,8 @@ impl Network {
|
||||||
pub fn to_core_arg(self) -> &'static str {
|
pub fn to_core_arg(self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
Network::Bitcoin => "main",
|
Network::Bitcoin => "main",
|
||||||
Network::Testnet => "test",
|
// For user-side compatibility, testnet3 is retained as test
|
||||||
|
Network::Testnet(TestnetVersion::V3) => "test",
|
||||||
Network::Signet => "signet",
|
Network::Signet => "signet",
|
||||||
Network::Regtest => "regtest",
|
Network::Regtest => "regtest",
|
||||||
}
|
}
|
||||||
|
@ -138,7 +182,7 @@ impl Network {
|
||||||
|
|
||||||
let network = match core_arg {
|
let network = match core_arg {
|
||||||
"main" => Bitcoin,
|
"main" => Bitcoin,
|
||||||
"test" => Testnet,
|
"test" => Testnet(TestnetVersion::V3),
|
||||||
"signet" => Signet,
|
"signet" => Signet,
|
||||||
"regtest" => Regtest,
|
"regtest" => Regtest,
|
||||||
_ => return Err(ParseNetworkError(core_arg.to_owned())),
|
_ => return Err(ParseNetworkError(core_arg.to_owned())),
|
||||||
|
@ -175,13 +219,23 @@ impl Network {
|
||||||
|
|
||||||
/// Returns the associated network parameters.
|
/// Returns the associated network parameters.
|
||||||
pub const fn params(self) -> &'static Params {
|
pub const fn params(self) -> &'static Params {
|
||||||
const PARAMS: [Params; 4] = [
|
match self {
|
||||||
Params::new(Network::Bitcoin),
|
Network::Bitcoin => &Params::BITCOIN,
|
||||||
Params::new(Network::Testnet),
|
Network::Testnet(TestnetVersion::V3) => &Params::TESTNET,
|
||||||
Params::new(Network::Signet),
|
Network::Signet => &Params::SIGNET,
|
||||||
Params::new(Network::Regtest),
|
Network::Regtest => &Params::REGTEST,
|
||||||
];
|
}
|
||||||
&PARAMS[self as usize]
|
}
|
||||||
|
|
||||||
|
/// Returns a string representation of the `Network` enum variant.
|
||||||
|
/// This is useful for displaying the network type as a string.
|
||||||
|
const fn as_display_str(self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
Network::Bitcoin => "bitcoin",
|
||||||
|
Network::Testnet(TestnetVersion::V3) => "testnet",
|
||||||
|
Network::Signet => "signet",
|
||||||
|
Network::Regtest => "regtest",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,31 +303,26 @@ impl FromStr for Network {
|
||||||
type Err = ParseNetworkError;
|
type Err = ParseNetworkError;
|
||||||
|
|
||||||
#[inline]
|
#[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<Self, Self::Err> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
use Network::*;
|
match s {
|
||||||
|
"bitcoin" => Ok(Network::Bitcoin),
|
||||||
let network = match s {
|
// For user-side compatibility, testnet3 is retained as testnet
|
||||||
"bitcoin" => Bitcoin,
|
"testnet" => Ok(Network::Testnet(TestnetVersion::V3)),
|
||||||
"testnet" => Testnet,
|
"signet" => Ok(Network::Signet),
|
||||||
"signet" => Signet,
|
"regtest" => Ok(Network::Regtest),
|
||||||
"regtest" => Regtest,
|
_ => Err(ParseNetworkError(s.to_owned())),
|
||||||
_ => return Err(ParseNetworkError(s.to_owned())),
|
}
|
||||||
};
|
|
||||||
Ok(network)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Network {
|
impl fmt::Display for Network {
|
||||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||||
use Network::*;
|
write!(f, "{}", self.as_display_str())
|
||||||
|
|
||||||
let s = match *self {
|
|
||||||
Bitcoin => "bitcoin",
|
|
||||||
Testnet => "testnet",
|
|
||||||
Signet => "signet",
|
|
||||||
Regtest => "regtest",
|
|
||||||
};
|
|
||||||
write!(f, "{}", s)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,7 +349,7 @@ impl TryFrom<ChainHash> for Network {
|
||||||
match chain_hash {
|
match chain_hash {
|
||||||
// Note: any new network entries must be matched against here.
|
// Note: any new network entries must be matched against here.
|
||||||
ChainHash::BITCOIN => Ok(Network::Bitcoin),
|
ChainHash::BITCOIN => Ok(Network::Bitcoin),
|
||||||
ChainHash::TESTNET => Ok(Network::Testnet),
|
ChainHash::TESTNET => Ok(Network::Testnet(TestnetVersion::V3)),
|
||||||
ChainHash::SIGNET => Ok(Network::Signet),
|
ChainHash::SIGNET => Ok(Network::Signet),
|
||||||
ChainHash::REGTEST => Ok(Network::Regtest),
|
ChainHash::REGTEST => Ok(Network::Regtest),
|
||||||
_ => Err(UnknownChainHashError(chain_hash)),
|
_ => Err(UnknownChainHashError(chain_hash)),
|
||||||
|
@ -317,12 +366,18 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn serialize_test() {
|
fn serialize_test() {
|
||||||
assert_eq!(serialize(&Network::Bitcoin.magic()), &[0xf9, 0xbe, 0xb4, 0xd9]);
|
assert_eq!(serialize(&Network::Bitcoin.magic()), &[0xf9, 0xbe, 0xb4, 0xd9]);
|
||||||
assert_eq!(serialize(&Network::Testnet.magic()), &[0x0b, 0x11, 0x09, 0x07]);
|
assert_eq!(
|
||||||
|
serialize(&Network::Testnet(crate::TestnetVersion::V3).magic()),
|
||||||
|
&[0x0b, 0x11, 0x09, 0x07]
|
||||||
|
);
|
||||||
assert_eq!(serialize(&Network::Signet.magic()), &[0x0a, 0x03, 0xcf, 0x40]);
|
assert_eq!(serialize(&Network::Signet.magic()), &[0x0a, 0x03, 0xcf, 0x40]);
|
||||||
assert_eq!(serialize(&Network::Regtest.magic()), &[0xfa, 0xbf, 0xb5, 0xda]);
|
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(&[0xf9, 0xbe, 0xb4, 0xd9]).ok(), Some(Network::Bitcoin.magic()));
|
||||||
assert_eq!(deserialize(&[0x0b, 0x11, 0x09, 0x07]).ok(), Some(Network::Testnet.magic()));
|
assert_eq!(
|
||||||
|
deserialize(&[0x0b, 0x11, 0x09, 0x07]).ok(),
|
||||||
|
Some(Network::Testnet(crate::TestnetVersion::V3).magic())
|
||||||
|
);
|
||||||
assert_eq!(deserialize(&[0x0a, 0x03, 0xcf, 0x40]).ok(), Some(Network::Signet.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()));
|
assert_eq!(deserialize(&[0xfa, 0xbf, 0xb5, 0xda]).ok(), Some(Network::Regtest.magic()));
|
||||||
}
|
}
|
||||||
|
@ -330,12 +385,15 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn string_test() {
|
fn string_test() {
|
||||||
assert_eq!(Network::Bitcoin.to_string(), "bitcoin");
|
assert_eq!(Network::Bitcoin.to_string(), "bitcoin");
|
||||||
assert_eq!(Network::Testnet.to_string(), "testnet");
|
assert_eq!(Network::Testnet(crate::TestnetVersion::V3).to_string(), "testnet");
|
||||||
assert_eq!(Network::Regtest.to_string(), "regtest");
|
assert_eq!(Network::Regtest.to_string(), "regtest");
|
||||||
assert_eq!(Network::Signet.to_string(), "signet");
|
assert_eq!(Network::Signet.to_string(), "signet");
|
||||||
|
|
||||||
assert_eq!("bitcoin".parse::<Network>().unwrap(), Network::Bitcoin);
|
assert_eq!("bitcoin".parse::<Network>().unwrap(), Network::Bitcoin);
|
||||||
assert_eq!("testnet".parse::<Network>().unwrap(), Network::Testnet);
|
assert_eq!(
|
||||||
|
"testnet".parse::<Network>().unwrap(),
|
||||||
|
Network::Testnet(crate::TestnetVersion::V3)
|
||||||
|
);
|
||||||
assert_eq!("regtest".parse::<Network>().unwrap(), Network::Regtest);
|
assert_eq!("regtest".parse::<Network>().unwrap(), Network::Regtest);
|
||||||
assert_eq!("signet".parse::<Network>().unwrap(), Network::Signet);
|
assert_eq!("signet".parse::<Network>().unwrap(), Network::Signet);
|
||||||
assert!("fakenet".parse::<Network>().is_err());
|
assert!("fakenet".parse::<Network>().is_err());
|
||||||
|
@ -386,8 +444,12 @@ mod tests {
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
fn serde_roundtrip() {
|
fn serde_roundtrip() {
|
||||||
use Network::*;
|
use Network::*;
|
||||||
let tests =
|
let tests = vec![
|
||||||
[(Bitcoin, "bitcoin"), (Testnet, "testnet"), (Signet, "signet"), (Regtest, "regtest")];
|
(Bitcoin, "bitcoin"),
|
||||||
|
(Testnet(crate::TestnetVersion::V3), "testnet"),
|
||||||
|
(Signet, "signet"),
|
||||||
|
(Regtest, "regtest"),
|
||||||
|
];
|
||||||
|
|
||||||
for tc in tests {
|
for tc in tests {
|
||||||
let network = tc.0;
|
let network = tc.0;
|
||||||
|
@ -405,7 +467,7 @@ mod tests {
|
||||||
fn from_to_core_arg() {
|
fn from_to_core_arg() {
|
||||||
let expected_pairs = [
|
let expected_pairs = [
|
||||||
(Network::Bitcoin, "main"),
|
(Network::Bitcoin, "main"),
|
||||||
(Network::Testnet, "test"),
|
(Network::Testnet(crate::TestnetVersion::V3), "test"),
|
||||||
(Network::Regtest, "regtest"),
|
(Network::Regtest, "regtest"),
|
||||||
(Network::Signet, "signet"),
|
(Network::Signet, "signet"),
|
||||||
];
|
];
|
||||||
|
|
|
@ -73,6 +73,7 @@ use crate::network::Network;
|
||||||
#[cfg(doc)]
|
#[cfg(doc)]
|
||||||
use crate::pow::CompactTarget;
|
use crate::pow::CompactTarget;
|
||||||
use crate::pow::Target;
|
use crate::pow::Target;
|
||||||
|
use crate::TestnetVersion;
|
||||||
|
|
||||||
/// Parameters that influence chain consensus.
|
/// Parameters that influence chain consensus.
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
@ -158,7 +159,7 @@ impl Params {
|
||||||
|
|
||||||
/// The testnet parameters.
|
/// The testnet parameters.
|
||||||
pub const TESTNET: Params = Params {
|
pub const TESTNET: Params = Params {
|
||||||
network: Network::Testnet,
|
network: Network::Testnet(TestnetVersion::V3),
|
||||||
bip16_time: 1333238400, // Apr 1 2012
|
bip16_time: 1333238400, // Apr 1 2012
|
||||||
bip34_height: BlockHeight::from_u32(21111), // 0000000023b3a96d3484e5abb3755c413e7d41500f8e2a5c3f0dd01299cd8ef8
|
bip34_height: BlockHeight::from_u32(21111), // 0000000023b3a96d3484e5abb3755c413e7d41500f8e2a5c3f0dd01299cd8ef8
|
||||||
bip65_height: BlockHeight::from_u32(581885), // 00000000007f6655f22f98e72ed80d8b06dc761d5da09df0fa1dc4be4f861eb6
|
bip65_height: BlockHeight::from_u32(581885), // 00000000007f6655f22f98e72ed80d8b06dc761d5da09df0fa1dc4be4f861eb6
|
||||||
|
@ -211,7 +212,7 @@ impl Params {
|
||||||
pub const fn new(network: Network) -> Self {
|
pub const fn new(network: Network) -> Self {
|
||||||
match network {
|
match network {
|
||||||
Network::Bitcoin => Params::MAINNET,
|
Network::Bitcoin => Params::MAINNET,
|
||||||
Network::Testnet => Params::TESTNET,
|
Network::Testnet(TestnetVersion::V3) => Params::TESTNET,
|
||||||
Network::Signet => Params::SIGNET,
|
Network::Signet => Params::SIGNET,
|
||||||
Network::Regtest => Params::REGTEST,
|
Network::Regtest => Params::REGTEST,
|
||||||
}
|
}
|
||||||
|
@ -247,7 +248,7 @@ impl AsRef<Params> for Network {
|
||||||
fn as_ref(&self) -> &Params {
|
fn as_ref(&self) -> &Params {
|
||||||
match *self {
|
match *self {
|
||||||
Network::Bitcoin => &MAINNET,
|
Network::Bitcoin => &MAINNET,
|
||||||
Network::Testnet => &TESTNET,
|
Network::Testnet(TestnetVersion::V3) => &TESTNET,
|
||||||
Network::Signet => &SIGNET,
|
Network::Signet => &SIGNET,
|
||||||
Network::Regtest => ®TEST,
|
Network::Regtest => ®TEST,
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ use internals::{debug_from_display, impl_to_hex_from_lower_hex, write_err};
|
||||||
use io::{BufRead, Write};
|
use io::{BufRead, Write};
|
||||||
|
|
||||||
use crate::consensus::encode::{self, Decodable, Encodable};
|
use crate::consensus::encode::{self, Decodable, Encodable};
|
||||||
use crate::network::{Network, Params};
|
use crate::network::{Network, Params, TestnetVersion};
|
||||||
use crate::prelude::{Borrow, BorrowMut, String, ToOwned};
|
use crate::prelude::{Borrow, BorrowMut, String, ToOwned};
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
|
@ -216,7 +216,7 @@ pub struct Magic([u8; 4]);
|
||||||
impl Magic {
|
impl Magic {
|
||||||
/// Bitcoin mainnet network magic bytes.
|
/// Bitcoin mainnet network magic bytes.
|
||||||
pub const BITCOIN: Self = Self([0xF9, 0xBE, 0xB4, 0xD9]);
|
pub const BITCOIN: Self = Self([0xF9, 0xBE, 0xB4, 0xD9]);
|
||||||
/// Bitcoin testnet network magic bytes.
|
/// Bitcoin testnet3 network magic bytes.
|
||||||
pub const TESTNET: Self = Self([0x0B, 0x11, 0x09, 0x07]);
|
pub const TESTNET: Self = Self([0x0B, 0x11, 0x09, 0x07]);
|
||||||
/// Bitcoin signet network magic bytes.
|
/// Bitcoin signet network magic bytes.
|
||||||
pub const SIGNET: Self = Self([0x0A, 0x03, 0xCF, 0x40]);
|
pub const SIGNET: Self = Self([0x0A, 0x03, 0xCF, 0x40]);
|
||||||
|
@ -245,12 +245,12 @@ impl FromStr for Magic {
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! generate_network_magic_conversion {
|
macro_rules! generate_network_magic_conversion {
|
||||||
($(Network::$network:ident => Magic::$magic:ident,)*) => {
|
($(Network::$network:ident$((TestnetVersion::$testnet_version:ident))? => Magic::$magic:ident,)*) => {
|
||||||
impl From<Network> for Magic {
|
impl From<Network> for Magic {
|
||||||
fn from(network: Network) -> Magic {
|
fn from(network: Network) -> Magic {
|
||||||
match network {
|
match network {
|
||||||
$(
|
$(
|
||||||
Network::$network => Magic::$magic,
|
Network::$network$((TestnetVersion::$testnet_version))? => Magic::$magic,
|
||||||
)*
|
)*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -262,7 +262,7 @@ macro_rules! generate_network_magic_conversion {
|
||||||
fn try_from(magic: Magic) -> Result<Self, Self::Error> {
|
fn try_from(magic: Magic) -> Result<Self, Self::Error> {
|
||||||
match magic {
|
match magic {
|
||||||
$(
|
$(
|
||||||
Magic::$magic => Ok(Network::$network),
|
Magic::$magic => Ok(Network::$network$((TestnetVersion::$testnet_version))?),
|
||||||
)*
|
)*
|
||||||
_ => Err(UnknownMagicError(magic)),
|
_ => Err(UnknownMagicError(magic)),
|
||||||
}
|
}
|
||||||
|
@ -270,10 +270,11 @@ macro_rules! generate_network_magic_conversion {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
// Generate conversion functions for all known networks.
|
||||||
|
// `Network -> Magic` and `Magic -> Network`
|
||||||
generate_network_magic_conversion! {
|
generate_network_magic_conversion! {
|
||||||
Network::Bitcoin => Magic::BITCOIN,
|
Network::Bitcoin => Magic::BITCOIN,
|
||||||
Network::Testnet => Magic::TESTNET,
|
Network::Testnet(TestnetVersion::V3) => Magic::TESTNET,
|
||||||
Network::Signet => Magic::SIGNET,
|
Network::Signet => Magic::SIGNET,
|
||||||
Network::Regtest => Magic::REGTEST,
|
Network::Regtest => Magic::REGTEST,
|
||||||
}
|
}
|
||||||
|
@ -430,7 +431,7 @@ mod tests {
|
||||||
fn magic_from_str() {
|
fn magic_from_str() {
|
||||||
let known_network_magic_strs = [
|
let known_network_magic_strs = [
|
||||||
("f9beb4d9", Network::Bitcoin),
|
("f9beb4d9", Network::Bitcoin),
|
||||||
("0b110907", Network::Testnet),
|
("0b110907", Network::Testnet(TestnetVersion::V3)),
|
||||||
("fabfb5da", Network::Regtest),
|
("fabfb5da", Network::Regtest),
|
||||||
("0a03cf40", Network::Signet),
|
("0a03cf40", Network::Signet),
|
||||||
];
|
];
|
||||||
|
|
|
@ -94,7 +94,7 @@ fn psbt_sign_taproot() {
|
||||||
//
|
//
|
||||||
let keystore = Keystore {
|
let keystore = Keystore {
|
||||||
mfp: mfp.parse::<Fingerprint>().unwrap(),
|
mfp: mfp.parse::<Fingerprint>().unwrap(),
|
||||||
sk: PrivateKey::new(kp.secret_key(), Network::Testnet),
|
sk: PrivateKey::new(kp.secret_key(), Network::Testnet(bitcoin::TestnetVersion::V3)),
|
||||||
};
|
};
|
||||||
let _ = psbt_key_path_spend.sign(&keystore, secp);
|
let _ = psbt_key_path_spend.sign(&keystore, secp);
|
||||||
|
|
||||||
|
@ -124,7 +124,7 @@ fn psbt_sign_taproot() {
|
||||||
|
|
||||||
let keystore = Keystore {
|
let keystore = Keystore {
|
||||||
mfp: mfp.parse::<Fingerprint>().unwrap(),
|
mfp: mfp.parse::<Fingerprint>().unwrap(),
|
||||||
sk: PrivateKey::new(kp.secret_key(), Network::Testnet),
|
sk: PrivateKey::new(kp.secret_key(), Network::Testnet(bitcoin::TestnetVersion::V3)),
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -195,7 +195,7 @@ fn create_taproot_tree(
|
||||||
|
|
||||||
fn create_p2tr_address(tree: TaprootSpendInfo) -> Address {
|
fn create_p2tr_address(tree: TaprootSpendInfo) -> Address {
|
||||||
let output_key = tree.output_key();
|
let output_key = tree.output_key();
|
||||||
Address::p2tr_tweaked(output_key, Network::Testnet)
|
Address::p2tr_tweaked(output_key, Network::Testnet(bitcoin::TestnetVersion::V3))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_psbt_for_taproot_key_path_spend(
|
fn create_psbt_for_taproot_key_path_spend(
|
||||||
|
|
Loading…
Reference in New Issue