mirror of
https://github.com/mimblewimble/grin.git
synced 2025-01-20 19:11:08 +03:00
POW refactor (#100)
* Adding output stats from plugin, when available * adding grin config * moving pow crate from core/pow to it's own crate * moving POW/mining stuff into pow module, and removing mining dependency from chain * refactored most of mining into pow module...miner.rs still in server * update grin tests * updating genesis block mining to use configured miner, if available * chain tests back into chain, done with pow refactor * use tag of cuckoo-miner for pr
This commit is contained in:
parent
6772d9f516
commit
045f5bb4da
27 changed files with 417 additions and 215 deletions
|
@ -21,6 +21,7 @@ env:
|
|||
- TEST_DIR=p2p
|
||||
- TEST_DIR=api
|
||||
- TEST_DIR=pool
|
||||
- TEST_DIR=pow
|
||||
- RUST_TEST_THREADS=1 TEST_DIR=grin
|
||||
|
||||
script: cd $TEST_DIR && cargo test --verbose
|
||||
|
|
|
@ -12,6 +12,7 @@ grin_wallet = { path = "./wallet" }
|
|||
grin_grin = { path = "./grin" }
|
||||
grin_config = { path = "./config" }
|
||||
grin_core = { path = "./core" }
|
||||
grin_pow = { path = "./pow"}
|
||||
secp256k1zkp = { path = "./secp256k1zkp" }
|
||||
|
||||
blake2-rfc = "~0.2.17"
|
||||
|
|
|
@ -19,8 +19,5 @@ secp256k1zkp = { path = "../secp256k1zkp" }
|
|||
[dev-dependencies]
|
||||
env_logger="^0.3.5"
|
||||
rand = "^0.3"
|
||||
grin_pow = { path = "../pow" }
|
||||
|
||||
#just to instantiate a mining worker during a test
|
||||
#while the miner implementation supports both
|
||||
#cuckoo_miner and the built-in version
|
||||
grin_grin = { path = "../grin" }
|
||||
|
|
|
@ -23,14 +23,11 @@ use secp::pedersen::Commitment;
|
|||
use core::core::{Block, BlockHeader, Output};
|
||||
use core::core::target::Difficulty;
|
||||
use core::core::hash::Hash;
|
||||
use core::{consensus, genesis, pow};
|
||||
use core::pow::MiningWorker;
|
||||
use grin_store;
|
||||
use pipe;
|
||||
use store;
|
||||
use types::*;
|
||||
|
||||
use core::global;
|
||||
use core::global::{MiningParameterMode,MINING_PARAMETER_MODE};
|
||||
|
||||
const MAX_ORPHANS: usize = 20;
|
||||
|
@ -57,12 +54,28 @@ pub struct Chain {
|
|||
head: Arc<Mutex<Tip>>,
|
||||
block_process_lock: Arc<Mutex<bool>>,
|
||||
orphans: Arc<Mutex<VecDeque<(Options, Block)>>>,
|
||||
|
||||
//POW verification function
|
||||
pow_verifier: fn(&BlockHeader, u32) -> bool,
|
||||
}
|
||||
|
||||
unsafe impl Sync for Chain {}
|
||||
unsafe impl Send for Chain {}
|
||||
|
||||
impl Chain {
|
||||
|
||||
/// Check whether the chain exists. If not, the call to 'init' will
|
||||
/// expect an already mined genesis block. This keeps the chain free
|
||||
/// from needing to know about the mining implementation
|
||||
pub fn chain_exists(db_root: String)->bool {
|
||||
let chain_store = store::ChainKVStore::new(db_root).unwrap();
|
||||
match chain_store.head() {
|
||||
Ok(_) => {true},
|
||||
Err(grin_store::Error::NotFoundErr) => false,
|
||||
Err(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Initializes the blockchain and returns a new Chain instance. Does a
|
||||
/// check
|
||||
/// on the current chain head to make sure it exists and creates one based
|
||||
|
@ -71,6 +84,8 @@ impl Chain {
|
|||
pub fn init(
|
||||
db_root: String,
|
||||
adapter: Arc<ChainAdapter>,
|
||||
gen_block: Option<Block>,
|
||||
pow_verifier: fn(&BlockHeader, u32) -> bool,
|
||||
) -> Result<Chain, Error> {
|
||||
let chain_store = store::ChainKVStore::new(db_root)?;
|
||||
|
||||
|
@ -78,15 +93,11 @@ impl Chain {
|
|||
let head = match chain_store.head() {
|
||||
Ok(tip) => tip,
|
||||
Err(grin_store::Error::NotFoundErr) => {
|
||||
info!("No genesis block found, creating and saving one.");
|
||||
let mut gen = genesis::genesis();
|
||||
let diff = gen.header.difficulty.clone();
|
||||
|
||||
let sz = global::sizeshift();
|
||||
let proof_size = global::proofsize();
|
||||
if let None = gen_block {
|
||||
return Err(Error::GenesisBlockRequired);
|
||||
}
|
||||
|
||||
let mut internal_miner = pow::cuckoo::Miner::new(consensus::EASINESS, sz as u32, proof_size);
|
||||
pow::pow_size(&mut internal_miner, &mut gen.header, diff, sz as u32).unwrap();
|
||||
let gen = gen_block.unwrap();
|
||||
chain_store.save_block(&gen)?;
|
||||
|
||||
// saving a new tip based on genesis
|
||||
|
@ -107,6 +118,7 @@ impl Chain {
|
|||
head: Arc::new(Mutex::new(head)),
|
||||
block_process_lock: Arc::new(Mutex::new(true)),
|
||||
orphans: Arc::new(Mutex::new(VecDeque::with_capacity(MAX_ORPHANS + 1))),
|
||||
pow_verifier: pow_verifier,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -170,6 +182,7 @@ impl Chain {
|
|||
store: self.store.clone(),
|
||||
adapter: self.adapter.clone(),
|
||||
head: head,
|
||||
pow_verifier: self.pow_verifier,
|
||||
lock: self.block_process_lock.clone(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@ use time;
|
|||
use core::consensus;
|
||||
use core::core::hash::{Hash, Hashed};
|
||||
use core::core::{BlockHeader, Block};
|
||||
use core::pow;
|
||||
use types::*;
|
||||
use store;
|
||||
use core::global;
|
||||
|
@ -38,6 +37,8 @@ pub struct BlockContext {
|
|||
pub adapter: Arc<ChainAdapter>,
|
||||
/// The head
|
||||
pub head: Tip,
|
||||
/// The POW verification function
|
||||
pub pow_verifier: fn(&BlockHeader, u32) -> bool,
|
||||
/// The lock
|
||||
pub lock: Arc<Mutex<bool>>,
|
||||
}
|
||||
|
@ -157,7 +158,7 @@ fn validate_header(header: &BlockHeader, ctx: &mut BlockContext) -> Result<(), E
|
|||
consensus::DEFAULT_SIZESHIFT
|
||||
};
|
||||
debug!("Validating block with cuckoo size {}", cycle_size);
|
||||
if !pow::verify_size(header, cycle_size as u32) {
|
||||
if !(ctx.pow_verifier)(header, cycle_size as u32) {
|
||||
return Err(Error::InvalidPow);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,6 +61,8 @@ pub enum Error {
|
|||
StoreErr(grin_store::Error),
|
||||
/// Error serializing or deserializing a type
|
||||
SerErr(ser::Error),
|
||||
/// No chain exists and genesis block is required
|
||||
GenesisBlockRequired,
|
||||
/// Anything else
|
||||
Other(String),
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2016 The Grin Developers
|
||||
// Copyright 2017 The Grin Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
@ -12,32 +12,27 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
extern crate grin_core;
|
||||
extern crate grin_chain;
|
||||
extern crate grin_core as core;
|
||||
extern crate grin_chain as chain;
|
||||
extern crate env_logger;
|
||||
extern crate time;
|
||||
extern crate rand;
|
||||
extern crate secp256k1zkp as secp;
|
||||
|
||||
extern crate grin_grin as grin;
|
||||
extern crate grin_pow as pow;
|
||||
|
||||
use std::fs;
|
||||
use std::sync::Arc;
|
||||
use std::thread;
|
||||
use rand::os::OsRng;
|
||||
|
||||
use grin_chain::types::*;
|
||||
use grin_core::core::hash::Hashed;
|
||||
use grin_core::core::target::Difficulty;
|
||||
use grin_core::pow;
|
||||
use grin_core::core;
|
||||
use grin_core::consensus;
|
||||
use grin_core::pow::cuckoo;
|
||||
use grin_core::global;
|
||||
use grin_core::global::MiningParameterMode;
|
||||
|
||||
use grin_core::pow::MiningWorker;
|
||||
use chain::types::*;
|
||||
use core::core::hash::Hashed;
|
||||
use core::core::target::Difficulty;
|
||||
use core::consensus;
|
||||
use core::global;
|
||||
use core::global::MiningParameterMode;
|
||||
|
||||
use pow::{types, cuckoo, MiningWorker};
|
||||
|
||||
fn clean_output_dir(dir_name:&str){
|
||||
let _ = fs::remove_dir_all(dir_name);
|
||||
|
@ -50,14 +45,18 @@ fn mine_empty_chain() {
|
|||
global::set_mining_mode(MiningParameterMode::AutomatedTesting);
|
||||
|
||||
let mut rng = OsRng::new().unwrap();
|
||||
let chain = grin_chain::Chain::init(".grin".to_string(), Arc::new(NoopAdapter {}))
|
||||
.unwrap();
|
||||
let mut genesis_block = None;
|
||||
if !chain::Chain::chain_exists(".grin".to_string()){
|
||||
genesis_block=pow::mine_genesis_block(None);
|
||||
}
|
||||
let chain = chain::Chain::init(".grin".to_string(), Arc::new(NoopAdapter {}),
|
||||
genesis_block, pow::verify_size).unwrap();
|
||||
|
||||
// mine and add a few blocks
|
||||
let secp = secp::Secp256k1::with_caps(secp::ContextFlag::Commit);
|
||||
let reward_key = secp::key::SecretKey::new(&secp, &mut rng);
|
||||
|
||||
let mut miner_config = grin::MinerConfig {
|
||||
let mut miner_config = types::MinerConfig {
|
||||
enable_mining: true,
|
||||
burn_reward: true,
|
||||
..Default::default()
|
||||
|
@ -67,7 +66,7 @@ fn mine_empty_chain() {
|
|||
let mut cuckoo_miner = cuckoo::Miner::new(consensus::EASINESS, global::sizeshift() as u32, global::proofsize());
|
||||
for n in 1..4 {
|
||||
let prev = chain.head_header().unwrap();
|
||||
let mut b = core::Block::new(&prev, vec![], reward_key).unwrap();
|
||||
let mut b = core::core::Block::new(&prev, vec![], reward_key).unwrap();
|
||||
b.header.timestamp = prev.timestamp + time::Duration::seconds(60);
|
||||
|
||||
let difficulty = consensus::next_difficulty(chain.difficulty_iter()).unwrap();
|
||||
|
@ -81,7 +80,7 @@ fn mine_empty_chain() {
|
|||
).unwrap();
|
||||
|
||||
let bhash = b.hash();
|
||||
chain.process_block(b, grin_chain::EASY_POW).unwrap();
|
||||
chain.process_block(b, chain::EASY_POW).unwrap();
|
||||
|
||||
// checking our new head
|
||||
let head = chain.head().unwrap();
|
||||
|
@ -96,8 +95,13 @@ fn mine_forks() {
|
|||
clean_output_dir(".grin2");
|
||||
|
||||
let mut rng = OsRng::new().unwrap();
|
||||
let chain = grin_chain::Chain::init(".grin2".to_string(), Arc::new(NoopAdapter {}))
|
||||
.unwrap();
|
||||
|
||||
let mut genesis_block = None;
|
||||
if !chain::Chain::chain_exists(".grin2".to_string()){
|
||||
genesis_block=pow::mine_genesis_block(None);
|
||||
}
|
||||
let chain = chain::Chain::init(".grin2".to_string(), Arc::new(NoopAdapter {}),
|
||||
genesis_block, pow::verify_size).unwrap();
|
||||
|
||||
// mine and add a few blocks
|
||||
let secp = secp::Secp256k1::with_caps(secp::ContextFlag::Commit);
|
||||
|
@ -105,11 +109,11 @@ fn mine_forks() {
|
|||
|
||||
for n in 1..4 {
|
||||
let prev = chain.head_header().unwrap();
|
||||
let mut b = core::Block::new(&prev, vec![], reward_key).unwrap();
|
||||
let mut b = core::core::Block::new(&prev, vec![], reward_key).unwrap();
|
||||
b.header.timestamp = prev.timestamp + time::Duration::seconds(60);
|
||||
b.header.total_difficulty = Difficulty::from_num(2 * n);
|
||||
let bhash = b.hash();
|
||||
chain.process_block(b, grin_chain::SKIP_POW).unwrap();
|
||||
chain.process_block(b, chain::SKIP_POW).unwrap();
|
||||
|
||||
// checking our new head
|
||||
thread::sleep(::std::time::Duration::from_millis(50));
|
||||
|
@ -119,11 +123,11 @@ fn mine_forks() {
|
|||
assert_eq!(head.prev_block_h, prev.hash());
|
||||
|
||||
// build another block with higher difficulty
|
||||
let mut b = core::Block::new(&prev, vec![], reward_key).unwrap();
|
||||
let mut b = core::core::Block::new(&prev, vec![], reward_key).unwrap();
|
||||
b.header.timestamp = prev.timestamp + time::Duration::seconds(60);
|
||||
b.header.total_difficulty = Difficulty::from_num(2 * n + 1);
|
||||
let bhash = b.hash();
|
||||
chain.process_block(b, grin_chain::SKIP_POW).unwrap();
|
||||
chain.process_block(b, chain::SKIP_POW).unwrap();
|
||||
|
||||
// checking head switch
|
||||
thread::sleep(::std::time::Duration::from_millis(50));
|
||||
|
|
|
@ -10,5 +10,6 @@ serde_derive = "~1.0.8"
|
|||
toml = "0.4"
|
||||
|
||||
grin_grin = { path = "../grin" }
|
||||
grin_pow = { path = "../pow"}
|
||||
grin_p2p = { path = "../p2p" }
|
||||
grin_wallet = { path = "../wallet"}
|
||||
|
|
|
@ -20,9 +20,8 @@ use std::path::PathBuf;
|
|||
use std::fs::File;
|
||||
|
||||
use toml;
|
||||
use grin::{ServerConfig,
|
||||
MinerConfig};
|
||||
|
||||
use grin::ServerConfig;
|
||||
use pow::types::MinerConfig;
|
||||
use types::{ConfigMembers,
|
||||
GlobalConfig,
|
||||
ConfigError};
|
||||
|
|
|
@ -29,6 +29,7 @@ extern crate toml;
|
|||
extern crate grin_grin as grin;
|
||||
extern crate grin_p2p as p2p;
|
||||
extern crate grin_wallet as wallet;
|
||||
extern crate grin_pow as pow;
|
||||
|
||||
pub mod config;
|
||||
pub mod types;
|
||||
|
|
|
@ -18,9 +18,8 @@ use std::path::PathBuf;
|
|||
use std::io;
|
||||
use std::fmt;
|
||||
|
||||
use grin::{ServerConfig,
|
||||
MinerConfig};
|
||||
|
||||
use grin::ServerConfig;
|
||||
use pow::types::MinerConfig;
|
||||
|
||||
/// Error type wrapping config errors.
|
||||
#[derive(Debug)]
|
||||
|
|
|
@ -94,6 +94,17 @@ pub fn is_automated_testing_mode() -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
/// Are we in production mode?
|
||||
pub fn is_production_mode() -> bool {
|
||||
let param_ref=MINING_PARAMETER_MODE.read().unwrap();
|
||||
if let MiningParameterMode::Production=*param_ref {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Helper function to get a nonce known to create a valid POW on
|
||||
/// the genesis block, to prevent it taking ages. Should be fine for now
|
||||
/// as the genesis block POW solution turns out to be the same for every new block chain
|
||||
|
@ -104,6 +115,20 @@ pub fn get_genesis_nonce() -> u64 {
|
|||
match *param_ref {
|
||||
MiningParameterMode::AutomatedTesting => 0, //won't make a difference
|
||||
MiningParameterMode::UserTesting => 22141, //Magic nonce for current genesis block at cuckoo16
|
||||
MiningParameterMode::Production => 0, //TBD
|
||||
MiningParameterMode::Production => 1429942738856787200, //Magic nonce for current genesis at cuckoo30
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the genesis POW for production, because it takes far too long to mine at production values
|
||||
/// using the internal miner
|
||||
|
||||
pub fn get_genesis_pow() -> [u32;42]{
|
||||
//TODO: This is diff 26, probably just want a 10: mine one
|
||||
[7444824, 11926557, 28520390, 30594072, 50854023, 52797085, 57882033,
|
||||
59816511, 61404804, 84947619, 87779345, 115270337, 162618676,
|
||||
166860710, 178656003, 178971372, 200454733, 209197630, 221231015,
|
||||
228598741, 241012783, 245401183, 279080304, 295848517, 327300943,
|
||||
329741709, 366394532, 382493153, 389329248, 404353381, 406012911,
|
||||
418813499, 426573907, 452566575, 456930760, 463021458, 474340589,
|
||||
476248039, 478197093, 487576917, 495653489, 501862896]
|
||||
}
|
||||
|
|
|
@ -42,6 +42,5 @@ pub mod macros;
|
|||
pub mod consensus;
|
||||
pub mod core;
|
||||
pub mod genesis;
|
||||
pub mod pow;
|
||||
pub mod ser;
|
||||
pub mod global;
|
||||
|
|
|
@ -90,6 +90,11 @@ cuckoo_miner_plugin_type = "simple"
|
|||
#the list of parameters if you're using "edgetrim"
|
||||
#cuckoo_miner_parameter_list = {NUM_THREADS=4, NUM_TRIMS=7}
|
||||
|
||||
#The amount of time, in seconds, to attempt to mine on a particular
|
||||
#header before stopping and re-collecting transactions from the pool
|
||||
|
||||
attempt_time_per_block = 30
|
||||
|
||||
#the wallet reciever to which coinbase rewards will be sent
|
||||
|
||||
wallet_receiver_url = "http://127.0.0.1:13415"
|
||||
|
|
|
@ -13,12 +13,9 @@ grin_p2p = { path = "../p2p" }
|
|||
grin_pool = { path = "../pool" }
|
||||
grin_util = { path = "../util" }
|
||||
grin_wallet = { path = "../wallet" }
|
||||
grin_pow = { path = "../pow" }
|
||||
secp256k1zkp = { path = "../secp256k1zkp" }
|
||||
|
||||
cuckoo_miner = { git = "https://github.com/mimblewimble/cuckoo-miner", tag="grin_integration_5"}
|
||||
#cuckoo_miner = { path = "../../cuckoo-miner"}
|
||||
|
||||
blake2-rfc = "~0.2.17"
|
||||
env_logger="^0.3.5"
|
||||
futures = "^0.1.9"
|
||||
futures-cpupool = "^0.1.3"
|
||||
|
@ -30,5 +27,7 @@ serde_derive = "~1.0.8"
|
|||
tokio-core="^0.1.1"
|
||||
tokio-timer="^0.1.0"
|
||||
rand = "^0.3"
|
||||
lazy_static = "~0.2.8"
|
||||
itertools = "~0.6.0"
|
||||
|
||||
[dev_dependencies]
|
||||
blake2-rfc = "~0.2.17"
|
||||
|
|
|
@ -34,8 +34,6 @@ extern crate serde_derive;
|
|||
extern crate time;
|
||||
extern crate tokio_core;
|
||||
extern crate tokio_timer;
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
extern crate itertools;
|
||||
|
||||
extern crate grin_api as api;
|
||||
|
@ -47,18 +45,15 @@ extern crate grin_pool as pool;
|
|||
extern crate grin_store as store;
|
||||
extern crate grin_util as util;
|
||||
extern crate grin_wallet as wallet;
|
||||
extern crate grin_pow as pow;
|
||||
extern crate secp256k1zkp as secp;
|
||||
|
||||
extern crate cuckoo_miner;
|
||||
|
||||
mod adapters;
|
||||
mod miner;
|
||||
mod plugin;
|
||||
mod server;
|
||||
mod seed;
|
||||
mod sync;
|
||||
mod types;
|
||||
mod miner;
|
||||
|
||||
pub use server::{Server};
|
||||
pub use types::{ServerConfig, MinerConfig, Seeding, ServerStats};
|
||||
pub use plugin::PluginMiner;
|
||||
pub use types::{ServerConfig, Seeding, ServerStats};
|
||||
|
|
|
@ -27,24 +27,28 @@ use api;
|
|||
use core::consensus;
|
||||
use core::core;
|
||||
use core::core::Proof;
|
||||
use core::pow::cuckoo;
|
||||
use pow::cuckoo;
|
||||
use core::core::target::Difficulty;
|
||||
use core::core::{Block, BlockHeader};
|
||||
use core::core::hash::{Hash, Hashed};
|
||||
use core::pow::MiningWorker;
|
||||
use pow::MiningWorker;
|
||||
use pow::types::MinerConfig;
|
||||
use core::ser;
|
||||
use core::ser::{AsFixedBytes};
|
||||
|
||||
//use core::genesis;
|
||||
|
||||
use chain;
|
||||
use secp;
|
||||
use pool;
|
||||
use types::{MinerConfig, ServerConfig};
|
||||
use util;
|
||||
use wallet::{CbAmount, WalletReceiveRequest, CbData};
|
||||
|
||||
use plugin::PluginMiner;
|
||||
use pow::plugin::PluginMiner;
|
||||
|
||||
use itertools::Itertools;
|
||||
|
||||
|
||||
// Max number of transactions this miner will assemble in a block
|
||||
const MAX_TX: u32 = 5000;
|
||||
|
||||
|
@ -140,33 +144,47 @@ impl Miner {
|
|||
}
|
||||
|
||||
/// Inner part of the mining loop for cuckoo-miner asynch mode
|
||||
pub fn inner_loop_async(&self, plugin_miner:&mut PluginMiner,
|
||||
difficulty:Difficulty,
|
||||
b:&mut Block,
|
||||
cuckoo_size: u32,
|
||||
head:&BlockHeader,
|
||||
latest_hash:&Hash)
|
||||
-> Option<Proof> {
|
||||
pub fn inner_loop_async(&self,
|
||||
plugin_miner:&mut PluginMiner,
|
||||
difficulty:Difficulty,
|
||||
b:&mut Block,
|
||||
cuckoo_size: u32,
|
||||
head:&BlockHeader,
|
||||
latest_hash:&Hash,
|
||||
attempt_time_per_block: u32)
|
||||
-> Option<Proof> {
|
||||
|
||||
debug!("(Server ID: {}) Mining at Cuckoo{} for at most 2 secs at height {} and difficulty {}.",
|
||||
self.debug_output_id,
|
||||
cuckoo_size,
|
||||
b.header.height,
|
||||
b.header.difficulty);
|
||||
debug!("(Server ID: {}) Mining at Cuckoo{} for at most {} secs at height {} and difficulty {}.",
|
||||
self.debug_output_id,
|
||||
cuckoo_size,
|
||||
attempt_time_per_block,
|
||||
b.header.height,
|
||||
b.header.difficulty);
|
||||
|
||||
// look for a pow for at most 2 sec on the same block (to give a chance to new
|
||||
// look for a pow for at most 10 sec on the same block (to give a chance to new
|
||||
// transactions) and as long as the head hasn't changed
|
||||
// Will change this to something else at some point
|
||||
let deadline = time::get_time().sec + 2;
|
||||
let deadline = time::get_time().sec + attempt_time_per_block as i64;
|
||||
|
||||
// how often to output stats
|
||||
let stat_output_interval = 2;
|
||||
let mut next_stat_output = time::get_time().sec + stat_output_interval;
|
||||
|
||||
//Get parts of the header
|
||||
let mut header_parts = HeaderPartWriter::default();
|
||||
ser::Writeable::write(&b.header, &mut header_parts).unwrap();
|
||||
let (pre, post) = header_parts.parts_as_hex_strings();
|
||||
|
||||
//Just test output to mine a genesis block when needed
|
||||
/*let mut header_parts = HeaderPartWriter::default();
|
||||
let gen = genesis::genesis();
|
||||
ser::Writeable::write(&gen.header, &mut header_parts).unwrap();
|
||||
let (pre, post) = header_parts.parts_as_hex_strings();
|
||||
println!("pre, post: {}, {}", pre, post);*/
|
||||
|
||||
//Start the miner working
|
||||
let miner = plugin_miner.get_consumable();
|
||||
let job_handle=miner.notify(1, &pre, &post, difficulty.into_num()).unwrap();
|
||||
let miner = plugin_miner.get_consumable();
|
||||
let job_handle=miner.notify(1, &pre, &post, difficulty.into_num()).unwrap();
|
||||
|
||||
let mut sol=None;
|
||||
|
||||
|
@ -174,8 +192,26 @@ impl Miner {
|
|||
if let Some(s) = job_handle.get_solution() {
|
||||
sol = Some(Proof::new(s.solution_nonces.to_vec()));
|
||||
b.header.nonce=s.get_nonce_as_u64();
|
||||
println!("Nonce: {}", b.header.nonce);
|
||||
break;
|
||||
}
|
||||
if time::get_time().sec > next_stat_output {
|
||||
let stats = job_handle.get_stats();
|
||||
if let Ok(stat_vec) = stats {
|
||||
for s in stat_vec {
|
||||
if s.last_start_time==0 {
|
||||
continue;
|
||||
}
|
||||
let last_solution_time_secs = s.last_solution_time as f64 / 1000.0;
|
||||
let last_hashes_per_sec = 1.0 / last_solution_time_secs;
|
||||
debug!("Mining on Device {} - {}: Last hash time: {} - Hashes per second: {:.*} - Total Attempts: {}",
|
||||
s.device_id, s.device_name,
|
||||
last_solution_time_secs, 3, last_hashes_per_sec,
|
||||
s.iterations_completed);
|
||||
}
|
||||
}
|
||||
next_stat_output = time::get_time().sec + stat_output_interval;
|
||||
}
|
||||
}
|
||||
if sol==None {
|
||||
debug!("(Server ID: {}) No solution found after {} iterations, continuing...",
|
||||
|
@ -190,21 +226,23 @@ impl Miner {
|
|||
|
||||
/// The inner part of mining loop for synchronous mode
|
||||
pub fn inner_loop_sync<T: MiningWorker>(&self,
|
||||
miner:&mut T,
|
||||
b:&mut Block,
|
||||
cuckoo_size: u32,
|
||||
head:&BlockHeader,
|
||||
latest_hash:&mut Hash)
|
||||
-> Option<Proof> {
|
||||
miner:&mut T,
|
||||
b:&mut Block,
|
||||
cuckoo_size: u32,
|
||||
head:&BlockHeader,
|
||||
attempt_time_per_block: u32,
|
||||
latest_hash:&mut Hash)
|
||||
-> Option<Proof> {
|
||||
// look for a pow for at most 2 sec on the same block (to give a chance to new
|
||||
// transactions) and as long as the head hasn't changed
|
||||
let deadline = time::get_time().sec + 2;
|
||||
let deadline = time::get_time().sec + attempt_time_per_block as i64;
|
||||
|
||||
debug!("(Server ID: {}) Mining at Cuckoo{} for at most 2 secs on block {} at difficulty {}.",
|
||||
self.debug_output_id,
|
||||
cuckoo_size,
|
||||
latest_hash,
|
||||
b.header.difficulty);
|
||||
debug!("(Server ID: {}) Mining at Cuckoo{} for at most {} secs on block {} at difficulty {}.",
|
||||
self.debug_output_id,
|
||||
cuckoo_size,
|
||||
attempt_time_per_block,
|
||||
latest_hash,
|
||||
b.header.difficulty);
|
||||
let mut iter_count = 0;
|
||||
|
||||
if self.config.slow_down_in_millis != None && self.config.slow_down_in_millis.unwrap() > 0 {
|
||||
|
@ -224,7 +262,7 @@ impl Miner {
|
|||
b.header.difficulty,
|
||||
proof_diff);*/
|
||||
|
||||
if proof_diff >= b.header.difficulty {
|
||||
if proof_diff >= b.header.difficulty {
|
||||
sol = Some(proof);
|
||||
break;
|
||||
}
|
||||
|
@ -241,8 +279,8 @@ impl Miner {
|
|||
|
||||
if sol==None {
|
||||
debug!("(Server ID: {}) No solution found after {} iterations, continuing...",
|
||||
self.debug_output_id,
|
||||
iter_count)
|
||||
self.debug_output_id,
|
||||
iter_count)
|
||||
}
|
||||
|
||||
sol
|
||||
|
@ -251,17 +289,16 @@ impl Miner {
|
|||
/// Starts the mining loop, building a new block on top of the existing
|
||||
/// chain anytime required and looking for PoW solution.
|
||||
pub fn run_loop(&self,
|
||||
miner_config:MinerConfig,
|
||||
server_config:ServerConfig,
|
||||
cuckoo_size:u32,
|
||||
proof_size:usize) {
|
||||
miner_config:MinerConfig,
|
||||
cuckoo_size:u32,
|
||||
proof_size:usize) {
|
||||
|
||||
info!("(Server ID: {}) Starting miner loop.", self.debug_output_id);
|
||||
let mut plugin_miner=None;
|
||||
let mut miner=None;
|
||||
if miner_config.use_cuckoo_miner {
|
||||
plugin_miner = Some(PluginMiner::new(consensus::EASINESS, cuckoo_size, proof_size));
|
||||
plugin_miner.as_mut().unwrap().init(miner_config.clone(),server_config);
|
||||
plugin_miner.as_mut().unwrap().init(miner_config.clone());
|
||||
} else {
|
||||
miner = Some(cuckoo::Miner::new(consensus::EASINESS, cuckoo_size, proof_size));
|
||||
}
|
||||
|
@ -284,32 +321,35 @@ impl Miner {
|
|||
if let Some(mut p) = plugin_miner.as_mut() {
|
||||
if use_async {
|
||||
sol = self.inner_loop_async(&mut p,
|
||||
b.header.difficulty.clone(),
|
||||
&mut b,
|
||||
cuckoo_size,
|
||||
&head,
|
||||
&latest_hash);
|
||||
b.header.difficulty.clone(),
|
||||
&mut b,
|
||||
cuckoo_size,
|
||||
&head,
|
||||
&latest_hash,
|
||||
miner_config.attempt_time_per_block);
|
||||
} else {
|
||||
sol = self.inner_loop_sync(p,
|
||||
&mut b,
|
||||
cuckoo_size,
|
||||
&head,
|
||||
&mut latest_hash);
|
||||
&mut b,
|
||||
cuckoo_size,
|
||||
&head,
|
||||
miner_config.attempt_time_per_block,
|
||||
&mut latest_hash);
|
||||
}
|
||||
}
|
||||
if let Some(mut m) = miner.as_mut() {
|
||||
sol = self.inner_loop_sync(m,
|
||||
&mut b,
|
||||
cuckoo_size,
|
||||
&head,
|
||||
&mut latest_hash);
|
||||
&mut b,
|
||||
cuckoo_size,
|
||||
&head,
|
||||
miner_config.attempt_time_per_block,
|
||||
&mut latest_hash);
|
||||
}
|
||||
|
||||
// if we found a solution, push our block out
|
||||
if let Some(proof) = sol {
|
||||
info!("(Server ID: {}) Found valid proof of work, adding block {}.",
|
||||
self.debug_output_id, b.hash());
|
||||
b.header.pow = proof;
|
||||
self.debug_output_id, b.hash());
|
||||
b.header.pow = proof;
|
||||
let opts = if cuckoo_size < consensus::DEFAULT_SIZESHIFT as u32 {
|
||||
chain::EASY_POW
|
||||
} else {
|
||||
|
@ -346,10 +386,10 @@ impl Miner {
|
|||
let (output, kernel) = coinbase;
|
||||
let mut b = core::Block::with_reward(head, txs, output, kernel).unwrap();
|
||||
debug!("(Server ID: {}) Built new block with {} inputs and {} outputs, difficulty: {}",
|
||||
self.debug_output_id,
|
||||
b.inputs.len(),
|
||||
b.outputs.len(),
|
||||
difficulty);
|
||||
self.debug_output_id,
|
||||
b.inputs.len(),
|
||||
b.outputs.len(),
|
||||
difficulty);
|
||||
|
||||
// making sure we're not spending time mining a useless block
|
||||
let secp = secp::Secp256k1::with_caps(secp::ContextFlag::Commit);
|
||||
|
@ -370,7 +410,7 @@ impl Miner {
|
|||
core::Block::reward_output(skey, &secp_inst).unwrap()
|
||||
} else {
|
||||
let url = format!("{}/v1/receive/coinbase",
|
||||
self.config.wallet_receiver_url.as_str());
|
||||
self.config.wallet_receiver_url.as_str());
|
||||
let request = WalletReceiveRequest::Coinbase(CbAmount{amount: consensus::REWARD});
|
||||
let res: CbData = api::client::post(url.as_str(),
|
||||
&request)
|
||||
|
|
|
@ -34,6 +34,7 @@ use pool;
|
|||
use seed;
|
||||
use sync;
|
||||
use types::*;
|
||||
use pow;
|
||||
|
||||
use core::global;
|
||||
|
||||
|
@ -81,8 +82,17 @@ impl Server {
|
|||
let tx_pool = Arc::new(RwLock::new(pool::TransactionPool::new(pool_adapter.clone())));
|
||||
|
||||
let chain_adapter = Arc::new(ChainToPoolAndNetAdapter::new(tx_pool.clone()));
|
||||
|
||||
let mut genesis_block = None;
|
||||
if !chain::Chain::chain_exists(config.db_root.clone()){
|
||||
genesis_block=pow::mine_genesis_block(config.mining_config.clone());
|
||||
}
|
||||
|
||||
let shared_chain = Arc::new(chain::Chain::init(config.db_root.clone(),
|
||||
chain_adapter.clone())?);
|
||||
chain_adapter.clone(),
|
||||
genesis_block,
|
||||
pow::verify_size)?);
|
||||
|
||||
pool_adapter.set_chain(shared_chain.clone());
|
||||
|
||||
let peer_store = Arc::new(p2p::PeerStore::new(config.db_root.clone())?);
|
||||
|
@ -139,16 +149,14 @@ impl Server {
|
|||
|
||||
/// Start mining for blocks on a separate thread. Uses toy miner by default,
|
||||
/// mostly for testing, but can also load a plugin from cuckoo-miner
|
||||
pub fn start_miner(&self, config: MinerConfig) {
|
||||
pub fn start_miner(&self, config: pow::types::MinerConfig) {
|
||||
let cuckoo_size = global::sizeshift();
|
||||
let proof_size = global::proofsize();
|
||||
|
||||
|
||||
let mut miner = miner::Miner::new(config.clone(), self.chain.clone(), self.tx_pool.clone());
|
||||
miner.set_debug_output_id(format!("Port {}",self.config.p2p_config.unwrap().port));
|
||||
let server_config = self.config.clone();
|
||||
thread::spawn(move || {
|
||||
miner.run_loop(config.clone(), server_config, cuckoo_size as u32, proof_size);
|
||||
miner.run_loop(config.clone(), cuckoo_size as u32, proof_size);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -13,12 +13,12 @@
|
|||
// limitations under the License.
|
||||
|
||||
use std::convert::From;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use api;
|
||||
use chain;
|
||||
use p2p;
|
||||
use store;
|
||||
use pow;
|
||||
use core::global::MiningParameterMode;
|
||||
|
||||
/// Error type wrapping underlying module errors.
|
||||
|
@ -96,42 +96,7 @@ pub struct ServerConfig {
|
|||
pub p2p_config: Option<p2p::P2PConfig>,
|
||||
|
||||
/// Configuration for the mining daemon
|
||||
pub mining_config: Option<MinerConfig>,
|
||||
}
|
||||
|
||||
/// Mining configuration
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct MinerConfig {
|
||||
/// Whether to start the miner with the server
|
||||
pub enable_mining: bool,
|
||||
|
||||
/// Whether to use the cuckoo-miner crate and plugin for mining
|
||||
pub use_cuckoo_miner: bool,
|
||||
|
||||
/// Whether to use the async version of mining
|
||||
pub cuckoo_miner_async_mode: Option<bool>,
|
||||
|
||||
/// The location in which cuckoo miner plugins are stored
|
||||
pub cuckoo_miner_plugin_dir: Option<String>,
|
||||
|
||||
/// The type of plugin to use (ends up filtering the filename)
|
||||
pub cuckoo_miner_plugin_type: Option<String>,
|
||||
|
||||
/// Cuckoo-miner parameters... these vary according
|
||||
/// to the plugin being loaded
|
||||
pub cuckoo_miner_parameter_list: Option<HashMap<String, u32>>,
|
||||
|
||||
/// Base address to the HTTP wallet receiver
|
||||
pub wallet_receiver_url: String,
|
||||
|
||||
/// Attributes the reward to a random private key instead of contacting the
|
||||
/// wallet receiver. Mostly used for tests.
|
||||
pub burn_reward: bool,
|
||||
|
||||
/// a testing attribute for the time being that artifically slows down the
|
||||
/// mining loop by adding a sleep to the thread
|
||||
pub slow_down_in_millis: Option<u64>,
|
||||
|
||||
pub mining_config: Option<pow::types::MinerConfig>,
|
||||
}
|
||||
|
||||
impl Default for ServerConfig {
|
||||
|
@ -143,28 +108,12 @@ impl Default for ServerConfig {
|
|||
seeding_type: Seeding::None,
|
||||
seeds: None,
|
||||
p2p_config: Some(p2p::P2PConfig::default()),
|
||||
mining_config: Some(MinerConfig::default()),
|
||||
mining_config: Some(pow::types::MinerConfig::default()),
|
||||
mining_parameter_mode: Some(MiningParameterMode::Production),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for MinerConfig {
|
||||
fn default() -> MinerConfig {
|
||||
MinerConfig {
|
||||
enable_mining: false,
|
||||
use_cuckoo_miner: false,
|
||||
cuckoo_miner_async_mode: None,
|
||||
cuckoo_miner_plugin_dir: None,
|
||||
cuckoo_miner_plugin_type: None,
|
||||
cuckoo_miner_parameter_list: None,
|
||||
wallet_receiver_url: "http://localhost:13416".to_string(),
|
||||
burn_reward: false,
|
||||
slow_down_in_millis: Some(0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Thread-safe container to return all sever related stats that other
|
||||
/// consumers might be interested in, such as test results
|
||||
///
|
||||
|
@ -178,3 +127,4 @@ pub struct ServerStats {
|
|||
/// Chain head
|
||||
pub head: chain::Tip,
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ extern crate grin_p2p as p2p;
|
|||
extern crate grin_chain as chain;
|
||||
extern crate grin_api as api;
|
||||
extern crate grin_wallet as wallet;
|
||||
extern crate grin_pow as pow;
|
||||
extern crate secp256k1zkp as secp;
|
||||
|
||||
extern crate blake2_rfc as blake2;
|
||||
|
@ -200,7 +201,6 @@ impl LocalServerContainer {
|
|||
seeds=vec![self.config.seed_addr.to_string()];
|
||||
}
|
||||
|
||||
|
||||
let s = grin::Server::future(
|
||||
grin::ServerConfig{
|
||||
api_http_addr: api_addr,
|
||||
|
@ -219,7 +219,7 @@ impl LocalServerContainer {
|
|||
thread::sleep(time::Duration::from_millis(1000));
|
||||
}
|
||||
|
||||
let miner_config = grin::MinerConfig {
|
||||
let miner_config = pow::types::MinerConfig {
|
||||
enable_mining: self.config.start_miner,
|
||||
burn_reward: self.config.burn_mining_rewards,
|
||||
use_cuckoo_miner: false,
|
||||
|
|
|
@ -18,6 +18,7 @@ extern crate grin_p2p as p2p;
|
|||
extern crate grin_chain as chain;
|
||||
extern crate grin_api as api;
|
||||
extern crate grin_wallet as wallet;
|
||||
extern crate grin_pow as pow;
|
||||
extern crate secp256k1zkp as secp;
|
||||
|
||||
extern crate env_logger;
|
||||
|
@ -200,7 +201,7 @@ fn a_simulate_block_propagation() {
|
|||
let mut evtlp = reactor::Core::new().unwrap();
|
||||
let handle = evtlp.handle();
|
||||
|
||||
let miner_config = grin::MinerConfig {
|
||||
let miner_config = pow::types::MinerConfig {
|
||||
enable_mining: true,
|
||||
burn_reward: true,
|
||||
use_cuckoo_miner: false,
|
||||
|
@ -267,7 +268,7 @@ fn simulate_full_sync() {
|
|||
let mut evtlp = reactor::Core::new().unwrap();
|
||||
let handle = evtlp.handle();
|
||||
|
||||
let miner_config = grin::MinerConfig {
|
||||
let miner_config = pow::types::MinerConfig {
|
||||
enable_mining: true,
|
||||
burn_reward: true,
|
||||
use_cuckoo_miner: false,
|
||||
|
|
24
pow/Cargo.toml
Normal file
24
pow/Cargo.toml
Normal file
|
@ -0,0 +1,24 @@
|
|||
[package]
|
||||
name = "grin_pow"
|
||||
version = "0.1.0"
|
||||
authors = ["Ignotus Peverell <igno.peverell@protonmail.com>"]
|
||||
workspace = ".."
|
||||
|
||||
[dependencies]
|
||||
blake2-rfc = "~0.2.17"
|
||||
rand = "^0.3"
|
||||
time = "^0.1"
|
||||
env_logger="^0.3.5"
|
||||
log = "^0.3"
|
||||
lazy_static = "~0.2.8"
|
||||
serde = "~1.0.8"
|
||||
serde_derive = "~1.0.8"
|
||||
|
||||
cuckoo_miner = { git = "https://github.com/mimblewimble/cuckoo-miner", tag="grin_integration_6"}
|
||||
#cuckoo_miner = { path = "../../cuckoo-miner"}
|
||||
|
||||
grin_core = { path = "../core" }
|
||||
|
||||
[dev_dependencies]
|
||||
grin_chain = { path = "../chain"}
|
||||
secp256k1zkp = { path = "../secp256k1zkp" }
|
|
@ -22,9 +22,9 @@ use std::cmp;
|
|||
|
||||
use blake2;
|
||||
|
||||
use core::Proof;
|
||||
use pow::siphash::siphash24;
|
||||
use pow::MiningWorker;
|
||||
use core::core::Proof;
|
||||
use siphash::siphash24;
|
||||
use MiningWorker;
|
||||
|
||||
const MAXPATHLEN: usize = 8192;
|
||||
|
||||
|
@ -326,7 +326,7 @@ fn u8_to_u64(p:&[u8], i: usize) -> u64 {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use core::Proof;
|
||||
use core::core::Proof;
|
||||
|
||||
|
||||
static V1:[u32;42] = [0x1fe9, 0x2050, 0x4581, 0x6322, 0x65ab, 0xb3c1, 0xc1a4,
|
|
@ -22,18 +22,41 @@
|
|||
//! Note that this miner implementation is here mostly for tests and
|
||||
//! reference. It's not optimized for speed.
|
||||
|
||||
#![deny(non_upper_case_globals)]
|
||||
#![deny(non_camel_case_types)]
|
||||
#![deny(non_snake_case)]
|
||||
#![deny(unused_mut)]
|
||||
#![warn(missing_docs)]
|
||||
|
||||
extern crate blake2_rfc as blake2;
|
||||
extern crate rand;
|
||||
extern crate time;
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
extern crate env_logger;
|
||||
extern crate serde;
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
extern crate grin_core as core;
|
||||
|
||||
extern crate cuckoo_miner;
|
||||
|
||||
mod siphash;
|
||||
pub mod plugin;
|
||||
pub mod cuckoo;
|
||||
pub mod types;
|
||||
|
||||
use time;
|
||||
|
||||
use consensus::EASINESS;
|
||||
use core::BlockHeader;
|
||||
use core::hash::Hashed;
|
||||
use core::Proof;
|
||||
use core::target::Difficulty;
|
||||
use pow::cuckoo::{Cuckoo, Error};
|
||||
|
||||
use core::consensus;
|
||||
use core::core::BlockHeader;
|
||||
use core::core::hash::Hashed;
|
||||
use core::core::Proof;
|
||||
use core::core::target::Difficulty;
|
||||
use core::global;
|
||||
use core::genesis;
|
||||
use cuckoo::{Cuckoo, Error};
|
||||
|
||||
/// Should be implemented by anything providing mining services
|
||||
///
|
||||
|
@ -41,7 +64,7 @@ use pow::cuckoo::{Cuckoo, Error};
|
|||
pub trait MiningWorker {
|
||||
|
||||
/// This only sets parameters and does initialisation work now
|
||||
fn new(ease: u32, sizeshift: u32, proof_size:usize) -> Self;
|
||||
fn new(ease: u32, sizeshift: u32, proof_size:usize) -> Self where Self:Sized;
|
||||
|
||||
/// Actually perform a mining attempt on the given input and
|
||||
/// return a proof if found
|
||||
|
@ -57,7 +80,7 @@ pub fn verify_size(bh: &BlockHeader, cuckoo_sz: u32) -> bool {
|
|||
if bh.difficulty > bh.pow.clone().to_difficulty() {
|
||||
return false;
|
||||
}
|
||||
Cuckoo::new(&bh.hash()[..], cuckoo_sz).verify(bh.pow.clone(), EASINESS as u64)
|
||||
Cuckoo::new(&bh.hash()[..], cuckoo_sz).verify(bh.pow.clone(), consensus::EASINESS as u64)
|
||||
}
|
||||
|
||||
/// Uses the much easier Cuckoo20 (mostly for
|
||||
|
@ -66,12 +89,50 @@ pub fn pow20<T: MiningWorker>(miner:&mut T, bh: &mut BlockHeader, diff: Difficul
|
|||
pow_size(miner, bh, diff, 20)
|
||||
}
|
||||
|
||||
/// Mines a genesis block, using the config specified miner if specified. Otherwise,
|
||||
/// uses the internal miner
|
||||
///
|
||||
|
||||
pub fn mine_genesis_block(miner_config:Option<types::MinerConfig>)->Option<core::core::Block> {
|
||||
info!("Starting miner loop for Genesis Block");
|
||||
let mut gen = genesis::genesis();
|
||||
let diff = gen.header.difficulty.clone();
|
||||
|
||||
let sz = global::sizeshift() as u32;
|
||||
let proof_size = global::proofsize();
|
||||
|
||||
let mut miner:Box<MiningWorker> = match miner_config {
|
||||
Some(c) => {
|
||||
if c.use_cuckoo_miner {
|
||||
let mut p = plugin::PluginMiner::new(consensus::EASINESS, sz, proof_size);
|
||||
p.init(c.clone());
|
||||
Box::new(p)
|
||||
|
||||
} else {
|
||||
Box::new(cuckoo::Miner::new(consensus::EASINESS, sz, proof_size))
|
||||
}
|
||||
},
|
||||
None => Box::new(cuckoo::Miner::new(consensus::EASINESS, sz, proof_size)),
|
||||
};
|
||||
pow_size(&mut *miner, &mut gen.header, diff, sz as u32).unwrap();
|
||||
Some(gen)
|
||||
}
|
||||
|
||||
/// Runs a proof of work computation over the provided block using the provided Mining Worker,
|
||||
/// until the required difficulty target is reached. May take a while for a low target...
|
||||
pub fn pow_size<T: MiningWorker>(miner:&mut T, bh: &mut BlockHeader,
|
||||
pub fn pow_size<T: MiningWorker + ?Sized>(miner:&mut T, bh: &mut BlockHeader,
|
||||
diff: Difficulty, _: u32) -> Result<(), Error> {
|
||||
let start_nonce = bh.nonce;
|
||||
|
||||
// if we're in production mode, try the pre-mined solution first
|
||||
if global::is_production_mode() {
|
||||
let p = Proof::new(global::get_genesis_pow().to_vec());
|
||||
if p.clone().to_difficulty() >= diff {
|
||||
bh.pow = p;
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
// try to find a cuckoo cycle on that header hash
|
||||
loop {
|
||||
// can be trivially optimized by avoiding re-serialization every time but this
|
||||
|
@ -103,10 +164,10 @@ pub fn pow_size<T: MiningWorker>(miner:&mut T, bh: &mut BlockHeader,
|
|||
mod test {
|
||||
use super::*;
|
||||
use global;
|
||||
use core::target::Difficulty;
|
||||
use genesis;
|
||||
use consensus::MINIMUM_DIFFICULTY;
|
||||
use global::MiningParameterMode;
|
||||
use core::core::target::Difficulty;
|
||||
use core::genesis;
|
||||
use core::consensus::MINIMUM_DIFFICULTY;
|
||||
use core::global::MiningParameterMode;
|
||||
|
||||
|
||||
#[test]
|
||||
|
@ -114,7 +175,7 @@ mod test {
|
|||
global::set_mining_mode(MiningParameterMode::AutomatedTesting);
|
||||
let mut b = genesis::genesis();
|
||||
b.header.nonce = 310;
|
||||
let mut internal_miner = cuckoo::Miner::new(EASINESS, global::sizeshift() as u32, global::proofsize());
|
||||
let mut internal_miner = cuckoo::Miner::new(consensus::EASINESS, global::sizeshift() as u32, global::proofsize());
|
||||
pow_size(&mut internal_miner, &mut b.header, Difficulty::from_num(MINIMUM_DIFFICULTY), global::sizeshift() as u32).unwrap();
|
||||
assert!(b.header.nonce != 310);
|
||||
assert!(b.header.pow.clone().to_difficulty() >= Difficulty::from_num(MINIMUM_DIFFICULTY));
|
|
@ -19,13 +19,13 @@
|
|||
|
||||
use std::env;
|
||||
|
||||
use core::pow::cuckoo;
|
||||
use core::pow::cuckoo::Error;
|
||||
use core::pow::MiningWorker;
|
||||
use cuckoo;
|
||||
use cuckoo::Error;
|
||||
use MiningWorker;
|
||||
use core::global;
|
||||
|
||||
use core::core::Proof;
|
||||
use types::{MinerConfig, ServerConfig};
|
||||
use types::MinerConfig;
|
||||
|
||||
use std::sync::{Mutex};
|
||||
|
||||
|
@ -64,12 +64,14 @@ impl Default for PluginMiner {
|
|||
|
||||
impl PluginMiner {
|
||||
/// Init the plugin miner
|
||||
pub fn init(&mut self, miner_config: MinerConfig, _server_config: ServerConfig){
|
||||
pub fn init(&mut self, miner_config: MinerConfig){
|
||||
//Get directory of executable
|
||||
let mut exe_path=env::current_exe().unwrap();
|
||||
exe_path.pop();
|
||||
let exe_path=exe_path.to_str().unwrap();
|
||||
|
||||
//println!("Plugin dir: {}", miner_config.clone().cuckoo_miner_plugin_dir.unwrap());
|
||||
|
||||
let plugin_install_path = match miner_config.cuckoo_miner_plugin_dir {
|
||||
Some(s) => s,
|
||||
None => String::from(format!("{}/deps", exe_path))
|
||||
|
@ -86,7 +88,7 @@ impl PluginMiner {
|
|||
//when packaging is more//thought out
|
||||
|
||||
let mut loaded_config_ref = LOADED_CONFIG.lock().unwrap();
|
||||
|
||||
|
||||
//Load from here instead
|
||||
if let Some(ref c) = *loaded_config_ref {
|
||||
debug!("Not re-loading plugin or directory.");
|
74
pow/src/types.rs
Normal file
74
pow/src/types.rs
Normal file
|
@ -0,0 +1,74 @@
|
|||
// Copyright 2017 The Grin Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//! Mining configuration type
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// Mining configuration
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct MinerConfig {
|
||||
/// Whether to start the miner with the server
|
||||
pub enable_mining: bool,
|
||||
|
||||
/// Whether to use the cuckoo-miner crate and plugin for mining
|
||||
pub use_cuckoo_miner: bool,
|
||||
|
||||
/// Whether to use the async version of mining
|
||||
pub cuckoo_miner_async_mode: Option<bool>,
|
||||
|
||||
/// The location in which cuckoo miner plugins are stored
|
||||
pub cuckoo_miner_plugin_dir: Option<String>,
|
||||
|
||||
/// The type of plugin to use (ends up filtering the filename)
|
||||
pub cuckoo_miner_plugin_type: Option<String>,
|
||||
|
||||
/// Cuckoo-miner parameters... these vary according
|
||||
/// to the plugin being loaded
|
||||
pub cuckoo_miner_parameter_list: Option<HashMap<String, u32>>,
|
||||
|
||||
/// How long to wait before stopping the miner, recollecting transactions
|
||||
/// and starting again
|
||||
pub attempt_time_per_block: u32,
|
||||
|
||||
/// Base address to the HTTP wallet receiver
|
||||
pub wallet_receiver_url: String,
|
||||
|
||||
/// Attributes the reward to a random private key instead of contacting the
|
||||
/// wallet receiver. Mostly used for tests.
|
||||
pub burn_reward: bool,
|
||||
|
||||
/// a testing attribute for the time being that artifically slows down the
|
||||
/// mining loop by adding a sleep to the thread
|
||||
pub slow_down_in_millis: Option<u64>,
|
||||
|
||||
}
|
||||
|
||||
impl Default for MinerConfig {
|
||||
fn default() -> MinerConfig {
|
||||
MinerConfig {
|
||||
enable_mining: false,
|
||||
use_cuckoo_miner: false,
|
||||
cuckoo_miner_async_mode: None,
|
||||
cuckoo_miner_plugin_dir: None,
|
||||
cuckoo_miner_plugin_type: None,
|
||||
cuckoo_miner_parameter_list: None,
|
||||
wallet_receiver_url: "http://localhost:13416".to_string(),
|
||||
burn_reward: false,
|
||||
slow_down_in_millis: Some(0),
|
||||
attempt_time_per_block: 2,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in a new issue