Merge rust-bitcoin/rust-bitcoin#2541: Reduce usage of `Network` in the public API
f6467ac98d
Minimize usage of Network in public API (Tobin C. Harding)3ec5eff56e
Add Magic::from_params (Tobin C. Harding) Pull request description: Minimize usage of the `Network` enum in the public API. See #2225 for context, and https://github.com/rust-bitcoin/rust-bitcoin/pull/1291#discussion_r1492993788 for an interpretation of that long discussion. Close: #2169 ACKs for top commit: sanket1729: reACKf6467ac98d
. apoelstra: ACKf6467ac98d
Tree-SHA512: f12ecd9578371b3162382a9181f7f982e4d0661915af3cfdc21516192cc4abb745e1ff452649a0862445e91232f74287f98eb7e9fc68ed1581ff1a97b7216b6a
This commit is contained in:
commit
b5fbdcd68a
|
@ -43,6 +43,7 @@ use crate::blockdata::constants::{
|
||||||
use crate::blockdata::script::witness_program::WitnessProgram;
|
use crate::blockdata::script::witness_program::WitnessProgram;
|
||||||
use crate::blockdata::script::witness_version::WitnessVersion;
|
use crate::blockdata::script::witness_version::WitnessVersion;
|
||||||
use crate::blockdata::script::{self, Script, ScriptBuf, ScriptHash};
|
use crate::blockdata::script::{self, Script, ScriptBuf, ScriptHash};
|
||||||
|
use crate::consensus::Params;
|
||||||
use crate::crypto::key::{
|
use crate::crypto::key::{
|
||||||
CompressedPublicKey, PubkeyHash, PublicKey, TweakedPublicKey, UntweakedPublicKey,
|
CompressedPublicKey, PubkeyHash, PublicKey, TweakedPublicKey, UntweakedPublicKey,
|
||||||
};
|
};
|
||||||
|
@ -505,7 +506,8 @@ impl Address {
|
||||||
pub fn is_spend_standard(&self) -> bool { self.address_type().is_some() }
|
pub fn is_spend_standard(&self) -> bool { self.address_type().is_some() }
|
||||||
|
|
||||||
/// Constructs an [`Address`] from an output script (`scriptPubkey`).
|
/// Constructs an [`Address`] from an output script (`scriptPubkey`).
|
||||||
pub fn from_script(script: &Script, network: Network) -> Result<Address, FromScriptError> {
|
pub fn from_script(script: &Script, params: impl AsRef<Params>) -> Result<Address, FromScriptError> {
|
||||||
|
let network = params.as_ref().network;
|
||||||
if script.is_p2pkh() {
|
if script.is_p2pkh() {
|
||||||
let bytes = script.as_bytes()[3..23].try_into().expect("statically 20B long");
|
let bytes = script.as_bytes()[3..23].try_into().expect("statically 20B long");
|
||||||
let hash = PubkeyHash::from_byte_array(bytes);
|
let hash = PubkeyHash::from_byte_array(bytes);
|
||||||
|
@ -820,6 +822,7 @@ mod tests {
|
||||||
use hex_lit::hex;
|
use hex_lit::hex;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::consensus::params;
|
||||||
use crate::network::Network::{Bitcoin, Testnet};
|
use crate::network::Network::{Bitcoin, Testnet};
|
||||||
|
|
||||||
fn roundtrips(addr: &Address, network: Network) {
|
fn roundtrips(addr: &Address, network: Network) {
|
||||||
|
@ -1281,7 +1284,7 @@ mod tests {
|
||||||
assert_eq!(Address::from_script(&bad_p2wpkh, Network::Bitcoin), expected);
|
assert_eq!(Address::from_script(&bad_p2wpkh, Network::Bitcoin), expected);
|
||||||
assert_eq!(Address::from_script(&bad_p2wsh, Network::Bitcoin), expected);
|
assert_eq!(Address::from_script(&bad_p2wsh, Network::Bitcoin), expected);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Address::from_script(&invalid_segwitv0_script, Network::Bitcoin),
|
Address::from_script(&invalid_segwitv0_script, ¶ms::MAINNET),
|
||||||
Err(FromScriptError::WitnessProgram(witness_program::Error::InvalidSegwitV0Length(17)))
|
Err(FromScriptError::WitnessProgram(witness_program::Error::InvalidSegwitV0Length(17)))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ use crate::blockdata::opcodes::all::*;
|
||||||
use crate::blockdata::script;
|
use crate::blockdata::script;
|
||||||
use crate::blockdata::transaction::{self, OutPoint, Sequence, Transaction, TxIn, TxOut};
|
use crate::blockdata::transaction::{self, OutPoint, Sequence, Transaction, TxIn, TxOut};
|
||||||
use crate::blockdata::witness::Witness;
|
use crate::blockdata::witness::Witness;
|
||||||
|
use crate::consensus::Params;
|
||||||
use crate::internal_macros::impl_bytes_newtype;
|
use crate::internal_macros::impl_bytes_newtype;
|
||||||
use crate::network::Network;
|
use crate::network::Network;
|
||||||
use crate::pow::CompactTarget;
|
use crate::pow::CompactTarget;
|
||||||
|
@ -84,11 +85,11 @@ fn bitcoin_genesis_tx() -> Transaction {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructs and returns the genesis block.
|
/// Constructs and returns the genesis block.
|
||||||
pub fn genesis_block(network: Network) -> Block {
|
pub fn genesis_block(params: impl AsRef<Params>) -> Block {
|
||||||
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 = hash.into();
|
||||||
match network {
|
match params.as_ref().network {
|
||||||
Network::Bitcoin => Block {
|
Network::Bitcoin => Block {
|
||||||
header: block::Header {
|
header: block::Header {
|
||||||
version: block::Version::ONE,
|
version: block::Version::ONE,
|
||||||
|
@ -169,7 +170,17 @@ 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(network: Network) -> Self {
|
pub fn using_genesis_block(params: impl AsRef<Params>) -> Self {
|
||||||
|
let network = params.as_ref().network;
|
||||||
|
let hashes = [Self::BITCOIN, Self::TESTNET, Self::SIGNET, Self::REGTEST];
|
||||||
|
hashes[network as usize]
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the hash of the `network` genesis block for use as a chain hash.
|
||||||
|
///
|
||||||
|
/// See [BOLT 0](https://github.com/lightning/bolts/blob/ffeece3dab1c52efdb9b53ae476539320fa44938/00-introduction.md#chain_hash)
|
||||||
|
/// for specification.
|
||||||
|
pub const fn using_genesis_block_const(network: Network) -> Self {
|
||||||
let hashes = [Self::BITCOIN, Self::TESTNET, Self::SIGNET, Self::REGTEST];
|
let hashes = [Self::BITCOIN, Self::TESTNET, Self::SIGNET, Self::REGTEST];
|
||||||
hashes[network as usize]
|
hashes[network as usize]
|
||||||
}
|
}
|
||||||
|
@ -187,6 +198,7 @@ mod test {
|
||||||
use hex::test_hex_unwrap as hex;
|
use hex::test_hex_unwrap as hex;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::consensus::params;
|
||||||
use crate::consensus::encode::serialize;
|
use crate::consensus::encode::serialize;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -213,9 +225,21 @@ mod test {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn bitcoin_genesis_block_calling_convention() {
|
||||||
|
// This is the best.
|
||||||
|
let _ = genesis_block(¶ms::MAINNET);
|
||||||
|
// this works and is ok too.
|
||||||
|
let _ = genesis_block(&Network::Bitcoin);
|
||||||
|
let _ = genesis_block(Network::Bitcoin);
|
||||||
|
// This works too, but is suboptimal because it inlines the const.
|
||||||
|
let _ = genesis_block(Params::MAINNET);
|
||||||
|
let _ = genesis_block(&Params::MAINNET);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn bitcoin_genesis_full_block() {
|
fn bitcoin_genesis_full_block() {
|
||||||
let gen = genesis_block(Network::Bitcoin);
|
let gen = genesis_block(¶ms::MAINNET);
|
||||||
|
|
||||||
assert_eq!(gen.header.version, block::Version::ONE);
|
assert_eq!(gen.header.version, block::Version::ONE);
|
||||||
assert_eq!(gen.header.prev_blockhash, Hash::all_zeros());
|
assert_eq!(gen.header.prev_blockhash, Hash::all_zeros());
|
||||||
|
@ -235,7 +259,7 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn testnet_genesis_full_block() {
|
fn testnet_genesis_full_block() {
|
||||||
let gen = genesis_block(Network::Testnet);
|
let gen = genesis_block(¶ms::TESTNET);
|
||||||
assert_eq!(gen.header.version, block::Version::ONE);
|
assert_eq!(gen.header.version, block::Version::ONE);
|
||||||
assert_eq!(gen.header.prev_blockhash, Hash::all_zeros());
|
assert_eq!(gen.header.prev_blockhash, Hash::all_zeros());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -253,7 +277,7 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn signet_genesis_full_block() {
|
fn signet_genesis_full_block() {
|
||||||
let gen = genesis_block(Network::Signet);
|
let gen = genesis_block(¶ms::SIGNET);
|
||||||
assert_eq!(gen.header.version, block::Version::ONE);
|
assert_eq!(gen.header.version, block::Version::ONE);
|
||||||
assert_eq!(gen.header.prev_blockhash, Hash::all_zeros());
|
assert_eq!(gen.header.prev_blockhash, Hash::all_zeros());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -280,7 +304,7 @@ mod test {
|
||||||
let hash = sha256::Hash::from_slice(genesis_hash.as_byte_array()).unwrap();
|
let hash = sha256::Hash::from_slice(genesis_hash.as_byte_array()).unwrap();
|
||||||
let want = format!("{:02x}", hash);
|
let want = format!("{:02x}", hash);
|
||||||
|
|
||||||
let chain_hash = ChainHash::using_genesis_block(network);
|
let chain_hash = ChainHash::using_genesis_block_const(network);
|
||||||
let got = format!("{:02x}", chain_hash);
|
let got = format!("{:02x}", chain_hash);
|
||||||
|
|
||||||
// Compare strings because the spec specifically states how the chain hash must encode to hex.
|
// Compare strings because the spec specifically states how the chain hash must encode to hex.
|
||||||
|
@ -317,7 +341,7 @@ mod test {
|
||||||
// Test vector taken from: https://github.com/lightning/bolts/blob/master/00-introduction.md
|
// Test vector taken from: https://github.com/lightning/bolts/blob/master/00-introduction.md
|
||||||
#[test]
|
#[test]
|
||||||
fn mainnet_chain_hash_test_vector() {
|
fn mainnet_chain_hash_test_vector() {
|
||||||
let got = ChainHash::using_genesis_block(Network::Bitcoin).to_string();
|
let got = ChainHash::using_genesis_block_const(Network::Bitcoin).to_string();
|
||||||
let want = "6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000";
|
let want = "6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000";
|
||||||
assert_eq!(got, want);
|
assert_eq!(got, want);
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,10 +91,11 @@ impl OutPoint {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// use bitcoin::consensus::params;
|
||||||
/// use bitcoin::constants::genesis_block;
|
/// use bitcoin::constants::genesis_block;
|
||||||
/// use bitcoin::Network;
|
/// use bitcoin::Network;
|
||||||
///
|
///
|
||||||
/// let block = genesis_block(Network::Bitcoin);
|
/// let block = genesis_block(¶ms::MAINNET);
|
||||||
/// let tx = &block.txdata[0];
|
/// let tx = &block.txdata[0];
|
||||||
///
|
///
|
||||||
/// // Coinbase transactions don't have any previous output.
|
/// // Coinbase transactions don't have any previous output.
|
||||||
|
|
|
@ -56,6 +56,21 @@ pub struct Params {
|
||||||
pub no_pow_retargeting: bool,
|
pub no_pow_retargeting: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The mainnet parameters.
|
||||||
|
///
|
||||||
|
/// Use this for a static reference e.g., `¶ms::MAINNET`.
|
||||||
|
///
|
||||||
|
/// For more on static vs const see The Rust Reference [using-statics-or-consts] section.
|
||||||
|
///
|
||||||
|
/// [using-statics-or-consts]: <https://doc.rust-lang.org/reference/items/static-items.html#using-statics-or-consts>
|
||||||
|
pub static MAINNET: Params = Params::MAINNET;
|
||||||
|
/// The testnet parameters.
|
||||||
|
pub static TESTNET: Params = Params::TESTNET;
|
||||||
|
/// The signet parameters.
|
||||||
|
pub static SIGNET: Params = Params::SIGNET;
|
||||||
|
/// The regtest parameters.
|
||||||
|
pub static REGTEST: Params = Params::REGTEST;
|
||||||
|
|
||||||
impl Params {
|
impl Params {
|
||||||
/// The mainnet parameters (alias for `Params::MAINNET`).
|
/// The mainnet parameters (alias for `Params::MAINNET`).
|
||||||
pub const BITCOIN: Params = Params::MAINNET;
|
pub const BITCOIN: Params = Params::MAINNET;
|
||||||
|
@ -163,3 +178,14 @@ impl From<&Network> for &'static Params {
|
||||||
impl AsRef<Params> for Params {
|
impl AsRef<Params> for Params {
|
||||||
fn as_ref(&self) -> &Params { self }
|
fn as_ref(&self) -> &Params { self }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AsRef<Params> for Network {
|
||||||
|
fn as_ref(&self) -> &Params {
|
||||||
|
match *self {
|
||||||
|
Network::Bitcoin => &MAINNET,
|
||||||
|
Network::Testnet => &TESTNET,
|
||||||
|
Network::Signet => &SIGNET,
|
||||||
|
Network::Regtest => ®TEST,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -129,6 +129,7 @@ pub use crate::{
|
||||||
blockdata::weight::Weight,
|
blockdata::weight::Weight,
|
||||||
blockdata::witness::{self, Witness},
|
blockdata::witness::{self, Witness},
|
||||||
consensus::encode::VarInt,
|
consensus::encode::VarInt,
|
||||||
|
consensus::params,
|
||||||
crypto::ecdsa,
|
crypto::ecdsa,
|
||||||
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},
|
||||||
|
|
|
@ -154,7 +154,7 @@ impl Network {
|
||||||
/// let network = Network::Bitcoin;
|
/// let network = Network::Bitcoin;
|
||||||
/// assert_eq!(network.chain_hash(), ChainHash::BITCOIN);
|
/// assert_eq!(network.chain_hash(), ChainHash::BITCOIN);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn chain_hash(self) -> ChainHash { ChainHash::using_genesis_block(self) }
|
pub fn chain_hash(self) -> ChainHash { ChainHash::using_genesis_block_const(self) }
|
||||||
|
|
||||||
/// Creates a `Network` from the chain hash (genesis block hash).
|
/// Creates a `Network` from the chain hash (genesis block hash).
|
||||||
///
|
///
|
||||||
|
|
|
@ -28,6 +28,7 @@ use internals::{debug_from_display, 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::consensus::Params;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::Network;
|
use crate::Network;
|
||||||
|
|
||||||
|
@ -226,6 +227,11 @@ impl Magic {
|
||||||
|
|
||||||
/// Get network magic bytes.
|
/// Get network magic bytes.
|
||||||
pub fn to_bytes(self) -> [u8; 4] { self.0 }
|
pub fn to_bytes(self) -> [u8; 4] { self.0 }
|
||||||
|
|
||||||
|
/// Returns the magic bytes for the network defined by `params`.
|
||||||
|
pub fn from_params(params: impl AsRef<Params>) -> Self {
|
||||||
|
params.as_ref().network.into()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromStr for Magic {
|
impl FromStr for Magic {
|
||||||
|
|
Loading…
Reference in New Issue