use crate::dogecoin::Network;
use crate::Target;
const ONE_SECOND: i64 = 1;
const ONE_MINUTE: i64 = 60;
const FOUR_HOURS: i64 = 4 * 60 * 60;
#[non_exhaustive]
#[derive(Debug, Clone)]
pub struct Params {
pub network: Network,
pub bip16_time: u32,
pub bip34_height: u32,
pub bip65_height: u32,
pub bip66_height: u32,
pub rule_change_activation_threshold: u32,
pub miner_confirmation_window: u32,
#[deprecated(since = "0.32.0", note = "field renamed to max_attainable_target")]
pub pow_limit: Target,
pub max_attainable_target: Target,
pub pow_target_spacing: i64,
pub no_pow_retargeting: bool,
pub digishield_activation_height: u32,
pub auxpow_height: u32,
pub strict_chain_id: bool,
pub auxpow_chain_id: i32,
}
pub static MAINNET: Params = Params::MAINNET;
pub static TESTNET: Params = Params::TESTNET;
pub static REGTEST: Params = Params::REGTEST;
impl Params {
pub const DOGECOIN: Params = Params::MAINNET;
pub const MAINNET: Params = Params {
network: Network::Dogecoin,
bip16_time: 1333238400, bip34_height: 1034383, bip65_height: 3464751, bip66_height: 1034383, rule_change_activation_threshold: 9576, miner_confirmation_window: 10080, pow_limit: Target::MAX_ATTAINABLE_MAINNET_DOGE,
max_attainable_target: Target::MAX_ATTAINABLE_MAINNET_DOGE,
pow_target_spacing: ONE_MINUTE, no_pow_retargeting: false,
auxpow_height: 371_337,
strict_chain_id: true,
auxpow_chain_id: 0x0062,
digishield_activation_height: 145000,
};
pub const TESTNET: Params = Params {
network: Network::Testnet,
bip16_time: 1333238400, bip34_height: 708658, bip65_height: 1854705, bip66_height: 708658, rule_change_activation_threshold: 2880, miner_confirmation_window: 10080, pow_limit: Target::MAX_ATTAINABLE_TESTNET_DOGE,
max_attainable_target: Target::MAX_ATTAINABLE_TESTNET_DOGE,
pow_target_spacing: ONE_MINUTE, no_pow_retargeting: false,
auxpow_height: 158_100,
strict_chain_id: false,
auxpow_chain_id: 0x0062,
digishield_activation_height: 145000,
};
pub const REGTEST: Params = Params {
network: Network::Regtest,
bip16_time: 1333238400, bip34_height: 100000000, bip65_height: 1351,
bip66_height: 1251, rule_change_activation_threshold: 540, miner_confirmation_window: 720,
pow_limit: Target::MAX_ATTAINABLE_REGTEST_DOGE,
max_attainable_target: Target::MAX_ATTAINABLE_REGTEST_DOGE,
pow_target_spacing: ONE_SECOND, no_pow_retargeting: true,
auxpow_height: 20,
strict_chain_id: true,
auxpow_chain_id: 0x0062,
digishield_activation_height: 10,
};
pub const fn new(network: Network) -> Self {
match network {
Network::Dogecoin => Params::MAINNET,
Network::Testnet => Params::TESTNET,
Network::Regtest => Params::REGTEST,
}
}
pub const fn is_digishield_activated(&self, height: u32) -> bool {
height >= self.digishield_activation_height
}
pub const fn pow_target_timespan(&self, height: u32) -> i64 {
if !self.is_digishield_activated(height) {
FOUR_HOURS
} else {
match self.network {
Network::Dogecoin => ONE_MINUTE,
Network::Testnet => ONE_MINUTE,
Network::Regtest => ONE_SECOND,
}
}
}
pub const fn allow_min_difficulty_blocks(&self, height: u32) -> bool {
match self.network {
Network::Dogecoin => false,
Network::Testnet => match height {
0..=144_999 => true,
145_000..=157_499 => false,
157_500.. => true,
}
Network::Regtest => true,
}
}
pub const fn allow_legacy_blocks(&self, height: u32) -> bool {
height < self.auxpow_height
}
}
impl AsRef<Params> for Params {
fn as_ref(&self) -> &Params { self }
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn digishield_activation() {
let pre_digishield_heights = [5_000, 10_000, 144_999];
let digishield_heights = [145_000, 145_001, 1_000_000];
let params = [Params::MAINNET, Params::TESTNET];
for param in params {
for &height in pre_digishield_heights.iter() {
assert!(!param.is_digishield_activated(height));
}
for &height in digishield_heights.iter() {
assert!(param.is_digishield_activated(height));
}
}
let pre_digishield_heights_regtest = [0, 5, 9];
let digishield_heights_regtest = [10, 11, 100];
for &height in pre_digishield_heights_regtest.iter() {
assert!(!Params::REGTEST.is_digishield_activated(height));
}
for &height in digishield_heights_regtest.iter() {
assert!(Params::REGTEST.is_digishield_activated(height));
}
}
#[test]
fn hardfork_parameters() {
let params = &Params::MAINNET;
let initial_height = 0;
assert_eq!(params.pow_target_timespan(initial_height), 14400); assert!(params.allow_legacy_blocks(initial_height));
assert!(!params.is_digishield_activated(initial_height));
let initial_end_height = 144999;
assert_eq!(params.pow_target_timespan(initial_end_height), 14400); assert!(params.allow_legacy_blocks(initial_end_height));
assert!(!params.is_digishield_activated(initial_end_height));
let digishield_height = 145000;
assert_eq!(params.pow_target_timespan(digishield_height), 60); assert!(params.allow_legacy_blocks(digishield_height));
assert!(params.is_digishield_activated(digishield_height));
let digishield_end_height = 371336;
assert_eq!(params.pow_target_timespan(digishield_end_height), 60); assert!(params.allow_legacy_blocks(digishield_end_height));
assert!(params.is_digishield_activated(digishield_end_height));
let auxpow_height = 371337;
assert_eq!(params.pow_target_timespan(auxpow_height), 60); assert!(!params.allow_legacy_blocks(auxpow_height));
assert!(params.is_digishield_activated(auxpow_height));
let auxpow_high_height = 700000;
assert_eq!(params.pow_target_timespan(auxpow_high_height), 60); assert!(!params.allow_legacy_blocks(auxpow_high_height));
assert!(params.is_digishield_activated(auxpow_high_height));
}
}