From 38005f6aa7a580e9f4d28cb1b37b10375a304e6d Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Wed, 11 Oct 2023 08:50:42 +1100 Subject: [PATCH] Use Target for pow_limit The `Params::pow_limit` field is currently a `Work` type, this is incorrect. The proof of work limit is the highest _target_ not the lowest work (even though these have a relationship). Note that we use the highest _attainable_ target, this differs from Bitcoin Core and the reasoning is already documented in the code. Add new consts and document where they came from as well as how they differ to Core. Use the new consts in the various network specific `Params` types. --- bitcoin/src/consensus/params.rs | 12 ++++++------ bitcoin/src/pow.rs | 33 +++++++++++++++++++++------------ 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/bitcoin/src/consensus/params.rs b/bitcoin/src/consensus/params.rs index 12eb1f5e..e2d747f8 100644 --- a/bitcoin/src/consensus/params.rs +++ b/bitcoin/src/consensus/params.rs @@ -7,7 +7,7 @@ //! use crate::network::Network; -use crate::pow::Work; +use crate::pow::Target; /// Parameters that influence chain consensus. #[non_exhaustive] @@ -37,7 +37,7 @@ pub struct Params { /// 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 pow_limit: Work, + pub pow_limit: Target, /// Expected amount of time to mine one block. pub pow_target_spacing: u64, /// Difficulty recalculation interval. @@ -60,7 +60,7 @@ impl Params { bip66_height: 363725, // 00000000000000000379eaa19dce8c9b722d46ae6a57c2f1a988119488b50931 rule_change_activation_threshold: 1916, // 95% miner_confirmation_window: 2016, - pow_limit: Work::MAINNET_MIN, + pow_limit: 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, @@ -74,7 +74,7 @@ impl Params { bip66_height: 330776, // 000000002104c8c45e99a8853285a3b592602a3ccde2b832481da85e9e4ba182 rule_change_activation_threshold: 1512, // 75% miner_confirmation_window: 2016, - pow_limit: Work::TESTNET_MIN, + pow_limit: 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, @@ -88,7 +88,7 @@ impl Params { bip66_height: 1, rule_change_activation_threshold: 1916, // 95% miner_confirmation_window: 2016, - pow_limit: Work::SIGNET_MIN, + pow_limit: 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, @@ -102,7 +102,7 @@ impl Params { bip66_height: 1251, // used only in rpc tests rule_change_activation_threshold: 108, // 75% miner_confirmation_window: 144, - pow_limit: Work::REGTEST_MIN, + pow_limit: 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, diff --git a/bitcoin/src/pow.rs b/bitcoin/src/pow.rs index d7079b64..f81b9700 100644 --- a/bitcoin/src/pow.rs +++ b/bitcoin/src/pow.rs @@ -67,18 +67,6 @@ macro_rules! do_impl { pub struct Work(U256); impl Work { - /// Lowest possible work value for Mainnet. See comment on [`Params::pow_limit`] for more info. - pub const MAINNET_MIN: Work = Work(U256(0x0000_0000_ffff_0000_0000_0000_0000_0000_u128, 0)); - - /// Lowest possible work value for Testnet. See comment on [`Params::pow_limit`] for more info. - pub const TESTNET_MIN: Work = Work(U256(0x0000_0000_ffff_0000_0000_0000_0000_0000_u128, 0)); - - /// Lowest possible work value for Signet. See comment on [`Params::pow_limit`] for more info. - pub const SIGNET_MIN: Work = Work(U256(0x0000_0377_ae00_0000_0000_0000_0000_0000_u128, 0)); - - /// Lowest possible work value for Regtest. See comment on [`Params::pow_limit`] for more info. - pub const REGTEST_MIN: Work = Work(U256(0x7fff_ff00_0000_0000_0000_0000_0000_0000_u128, 0)); - /// Converts this [`Work`] to [`Target`]. pub fn to_target(self) -> Target { Target(self.0.inverse()) } @@ -128,6 +116,27 @@ impl Target { // the low 208 bits are all zero. pub const MAX: Self = Target(U256(0xFFFF_u128 << (208 - 128), 0)); + /// The maximum **attainable** target value on mainnet. + /// + /// Not all target values are attainable because consensus code uses the compact format to + /// represent targets (see `CompactTarget`). + pub const MAX_ATTAINABLE_MAINNET: Self = Target(U256(0xFFFF_u128 << (208 - 128), 0)); + + /// The proof of work limit on testnet. + // Taken from Bitcoin Core but had lossy conversion to/from compact form. + // https://github.com/bitcoin/bitcoin/blob/8105bce5b384c72cf08b25b7c5343622754e7337/src/kernel/chainparams.cpp#L208 + pub const MAX_ATTAINABLE_TESTNET: Self = Target(U256(0xFFFF_u128 << (208 - 128), 0)); + + /// The proof of work limit on regtest. + // Taken from Bitcoin Core but had lossy conversion to/from compact form. + // https://github.com/bitcoin/bitcoin/blob/8105bce5b384c72cf08b25b7c5343622754e7337/src/kernel/chainparams.cpp#L411 + pub const MAX_ATTAINABLE_REGTEST: Self = Target(U256(0x7FFF_FF00u128 << 96, 0)); + + /// The proof of work limit on signet. + // Taken from Bitcoin Core but had lossy conversion to/from compact form. + // https://github.com/bitcoin/bitcoin/blob/8105bce5b384c72cf08b25b7c5343622754e7337/src/kernel/chainparams.cpp#L348 + pub const MAX_ATTAINABLE_SIGNET: Self = Target(U256(0x0377_ae00 << 80, 0)); + /// The maximum possible target (see [`Target::MAX`]). /// /// This is provided for consistency with Rust 1.41.1, newer code should use [`Target::MAX`].