Merge pull request #260 from ethcore/testnet_difficulty_fix

fixed difficulty calculcation on testnet
This commit is contained in:
Nikolay Volf 2016-12-06 11:07:23 +03:00 committed by GitHub
commit b851f04100
3 changed files with 21 additions and 15 deletions

View File

@ -29,6 +29,7 @@ mod error;
mod update_context;
mod indexed_block;
#[derive(Debug, Clone)]
pub enum BlockRef {
Number(u32),
Hash(primitives::hash::H256),

View File

@ -1,7 +1,7 @@
//! Bitcoin chain verifier
use std::collections::BTreeSet;
use db::{self, BlockLocation, PreviousTransactionOutputProvider, BlockHeaderProvider};
use db::{self, BlockLocation, PreviousTransactionOutputProvider, BlockHeaderProvider, BlockRef};
use network::{Magic, ConsensusParams};
use script::Script;
use super::{Verify, VerificationResult, Chain, Error, TransactionError};
@ -377,20 +377,27 @@ impl ChainVerifier {
}
fn work_required_testnet(&self, header: &chain::BlockHeader, height: u32) -> u32 {
let mut bits = BTreeSet::new();
let mut block_ref = header.previous_header_hash.clone().into();
// TODO: optimize it, so it does not make 11 redundant queries each time
for _ in 0..11 {
let mut bits = Vec::new();
let mut block_ref: BlockRef = header.previous_header_hash.clone().into();
let parent_header = self.store.block_header(block_ref.clone()).expect("can be called only during ordered verification");
let max_time_gap = parent_header.time + utils::DOUBLE_SPACING_SECONDS;
if header.time > max_time_gap {
return self.network.max_nbits();
}
// TODO: optimize it, so it does not make 2016!!! redundant queries each time
for _ in 0..utils::RETARGETING_INTERVAL {
let previous_header = match self.store.block_header(block_ref) {
Some(h) => h,
None => { break; }
};
bits.insert(previous_header.nbits);
bits.push(previous_header.nbits);
block_ref = previous_header.previous_header_hash.into();
}
for (index, bit) in bits.into_iter().enumerate() {
if bit != self.network.max_nbits() || utils::is_retarget_height(height - index as u32) {
if bit != self.network.max_nbits() || utils::is_retarget_height(height - index as u32 - 1) {
return bit;
}
}

View File

@ -9,7 +9,7 @@ use compact::Compact;
// Timespan constants
const RETARGETING_FACTOR: u32 = 4;
const TARGET_SPACING_SECONDS: u32 = 10 * 60;
const DOUBLE_SPACING_SECONDS: u32 = 2 * TARGET_SPACING_SECONDS;
pub const DOUBLE_SPACING_SECONDS: u32 = 2 * TARGET_SPACING_SECONDS;
const TARGET_TIMESPAN_SECONDS: u32 = 2 * 7 * 24 * 60 * 60;
// The upper and lower bounds for retargeting timespan
@ -24,8 +24,10 @@ pub fn is_retarget_height(height: u32) -> bool {
}
fn retarget_timespan(retarget_timestamp: u32, last_timestamp: u32) -> u32 {
let timespan = last_timestamp - retarget_timestamp;
range_constrain(timespan as u32, MIN_TIMESPAN, MAX_TIMESPAN)
// According to libbitcoin we need to
// Subtract 32 bit numbers in 64 bit space and constrain result to 32 bits.
let timespan = last_timestamp as u64 - retarget_timestamp as u64;
range_constrain(timespan, MIN_TIMESPAN as u64, MAX_TIMESPAN as u64) as u32
}
pub fn work_required_retarget(max_nbits: u32, retarget_timestamp: u32, last_timestamp: u32, last_nbits: u32) -> u32 {
@ -44,11 +46,7 @@ pub fn work_required_retarget(max_nbits: u32, retarget_timestamp: u32, last_time
}
}
pub fn work_required_testnet() -> u32 {
unimplemented!();
}
fn range_constrain(value: u32, min: u32, max: u32) -> u32 {
fn range_constrain(value: u64, min: u64, max: u64) -> u64 {
cmp::min(cmp::max(value, min), max)
}