Apply new difficulty algo, remove configurable cuckoo size

Integrate the new difficulty calculation into the block chain
validation, the miner and tests. As the difficulty calculation
doesn't use varying Cuckoo sizes anymore and we narrowed down
reasonable final Cuckoo Cycle parameters, removed all Cuckoo
Cycle sizes from block headers.

Formalized easier Cuckoo Cycle sizes for testing (and possibly
testnet) by introducing a test mode in configuration. Updated
all tests.
This commit is contained in:
Ignotus Peverell
2017-06-19 08:59:56 -07:00
parent 163b1133a7
commit e8a6b61100
14 changed files with 166 additions and 138 deletions
+1 -1
View File
@@ -41,4 +41,4 @@ pub mod types;
// Re-export the base interface
pub use types::{ChainStore, Tip, ChainAdapter};
pub use pipe::{SYNC, NONE, process_block, process_block_header, Error};
pub use pipe::{SYNC, NONE, EASY_POW, process_block, process_block_header, Options, Error};
+15 -9
View File
@@ -37,8 +37,10 @@ bitflags! {
const NONE = 0b00000001,
/// Runs without checking the Proof of Work, mostly to make testing easier.
const SKIP_POW = 0b00000010,
/// Runs PoW verification with a lower cycle size.
const EASY_POW = 0b00000100,
/// Adds block while in syncing mode.
const SYNC = 0b00000100,
const SYNC = 0b00001000,
}
}
@@ -72,6 +74,7 @@ pub enum Error {
/// Internal issue when trying to save or load data from store
StoreErr(grin_store::Error),
SerErr(ser::Error),
Other(String),
}
impl From<grin_store::Error> for Error {
@@ -201,17 +204,20 @@ fn validate_header(header: &BlockHeader, ctx: &mut BlockContext) -> Result<(), E
return Err(Error::WrongTotalDifficulty);
}
let (difficulty, cuckoo_sz) = consensus::next_target(header.timestamp.to_timespec().sec,
prev.timestamp.to_timespec().sec,
prev.difficulty,
prev.cuckoo_len);
let diff_iter = store::DifficultyIter::from(header.previous, ctx.store.clone());
let difficulty =
consensus::next_difficulty(diff_iter).map_err(|e| Error::Other(e.to_string()))?;
if header.difficulty < difficulty {
return Err(Error::DifficultyTooLow);
}
if header.cuckoo_len != cuckoo_sz {
return Err(Error::WrongCuckooSize);
}
if !pow::verify(header) {
let cycle_size = if ctx.opts.intersects(EASY_POW) {
consensus::TEST_SIZESHIFT
} else {
consensus::DEFAULT_SIZESHIFT
};
debug!("Validating block with cuckoo size {}", cycle_size);
if !pow::verify_size(header, cycle_size as u32) {
return Err(Error::InvalidPow);
}
}
+42
View File
@@ -14,11 +14,15 @@
//! Implements storage primitives required by the chain
use std::sync::Arc;
use secp::pedersen::Commitment;
use types::*;
use core::core::hash::{Hash, Hashed};
use core::core::{Block, BlockHeader, Output};
use core::consensus::TargetError;
use core::core::target::Difficulty;
use grin_store::{self, Error, to_key, u64_to_key, option_to_not_found};
const STORE_SUBPATH: &'static str = "chain";
@@ -141,3 +145,41 @@ impl ChainStore for ChainKVStore {
Ok(())
}
}
/// An iterator on blocks, from latest to earliest, specialized to return
/// information pertaining to block difficulty calculation (timestamp and
/// previous difficulties). Mostly used by the consensus next difficulty
/// calculation.
pub struct DifficultyIter {
next: Hash,
store: Arc<ChainStore>,
}
impl DifficultyIter {
/// Build a new iterator using the provided chain store and starting from
/// the provided block hash.
pub fn from(start: Hash, store: Arc<ChainStore>) -> DifficultyIter {
DifficultyIter {
next: start,
store: store,
}
}
}
impl Iterator for DifficultyIter {
type Item = Result<(i64, Difficulty), TargetError>;
fn next(&mut self) -> Option<Self::Item> {
let bhe = self.store.get_block_header(&self.next);
match bhe {
Err(e) => Some(Err(TargetError(e.to_string()))),
Ok(bh) => {
if bh.height == 0 {
return None;
}
self.next = bh.previous;
Some(Ok((bh.timestamp.to_timespec().sec, bh.difficulty)))
}
}
}
}