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
This commit is contained in:
John Tromp 2020-11-25 16:13:43 +01:00 committed by GitHub
parent 6e73e00d6b
commit 97425af637
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 31 additions and 30 deletions

View file

@ -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 /// Number of blocks used to calculate difficulty adjustment by Damped Moving Average
pub const DMA_WINDOW: u64 = HOUR_HEIGHT; 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; pub const WTEMA_HALF_LIFE: u64 = 4 * HOUR_SEC;
/// Average time span of the DMA difficulty adjustment window /// 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 /// avoids getting stuck when trying to increase difficulty subject to dampening
pub const MIN_DMA_DIFFICULTY: u64 = DMA_DAMP_FACTOR; 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 /// Minimum scaling factor for AR pow, enforced in diff retargetting
/// avoids getting stuck when trying to increase ar_scale subject to dampening /// avoids getting stuck when trying to increase ar_scale subject to dampening
pub const MIN_AR_SCALE: u64 = AR_SCALE_DAMP_FACTOR; pub const MIN_AR_SCALE: u64 = AR_SCALE_DAMP_FACTOR;
@ -375,11 +371,11 @@ where
let next_diff = let next_diff =
last_diff * WTEMA_HALF_LIFE / (WTEMA_HALF_LIFE - BLOCK_TIME_SEC + last_block_time); 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 // 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. /// 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 // initial weights
assert_eq!(graph_weight(1, 31), 256 * 31); 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); assert_eq!(graph_weight(1, 33), 1024 * 33);
// one year in, 31 starts going down, the rest stays the same // 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, 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); assert_eq!(graph_weight(YEAR_HEIGHT, 33), 1024 * 33);
// 31 loses one factor per week // 31 loses one factor per week
@ -440,7 +436,7 @@ mod test {
// 2 years in, 31 still at 0, 32 starts decreasing // 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, 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); assert_eq!(graph_weight(2 * YEAR_HEIGHT, 33), 1024 * 33);
// 32 phaseout on hold // 32 phaseout on hold
@ -460,12 +456,12 @@ mod test {
// 3 years in, nothing changes // 3 years in, nothing changes
assert_eq!(graph_weight(3 * YEAR_HEIGHT, 31), 0); 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); assert_eq!(graph_weight(3 * YEAR_HEIGHT, 33), 1024 * 33);
// 4 years in, still on hold // 4 years in, still on hold
assert_eq!(graph_weight(4 * YEAR_HEIGHT, 31), 0); 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);
assert_eq!(graph_weight(4 * YEAR_HEIGHT, 33), 1024 * 33); assert_eq!(graph_weight(4 * YEAR_HEIGHT, 33), 1024 * 33);
} }

View file

@ -18,8 +18,8 @@
use crate::consensus::{ use crate::consensus::{
graph_weight, header_version, HeaderInfo, BASE_EDGE_BITS, BLOCK_KERNEL_WEIGHT, graph_weight, header_version, HeaderInfo, BASE_EDGE_BITS, BLOCK_KERNEL_WEIGHT,
BLOCK_OUTPUT_WEIGHT, BLOCK_TIME_SEC, COINBASE_MATURITY, CUT_THROUGH_HORIZON, DAY_HEIGHT, BLOCK_OUTPUT_WEIGHT, BLOCK_TIME_SEC, C32_GRAPH_WEIGHT, COINBASE_MATURITY, CUT_THROUGH_HORIZON,
DEFAULT_MIN_EDGE_BITS, DMA_WINDOW, INITIAL_DIFFICULTY, MAX_BLOCK_WEIGHT, PROOFSIZE, DAY_HEIGHT, DEFAULT_MIN_EDGE_BITS, DMA_WINDOW, INITIAL_DIFFICULTY, MAX_BLOCK_WEIGHT, PROOFSIZE,
SECOND_POW_EDGE_BITS, STATE_SYNC_THRESHOLD, SECOND_POW_EDGE_BITS, STATE_SYNC_THRESHOLD,
}; };
use crate::core::block::HeaderVersion; use crate::core::block::HeaderVersion;
@ -72,9 +72,6 @@ pub const USER_TESTING_CUT_THROUGH_HORIZON: u32 = 70;
/// Testing state sync threshold in blocks /// Testing state sync threshold in blocks
pub const TESTING_STATE_SYNC_THRESHOLD: u32 = 20; pub const TESTING_STATE_SYNC_THRESHOLD: u32 = 20;
/// Testing initial graph weight
pub const TESTING_INITIAL_GRAPH_WEIGHT: u32 = 1;
/// Testing initial block difficulty /// Testing initial block difficulty
pub const TESTING_INITIAL_DIFFICULTY: u64 = 1; pub const TESTING_INITIAL_DIFFICULTY: u64 = 1;
@ -327,16 +324,27 @@ pub fn initial_block_difficulty() -> u64 {
ChainTypes::Mainnet => INITIAL_DIFFICULTY, ChainTypes::Mainnet => INITIAL_DIFFICULTY,
} }
} }
/// Initial mining secondary scale /// Initial mining secondary scale
pub fn initial_graph_weight() -> u32 { pub fn initial_graph_weight() -> u32 {
match get_chain_type() { match get_chain_type() {
ChainTypes::AutomatedTesting => TESTING_INITIAL_GRAPH_WEIGHT, ChainTypes::AutomatedTesting => graph_weight(0, AUTOMATED_TESTING_MIN_EDGE_BITS) as u32,
ChainTypes::UserTesting => TESTING_INITIAL_GRAPH_WEIGHT, ChainTypes::UserTesting => graph_weight(0, USER_TESTING_MIN_EDGE_BITS) as u32,
ChainTypes::Testnet => graph_weight(0, SECOND_POW_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, 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. /// Maximum allowed block weight.
pub fn max_block_weight() -> u64 { pub fn max_block_weight() -> u64 {
match get_chain_type() { match get_chain_type() {

View file

@ -12,9 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::consensus::{ use crate::consensus::{graph_weight, MIN_DMA_DIFFICULTY, SECOND_POW_EDGE_BITS};
graph_weight, MIN_DMA_DIFFICULTY, MIN_WTEMA_DIFFICULTY, SECOND_POW_EDGE_BITS,
};
use crate::core::hash::{DefaultHashable, Hashed}; use crate::core::hash::{DefaultHashable, Hashed};
use crate::global; use crate::global;
use crate::pow::error::Error; use crate::pow::error::Error;
@ -67,7 +65,7 @@ impl Difficulty {
/// Difficulty of MIN_DIFFICULTY /// Difficulty of MIN_DIFFICULTY
pub fn min_wtema() -> Difficulty { pub fn min_wtema() -> Difficulty {
Difficulty { Difficulty {
num: MIN_WTEMA_DIFFICULTY, num: global::min_wtema_graph_weight(),
} }
} }

View file

@ -14,7 +14,7 @@
use chrono::Utc; use chrono::Utc;
use grin_core::consensus::{ use grin_core::consensus::{
next_dma_difficulty, next_wtema_difficulty, HeaderInfo, AR_SCALE_DAMP_FACTOR, BLOCK_TIME_SEC, 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::global;
use grin_core::pow::Difficulty; use grin_core::pow::Difficulty;
@ -26,14 +26,14 @@ fn next_dma_difficulty_adjustment() {
let cur_time = Utc::now().timestamp() as u64; let cur_time = Utc::now().timestamp() as u64;
let diff_min = Difficulty::min_dma(); 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); let mut hi = HeaderInfo::from_diff_scaling(diff_min, AR_SCALE_DAMP_FACTOR as u32);
hi.is_secondary = false; hi.is_secondary = false;
let hinext = next_dma_difficulty(1, repeat(BLOCK_TIME_SEC / 4, hi.clone(), DMA_WINDOW, None)); let hinext = next_dma_difficulty(1, repeat(BLOCK_TIME_SEC / 4, hi.clone(), DMA_WINDOW, None));
assert_ne!(hinext.difficulty, diff_min); 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); assert_ne!(hinext.secondary_scaling, MIN_AR_SCALE as u32);
// just enough data, right interval, should stay constant // 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 /// Checks different next_wtema_difficulty adjustments and difficulty boundaries
#[test] #[test]
fn next_wtema_difficulty_adjustment() { fn next_wtema_difficulty_adjustment() {
global::set_local_chain_type(global::ChainTypes::AutomatedTesting); global::set_local_chain_type(global::ChainTypes::Mainnet);
let cur_time = Utc::now().timestamp() as u64;
let hf4 = 2 * YEAR_HEIGHT; // height of HardFork4, switching to wtema DAA let hf4 = 2 * YEAR_HEIGHT; // height of HardFork4, switching to wtema DAA
let diff_min = Difficulty::min_wtema(); 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); let mut hi = HeaderInfo::from_diff_scaling(diff_min, 0);
hi.is_secondary = false; hi.is_secondary = false;
let hinext = next_wtema_difficulty(hf4, repeat(BLOCK_TIME_SEC - 1, hi.clone(), 2, None)); let hinext = next_wtema_difficulty(hf4, repeat(BLOCK_TIME_SEC - 1, hi.clone(), 2, None));