Skip to content

Work constants are incorrect #2103

@junderw

Description

@junderw

Work and Target have an inverse relationship, so min work should equal max target.

println!("{:?}", Target::MAX.to_work());
println!("{:?}", Work::MAINNET_MIN.to_target());
println!("{:?}", Target::MAX);
println!("{:?}", Work::MAINNET_MIN);
println!("{:?}", Work::MAINNET_MIN.to_target().to_compact_lossy().to_consensus());
println!("{:?}", Target::MAX.to_compact_lossy().to_consensus());

Expected:

Work(0x0000000000000000000000000000000000000000000000000000000100010000)
Target(0x00000000ffff00000000ffff00000000ffff00000000ffff00000000fffeffff)
Target(0x00000000ffff0000000000000000000000000000000000000000000000000000)
Work(0x0000000000000000000000000000000000000000000000000000000100010000)
486604799
486604799

Got:

Work(0x0000000000000000000000000000000000000000000000000000000100010001)
Target(0x0000000000000000000000000000000000000000000000000000000100010001)
Target(0x00000000ffff0000000000000000000000000000000000000000000000000000)
Work(0x00000000ffff0000000000000000000000000000000000000000000000000000)
83951617
486604799

This diff is what got me from Got to Expected... without the fix to the inverse function, the Target was slightly off.

diff --git a/bitcoin/src/pow.rs b/bitcoin/src/pow.rs
index 99e50014..09eb9466 100644
--- a/bitcoin/src/pow.rs
+++ b/bitcoin/src/pow.rs
@@ -71,7 +71,7 @@ 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));
+    pub const MAINNET_MIN: Work = Work(U256(0, 0x100010000));
 
     /// 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));
@@ -382,8 +382,7 @@ impl U256 {
             return U256::ONE;
         }
 
-        let ret = !*self / self.wrapping_inc();
-        ret.wrapping_inc()
+        !*self / self.wrapping_inc()
     }
 
     #[cfg_attr(all(test, mutate), mutate)]

I noticed this when making a fix PR for the next target PR.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions