Skip to content

Commit

Permalink
[T4] Secondary proof of work difficulty adjustments (mimblewimble#1709)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
ignopeverell authored Oct 13, 2018
1 parent e9f62b7 commit 43f4f92
Show file tree
Hide file tree
Showing 21 changed files with 377 additions and 302 deletions.
6 changes: 3 additions & 3 deletions chain/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
33 changes: 13 additions & 20 deletions chain/src/pipe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand Down Expand Up @@ -364,16 +362,10 @@ fn validate_header(header: &BlockHeader, ctx: &mut BlockContext) -> Result<(), E
}

if !ctx.opts.contains(Options::SKIP_POW) {
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 !header.pow.is_primary() && !header.pow.is_secondary() {
return Err(ErrorKind::InvalidSizeshift.into());
}
let shift = header.pow.cuckoo_sizeshift();
if !(ctx.pow_verifier)(header, shift).is_ok() {
error!(
LOGGER,
Expand Down Expand Up @@ -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(())
Expand All @@ -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(())
}

Expand Down
14 changes: 10 additions & 4 deletions chain/src/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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;

Some(Ok((header.timestamp.timestamp() as u64, difficulty)))
let scaling = header.pow.scaling_difficulty;

Some(HeaderInfo::new(
header.timestamp.timestamp() as u64,
difficulty,
scaling,
header.pow.is_secondary(),
))
} else {
return None;
}
Expand Down
8 changes: 5 additions & 3 deletions chain/tests/data_file_integrity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,17 +82,19 @@ fn data_files() {

for n in 1..4 {
let prev = chain.head_header().unwrap();
let difficulty = consensus::next_difficulty(chain.difficulty_iter()).unwrap();
let next_header_info = consensus::next_difficulty(1, chain.difficulty_iter());
let pk = ExtKeychainPath::new(1, n as u32, 0, 0, 0).to_identifier();
let reward = libtx::reward::output(&keychain, &pk, 0, prev.height).unwrap();
let mut b = core::core::Block::new(&prev, vec![], difficulty.clone(), reward).unwrap();
let mut b =
core::core::Block::new(&prev, vec![], next_header_info.clone().difficulty, reward)
.unwrap();
b.header.timestamp = prev.timestamp + Duration::seconds(60);

chain.set_txhashset_roots(&mut b, false).unwrap();

pow::pow_size(
&mut b.header,
difficulty,
next_header_info.difficulty,
global::proofsize(),
global::min_sizeshift(),
).unwrap();
Expand Down
39 changes: 26 additions & 13 deletions chain/tests/mine_simple_chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,12 @@ fn mine_empty_chain() {

for n in 1..4 {
let prev = chain.head_header().unwrap();
let difficulty = consensus::next_difficulty(chain.difficulty_iter()).unwrap();
let next_header_info = consensus::next_difficulty(1, chain.difficulty_iter());
let pk = ExtKeychainPath::new(1, n as u32, 0, 0, 0).to_identifier();
let reward = libtx::reward::output(&keychain, &pk, 0, prev.height).unwrap();
let mut b = core::core::Block::new(&prev, vec![], difficulty.clone(), reward).unwrap();
let mut b =
core::core::Block::new(&prev, vec![], next_header_info.clone().difficulty, reward)
.unwrap();
b.header.timestamp = prev.timestamp + Duration::seconds(60);

chain.set_txhashset_roots(&mut b, false).unwrap();
Expand All @@ -78,7 +80,12 @@ fn mine_empty_chain() {
global::min_sizeshift()
};
b.header.pow.proof.cuckoo_sizeshift = sizeshift;
pow::pow_size(&mut b.header, difficulty, global::proofsize(), sizeshift).unwrap();
pow::pow_size(
&mut b.header,
next_header_info.difficulty,
global::proofsize(),
sizeshift,
).unwrap();
b.header.pow.proof.cuckoo_sizeshift = sizeshift;

let bhash = b.hash();
Expand Down Expand Up @@ -379,11 +386,13 @@ fn output_header_mappings() {

for n in 1..15 {
let prev = chain.head_header().unwrap();
let difficulty = consensus::next_difficulty(chain.difficulty_iter()).unwrap();
let next_header_info = consensus::next_difficulty(1, chain.difficulty_iter());
let pk = ExtKeychainPath::new(1, n as u32, 0, 0, 0).to_identifier();
let reward = libtx::reward::output(&keychain, &pk, 0, prev.height).unwrap();
reward_outputs.push(reward.0.clone());
let mut b = core::core::Block::new(&prev, vec![], difficulty.clone(), reward).unwrap();
let mut b =
core::core::Block::new(&prev, vec![], next_header_info.clone().difficulty, reward)
.unwrap();
b.header.timestamp = prev.timestamp + Duration::seconds(60);

chain.set_txhashset_roots(&mut b, false).unwrap();
Expand All @@ -394,7 +403,12 @@ fn output_header_mappings() {
global::min_sizeshift()
};
b.header.pow.proof.cuckoo_sizeshift = sizeshift;
pow::pow_size(&mut b.header, difficulty, global::proofsize(), sizeshift).unwrap();
pow::pow_size(
&mut b.header,
next_header_info.difficulty,
global::proofsize(),
sizeshift,
).unwrap();
b.header.pow.proof.cuckoo_sizeshift = sizeshift;

chain.process_block(b, chain::Options::MINE).unwrap();
Expand Down Expand Up @@ -506,18 +520,17 @@ fn actual_diff_iter_output() {
let iter = chain.difficulty_iter();
let mut last_time = 0;
let mut first = true;
for i in iter.into_iter() {
let elem = i.unwrap();
for elem in iter.into_iter() {
if first {
last_time = elem.0;
last_time = elem.timestamp;
first = false;
}
println!(
"next_difficulty time: {}, diff: {}, duration: {} ",
elem.0,
elem.1.to_num(),
last_time - elem.0
elem.timestamp,
elem.difficulty.to_num(),
last_time - elem.timestamp
);
last_time = elem.0;
last_time = elem.timestamp;
}
}
16 changes: 8 additions & 8 deletions chain/tests/test_coinbase_maturity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,13 @@ fn test_coinbase_maturity() {
let mut block = core::core::Block::new(&prev, vec![], Difficulty::one(), reward).unwrap();
block.header.timestamp = prev.timestamp + Duration::seconds(60);

let difficulty = consensus::next_difficulty(chain.difficulty_iter()).unwrap();
let next_header_info = consensus::next_difficulty(1, chain.difficulty_iter());

chain.set_txhashset_roots(&mut block, false).unwrap();

pow::pow_size(
&mut block.header,
difficulty,
next_header_info.difficulty,
global::proofsize(),
global::min_sizeshift(),
).unwrap();
Expand Down Expand Up @@ -119,7 +119,7 @@ fn test_coinbase_maturity() {
let mut block = core::core::Block::new(&prev, txs, Difficulty::one(), reward).unwrap();
block.header.timestamp = prev.timestamp + Duration::seconds(60);

let difficulty = consensus::next_difficulty(chain.difficulty_iter()).unwrap();
let next_header_info = consensus::next_difficulty(1, chain.difficulty_iter());

chain.set_txhashset_roots(&mut block, false).unwrap();

Expand All @@ -135,7 +135,7 @@ fn test_coinbase_maturity() {

pow::pow_size(
&mut block.header,
difficulty,
next_header_info.difficulty,
global::proofsize(),
global::min_sizeshift(),
).unwrap();
Expand All @@ -152,13 +152,13 @@ fn test_coinbase_maturity() {
let mut block = core::core::Block::new(&prev, vec![], Difficulty::one(), reward).unwrap();
block.header.timestamp = prev.timestamp + Duration::seconds(60);

let difficulty = consensus::next_difficulty(chain.difficulty_iter()).unwrap();
let next_header_info = consensus::next_difficulty(1, chain.difficulty_iter());

chain.set_txhashset_roots(&mut block, false).unwrap();

pow::pow_size(
&mut block.header,
difficulty,
next_header_info.difficulty,
global::proofsize(),
global::min_sizeshift(),
).unwrap();
Expand All @@ -179,13 +179,13 @@ fn test_coinbase_maturity() {

block.header.timestamp = prev.timestamp + Duration::seconds(60);

let difficulty = consensus::next_difficulty(chain.difficulty_iter()).unwrap();
let next_header_info = consensus::next_difficulty(1, chain.difficulty_iter());

chain.set_txhashset_roots(&mut block, false).unwrap();

pow::pow_size(
&mut block.header,
difficulty,
next_header_info.difficulty,
global::proofsize(),
global::min_sizeshift(),
).unwrap();
Expand Down
Loading

0 comments on commit 43f4f92

Please sign in to comment.