[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:
+3
-3
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user