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