From 10a1ddf5e8288b251b01f7f101e691f961d44a79 Mon Sep 17 00:00:00 2001 From: AntiochP <30642645+antiochp@users.noreply.github.com> Date: Mon, 13 Nov 2017 19:45:10 -0500 Subject: [PATCH] Use consensus rule that minimum difficulty is 10 (#251) --- chain/src/pipe.rs | 7 +++++++ core/src/consensus.rs | 18 ++++++++++++++---- core/src/core/target.rs | 9 ++++++++- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/chain/src/pipe.rs b/chain/src/pipe.rs index 2e8e04c85..e436acae6 100644 --- a/chain/src/pipe.rs +++ b/chain/src/pipe.rs @@ -21,6 +21,7 @@ use time; use core::consensus; use core::core::hash::{Hash, Hashed}; use core::core::{Block, BlockHeader}; +use core::core::target::Difficulty; use core::core::transaction; use types::*; use store; @@ -182,6 +183,12 @@ fn validate_header(header: &BlockHeader, ctx: &mut BlockContext) -> Result<(), E if !ctx.opts.intersects(SKIP_POW) { // verify the proof of work and related parameters + // explicit check to ensure we are not below the minimum difficulty + // we will also check difficulty based on next_difficulty later on + if header.difficulty < Difficulty::minimum() { + return Err(Error::DifficultyTooLow); + } + if header.total_difficulty != prev.total_difficulty.clone() + prev.pow.to_difficulty() { return Err(Error::WrongTotalDifficulty); } diff --git a/core/src/consensus.rs b/core/src/consensus.rs index d06a6f5f8..1624f61c6 100644 --- a/core/src/consensus.rs +++ b/core/src/consensus.rs @@ -20,6 +20,7 @@ //! here. use std::fmt; +use std::cmp::max; use ser; use core::target::Difficulty; @@ -119,10 +120,10 @@ pub const DIFFICULTY_ADJUST_WINDOW: u64 = 23; /// Average time span of the difficulty adjustment window pub const BLOCK_TIME_WINDOW: u64 = DIFFICULTY_ADJUST_WINDOW * BLOCK_TIME_SEC; -/// Maximum size time window used for difficutly adjustments +/// Maximum size time window used for difficulty adjustments pub const UPPER_TIME_BOUND: u64 = BLOCK_TIME_WINDOW * 4 / 3; -/// Minimum size time window used for difficutly adjustments +/// Minimum size time window used for difficulty adjustments pub const LOWER_TIME_BOUND: u64 = BLOCK_TIME_WINDOW * 5 / 6; /// Error when computing the next difficulty adjustment. @@ -181,7 +182,7 @@ where // Check we have enough blocks if window_end.len() < (MEDIAN_TIME_WINDOW as usize) { - return Ok(Difficulty::from_num(MINIMUM_DIFFICULTY)); + return Ok(Difficulty::minimum()); } // Calculating time medians at the beginning and end of the window. @@ -203,7 +204,10 @@ where ts_damp }; - Ok(diff_avg * Difficulty::from_num(BLOCK_TIME_WINDOW) / Difficulty::from_num(adj_ts)) + let difficulty = + diff_avg * Difficulty::from_num(BLOCK_TIME_WINDOW) / Difficulty::from_num(adj_ts); + + Ok(max(difficulty, Difficulty::minimum())) } /// Consensus rule that collections of items are sorted lexicographically over the wire. @@ -319,6 +323,12 @@ mod test { next_difficulty(repeat(200, 1000, just_enough)).unwrap(), Difficulty::from_num(750) ); + + // We should never drop below MINIMUM_DIFFICULTY (10) + assert_eq!( + next_difficulty(repeat(90, 10, just_enough)).unwrap(), + Difficulty::from_num(10) + ); } #[test] diff --git a/core/src/core/target.rs b/core/src/core/target.rs index 673f6e559..87a31120f 100644 --- a/core/src/core/target.rs +++ b/core/src/core/target.rs @@ -25,6 +25,7 @@ use std::ops::{Add, Div, Mul, Sub}; use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; use byteorder::{BigEndian, ByteOrder}; +use consensus; use core::hash::Hash; use ser::{self, Readable, Reader, Writeable, Writer}; @@ -38,7 +39,7 @@ pub struct Difficulty { } impl Difficulty { - /// Difficulty of zero, which is practically invalid (not target can be + /// Difficulty of zero, which is invalid (no target can be /// calculated from it) but very useful as a start for additions. pub fn zero() -> Difficulty { Difficulty { num: 0 } @@ -46,10 +47,16 @@ impl Difficulty { /// Difficulty of one, which is the minumum difficulty (when the hash /// equals the max target) + /// TODO - is this the minimum dificulty or is consensus::MINIMUM_DIFFICULTY the minimum? pub fn one() -> Difficulty { Difficulty { num: 1 } } + /// Minimum difficulty according to our consensus rules. + pub fn minimum() -> Difficulty { + Difficulty { num: consensus::MINIMUM_DIFFICULTY } + } + /// Convert a `u32` into a `Difficulty` pub fn from_num(num: u64) -> Difficulty { Difficulty { num: num }