[T4] Secondary proof of work difficulty adjustments (#1709)

* First pass at secondary proof of work difficulty adjustments
* Core and chain test fixes
* Next difficulty calc now needs a height. Scaling calculation fixes. Setting scaling on mined block.
* Change factor to u32 instead of u64.
* Cleanup structs used by next_difficulty
* Fix header size calc with u32 scaling
This commit is contained in:
Ignotus Peverell
2018-10-13 13:57:01 -07:00
committed by GitHub
parent e9f62b74d5
commit 43f4f92730
21 changed files with 376 additions and 301 deletions
+3 -3
View File
@@ -45,9 +45,9 @@ pub enum ErrorKind {
/// Addition of difficulties on all previous block is wrong
#[fail(display = "Addition of difficulties on all previous blocks is wrong")]
WrongTotalDifficulty,
/// Block header sizeshift is lower than our min
#[fail(display = "Cuckoo Size too Low")]
LowSizeshift,
/// Block header sizeshift is incorrect
#[fail(display = "Cuckoo size shift is invalid")]
InvalidSizeshift,
/// Scaling factor between primary and secondary PoW is invalid
#[fail(display = "Wrong scaling factor")]
InvalidScaling,
+13 -20
View File
@@ -36,8 +36,6 @@ use txhashset;
use types::{Options, Tip};
use util::LOGGER;
use failure::ResultExt;
/// Contextual information required to process a new block and either reject or
/// accept it.
pub struct BlockContext<'a> {
@@ -364,16 +362,10 @@ fn validate_header(header: &BlockHeader, ctx: &mut BlockContext) -> Result<(), E
}
if !ctx.opts.contains(Options::SKIP_POW) {
if !header.pow.is_primary() && !header.pow.is_secondary() {
return Err(ErrorKind::InvalidSizeshift.into());
}
let shift = header.pow.cuckoo_sizeshift();
// size shift can either be larger than the minimum on the primary PoW
// or equal to the seconday PoW size shift
if shift != consensus::SECOND_POW_SIZESHIFT && global::min_sizeshift() > shift {
return Err(ErrorKind::LowSizeshift.into());
}
// primary PoW must have a scaling factor of 1
if shift != consensus::SECOND_POW_SIZESHIFT && header.pow.scaling_difficulty != 1 {
return Err(ErrorKind::InvalidScaling.into());
}
if !(ctx.pow_verifier)(header, shift).is_ok() {
error!(
LOGGER,
@@ -435,17 +427,20 @@ fn validate_header(header: &BlockHeader, ctx: &mut BlockContext) -> Result<(), E
// (during testnet1 we use _block_ difficulty here)
let child_batch = ctx.batch.child()?;
let diff_iter = store::DifficultyIter::from_batch(header.previous, child_batch);
let network_difficulty = consensus::next_difficulty(diff_iter)
.context(ErrorKind::Other("network difficulty".to_owned()))?;
if target_difficulty != network_difficulty.clone() {
error!(
let next_header_info = consensus::next_difficulty(header.height, diff_iter);
if target_difficulty != next_header_info.difficulty {
info!(
LOGGER,
"validate_header: header target difficulty {} != {}",
target_difficulty.to_num(),
network_difficulty.to_num()
next_header_info.difficulty.to_num()
);
return Err(ErrorKind::WrongTotalDifficulty.into());
}
// check the secondary PoW scaling factor if applicable
if header.pow.scaling_difficulty != next_header_info.secondary_scaling {
return Err(ErrorKind::InvalidScaling.into());
}
}
Ok(())
@@ -454,10 +449,8 @@ fn validate_header(header: &BlockHeader, ctx: &mut BlockContext) -> Result<(), E
fn validate_block(block: &Block, ctx: &mut BlockContext) -> Result<(), Error> {
let prev = ctx.batch.get_block_header(&block.header.previous)?;
block
.validate(
&prev.total_kernel_offset,
ctx.verifier_cache.clone(),
).map_err(|e| ErrorKind::InvalidBlockProof(e))?;
.validate(&prev.total_kernel_offset, ctx.verifier_cache.clone())
.map_err(|e| ErrorKind::InvalidBlockProof(e))?;
Ok(())
}
+9 -3
View File
@@ -22,7 +22,7 @@ use lru_cache::LruCache;
use util::secp::pedersen::Commitment;
use core::consensus::TargetError;
use core::consensus::HeaderInfo;
use core::core::hash::{Hash, Hashed};
use core::core::{Block, BlockHeader, BlockSums};
use core::pow::Difficulty;
@@ -613,7 +613,7 @@ impl<'a> DifficultyIter<'a> {
}
impl<'a> Iterator for DifficultyIter<'a> {
type Item = Result<(u64, Difficulty), TargetError>;
type Item = HeaderInfo;
fn next(&mut self) -> Option<Self::Item> {
// Get both header and previous_header if this is the initial iteration.
@@ -650,8 +650,14 @@ impl<'a> Iterator for DifficultyIter<'a> {
.clone()
.map_or(Difficulty::zero(), |x| x.total_difficulty());
let difficulty = header.total_difficulty() - prev_difficulty;
let scaling = header.pow.scaling_difficulty;
Some(Ok((header.timestamp.timestamp() as u64, difficulty)))
Some(HeaderInfo::new(
header.timestamp.timestamp() as u64,
difficulty,
scaling,
header.pow.is_secondary(),
))
} else {
return None;
}