// SPDX-License-Identifier: CC0-1.0 //! Bitcoin consensus parameters. //! //! This module provides a predefined set of parameters for different Bitcoin //! chains (such as mainnet, testnet). //! //! # Custom Signets Example //! //! In various places in this crate we take `AsRef` as a parameter, in order to create a //! custom type that can be used is such places you might want to do the following: //! //! ``` //! use bitcoin::network::Params; //! use bitcoin::{p2p, Script, ScriptBuf, Network, Target}; //! //! const POW_TARGET_SPACING: u64 = 120; // Two minutes. //! const MAGIC: [u8; 4] = [1, 2, 3, 4]; //! //! pub struct CustomParams { //! params: Params, //! magic: [u8; 4], //! challenge_script: ScriptBuf, //! } //! //! impl CustomParams { //! /// Creates a new custom params. //! pub fn new() -> Self { //! let mut params = Params::new(Network::Signet); //! params.pow_target_spacing = POW_TARGET_SPACING; //! //! // This would be something real (see BIP-325). //! let challenge_script = ScriptBuf::new(); //! //! Self { //! params, //! magic: MAGIC, //! challenge_script, //! } //! } //! //! /// Returns the custom magic bytes. //! pub fn magic(&self) -> p2p::Magic { p2p::Magic::from_bytes(self.magic) } //! //! /// Returns the custom signet challenge script. //! pub fn challenge_script(&self) -> &Script { &self.challenge_script } //! } //! //! impl AsRef for CustomParams { //! fn as_ref(&self) -> &Params { &self.params } //! } //! //! impl Default for CustomParams { //! fn default() -> Self { Self::new() } //! } //! //! # { // Just check the code above is usable. //! # let target = Target::MAX_ATTAINABLE_SIGNET; //! # //! # let signet = Params::SIGNET; //! # let _ = target.difficulty(signet); //! # //! # let custom = CustomParams::new(); //! # let _ = custom.magic(); //! # let _ = custom.challenge_script(); //! # let _ = target.difficulty(custom); //! # } //! ``` use units::{BlockHeight, BlockInterval}; use crate::network::Network; #[cfg(doc)] use crate::pow::CompactTarget; use crate::pow::Target; /// Parameters that influence chain consensus. #[non_exhaustive] #[derive(Debug, Clone)] pub struct Params { /// Network for which parameters are valid. pub network: Network, /// Time when BIP16 becomes active. pub bip16_time: u32, /// Block height at which BIP34 becomes active. pub bip34_height: BlockHeight, /// Block height at which BIP65 becomes active. pub bip65_height: BlockHeight, /// Block height at which BIP66 becomes active. pub bip66_height: BlockHeight, /// Minimum blocks including miner confirmation of the total of 2016 blocks in a retargeting period, /// (nPowTargetTimespan / nPowTargetSpacing) which is also used for BIP9 deployments. /// Examples: 1916 for 95%, 1512 for testchains. pub rule_change_activation_threshold: BlockInterval, /// Number of blocks with the same set of rules. pub miner_confirmation_window: BlockInterval, /// Proof of work limit value. It contains the lowest possible difficulty. #[deprecated(since = "0.32.0", note = "field renamed to max_attainable_target")] pub pow_limit: Target, /// The maximum **attainable** target value for these params. /// /// Not all target values are attainable because consensus code uses the compact format to /// represent targets (see [`CompactTarget`]). /// /// Note that this value differs from Bitcoin Core's powLimit field in that this value is /// attainable, but Bitcoin Core's is not. Specifically, because targets in Bitcoin are always /// rounded to the nearest float expressible in "compact form", not all targets are attainable. /// Still, this should not affect consensus as the only place where the non-compact form of /// this is used in Bitcoin Core's consensus algorithm is in comparison and there are no /// compact-expressible values between Bitcoin Core's and the limit expressed here. pub max_attainable_target: Target, /// Expected amount of time to mine one block. pub pow_target_spacing: u64, /// Difficulty recalculation interval. pub pow_target_timespan: u64, /// Determines whether minimal difficulty may be used for blocks or not. pub allow_min_difficulty_blocks: bool, /// Determines whether retargeting is disabled for this network or not. 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]: 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; #[allow(deprecated)] // For `pow_limit`. impl Params { /// The mainnet parameters (alias for `Params::MAINNET`). pub const BITCOIN: Params = Params::MAINNET; /// The mainnet parameters. pub const MAINNET: Params = Params { network: Network::Bitcoin, bip16_time: 1333238400, // Apr 1 2012 bip34_height: BlockHeight::from_u32(227931), // 000000000000024b89b42a942fe0d9fea3bb44ab7bd1b19115dd6a759c0808b8 bip65_height: BlockHeight::from_u32(388381), // 000000000000000004c2b624ed5d7756c508d90fd0da2c7c679febfa6c4735f0 bip66_height: BlockHeight::from_u32(363725), // 00000000000000000379eaa19dce8c9b722d46ae6a57c2f1a988119488b50931 rule_change_activation_threshold: BlockInterval::from_u32(1916), // 95% miner_confirmation_window: BlockInterval::from_u32(2016), pow_limit: Target::MAX_ATTAINABLE_MAINNET, max_attainable_target: Target::MAX_ATTAINABLE_MAINNET, pow_target_spacing: 10 * 60, // 10 minutes. pow_target_timespan: 14 * 24 * 60 * 60, // 2 weeks. allow_min_difficulty_blocks: false, no_pow_retargeting: false, }; /// The testnet parameters. pub const TESTNET: Params = Params { network: Network::Testnet, 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 signet parameters. pub const SIGNET: Params = Params { network: Network::Signet, 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(1916), // 95% miner_confirmation_window: BlockInterval::from_u32(2016), pow_limit: Target::MAX_ATTAINABLE_SIGNET, max_attainable_target: Target::MAX_ATTAINABLE_SIGNET, pow_target_spacing: 10 * 60, // 10 minutes. pow_target_timespan: 14 * 24 * 60 * 60, // 2 weeks. allow_min_difficulty_blocks: false, no_pow_retargeting: false, }; /// The regtest parameters. pub const REGTEST: Params = Params { network: Network::Regtest, bip16_time: 1333238400, // Apr 1 2012 bip34_height: BlockHeight::from_u32(100000000), // not activated on regtest bip65_height: BlockHeight::from_u32(1351), bip66_height: BlockHeight::from_u32(1251), // used only in rpc tests rule_change_activation_threshold: BlockInterval::from_u32(108), // 75% miner_confirmation_window: BlockInterval::from_u32(144), pow_limit: Target::MAX_ATTAINABLE_REGTEST, max_attainable_target: Target::MAX_ATTAINABLE_REGTEST, pow_target_spacing: 10 * 60, // 10 minutes. pow_target_timespan: 14 * 24 * 60 * 60, // 2 weeks. allow_min_difficulty_blocks: true, no_pow_retargeting: true, }; /// 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 => Params::TESTNET, Network::Signet => Params::SIGNET, Network::Regtest => Params::REGTEST, } } /// Calculates the number of blocks between difficulty adjustments. pub fn difficulty_adjustment_interval(&self) -> u64 { self.pow_target_timespan / self.pow_target_spacing } } impl From for Params { fn from(value: Network) -> Self { Self::new(value) } } impl From<&Network> for Params { fn from(value: &Network) -> Self { Self::new(*value) } } impl From for &'static Params { fn from(value: Network) -> Self { value.params() } } impl From<&Network> for &'static Params { fn from(value: &Network) -> Self { value.params() } } impl AsRef for Params { fn as_ref(&self) -> &Params { self } } impl AsRef for Network { fn as_ref(&self) -> &Params { match *self { Network::Bitcoin => &MAINNET, Network::Testnet => &TESTNET, Network::Signet => &SIGNET, Network::Regtest => ®TEST, } } }