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.
This commit is contained in:
Tobin C. Harding 2023-10-11 08:50:42 +11:00
parent 2095faed71
commit 38005f6aa7
No known key found for this signature in database
GPG Key ID: 40BF9E4C269D6607
2 changed files with 27 additions and 18 deletions

View File

@ -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,

View File

@ -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`].