diff --git a/core/src/consensus.rs b/core/src/consensus.rs index f88101f33..6d011fef6 100644 --- a/core/src/consensus.rs +++ b/core/src/consensus.rs @@ -63,7 +63,17 @@ pub const COINBASE_MATURITY: u64 = DAY_HEIGHT; /// function of block height (time). Starts at 90% losing a percent /// approximately every week. Represented as an integer between 0 and 100. pub fn secondary_pow_ratio(height: u64) -> u64 { - 90u64.saturating_sub(height / WEEK_HEIGHT) + // TODO - this should all be cleaned up and simplified before mainnet. + if global::is_mainnet() { + 90u64.saturating_sub(height / (2 * YEAR_HEIGHT / 90)) + } else { + if height < T4_CUCKAROO_HARDFORK { + // Maintaining pre hardfork testnet4 behavior + 90u64.saturating_sub(height / WEEK_HEIGHT) + } else { + 90u64.saturating_sub(height / (2 * YEAR_HEIGHT / 90)) + } + } } /// Cuckoo-cycle proof size (cycle length) diff --git a/core/src/global.rs b/core/src/global.rs index a7fb85a57..fe2c52b68 100644 --- a/core/src/global.rs +++ b/core/src/global.rs @@ -19,8 +19,8 @@ use consensus::HeaderInfo; use consensus::{ graph_weight, BASE_EDGE_BITS, BLOCK_TIME_SEC, COINBASE_MATURITY, CUT_THROUGH_HORIZON, - DAY_HEIGHT, DIFFICULTY_ADJUST_WINDOW, INITIAL_DIFFICULTY, PROOFSIZE, SECOND_POW_EDGE_BITS, - STATE_SYNC_THRESHOLD, T4_CUCKAROO_HARDFORK, UNIT_DIFFICULTY, DEFAULT_MIN_EDGE_BITS, + DAY_HEIGHT, DEFAULT_MIN_EDGE_BITS, DIFFICULTY_ADJUST_WINDOW, INITIAL_DIFFICULTY, PROOFSIZE, + SECOND_POW_EDGE_BITS, STATE_SYNC_THRESHOLD, T4_CUCKAROO_HARDFORK, UNIT_DIFFICULTY, }; use pow::{self, new_cuckaroo_ctx, new_cuckatoo_ctx, EdgeType, PoWContext}; /// An enum collecting sets of parameters used throughout the @@ -294,6 +294,12 @@ pub fn is_production_mode() -> bool { || ChainTypes::Mainnet == *param_ref } +/// Are we in mainnet? +pub fn is_mainnet() -> bool { + let param_ref = CHAIN_TYPE.read(); + ChainTypes::Mainnet == *param_ref +} + /// Helper function to get a nonce known to create a valid POW on /// the genesis block, to prevent it taking ages. Should be fine for now /// as the genesis block POW solution turns out to be the same for every new diff --git a/core/tests/consensus.rs b/core/tests/consensus.rs index b252d9b00..18815af64 100644 --- a/core/tests/consensus.rs +++ b/core/tests/consensus.rs @@ -146,8 +146,7 @@ fn get_diff_stats(chain_sim: &Vec) -> DiffStats { time: n.timestamp, duration: dur, } - }) - .collect(); + }).collect(); let block_time_sum = sum_entries.iter().fold(0, |sum, t| sum + t.duration); let block_diff_sum = sum_entries.iter().fold(0, |sum, d| sum + d.difficulty); @@ -472,7 +471,94 @@ fn next_target_adjustment() { } #[test] -fn secondary_pow_scale() { +fn test_secondary_pow_ratio() { + // Tests for mainnet chain type. + { + global::set_mining_mode(global::ChainTypes::Mainnet); + assert_eq!(global::is_mainnet(), true); + + assert_eq!(secondary_pow_ratio(1), 90); + assert_eq!(secondary_pow_ratio(89), 90); + assert_eq!(secondary_pow_ratio(90), 90); + assert_eq!(secondary_pow_ratio(91), 90); + assert_eq!(secondary_pow_ratio(179), 90); + assert_eq!(secondary_pow_ratio(180), 90); + assert_eq!(secondary_pow_ratio(181), 90); + + let one_week = 60 * 24 * 7; + assert_eq!(secondary_pow_ratio(one_week - 1), 90); + assert_eq!(secondary_pow_ratio(one_week), 90); + assert_eq!(secondary_pow_ratio(one_week + 1), 90); + + let two_weeks = one_week * 2; + assert_eq!(secondary_pow_ratio(two_weeks - 1), 89); + assert_eq!(secondary_pow_ratio(two_weeks), 89); + assert_eq!(secondary_pow_ratio(two_weeks + 1), 89); + + let t4_fork_height = 64_000; + assert_eq!(secondary_pow_ratio(t4_fork_height - 1), 85); + assert_eq!(secondary_pow_ratio(t4_fork_height), 85); + assert_eq!(secondary_pow_ratio(t4_fork_height + 1), 85); + + let one_year = one_week * 52; + assert_eq!(secondary_pow_ratio(one_year), 45); + + let ninety_one_weeks = one_week * 91; + assert_eq!(secondary_pow_ratio(ninety_one_weeks - 1), 12); + assert_eq!(secondary_pow_ratio(ninety_one_weeks), 12); + assert_eq!(secondary_pow_ratio(ninety_one_weeks + 1), 12); + + let two_year = one_year * 2; + assert_eq!(secondary_pow_ratio(two_year - 1), 1); + assert_eq!(secondary_pow_ratio(two_year), 0); + assert_eq!(secondary_pow_ratio(two_year + 1), 0); + } + + // Tests for testnet4 chain type (covers pre and post hardfork). + { + global::set_mining_mode(global::ChainTypes::Testnet4); + assert_eq!(global::is_mainnet(), false); + + assert_eq!(secondary_pow_ratio(1), 90); + assert_eq!(secondary_pow_ratio(89), 90); + assert_eq!(secondary_pow_ratio(90), 90); + assert_eq!(secondary_pow_ratio(91), 90); + assert_eq!(secondary_pow_ratio(179), 90); + assert_eq!(secondary_pow_ratio(180), 90); + assert_eq!(secondary_pow_ratio(181), 90); + + let one_week = 60 * 24 * 7; + assert_eq!(secondary_pow_ratio(one_week - 1), 90); + assert_eq!(secondary_pow_ratio(one_week), 89); + assert_eq!(secondary_pow_ratio(one_week + 1), 89); + + let two_weeks = one_week * 2; + assert_eq!(secondary_pow_ratio(two_weeks - 1), 89); + assert_eq!(secondary_pow_ratio(two_weeks), 88); + assert_eq!(secondary_pow_ratio(two_weeks + 1), 88); + + let t4_fork_height = 64_000; + assert_eq!(secondary_pow_ratio(t4_fork_height - 1), 84); + assert_eq!(secondary_pow_ratio(t4_fork_height), 85); + assert_eq!(secondary_pow_ratio(t4_fork_height + 1), 85); + + let one_year = one_week * 52; + assert_eq!(secondary_pow_ratio(one_year), 45); + + let ninety_one_weeks = one_week * 91; + assert_eq!(secondary_pow_ratio(ninety_one_weeks - 1), 12); + assert_eq!(secondary_pow_ratio(ninety_one_weeks), 12); + assert_eq!(secondary_pow_ratio(ninety_one_weeks + 1), 12); + + let two_year = one_year * 2; + assert_eq!(secondary_pow_ratio(two_year - 1), 1); + assert_eq!(secondary_pow_ratio(two_year), 0); + assert_eq!(secondary_pow_ratio(two_year + 1), 0); + } +} + +#[test] +fn test_secondary_pow_scale() { let window = DIFFICULTY_ADJUST_WINDOW; let mut hi = HeaderInfo::from_diff_scaling(Difficulty::from_num(10), 100); @@ -501,7 +587,10 @@ fn secondary_pow_scale() { let mut low_hi = HeaderInfo::from_diff_scaling(Difficulty::from_num(10), MIN_DIFFICULTY as u32); low_hi.is_secondary = true; assert_eq!( - secondary_pow_scaling(890_000, &(0..window).map(|_| low_hi.clone()).collect::>()), + secondary_pow_scaling( + 890_000, + &(0..window).map(|_| low_hi.clone()).collect::>() + ), MIN_DIFFICULTY as u32 ); // just about the right ratio, also no longer playing with median