diff --git a/chain/src/lib.rs b/chain/src/lib.rs index 03f96694..cff9ef77 100644 --- a/chain/src/lib.rs +++ b/chain/src/lib.rs @@ -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}; diff --git a/chain/src/pipe.rs b/chain/src/pipe.rs index 4add3e85..df391b05 100644 --- a/chain/src/pipe.rs +++ b/chain/src/pipe.rs @@ -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 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); } } diff --git a/chain/src/store.rs b/chain/src/store.rs index 20af053c..281d8c5d 100644 --- a/chain/src/store.rs +++ b/chain/src/store.rs @@ -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, +} + +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) -> DifficultyIter { + DifficultyIter { + next: start, + store: store, + } + } +} + +impl Iterator for DifficultyIter { + type Item = Result<(i64, Difficulty), TargetError>; + + fn next(&mut self) -> Option { + 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))) + } + } + } +} diff --git a/chain/tests/mine_simple_chain.rs b/chain/tests/mine_simple_chain.rs index 504bbcae..9e7b1fb4 100644 --- a/chain/tests/mine_simple_chain.rs +++ b/chain/tests/mine_simple_chain.rs @@ -24,6 +24,7 @@ use std::thread; use rand::os::OsRng; use grin_chain::types::*; +use grin_chain::store; use grin_core::core::hash::Hashed; use grin_core::core::target::Difficulty; use grin_core::pow; @@ -38,9 +39,8 @@ fn mine_empty_chain() { // save a genesis block let mut gen = grin_core::genesis::genesis(); - gen.header.cuckoo_len = 12; let diff = gen.header.difficulty.clone(); - pow::pow(&mut gen.header, diff).unwrap(); + pow::pow_size(&mut gen.header, diff, consensus::TEST_SIZESHIFT as u32).unwrap(); store.save_block(&gen).unwrap(); // setup a new head tip @@ -58,17 +58,15 @@ fn mine_empty_chain() { let mut b = core::Block::new(&prev.header, vec![], reward_key).unwrap(); b.header.timestamp = prev.header.timestamp + time::Duration::seconds(60); - let (difficulty, _) = consensus::next_target(b.header.timestamp.to_timespec().sec, - prev.header.timestamp.to_timespec().sec, - prev.header.difficulty.clone(), - prev.header.cuckoo_len); + let diff_iter = store::DifficultyIter::from(b.header.previous, arc_store.clone()); + let difficulty = consensus::next_difficulty(diff_iter).unwrap(); b.header.difficulty = difficulty.clone(); - pow::pow(&mut b.header, difficulty).unwrap(); + pow::pow_size(&mut b.header, difficulty, consensus::TEST_SIZESHIFT as u32).unwrap(); grin_chain::pipe::process_block(&b, arc_store.clone(), adapter.clone(), - grin_chain::pipe::NONE) + grin_chain::pipe::EASY_POW) .unwrap(); // checking our new head @@ -88,9 +86,8 @@ fn mine_forks() { // save a genesis block let mut gen = grin_core::genesis::genesis(); - gen.header.cuckoo_len = 12; let diff = gen.header.difficulty.clone(); - pow::pow(&mut gen.header, diff).unwrap(); + pow::pow_size(&mut gen.header, diff, consensus::TEST_SIZESHIFT as u32).unwrap(); store.save_block(&gen).unwrap(); // setup a new head tip diff --git a/core/src/consensus.rs b/core/src/consensus.rs index 29d2cb98..bf96ef87 100644 --- a/core/src/consensus.rs +++ b/core/src/consensus.rs @@ -20,6 +20,7 @@ //! here. use std::cmp; +use std::fmt; use bigint::{BigInt, Sign}; @@ -37,17 +38,11 @@ pub const BLOCK_TIME_SEC: i64 = 60; /// Cuckoo-cycle proof size (cycle length) pub const PROOFSIZE: usize = 42; -/// Origin Cuckoo Cycle size shift used by the genesis block. -pub const DEFAULT_SIZESHIFT: u8 = 25; +/// Default Cuckoo Cycle size shift used for mining and validating. +pub const DEFAULT_SIZESHIFT: u8 = 30; -/// Maximum Cuckoo Cycle size shift we'll ever use. We adopt a schedule that -/// progressively increases the size as the target becomes lower. -/// Start => 25 -/// MAX_TARGET >> 12 => 26 -/// MAX_TARGET >> 20 => 27 -/// MAX_TARGET >> 28 => 28 -/// MAX_TARGET >> 36 => 29 -pub const MAX_SIZESHIFT: u8 = 29; +/// Lower Cuckoo size shift for tests and testnet +pub const TEST_SIZESHIFT: u8 = 12; /// Default Cuckoo Cycle easiness, high enough to have good likeliness to find /// a solution. @@ -75,11 +70,28 @@ pub const UPPER_TIME_BOUND: i64 = BLOCK_TIME_WINDOW * 4 / 3; pub const LOWER_TIME_BOUND: i64 = BLOCK_TIME_WINDOW * 5 / 6; +/// Error when computing the next difficulty adjustment. #[derive(Debug, Clone)] -pub struct TargetError { - err: String, +pub struct TargetError(pub String); + +impl fmt::Display for TargetError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Error computing new difficulty: {}", self.0) + } } -pub fn next_target2(cursor: T) -> Result + +/// Computes the proof-of-work difficulty that the next block should comply +/// with. Takes an iterator over past blocks, from latest (highest height) to +/// oldest (lowest height). The iterator produces pairs of timestamp and +/// difficulty for each block. +/// +/// The difficulty calculation is based on both Digishield and GravityWave +/// family of difficulty computation, coming to something very close to Zcash. +/// The refence difficulty is an average of the difficulty over a window of +/// 23 blocks. The corresponding timespan is calculated by using the +/// difference between the median timestamps at the beginning and the end +/// of the window. +pub fn next_difficulty(cursor: T) -> Result where T: IntoIterator> { @@ -141,46 +153,6 @@ pub fn next_target2(cursor: T) -> Result Difficulty::from_num(adj_ts as u32)) } -/// Difficulty adjustment somewhat inspired by Ethereum's. Tuned to add or -/// remove 1/1024th of the target for each 10 seconds of deviation from the 30 -/// seconds block time. Increases Cuckoo size shift by one when next_target -/// reaches soft max. -pub fn next_target(ts: i64, - prev_ts: i64, - prev_diff: Difficulty, - prev_cuckoo_sz: u8) - -> (Difficulty, u8) { - let one = BigInt::new(Sign::Plus, vec![1]); - let two = BigInt::new(Sign::Plus, vec![2]); - let ten = BigInt::new(Sign::Plus, vec![10]); - - // increase the cuckoo size when the target gets lower than the soft min as - // long as we're not at the max size already; target gets 2x to compensate for - // increased next_target - let soft_min = one.clone() << - (((prev_cuckoo_sz - cmp::min(DEFAULT_SIZESHIFT, prev_cuckoo_sz)) * - 8 + 16) as usize); - let prev_diff = BigInt::from_biguint(Sign::Plus, prev_diff.into_biguint()); - let (pdiff, clen) = if prev_diff > soft_min && prev_cuckoo_sz < MAX_SIZESHIFT { - (prev_diff / two, prev_cuckoo_sz + 1) - } else { - (prev_diff, prev_cuckoo_sz) - }; - - // signed deviation from desired value divided by ten and bounded in [-6, 6] - let delta = cmp::max(cmp::min((ts - prev_ts - (BLOCK_TIME_SEC as i64)), 60), -60); - let delta_bigi = BigInt::new(if delta >= 0 { Sign::Plus } else { Sign::Minus }, - vec![delta.abs() as u32]); - let new_diff = pdiff.clone() - ((pdiff >> 10) + one.clone()) * delta_bigi / ten; - - // cannot be lower than one - if new_diff < one { - (Difficulty::one(), clen) - } else { - (Difficulty::from_biguint(new_diff.to_biguint().unwrap()), clen) - } -} - #[cfg(test)] mod test { use core::target::Difficulty; diff --git a/core/src/core/block.rs b/core/src/core/block.rs index 58530d41..d954a8a8 100644 --- a/core/src/core/block.rs +++ b/core/src/core/block.rs @@ -43,8 +43,6 @@ pub struct BlockHeader { pub previous: Hash, /// Timestamp at which the block was built. pub timestamp: time::Tm, - /// Length of the cuckoo cycle used to mine this block. - pub cuckoo_len: u8, /// Merkle root of the UTXO set pub utxo_merkle: Hash, /// Merkle tree of hashes for all inputs, outputs and kernels in the block @@ -67,7 +65,6 @@ impl Default for BlockHeader { height: 0, previous: ZERO_HASH, timestamp: time::at_utc(time::Timespec { sec: 0, nsec: 0 }), - cuckoo_len: 20, // only for tests difficulty: Difficulty::one(), total_difficulty: Difficulty::one(), utxo_merkle: ZERO_HASH, @@ -86,7 +83,6 @@ impl Writeable for BlockHeader { [write_u64, self.height], [write_fixed_bytes, &self.previous], [write_i64, self.timestamp.to_timespec().sec], - [write_u8, self.cuckoo_len], [write_fixed_bytes, &self.utxo_merkle], [write_fixed_bytes, &self.tx_merkle], [write_u8, self.features.bits()]); @@ -107,7 +103,7 @@ impl Readable for BlockHeader { fn read(reader: &mut Reader) -> Result { let height = try!(reader.read_u64()); let previous = try!(Hash::read(reader)); - let (timestamp, cuckoo_len) = ser_multiread!(reader, read_i64, read_u8); + let timestamp = reader.read_i64()?; let utxo_merkle = try!(Hash::read(reader)); let tx_merkle = try!(Hash::read(reader)); let (features, nonce) = ser_multiread!(reader, read_u8, read_u64); @@ -122,7 +118,6 @@ impl Readable for BlockHeader { sec: timestamp, nsec: 0, }), - cuckoo_len: cuckoo_len, utxo_merkle: utxo_merkle, tx_merkle: tx_merkle, features: BlockFeatures::from_bits(features).ok_or(ser::Error::CorruptedData)?, @@ -284,7 +279,6 @@ impl Block { timestamp: time::now(), previous: prev.hash(), total_difficulty: prev.pow.to_difficulty() + prev.total_difficulty.clone(), - cuckoo_len: prev.cuckoo_len, ..Default::default() }, inputs: inputs, diff --git a/core/src/genesis.rs b/core/src/genesis.rs index 6a524852..60fca856 100644 --- a/core/src/genesis.rs +++ b/core/src/genesis.rs @@ -34,7 +34,6 @@ pub fn genesis() -> core::Block { tm_mday: 4, ..time::empty_tm() }, - cuckoo_len: DEFAULT_SIZESHIFT, difficulty: Difficulty::one(), total_difficulty: Difficulty::one(), utxo_merkle: [].hash(), diff --git a/core/src/pow/mod.rs b/core/src/pow/mod.rs index 1d8640eb..6914d286 100644 --- a/core/src/pow/mod.rs +++ b/core/src/pow/mod.rs @@ -33,11 +33,6 @@ use core::hash::Hashed; use core::target::Difficulty; use pow::cuckoo::{Cuckoo, Miner, Error}; -/// Validates the proof of work of a given header. -pub fn verify(bh: &BlockHeader) -> bool { - verify_size(bh, bh.cuckoo_len as u32) -} - /// Validates the proof of work of a given header, and that the proof of work /// satisfies the requirements of the header. pub fn verify_size(bh: &BlockHeader, cuckoo_sz: u32) -> bool { @@ -49,21 +44,15 @@ pub fn verify_size(bh: &BlockHeader, cuckoo_sz: u32) -> bool { Cuckoo::new(&bh.hash()[..], cuckoo_sz).verify(bh.pow, EASINESS as u64) } -/// Runs a naive single-threaded proof of work computation over the provided -/// block, until the required difficulty target is reached. May take a -/// while for a low target... -pub fn pow(bh: &mut BlockHeader, diff: Difficulty) -> Result<(), Error> { - let cuckoo_len = bh.cuckoo_len as u32; - pow_size(bh, diff, cuckoo_len) -} - -/// Same as default pow function but uses the much easier Cuckoo20 (mostly for +/// Uses the much easier Cuckoo20 (mostly for /// tests). pub fn pow20(bh: &mut BlockHeader, diff: Difficulty) -> Result<(), Error> { pow_size(bh, diff, 20) } -/// Actual pow function, takes an arbitrary pow size as input +/// Runs a naive single-threaded proof of work computation over the provided +/// block, until the required difficulty target is reached. May take a +/// while for a low target... pub fn pow_size(bh: &mut BlockHeader, diff: Difficulty, sizeshift: u32) -> Result<(), Error> { let start_nonce = bh.nonce; diff --git a/grin/src/adapters.rs b/grin/src/adapters.rs index cb53d8da..9485e809 100644 --- a/grin/src/adapters.rs +++ b/grin/src/adapters.rs @@ -32,6 +32,7 @@ use sync; /// blocks and transactions are received and forwards to the chain and pool /// implementations. pub struct NetToChainAdapter { + test_mode: bool, /// the reference copy of the current chain state chain_head: Arc>, chain_store: Arc, @@ -64,12 +65,7 @@ impl NetAdapter for NetToChainAdapter { // pushing the new block through the chain pipeline let store = self.chain_store.clone(); let chain_adapter = self.chain_adapter.clone(); - let opts = if self.syncer.borrow().syncing() { - chain::SYNC - } else { - chain::NONE - }; - let res = chain::process_block(&b, store, chain_adapter, opts); + let res = chain::process_block(&b, store, chain_adapter, self.chain_opts()); // log errors and update the shared head reference on success if let Err(e) = res { @@ -86,19 +82,13 @@ impl NetAdapter for NetToChainAdapter { } fn headers_received(&self, bhs: Vec) { - let opts = if self.syncer.borrow().syncing() { - chain::SYNC - } else { - chain::NONE - }; - // try to add each header to our header chain let mut added_hs = vec![]; for bh in bhs { let store = self.chain_store.clone(); let chain_adapter = self.chain_adapter.clone(); - let res = chain::process_block_header(&bh, store, chain_adapter, opts); + let res = chain::process_block_header(&bh, store, chain_adapter, self.chain_opts()); match res { Ok(_) => { added_hs.push(bh.hash()); @@ -216,13 +206,15 @@ impl NetAdapter for NetToChainAdapter { } impl NetToChainAdapter { - pub fn new(chain_head: Arc>, + pub fn new(test_mode: bool, + chain_head: Arc>, chain_store: Arc, chain_adapter: Arc, tx_pool: Arc>>, peer_store: Arc) -> NetToChainAdapter { NetToChainAdapter { + test_mode: test_mode, chain_head: chain_head, chain_store: chain_store, chain_adapter: chain_adapter, @@ -232,6 +224,8 @@ impl NetToChainAdapter { } } + /// Start syncing the chain by instantiating and running the Syncer in the + /// background (a new thread is created). pub fn start_sync(&self, sync: sync::Syncer) { let arc_sync = Arc::new(sync); self.syncer.init(arc_sync.clone()); @@ -239,6 +233,19 @@ impl NetToChainAdapter { arc_sync.run(); }); } + + /// Prepare options for the chain pipeline + fn chain_opts(&self) -> chain::Options { + let mut opts = if self.syncer.borrow().syncing() { + chain::SYNC + } else { + chain::NONE + }; + if self.test_mode { + opts = opts | chain::EASY_POW; + } + opts + } } /// Implementation of the ChainAdapter for the network. Gets notified when the diff --git a/grin/src/miner.rs b/grin/src/miner.rs index 399d92fa..8f33c715 100644 --- a/grin/src/miner.rs +++ b/grin/src/miner.rs @@ -82,15 +82,14 @@ impl Miner { let deadline = time::get_time().sec + 2; let mut sol = None; debug!("Mining at Cuckoo{} for at most 2 secs on block {} at difficulty {}.", - b.header.cuckoo_len, + self.config.cuckoo_size, latest_hash, b.header.difficulty); let mut iter_count = 0; while head.hash() == latest_hash && time::get_time().sec < deadline { let pow_hash = b.hash(); - let mut miner = cuckoo::Miner::new(&pow_hash[..], - consensus::EASINESS, - b.header.cuckoo_len as u32); + let mut miner = + cuckoo::Miner::new(&pow_hash[..], consensus::EASINESS, self.config.cuckoo_size); if let Ok(proof) = miner.mine() { if proof.to_difficulty() >= b.header.difficulty { sol = Some(proof); @@ -108,10 +107,15 @@ impl Miner { if let Some(proof) = sol { info!("Found valid proof of work, adding block {}.", b.hash()); b.header.pow = proof; + let opts = if self.config.cuckoo_size < consensus::DEFAULT_SIZESHIFT as u32 { + chain::EASY_POW + } else { + chain::NONE + }; let res = chain::process_block(&b, self.chain_store.clone(), self.chain_adapter.clone(), - chain::NONE); + opts); if let Err(e) = res { error!("Error validating mined block: {:?}", e); } else if let Ok(Some(tip)) = res { @@ -138,8 +142,9 @@ impl Miner { if now_sec == head_sec { now_sec += 1; } - let (difficulty, cuckoo_len) = - consensus::next_target(now_sec, head_sec, head.difficulty.clone(), head.cuckoo_len); + + let diff_iter = chain::store::DifficultyIter::from(head.hash(), self.chain_store.clone()); + let difficulty = consensus::next_difficulty(diff_iter).unwrap(); let txs_box = self.tx_pool.read().unwrap().prepare_mineable_transactions(MAX_TX); let txs = txs_box.iter().map(|tx| tx.as_ref()).collect(); @@ -155,7 +160,6 @@ impl Miner { let mut rng = rand::OsRng::new().unwrap(); b.header.nonce = rng.gen(); - b.header.cuckoo_len = cuckoo_len; b.header.difficulty = difficulty; b.header.timestamp = time::at(time::Timespec::new(now_sec, 0)); b diff --git a/grin/src/server.rs b/grin/src/server.rs index 864c077a..5f738aaa 100644 --- a/grin/src/server.rs +++ b/grin/src/server.rs @@ -29,7 +29,7 @@ use adapters::*; use api; use chain; use chain::ChainStore; -use core; +use core::{self, consensus}; use core::core::hash::Hashed; use miner; use p2p; @@ -58,8 +58,10 @@ pub struct Server { impl Server { /// Instantiates and starts a new server. - pub fn start(config: ServerConfig) -> Result { + pub fn start(mut config: ServerConfig) -> Result { + check_config(&mut config); let mut evtlp = reactor::Core::new().unwrap(); + let mining_config = config.mining_config.clone(); let serv = Server::future(config, &evtlp.handle())?; if mining_config.enable_mining { @@ -79,7 +81,9 @@ impl Server { } /// Instantiates a new server associated with the provided future reactor. - pub fn future(config: ServerConfig, evt_handle: &reactor::Handle) -> Result { + pub fn future(mut config: ServerConfig, evt_handle: &reactor::Handle) -> Result { + check_config(&mut config); + let (chain_store, head) = try!(store_head(&config)); let shared_head = Arc::new(Mutex::new(head)); @@ -90,7 +94,8 @@ impl Server { let tx_pool = Arc::new(RwLock::new(pool::TransactionPool::new(pool_adapter))); let chain_adapter = Arc::new(ChainToPoolAndNetAdapter::new(tx_pool.clone())); - let net_adapter = Arc::new(NetToChainAdapter::new(shared_head.clone(), + let net_adapter = Arc::new(NetToChainAdapter::new(config.test_mode, + shared_head.clone(), chain_store.clone(), chain_adapter.clone(), tx_pool.clone(), @@ -176,14 +181,14 @@ fn store_head(config: &ServerConfig) Err(store::Error::NotFoundErr) => { info!("No genesis block found, creating and saving one."); let mut gen = core::genesis::genesis(); - if config.cuckoo_size > 0 { - gen.header.cuckoo_len = config.cuckoo_size; - let diff = gen.header.difficulty.clone(); - core::pow::pow(&mut gen.header, diff).unwrap(); - } - try!(chain_store.save_block(&gen).map_err(&Error::Store)); + let diff = gen.header.difficulty.clone(); + core::pow::pow_size(&mut gen.header, + diff, + config.mining_config.cuckoo_size as u32) + .unwrap(); + chain_store.save_block(&gen).map_err(&Error::Store)?; let tip = chain::types::Tip::new(gen.hash()); - try!(chain_store.save_head(&tip).map_err(&Error::Store)); + chain_store.save_head(&tip).map_err(&Error::Store)?; info!("Saved genesis block with hash {}", gen.hash()); tip } @@ -200,3 +205,12 @@ fn store_head(config: &ServerConfig) Ok((Arc::new(chain_store), head)) } + +fn check_config(config: &mut ServerConfig) { + // applying test/normal config + config.mining_config.cuckoo_size = if config.test_mode { + consensus::TEST_SIZESHIFT as u32 + } else { + consensus::DEFAULT_SIZESHIFT as u32 + }; +} diff --git a/grin/src/types.rs b/grin/src/types.rs index 5fd65652..deea4f5b 100644 --- a/grin/src/types.rs +++ b/grin/src/types.rs @@ -77,9 +77,6 @@ pub struct ServerConfig { /// Network address for the Rest API HTTP server. pub api_http_addr: String, - /// Allows overriding the default cuckoo cycle size - pub cuckoo_size: u8, - /// Capabilities expose by this node, also conditions which other peers this /// node will have an affinity toward when connection. pub capabilities: p2p::Capabilities, @@ -92,6 +89,9 @@ pub struct ServerConfig { /// Configuration for the mining daemon pub mining_config: MinerConfig, + + /// Setup the server for tests and testnet + pub test_mode: bool, } /// Mining configuration @@ -106,6 +106,9 @@ pub struct MinerConfig { /// Attributes the reward to a random private key instead of contacting the /// wallet receiver. Mostly used for tests. pub burn_reward: bool, + + /// Size of Cuckoo Cycle to mine on + pub cuckoo_size: u32, } impl Default for ServerConfig { @@ -113,11 +116,11 @@ impl Default for ServerConfig { ServerConfig { db_root: ".grin".to_string(), api_http_addr: "127.0.0.1:13415".to_string(), - cuckoo_size: 0, capabilities: p2p::FULL_NODE, seeding_type: Seeding::None, p2p_config: p2p::P2PConfig::default(), mining_config: MinerConfig::default(), + test_mode: true, } } } @@ -128,6 +131,7 @@ impl Default for MinerConfig { enable_mining: false, wallet_receiver_url: "http://localhost:13416".to_string(), burn_reward: false, + cuckoo_size: 0, } } } diff --git a/grin/tests/simulnet.rs b/grin/tests/simulnet.rs index fe032857..8eec8ff2 100644 --- a/grin/tests/simulnet.rs +++ b/grin/tests/simulnet.rs @@ -41,6 +41,7 @@ use secp::Secp256k1; use secp::key::SecretKey; use tiny_keccak::Keccak; +use core::consensus; use wallet::WalletConfig; @@ -75,7 +76,6 @@ impl LocalServerContainer { grin::ServerConfig{ api_http_addr: api_addr, db_root: format!("{}/grin-prop", working_dir), - cuckoo_size: 12, p2p_config: p2p::P2PConfig{port: server_port, ..p2p::P2PConfig::default()}, ..Default::default() }, &event_loop.handle()).unwrap(); @@ -223,6 +223,7 @@ impl LocalServerContainerPool { enable_mining: true, burn_reward: true, wallet_receiver_url : format!("http://{}", wallet_url), + cuckoo_size: consensus::TEST_SIZESHIFT as u32, ..Default::default() }; if s.enable_wallet == true { @@ -285,6 +286,7 @@ fn simulate_block_propagation() { let miner_config = grin::MinerConfig{ enable_mining: true, burn_reward: true, + cuckoo_size: consensus::TEST_SIZESHIFT as u32, ..Default::default() }; @@ -295,7 +297,6 @@ fn simulate_block_propagation() { grin::ServerConfig{ api_http_addr: format!("127.0.0.1:{}", 20000+n), db_root: format!("target/grin-prop-{}", n), - cuckoo_size: 12, p2p_config: p2p::P2PConfig{port: 10000+n, ..p2p::P2PConfig::default()}, ..Default::default() }, &handle).unwrap(); @@ -335,6 +336,7 @@ fn simulate_full_sync() { let miner_config = grin::MinerConfig{ enable_mining: true, burn_reward: true, + cuckoo_size: consensus::TEST_SIZESHIFT as u32, ..Default::default() }; @@ -344,7 +346,6 @@ fn simulate_full_sync() { let s = grin::Server::future( grin::ServerConfig{ db_root: format!("target/grin-sync-{}", n), - cuckoo_size: 12, p2p_config: p2p::P2PConfig{port: 11000+n, ..p2p::P2PConfig::default()}, ..Default::default() }, &handle).unwrap(); @@ -378,7 +379,6 @@ fn simulate_seeding() { let s = grin::Server::future( grin::ServerConfig{ db_root: format!("target/grin-seed-{}", n), - cuckoo_size: 12, p2p_config: p2p::P2PConfig{port: 12000+n, ..p2p::P2PConfig::default()}, seeding_type: grin::Seeding::List(vec!["127.0.0.1:12000".to_string()]), ..Default::default() diff --git a/src/bin/grin.rs b/src/bin/grin.rs index 8415ffe7..b91b0234 100644 --- a/src/bin/grin.rs +++ b/src/bin/grin.rs @@ -282,7 +282,7 @@ fn read_config() -> grin::ServerConfig { fn default_config() -> grin::ServerConfig { grin::ServerConfig { - cuckoo_size: 12, + test_mode: true, seeding_type: grin::Seeding::WebStatic, ..Default::default() }