Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat add from_next_work_required to CompactTarget #2

Open
wants to merge 1 commit into
base: bitlayer/preview
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions bitcoin/src/consensus/params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,21 @@ pub struct Params {
pub no_pow_retargeting: bool,
}

/// The mainnet parameters.
///
/// Use this for a static reference e.g., `&params::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 {
/// The mainnet parameters (alias for `Params::MAINNET`).
pub const BITCOIN: Params = Params::MAINNET;
Expand Down Expand Up @@ -148,3 +163,18 @@ impl From<Network> for &'static Params {
impl From<&Network> for &'static Params {
fn from(value: &Network) -> Self { value.params() }
}

impl AsRef<Params> for Params {
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 => &REGTEST,
}
}
}
34 changes: 32 additions & 2 deletions bitcoin/src/pow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,14 @@

use core::fmt::{self, LowerHex, UpperHex};
use core::ops::{Add, Div, Mul, Not, Rem, Shl, Shr, Sub};

use std::cmp;
use io::{BufRead, Write};
#[cfg(all(test, mutate))]
use mutagen::mutate;
use units::parse;

use crate::blockdata::block::BlockHash;
use crate::consensus::encode::{self, Decodable, Encodable};
#[cfg(doc)]
use crate::consensus::Params;
use crate::error::{PrefixedHexError, UnprefixedHexError, ContainsPrefixError, MissingPrefixError};
use crate::Network;
Expand Down Expand Up @@ -256,6 +255,11 @@ impl Target {
/// The difficulty can only decrease or increase by a factor of 4 max on each difficulty
/// adjustment period.
pub fn max_difficulty_transition_threshold(&self) -> Self { Self(self.0 << 2) }

pub fn max_transition_threshold(&self, params: impl AsRef<Params>) -> Self {
let max_attainable = params.as_ref().pow_limit;
cmp::min(self.max_difficulty_transition_threshold(), max_attainable)
}
}
do_impl!(Target);

Expand Down Expand Up @@ -300,6 +304,32 @@ impl CompactTarget {

/// Returns the consensus encoded `u32` representation of this [`CompactTarget`].
pub fn to_consensus(self) -> u32 { self.0 }

pub fn from_next_work_required(
last: CompactTarget,
timespan: u64,
params: impl AsRef<Params>,
) -> CompactTarget {
let params = params.as_ref();
if params.no_pow_retargeting {
return last;
}
// Comments relate to the `pow.cpp` file from Core.
// ref: <https://github.com/bitcoin/bitcoin/blob/0503cbea9aab47ec0a87d34611e5453158727169/src/pow.cpp>
let min_timespan = params.pow_target_timespan >> 2; // Lines 56/57
let max_timespan = params.pow_target_timespan << 2; // Lines 58/59
let actual_timespan = timespan.clamp(min_timespan, max_timespan);
let prev_target: Target = last.into();
let maximum_retarget = prev_target.max_transition_threshold(params); // bnPowLimit
let retarget = prev_target.0; // bnNew
let retarget = retarget.mul(actual_timespan.into());
let retarget = retarget.div(params.pow_target_timespan.into());
let retarget = Target(retarget);
if retarget.ge(&maximum_retarget) {
return maximum_retarget.to_compact_lossy();
}
retarget.to_compact_lossy()
}
}

impl From<CompactTarget> for Target {
Expand Down
Loading