From 97425af637c3ac84654533dc322ce40bbadcdb0c Mon Sep 17 00:00:00 2001 From: John Tromp Date: Wed, 25 Nov 2020 16:13:43 +0100 Subject: [PATCH] make min_wtema difficulty chain type dependent (#3502) * make min_wtema difficulty chain type dependent * fix bad graph weights for automated and user testing * only mainnet can get wtema difficulty unstuck at 59s blocks --- core/src/consensus.rs | 22 +++++++++------------- core/src/global.rs | 22 +++++++++++++++------- core/src/pow/types.rs | 6 ++---- core/tests/consensus_automated.rs | 11 +++++------ 4 files changed, 31 insertions(+), 30 deletions(-) diff --git a/core/src/consensus.rs b/core/src/consensus.rs index 8eb294246..2724d0f65 100644 --- a/core/src/consensus.rs +++ b/core/src/consensus.rs @@ -174,7 +174,7 @@ pub fn valid_header_version(height: u64, version: HeaderVersion) -> bool { /// Number of blocks used to calculate difficulty adjustment by Damped Moving Average pub const DMA_WINDOW: u64 = HOUR_HEIGHT; -/// Difficulty adjustment half life is 4 hours +/// Difficulty adjustment half life (actually, 60s * number of 0s-blocks to raise diff by factor e) is 4 hours pub const WTEMA_HALF_LIFE: u64 = 4 * HOUR_SEC; /// Average time span of the DMA difficulty adjustment window @@ -212,10 +212,6 @@ pub const C32_GRAPH_WEIGHT: u64 = (2u64 << (32 - BASE_EDGE_BITS) as u64) * 32; / /// avoids getting stuck when trying to increase difficulty subject to dampening pub const MIN_DMA_DIFFICULTY: u64 = DMA_DAMP_FACTOR; -/// Minimum difficulty, enforced in Weighted Target Exponential Moving Average diff retargetting -/// avoids getting stuck when trying to increase difficulty -pub const MIN_WTEMA_DIFFICULTY: u64 = C32_GRAPH_WEIGHT; - /// Minimum scaling factor for AR pow, enforced in diff retargetting /// avoids getting stuck when trying to increase ar_scale subject to dampening pub const MIN_AR_SCALE: u64 = AR_SCALE_DAMP_FACTOR; @@ -375,11 +371,11 @@ where let next_diff = last_diff * WTEMA_HALF_LIFE / (WTEMA_HALF_LIFE - BLOCK_TIME_SEC + last_block_time); - // minimum difficulty at graph_weight(32) ensures difficulty increase on 59s block + // mainnet minimum difficulty at graph_weight(32) ensures difficulty increase on 59s block // since 16384 * WTEMA_HALF_LIFE / (WTEMA_HALF_LIFE - 1) > 16384 - let difficulty = max(MIN_WTEMA_DIFFICULTY, next_diff); + let difficulty = max(Difficulty::min_wtema(), Difficulty::from_num(next_diff)); - HeaderInfo::from_diff_scaling(Difficulty::from_num(difficulty), 0) // no more secondary PoW + HeaderInfo::from_diff_scaling(difficulty, 0) // no more secondary PoW } /// Count, in units of 1/100 (a percent), the number of "secondary" (AR) blocks in the provided window of blocks. @@ -425,12 +421,12 @@ mod test { // initial weights assert_eq!(graph_weight(1, 31), 256 * 31); - assert_eq!(graph_weight(1, 32), C32_GRAPH_WEIGHT); + assert_eq!(graph_weight(1, 32), 512 * 32); assert_eq!(graph_weight(1, 33), 1024 * 33); // one year in, 31 starts going down, the rest stays the same assert_eq!(graph_weight(YEAR_HEIGHT, 31), 256 * 30); - assert_eq!(graph_weight(YEAR_HEIGHT, 32), C32_GRAPH_WEIGHT); + assert_eq!(graph_weight(YEAR_HEIGHT, 32), 512 * 32); assert_eq!(graph_weight(YEAR_HEIGHT, 33), 1024 * 33); // 31 loses one factor per week @@ -440,7 +436,7 @@ mod test { // 2 years in, 31 still at 0, 32 starts decreasing assert_eq!(graph_weight(2 * YEAR_HEIGHT, 31), 0); - assert_eq!(graph_weight(2 * YEAR_HEIGHT, 32), C32_GRAPH_WEIGHT); + assert_eq!(graph_weight(2 * YEAR_HEIGHT, 32), 512 * 32); assert_eq!(graph_weight(2 * YEAR_HEIGHT, 33), 1024 * 33); // 32 phaseout on hold @@ -460,12 +456,12 @@ mod test { // 3 years in, nothing changes assert_eq!(graph_weight(3 * YEAR_HEIGHT, 31), 0); - assert_eq!(graph_weight(3 * YEAR_HEIGHT, 32), C32_GRAPH_WEIGHT); + assert_eq!(graph_weight(3 * YEAR_HEIGHT, 32), 512 * 32); assert_eq!(graph_weight(3 * YEAR_HEIGHT, 33), 1024 * 33); // 4 years in, still on hold assert_eq!(graph_weight(4 * YEAR_HEIGHT, 31), 0); - assert_eq!(graph_weight(4 * YEAR_HEIGHT, 32), C32_GRAPH_WEIGHT); + assert_eq!(graph_weight(4 * YEAR_HEIGHT, 32), 512 * 32); assert_eq!(graph_weight(4 * YEAR_HEIGHT, 33), 1024 * 33); assert_eq!(graph_weight(4 * YEAR_HEIGHT, 33), 1024 * 33); } diff --git a/core/src/global.rs b/core/src/global.rs index 5261b405b..aaa4303d6 100644 --- a/core/src/global.rs +++ b/core/src/global.rs @@ -18,8 +18,8 @@ use crate::consensus::{ graph_weight, header_version, HeaderInfo, BASE_EDGE_BITS, BLOCK_KERNEL_WEIGHT, - BLOCK_OUTPUT_WEIGHT, BLOCK_TIME_SEC, COINBASE_MATURITY, CUT_THROUGH_HORIZON, DAY_HEIGHT, - DEFAULT_MIN_EDGE_BITS, DMA_WINDOW, INITIAL_DIFFICULTY, MAX_BLOCK_WEIGHT, PROOFSIZE, + BLOCK_OUTPUT_WEIGHT, BLOCK_TIME_SEC, C32_GRAPH_WEIGHT, COINBASE_MATURITY, CUT_THROUGH_HORIZON, + DAY_HEIGHT, DEFAULT_MIN_EDGE_BITS, DMA_WINDOW, INITIAL_DIFFICULTY, MAX_BLOCK_WEIGHT, PROOFSIZE, SECOND_POW_EDGE_BITS, STATE_SYNC_THRESHOLD, }; use crate::core::block::HeaderVersion; @@ -72,9 +72,6 @@ pub const USER_TESTING_CUT_THROUGH_HORIZON: u32 = 70; /// Testing state sync threshold in blocks pub const TESTING_STATE_SYNC_THRESHOLD: u32 = 20; -/// Testing initial graph weight -pub const TESTING_INITIAL_GRAPH_WEIGHT: u32 = 1; - /// Testing initial block difficulty pub const TESTING_INITIAL_DIFFICULTY: u64 = 1; @@ -327,16 +324,27 @@ pub fn initial_block_difficulty() -> u64 { ChainTypes::Mainnet => INITIAL_DIFFICULTY, } } + /// Initial mining secondary scale pub fn initial_graph_weight() -> u32 { match get_chain_type() { - ChainTypes::AutomatedTesting => TESTING_INITIAL_GRAPH_WEIGHT, - ChainTypes::UserTesting => TESTING_INITIAL_GRAPH_WEIGHT, + ChainTypes::AutomatedTesting => graph_weight(0, AUTOMATED_TESTING_MIN_EDGE_BITS) as u32, + ChainTypes::UserTesting => graph_weight(0, USER_TESTING_MIN_EDGE_BITS) as u32, ChainTypes::Testnet => graph_weight(0, SECOND_POW_EDGE_BITS) as u32, ChainTypes::Mainnet => graph_weight(0, SECOND_POW_EDGE_BITS) as u32, } } +/// Minimum valid graph weight post HF4 +pub fn min_wtema_graph_weight() -> u64 { + match get_chain_type() { + ChainTypes::AutomatedTesting => graph_weight(0, AUTOMATED_TESTING_MIN_EDGE_BITS), + ChainTypes::UserTesting => graph_weight(0, USER_TESTING_MIN_EDGE_BITS), + ChainTypes::Testnet => graph_weight(0, SECOND_POW_EDGE_BITS), + ChainTypes::Mainnet => C32_GRAPH_WEIGHT, + } +} + /// Maximum allowed block weight. pub fn max_block_weight() -> u64 { match get_chain_type() { diff --git a/core/src/pow/types.rs b/core/src/pow/types.rs index 6dfba0a6e..7eb6c5d3c 100644 --- a/core/src/pow/types.rs +++ b/core/src/pow/types.rs @@ -12,9 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::consensus::{ - graph_weight, MIN_DMA_DIFFICULTY, MIN_WTEMA_DIFFICULTY, SECOND_POW_EDGE_BITS, -}; +use crate::consensus::{graph_weight, MIN_DMA_DIFFICULTY, SECOND_POW_EDGE_BITS}; use crate::core::hash::{DefaultHashable, Hashed}; use crate::global; use crate::pow::error::Error; @@ -67,7 +65,7 @@ impl Difficulty { /// Difficulty of MIN_DIFFICULTY pub fn min_wtema() -> Difficulty { Difficulty { - num: MIN_WTEMA_DIFFICULTY, + num: global::min_wtema_graph_weight(), } } diff --git a/core/tests/consensus_automated.rs b/core/tests/consensus_automated.rs index cc6c1498d..67f82fe93 100644 --- a/core/tests/consensus_automated.rs +++ b/core/tests/consensus_automated.rs @@ -14,7 +14,7 @@ use chrono::Utc; use grin_core::consensus::{ next_dma_difficulty, next_wtema_difficulty, HeaderInfo, AR_SCALE_DAMP_FACTOR, BLOCK_TIME_SEC, - DMA_WINDOW, MIN_AR_SCALE, MIN_DMA_DIFFICULTY, MIN_WTEMA_DIFFICULTY, YEAR_HEIGHT, + DMA_WINDOW, MIN_AR_SCALE, YEAR_HEIGHT, }; use grin_core::global; use grin_core::pow::Difficulty; @@ -26,14 +26,14 @@ fn next_dma_difficulty_adjustment() { let cur_time = Utc::now().timestamp() as u64; let diff_min = Difficulty::min_dma(); - // Check we don't get stuck on difficulty <= MIN_DMA_DIFFICULTY (at 4x faster blocks at least) + // Check we don't get stuck on difficulty <= Difficulty::min_dma (at 4x faster blocks at least) let mut hi = HeaderInfo::from_diff_scaling(diff_min, AR_SCALE_DAMP_FACTOR as u32); hi.is_secondary = false; let hinext = next_dma_difficulty(1, repeat(BLOCK_TIME_SEC / 4, hi.clone(), DMA_WINDOW, None)); assert_ne!(hinext.difficulty, diff_min); - // Check we don't get stuck on scale MIN_DMA_DIFFICULTY, when primary frequency is too high + // Check we don't get stuck on scale MIN_AR_SCALE, when primary frequency is too high assert_ne!(hinext.secondary_scaling, MIN_AR_SCALE as u32); // just enough data, right interval, should stay constant @@ -118,12 +118,11 @@ fn next_dma_difficulty_adjustment() { /// Checks different next_wtema_difficulty adjustments and difficulty boundaries #[test] fn next_wtema_difficulty_adjustment() { - global::set_local_chain_type(global::ChainTypes::AutomatedTesting); - let cur_time = Utc::now().timestamp() as u64; + global::set_local_chain_type(global::ChainTypes::Mainnet); let hf4 = 2 * YEAR_HEIGHT; // height of HardFork4, switching to wtema DAA let diff_min = Difficulty::min_wtema(); - // Check we don't get stuck on difficulty <= MIN_WTEMA_DIFFICULTY (at 4x faster blocks at least) + // Check we don't get stuck on mainnet difficulty <= Difficulty::min_wtema (on 59s blocks) let mut hi = HeaderInfo::from_diff_scaling(diff_min, 0); hi.is_secondary = false; let hinext = next_wtema_difficulty(hf4, repeat(BLOCK_TIME_SEC - 1, hi.clone(), 2, None));