mirror of
https://github.com/mimblewimble/grin.git
synced 2025-02-01 08:51: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=p2p
|
||||||
- TEST_DIR=api
|
- TEST_DIR=api
|
||||||
- TEST_DIR=pool
|
- TEST_DIR=pool
|
||||||
|
- TEST_DIR=pow
|
||||||
- RUST_TEST_THREADS=1 TEST_DIR=grin
|
- RUST_TEST_THREADS=1 TEST_DIR=grin
|
||||||
|
|
||||||
script: cd $TEST_DIR && cargo test --verbose
|
script: cd $TEST_DIR && cargo test --verbose
|
||||||
|
|
|
@ -12,6 +12,7 @@ grin_wallet = { path = "./wallet" }
|
||||||
grin_grin = { path = "./grin" }
|
grin_grin = { path = "./grin" }
|
||||||
grin_config = { path = "./config" }
|
grin_config = { path = "./config" }
|
||||||
grin_core = { path = "./core" }
|
grin_core = { path = "./core" }
|
||||||
|
grin_pow = { path = "./pow"}
|
||||||
secp256k1zkp = { path = "./secp256k1zkp" }
|
secp256k1zkp = { path = "./secp256k1zkp" }
|
||||||
|
|
||||||
blake2-rfc = "~0.2.17"
|
blake2-rfc = "~0.2.17"
|
||||||
|
|
|
@ -19,8 +19,5 @@ secp256k1zkp = { path = "../secp256k1zkp" }
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
env_logger="^0.3.5"
|
env_logger="^0.3.5"
|
||||||
rand = "^0.3"
|
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::{Block, BlockHeader, Output};
|
||||||
use core::core::target::Difficulty;
|
use core::core::target::Difficulty;
|
||||||
use core::core::hash::Hash;
|
use core::core::hash::Hash;
|
||||||
use core::{consensus, genesis, pow};
|
|
||||||
use core::pow::MiningWorker;
|
|
||||||
use grin_store;
|
use grin_store;
|
||||||
use pipe;
|
use pipe;
|
||||||
use store;
|
use store;
|
||||||
use types::*;
|
use types::*;
|
||||||
|
|
||||||
use core::global;
|
|
||||||
use core::global::{MiningParameterMode,MINING_PARAMETER_MODE};
|
use core::global::{MiningParameterMode,MINING_PARAMETER_MODE};
|
||||||
|
|
||||||
const MAX_ORPHANS: usize = 20;
|
const MAX_ORPHANS: usize = 20;
|
||||||
|
@ -57,12 +54,28 @@ pub struct Chain {
|
||||||
head: Arc<Mutex<Tip>>,
|
head: Arc<Mutex<Tip>>,
|
||||||
block_process_lock: Arc<Mutex<bool>>,
|
block_process_lock: Arc<Mutex<bool>>,
|
||||||
orphans: Arc<Mutex<VecDeque<(Options, Block)>>>,
|
orphans: Arc<Mutex<VecDeque<(Options, Block)>>>,
|
||||||
|
|
||||||
|
//POW verification function
|
||||||
|
pow_verifier: fn(&BlockHeader, u32) -> bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Sync for Chain {}
|
unsafe impl Sync for Chain {}
|
||||||
unsafe impl Send for Chain {}
|
unsafe impl Send for Chain {}
|
||||||
|
|
||||||
impl 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
|
/// Initializes the blockchain and returns a new Chain instance. Does a
|
||||||
/// check
|
/// check
|
||||||
/// on the current chain head to make sure it exists and creates one based
|
/// on the current chain head to make sure it exists and creates one based
|
||||||
|
@ -71,6 +84,8 @@ impl Chain {
|
||||||
pub fn init(
|
pub fn init(
|
||||||
db_root: String,
|
db_root: String,
|
||||||
adapter: Arc<ChainAdapter>,
|
adapter: Arc<ChainAdapter>,
|
||||||
|
gen_block: Option<Block>,
|
||||||
|
pow_verifier: fn(&BlockHeader, u32) -> bool,
|
||||||
) -> Result<Chain, Error> {
|
) -> Result<Chain, Error> {
|
||||||
let chain_store = store::ChainKVStore::new(db_root)?;
|
let chain_store = store::ChainKVStore::new(db_root)?;
|
||||||
|
|
||||||
|
@ -78,15 +93,11 @@ impl Chain {
|
||||||
let head = match chain_store.head() {
|
let head = match chain_store.head() {
|
||||||
Ok(tip) => tip,
|
Ok(tip) => tip,
|
||||||
Err(grin_store::Error::NotFoundErr) => {
|
Err(grin_store::Error::NotFoundErr) => {
|
||||||
info!("No genesis block found, creating and saving one.");
|
if let None = gen_block {
|
||||||
let mut gen = genesis::genesis();
|
return Err(Error::GenesisBlockRequired);
|
||||||
let diff = gen.header.difficulty.clone();
|
}
|
||||||
|
|
||||||
let sz = global::sizeshift();
|
|
||||||
let proof_size = global::proofsize();
|
|
||||||
|
|
||||||
let mut internal_miner = pow::cuckoo::Miner::new(consensus::EASINESS, sz as u32, proof_size);
|
let gen = gen_block.unwrap();
|
||||||
pow::pow_size(&mut internal_miner, &mut gen.header, diff, sz as u32).unwrap();
|
|
||||||
chain_store.save_block(&gen)?;
|
chain_store.save_block(&gen)?;
|
||||||
|
|
||||||
// saving a new tip based on genesis
|
// saving a new tip based on genesis
|
||||||
|
@ -107,6 +118,7 @@ impl Chain {
|
||||||
head: Arc::new(Mutex::new(head)),
|
head: Arc::new(Mutex::new(head)),
|
||||||
block_process_lock: Arc::new(Mutex::new(true)),
|
block_process_lock: Arc::new(Mutex::new(true)),
|
||||||
orphans: Arc::new(Mutex::new(VecDeque::with_capacity(MAX_ORPHANS + 1))),
|
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(),
|
store: self.store.clone(),
|
||||||
adapter: self.adapter.clone(),
|
adapter: self.adapter.clone(),
|
||||||
head: head,
|
head: head,
|
||||||
|
pow_verifier: self.pow_verifier,
|
||||||
lock: self.block_process_lock.clone(),
|
lock: self.block_process_lock.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,6 @@ use time;
|
||||||
use core::consensus;
|
use core::consensus;
|
||||||
use core::core::hash::{Hash, Hashed};
|
use core::core::hash::{Hash, Hashed};
|
||||||
use core::core::{BlockHeader, Block};
|
use core::core::{BlockHeader, Block};
|
||||||
use core::pow;
|
|
||||||
use types::*;
|
use types::*;
|
||||||
use store;
|
use store;
|
||||||
use core::global;
|
use core::global;
|
||||||
|
@ -38,6 +37,8 @@ pub struct BlockContext {
|
||||||
pub adapter: Arc<ChainAdapter>,
|
pub adapter: Arc<ChainAdapter>,
|
||||||
/// The head
|
/// The head
|
||||||
pub head: Tip,
|
pub head: Tip,
|
||||||
|
/// The POW verification function
|
||||||
|
pub pow_verifier: fn(&BlockHeader, u32) -> bool,
|
||||||
/// The lock
|
/// The lock
|
||||||
pub lock: Arc<Mutex<bool>>,
|
pub lock: Arc<Mutex<bool>>,
|
||||||
}
|
}
|
||||||
|
@ -157,7 +158,7 @@ fn validate_header(header: &BlockHeader, ctx: &mut BlockContext) -> Result<(), E
|
||||||
consensus::DEFAULT_SIZESHIFT
|
consensus::DEFAULT_SIZESHIFT
|
||||||
};
|
};
|
||||||
debug!("Validating block with cuckoo size {}", cycle_size);
|
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);
|
return Err(Error::InvalidPow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,6 +61,8 @@ pub enum Error {
|
||||||
StoreErr(grin_store::Error),
|
StoreErr(grin_store::Error),
|
||||||
/// Error serializing or deserializing a type
|
/// Error serializing or deserializing a type
|
||||||
SerErr(ser::Error),
|
SerErr(ser::Error),
|
||||||
|
/// No chain exists and genesis block is required
|
||||||
|
GenesisBlockRequired,
|
||||||
/// Anything else
|
/// Anything else
|
||||||
Other(String),
|
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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with 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
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
extern crate grin_core;
|
extern crate grin_core as core;
|
||||||
extern crate grin_chain;
|
extern crate grin_chain as chain;
|
||||||
extern crate env_logger;
|
extern crate env_logger;
|
||||||
extern crate time;
|
extern crate time;
|
||||||
extern crate rand;
|
extern crate rand;
|
||||||
extern crate secp256k1zkp as secp;
|
extern crate secp256k1zkp as secp;
|
||||||
|
extern crate grin_pow as pow;
|
||||||
extern crate grin_grin as grin;
|
|
||||||
|
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use rand::os::OsRng;
|
use rand::os::OsRng;
|
||||||
|
|
||||||
use grin_chain::types::*;
|
use chain::types::*;
|
||||||
use grin_core::core::hash::Hashed;
|
use core::core::hash::Hashed;
|
||||||
use grin_core::core::target::Difficulty;
|
use core::core::target::Difficulty;
|
||||||
use grin_core::pow;
|
use core::consensus;
|
||||||
use grin_core::core;
|
use core::global;
|
||||||
use grin_core::consensus;
|
use core::global::MiningParameterMode;
|
||||||
use grin_core::pow::cuckoo;
|
|
||||||
use grin_core::global;
|
|
||||||
use grin_core::global::MiningParameterMode;
|
|
||||||
|
|
||||||
use grin_core::pow::MiningWorker;
|
|
||||||
|
|
||||||
|
use pow::{types, cuckoo, MiningWorker};
|
||||||
|
|
||||||
fn clean_output_dir(dir_name:&str){
|
fn clean_output_dir(dir_name:&str){
|
||||||
let _ = fs::remove_dir_all(dir_name);
|
let _ = fs::remove_dir_all(dir_name);
|
||||||
|
@ -50,14 +45,18 @@ fn mine_empty_chain() {
|
||||||
global::set_mining_mode(MiningParameterMode::AutomatedTesting);
|
global::set_mining_mode(MiningParameterMode::AutomatedTesting);
|
||||||
|
|
||||||
let mut rng = OsRng::new().unwrap();
|
let mut rng = OsRng::new().unwrap();
|
||||||
let chain = grin_chain::Chain::init(".grin".to_string(), Arc::new(NoopAdapter {}))
|
let mut genesis_block = None;
|
||||||
.unwrap();
|
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
|
// mine and add a few blocks
|
||||||
let secp = secp::Secp256k1::with_caps(secp::ContextFlag::Commit);
|
let secp = secp::Secp256k1::with_caps(secp::ContextFlag::Commit);
|
||||||
let reward_key = secp::key::SecretKey::new(&secp, &mut rng);
|
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,
|
enable_mining: true,
|
||||||
burn_reward: true,
|
burn_reward: true,
|
||||||
..Default::default()
|
..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());
|
let mut cuckoo_miner = cuckoo::Miner::new(consensus::EASINESS, global::sizeshift() as u32, global::proofsize());
|
||||||
for n in 1..4 {
|
for n in 1..4 {
|
||||||
let prev = chain.head_header().unwrap();
|
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.timestamp = prev.timestamp + time::Duration::seconds(60);
|
||||||
|
|
||||||
let difficulty = consensus::next_difficulty(chain.difficulty_iter()).unwrap();
|
let difficulty = consensus::next_difficulty(chain.difficulty_iter()).unwrap();
|
||||||
|
@ -81,7 +80,7 @@ fn mine_empty_chain() {
|
||||||
).unwrap();
|
).unwrap();
|
||||||
|
|
||||||
let bhash = b.hash();
|
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
|
// checking our new head
|
||||||
let head = chain.head().unwrap();
|
let head = chain.head().unwrap();
|
||||||
|
@ -96,8 +95,13 @@ fn mine_forks() {
|
||||||
clean_output_dir(".grin2");
|
clean_output_dir(".grin2");
|
||||||
|
|
||||||
let mut rng = OsRng::new().unwrap();
|
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
|
// mine and add a few blocks
|
||||||
let secp = secp::Secp256k1::with_caps(secp::ContextFlag::Commit);
|
let secp = secp::Secp256k1::with_caps(secp::ContextFlag::Commit);
|
||||||
|
@ -105,11 +109,11 @@ fn mine_forks() {
|
||||||
|
|
||||||
for n in 1..4 {
|
for n in 1..4 {
|
||||||
let prev = chain.head_header().unwrap();
|
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.timestamp = prev.timestamp + time::Duration::seconds(60);
|
||||||
b.header.total_difficulty = Difficulty::from_num(2 * n);
|
b.header.total_difficulty = Difficulty::from_num(2 * n);
|
||||||
let bhash = b.hash();
|
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
|
// checking our new head
|
||||||
thread::sleep(::std::time::Duration::from_millis(50));
|
thread::sleep(::std::time::Duration::from_millis(50));
|
||||||
|
@ -119,11 +123,11 @@ fn mine_forks() {
|
||||||
assert_eq!(head.prev_block_h, prev.hash());
|
assert_eq!(head.prev_block_h, prev.hash());
|
||||||
|
|
||||||
// build another block with higher difficulty
|
// 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.timestamp = prev.timestamp + time::Duration::seconds(60);
|
||||||
b.header.total_difficulty = Difficulty::from_num(2 * n + 1);
|
b.header.total_difficulty = Difficulty::from_num(2 * n + 1);
|
||||||
let bhash = b.hash();
|
let bhash = b.hash();
|
||||||
chain.process_block(b, grin_chain::SKIP_POW).unwrap();
|
chain.process_block(b, chain::SKIP_POW).unwrap();
|
||||||
|
|
||||||
// checking head switch
|
// checking head switch
|
||||||
thread::sleep(::std::time::Duration::from_millis(50));
|
thread::sleep(::std::time::Duration::from_millis(50));
|
||||||
|
|
|
@ -10,5 +10,6 @@ serde_derive = "~1.0.8"
|
||||||
toml = "0.4"
|
toml = "0.4"
|
||||||
|
|
||||||
grin_grin = { path = "../grin" }
|
grin_grin = { path = "../grin" }
|
||||||
|
grin_pow = { path = "../pow"}
|
||||||
grin_p2p = { path = "../p2p" }
|
grin_p2p = { path = "../p2p" }
|
||||||
grin_wallet = { path = "../wallet"}
|
grin_wallet = { path = "../wallet"}
|
||||||
|
|
|
@ -20,9 +20,8 @@ use std::path::PathBuf;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
|
||||||
use toml;
|
use toml;
|
||||||
use grin::{ServerConfig,
|
use grin::ServerConfig;
|
||||||
MinerConfig};
|
use pow::types::MinerConfig;
|
||||||
|
|
||||||
use types::{ConfigMembers,
|
use types::{ConfigMembers,
|
||||||
GlobalConfig,
|
GlobalConfig,
|
||||||
ConfigError};
|
ConfigError};
|
||||||
|
|
|
@ -29,6 +29,7 @@ extern crate toml;
|
||||||
extern crate grin_grin as grin;
|
extern crate grin_grin as grin;
|
||||||
extern crate grin_p2p as p2p;
|
extern crate grin_p2p as p2p;
|
||||||
extern crate grin_wallet as wallet;
|
extern crate grin_wallet as wallet;
|
||||||
|
extern crate grin_pow as pow;
|
||||||
|
|
||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod types;
|
pub mod types;
|
||||||
|
|
|
@ -18,9 +18,8 @@ use std::path::PathBuf;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use grin::{ServerConfig,
|
use grin::ServerConfig;
|
||||||
MinerConfig};
|
use pow::types::MinerConfig;
|
||||||
|
|
||||||
|
|
||||||
/// Error type wrapping config errors.
|
/// Error type wrapping config errors.
|
||||||
#[derive(Debug)]
|
#[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
|
/// 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
|
/// 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
|
/// 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 {
|
match *param_ref {
|
||||||
MiningParameterMode::AutomatedTesting => 0, //won't make a difference
|
MiningParameterMode::AutomatedTesting => 0, //won't make a difference
|
||||||
MiningParameterMode::UserTesting => 22141, //Magic nonce for current genesis block at cuckoo16
|
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 consensus;
|
||||||
pub mod core;
|
pub mod core;
|
||||||
pub mod genesis;
|
pub mod genesis;
|
||||||
pub mod pow;
|
|
||||||
pub mod ser;
|
pub mod ser;
|
||||||
pub mod global;
|
pub mod global;
|
||||||
|
|
|
@ -90,6 +90,11 @@ cuckoo_miner_plugin_type = "simple"
|
||||||
#the list of parameters if you're using "edgetrim"
|
#the list of parameters if you're using "edgetrim"
|
||||||
#cuckoo_miner_parameter_list = {NUM_THREADS=4, NUM_TRIMS=7}
|
#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
|
#the wallet reciever to which coinbase rewards will be sent
|
||||||
|
|
||||||
wallet_receiver_url = "http://127.0.0.1:13415"
|
wallet_receiver_url = "http://127.0.0.1:13415"
|
||||||
|
|
|
@ -13,12 +13,9 @@ grin_p2p = { path = "../p2p" }
|
||||||
grin_pool = { path = "../pool" }
|
grin_pool = { path = "../pool" }
|
||||||
grin_util = { path = "../util" }
|
grin_util = { path = "../util" }
|
||||||
grin_wallet = { path = "../wallet" }
|
grin_wallet = { path = "../wallet" }
|
||||||
|
grin_pow = { path = "../pow" }
|
||||||
secp256k1zkp = { path = "../secp256k1zkp" }
|
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"
|
env_logger="^0.3.5"
|
||||||
futures = "^0.1.9"
|
futures = "^0.1.9"
|
||||||
futures-cpupool = "^0.1.3"
|
futures-cpupool = "^0.1.3"
|
||||||
|
@ -30,5 +27,7 @@ serde_derive = "~1.0.8"
|
||||||
tokio-core="^0.1.1"
|
tokio-core="^0.1.1"
|
||||||
tokio-timer="^0.1.0"
|
tokio-timer="^0.1.0"
|
||||||
rand = "^0.3"
|
rand = "^0.3"
|
||||||
lazy_static = "~0.2.8"
|
|
||||||
itertools = "~0.6.0"
|
itertools = "~0.6.0"
|
||||||
|
|
||||||
|
[dev_dependencies]
|
||||||
|
blake2-rfc = "~0.2.17"
|
||||||
|
|
|
@ -34,8 +34,6 @@ extern crate serde_derive;
|
||||||
extern crate time;
|
extern crate time;
|
||||||
extern crate tokio_core;
|
extern crate tokio_core;
|
||||||
extern crate tokio_timer;
|
extern crate tokio_timer;
|
||||||
#[macro_use]
|
|
||||||
extern crate lazy_static;
|
|
||||||
extern crate itertools;
|
extern crate itertools;
|
||||||
|
|
||||||
extern crate grin_api as api;
|
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_store as store;
|
||||||
extern crate grin_util as util;
|
extern crate grin_util as util;
|
||||||
extern crate grin_wallet as wallet;
|
extern crate grin_wallet as wallet;
|
||||||
|
extern crate grin_pow as pow;
|
||||||
extern crate secp256k1zkp as secp;
|
extern crate secp256k1zkp as secp;
|
||||||
|
|
||||||
extern crate cuckoo_miner;
|
|
||||||
|
|
||||||
mod adapters;
|
mod adapters;
|
||||||
mod miner;
|
|
||||||
mod plugin;
|
|
||||||
mod server;
|
mod server;
|
||||||
mod seed;
|
mod seed;
|
||||||
mod sync;
|
mod sync;
|
||||||
mod types;
|
mod types;
|
||||||
|
mod miner;
|
||||||
|
|
||||||
pub use server::{Server};
|
pub use server::{Server};
|
||||||
pub use types::{ServerConfig, MinerConfig, Seeding, ServerStats};
|
pub use types::{ServerConfig, Seeding, ServerStats};
|
||||||
pub use plugin::PluginMiner;
|
|
||||||
|
|
|
@ -27,24 +27,28 @@ use api;
|
||||||
use core::consensus;
|
use core::consensus;
|
||||||
use core::core;
|
use core::core;
|
||||||
use core::core::Proof;
|
use core::core::Proof;
|
||||||
use core::pow::cuckoo;
|
use pow::cuckoo;
|
||||||
use core::core::target::Difficulty;
|
use core::core::target::Difficulty;
|
||||||
use core::core::{Block, BlockHeader};
|
use core::core::{Block, BlockHeader};
|
||||||
use core::core::hash::{Hash, Hashed};
|
use core::core::hash::{Hash, Hashed};
|
||||||
use core::pow::MiningWorker;
|
use pow::MiningWorker;
|
||||||
|
use pow::types::MinerConfig;
|
||||||
use core::ser;
|
use core::ser;
|
||||||
use core::ser::{AsFixedBytes};
|
use core::ser::{AsFixedBytes};
|
||||||
|
|
||||||
|
//use core::genesis;
|
||||||
|
|
||||||
use chain;
|
use chain;
|
||||||
use secp;
|
use secp;
|
||||||
use pool;
|
use pool;
|
||||||
use types::{MinerConfig, ServerConfig};
|
|
||||||
use util;
|
use util;
|
||||||
use wallet::{CbAmount, WalletReceiveRequest, CbData};
|
use wallet::{CbAmount, WalletReceiveRequest, CbData};
|
||||||
|
|
||||||
use plugin::PluginMiner;
|
use pow::plugin::PluginMiner;
|
||||||
|
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
||||||
|
|
||||||
// Max number of transactions this miner will assemble in a block
|
// Max number of transactions this miner will assemble in a block
|
||||||
const MAX_TX: u32 = 5000;
|
const MAX_TX: u32 = 5000;
|
||||||
|
|
||||||
|
@ -140,33 +144,47 @@ impl Miner {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Inner part of the mining loop for cuckoo-miner asynch mode
|
/// Inner part of the mining loop for cuckoo-miner asynch mode
|
||||||
pub fn inner_loop_async(&self, plugin_miner:&mut PluginMiner,
|
pub fn inner_loop_async(&self,
|
||||||
difficulty:Difficulty,
|
plugin_miner:&mut PluginMiner,
|
||||||
b:&mut Block,
|
difficulty:Difficulty,
|
||||||
cuckoo_size: u32,
|
b:&mut Block,
|
||||||
head:&BlockHeader,
|
cuckoo_size: u32,
|
||||||
latest_hash:&Hash)
|
head:&BlockHeader,
|
||||||
-> Option<Proof> {
|
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 {}.",
|
debug!("(Server ID: {}) Mining at Cuckoo{} for at most {} secs at height {} and difficulty {}.",
|
||||||
self.debug_output_id,
|
self.debug_output_id,
|
||||||
cuckoo_size,
|
cuckoo_size,
|
||||||
b.header.height,
|
attempt_time_per_block,
|
||||||
b.header.difficulty);
|
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
|
// transactions) and as long as the head hasn't changed
|
||||||
// Will change this to something else at some point
|
// 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
|
//Get parts of the header
|
||||||
let mut header_parts = HeaderPartWriter::default();
|
let mut header_parts = HeaderPartWriter::default();
|
||||||
ser::Writeable::write(&b.header, &mut header_parts).unwrap();
|
ser::Writeable::write(&b.header, &mut header_parts).unwrap();
|
||||||
let (pre, post) = header_parts.parts_as_hex_strings();
|
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
|
//Start the miner working
|
||||||
let miner = plugin_miner.get_consumable();
|
let miner = plugin_miner.get_consumable();
|
||||||
let job_handle=miner.notify(1, &pre, &post, difficulty.into_num()).unwrap();
|
let job_handle=miner.notify(1, &pre, &post, difficulty.into_num()).unwrap();
|
||||||
|
|
||||||
let mut sol=None;
|
let mut sol=None;
|
||||||
|
|
||||||
|
@ -174,8 +192,26 @@ impl Miner {
|
||||||
if let Some(s) = job_handle.get_solution() {
|
if let Some(s) = job_handle.get_solution() {
|
||||||
sol = Some(Proof::new(s.solution_nonces.to_vec()));
|
sol = Some(Proof::new(s.solution_nonces.to_vec()));
|
||||||
b.header.nonce=s.get_nonce_as_u64();
|
b.header.nonce=s.get_nonce_as_u64();
|
||||||
|
println!("Nonce: {}", b.header.nonce);
|
||||||
break;
|
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 {
|
if sol==None {
|
||||||
debug!("(Server ID: {}) No solution found after {} iterations, continuing...",
|
debug!("(Server ID: {}) No solution found after {} iterations, continuing...",
|
||||||
|
@ -190,21 +226,23 @@ impl Miner {
|
||||||
|
|
||||||
/// The inner part of mining loop for synchronous mode
|
/// The inner part of mining loop for synchronous mode
|
||||||
pub fn inner_loop_sync<T: MiningWorker>(&self,
|
pub fn inner_loop_sync<T: MiningWorker>(&self,
|
||||||
miner:&mut T,
|
miner:&mut T,
|
||||||
b:&mut Block,
|
b:&mut Block,
|
||||||
cuckoo_size: u32,
|
cuckoo_size: u32,
|
||||||
head:&BlockHeader,
|
head:&BlockHeader,
|
||||||
latest_hash:&mut Hash)
|
attempt_time_per_block: u32,
|
||||||
-> Option<Proof> {
|
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
|
// 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
|
// 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 {}.",
|
debug!("(Server ID: {}) Mining at Cuckoo{} for at most {} secs on block {} at difficulty {}.",
|
||||||
self.debug_output_id,
|
self.debug_output_id,
|
||||||
cuckoo_size,
|
cuckoo_size,
|
||||||
latest_hash,
|
attempt_time_per_block,
|
||||||
b.header.difficulty);
|
latest_hash,
|
||||||
|
b.header.difficulty);
|
||||||
let mut iter_count = 0;
|
let mut iter_count = 0;
|
||||||
|
|
||||||
if self.config.slow_down_in_millis != None && self.config.slow_down_in_millis.unwrap() > 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,
|
b.header.difficulty,
|
||||||
proof_diff);*/
|
proof_diff);*/
|
||||||
|
|
||||||
if proof_diff >= b.header.difficulty {
|
if proof_diff >= b.header.difficulty {
|
||||||
sol = Some(proof);
|
sol = Some(proof);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -241,8 +279,8 @@ impl Miner {
|
||||||
|
|
||||||
if sol==None {
|
if sol==None {
|
||||||
debug!("(Server ID: {}) No solution found after {} iterations, continuing...",
|
debug!("(Server ID: {}) No solution found after {} iterations, continuing...",
|
||||||
self.debug_output_id,
|
self.debug_output_id,
|
||||||
iter_count)
|
iter_count)
|
||||||
}
|
}
|
||||||
|
|
||||||
sol
|
sol
|
||||||
|
@ -251,17 +289,16 @@ impl Miner {
|
||||||
/// Starts the mining loop, building a new block on top of the existing
|
/// Starts the mining loop, building a new block on top of the existing
|
||||||
/// chain anytime required and looking for PoW solution.
|
/// chain anytime required and looking for PoW solution.
|
||||||
pub fn run_loop(&self,
|
pub fn run_loop(&self,
|
||||||
miner_config:MinerConfig,
|
miner_config:MinerConfig,
|
||||||
server_config:ServerConfig,
|
cuckoo_size:u32,
|
||||||
cuckoo_size:u32,
|
proof_size:usize) {
|
||||||
proof_size:usize) {
|
|
||||||
|
|
||||||
info!("(Server ID: {}) Starting miner loop.", self.debug_output_id);
|
info!("(Server ID: {}) Starting miner loop.", self.debug_output_id);
|
||||||
let mut plugin_miner=None;
|
let mut plugin_miner=None;
|
||||||
let mut miner=None;
|
let mut miner=None;
|
||||||
if miner_config.use_cuckoo_miner {
|
if miner_config.use_cuckoo_miner {
|
||||||
plugin_miner = Some(PluginMiner::new(consensus::EASINESS, cuckoo_size, proof_size));
|
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 {
|
} else {
|
||||||
miner = Some(cuckoo::Miner::new(consensus::EASINESS, cuckoo_size, proof_size));
|
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 let Some(mut p) = plugin_miner.as_mut() {
|
||||||
if use_async {
|
if use_async {
|
||||||
sol = self.inner_loop_async(&mut p,
|
sol = self.inner_loop_async(&mut p,
|
||||||
b.header.difficulty.clone(),
|
b.header.difficulty.clone(),
|
||||||
&mut b,
|
&mut b,
|
||||||
cuckoo_size,
|
cuckoo_size,
|
||||||
&head,
|
&head,
|
||||||
&latest_hash);
|
&latest_hash,
|
||||||
|
miner_config.attempt_time_per_block);
|
||||||
} else {
|
} else {
|
||||||
sol = self.inner_loop_sync(p,
|
sol = self.inner_loop_sync(p,
|
||||||
&mut b,
|
&mut b,
|
||||||
cuckoo_size,
|
cuckoo_size,
|
||||||
&head,
|
&head,
|
||||||
&mut latest_hash);
|
miner_config.attempt_time_per_block,
|
||||||
|
&mut latest_hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(mut m) = miner.as_mut() {
|
if let Some(mut m) = miner.as_mut() {
|
||||||
sol = self.inner_loop_sync(m,
|
sol = self.inner_loop_sync(m,
|
||||||
&mut b,
|
&mut b,
|
||||||
cuckoo_size,
|
cuckoo_size,
|
||||||
&head,
|
&head,
|
||||||
&mut latest_hash);
|
miner_config.attempt_time_per_block,
|
||||||
|
&mut latest_hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we found a solution, push our block out
|
// if we found a solution, push our block out
|
||||||
if let Some(proof) = sol {
|
if let Some(proof) = sol {
|
||||||
info!("(Server ID: {}) Found valid proof of work, adding block {}.",
|
info!("(Server ID: {}) Found valid proof of work, adding block {}.",
|
||||||
self.debug_output_id, b.hash());
|
self.debug_output_id, b.hash());
|
||||||
b.header.pow = proof;
|
b.header.pow = proof;
|
||||||
let opts = if cuckoo_size < consensus::DEFAULT_SIZESHIFT as u32 {
|
let opts = if cuckoo_size < consensus::DEFAULT_SIZESHIFT as u32 {
|
||||||
chain::EASY_POW
|
chain::EASY_POW
|
||||||
} else {
|
} else {
|
||||||
|
@ -346,10 +386,10 @@ impl Miner {
|
||||||
let (output, kernel) = coinbase;
|
let (output, kernel) = coinbase;
|
||||||
let mut b = core::Block::with_reward(head, txs, output, kernel).unwrap();
|
let mut b = core::Block::with_reward(head, txs, output, kernel).unwrap();
|
||||||
debug!("(Server ID: {}) Built new block with {} inputs and {} outputs, difficulty: {}",
|
debug!("(Server ID: {}) Built new block with {} inputs and {} outputs, difficulty: {}",
|
||||||
self.debug_output_id,
|
self.debug_output_id,
|
||||||
b.inputs.len(),
|
b.inputs.len(),
|
||||||
b.outputs.len(),
|
b.outputs.len(),
|
||||||
difficulty);
|
difficulty);
|
||||||
|
|
||||||
// making sure we're not spending time mining a useless block
|
// making sure we're not spending time mining a useless block
|
||||||
let secp = secp::Secp256k1::with_caps(secp::ContextFlag::Commit);
|
let secp = secp::Secp256k1::with_caps(secp::ContextFlag::Commit);
|
||||||
|
@ -370,7 +410,7 @@ impl Miner {
|
||||||
core::Block::reward_output(skey, &secp_inst).unwrap()
|
core::Block::reward_output(skey, &secp_inst).unwrap()
|
||||||
} else {
|
} else {
|
||||||
let url = format!("{}/v1/receive/coinbase",
|
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 request = WalletReceiveRequest::Coinbase(CbAmount{amount: consensus::REWARD});
|
||||||
let res: CbData = api::client::post(url.as_str(),
|
let res: CbData = api::client::post(url.as_str(),
|
||||||
&request)
|
&request)
|
||||||
|
|
|
@ -34,6 +34,7 @@ use pool;
|
||||||
use seed;
|
use seed;
|
||||||
use sync;
|
use sync;
|
||||||
use types::*;
|
use types::*;
|
||||||
|
use pow;
|
||||||
|
|
||||||
use core::global;
|
use core::global;
|
||||||
|
|
||||||
|
@ -81,8 +82,17 @@ impl Server {
|
||||||
let tx_pool = Arc::new(RwLock::new(pool::TransactionPool::new(pool_adapter.clone())));
|
let tx_pool = Arc::new(RwLock::new(pool::TransactionPool::new(pool_adapter.clone())));
|
||||||
|
|
||||||
let chain_adapter = Arc::new(ChainToPoolAndNetAdapter::new(tx_pool.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(),
|
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());
|
pool_adapter.set_chain(shared_chain.clone());
|
||||||
|
|
||||||
let peer_store = Arc::new(p2p::PeerStore::new(config.db_root.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,
|
/// 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
|
/// 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 cuckoo_size = global::sizeshift();
|
||||||
let proof_size = global::proofsize();
|
let proof_size = global::proofsize();
|
||||||
|
|
||||||
|
|
||||||
let mut miner = miner::Miner::new(config.clone(), self.chain.clone(), self.tx_pool.clone());
|
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));
|
miner.set_debug_output_id(format!("Port {}",self.config.p2p_config.unwrap().port));
|
||||||
let server_config = self.config.clone();
|
|
||||||
thread::spawn(move || {
|
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.
|
// limitations under the License.
|
||||||
|
|
||||||
use std::convert::From;
|
use std::convert::From;
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
use api;
|
use api;
|
||||||
use chain;
|
use chain;
|
||||||
use p2p;
|
use p2p;
|
||||||
use store;
|
use store;
|
||||||
|
use pow;
|
||||||
use core::global::MiningParameterMode;
|
use core::global::MiningParameterMode;
|
||||||
|
|
||||||
/// Error type wrapping underlying module errors.
|
/// Error type wrapping underlying module errors.
|
||||||
|
@ -96,42 +96,7 @@ pub struct ServerConfig {
|
||||||
pub p2p_config: Option<p2p::P2PConfig>,
|
pub p2p_config: Option<p2p::P2PConfig>,
|
||||||
|
|
||||||
/// Configuration for the mining daemon
|
/// Configuration for the mining daemon
|
||||||
pub mining_config: Option<MinerConfig>,
|
pub mining_config: Option<pow::types::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>,
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ServerConfig {
|
impl Default for ServerConfig {
|
||||||
|
@ -143,28 +108,12 @@ impl Default for ServerConfig {
|
||||||
seeding_type: Seeding::None,
|
seeding_type: Seeding::None,
|
||||||
seeds: None,
|
seeds: None,
|
||||||
p2p_config: Some(p2p::P2PConfig::default()),
|
p2p_config: Some(p2p::P2PConfig::default()),
|
||||||
mining_config: Some(MinerConfig::default()),
|
mining_config: Some(pow::types::MinerConfig::default()),
|
||||||
mining_parameter_mode: Some(MiningParameterMode::Production),
|
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
|
/// Thread-safe container to return all sever related stats that other
|
||||||
/// consumers might be interested in, such as test results
|
/// consumers might be interested in, such as test results
|
||||||
///
|
///
|
||||||
|
@ -178,3 +127,4 @@ pub struct ServerStats {
|
||||||
/// Chain head
|
/// Chain head
|
||||||
pub head: chain::Tip,
|
pub head: chain::Tip,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ extern crate grin_p2p as p2p;
|
||||||
extern crate grin_chain as chain;
|
extern crate grin_chain as chain;
|
||||||
extern crate grin_api as api;
|
extern crate grin_api as api;
|
||||||
extern crate grin_wallet as wallet;
|
extern crate grin_wallet as wallet;
|
||||||
|
extern crate grin_pow as pow;
|
||||||
extern crate secp256k1zkp as secp;
|
extern crate secp256k1zkp as secp;
|
||||||
|
|
||||||
extern crate blake2_rfc as blake2;
|
extern crate blake2_rfc as blake2;
|
||||||
|
@ -200,7 +201,6 @@ impl LocalServerContainer {
|
||||||
seeds=vec![self.config.seed_addr.to_string()];
|
seeds=vec![self.config.seed_addr.to_string()];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let s = grin::Server::future(
|
let s = grin::Server::future(
|
||||||
grin::ServerConfig{
|
grin::ServerConfig{
|
||||||
api_http_addr: api_addr,
|
api_http_addr: api_addr,
|
||||||
|
@ -219,7 +219,7 @@ impl LocalServerContainer {
|
||||||
thread::sleep(time::Duration::from_millis(1000));
|
thread::sleep(time::Duration::from_millis(1000));
|
||||||
}
|
}
|
||||||
|
|
||||||
let miner_config = grin::MinerConfig {
|
let miner_config = pow::types::MinerConfig {
|
||||||
enable_mining: self.config.start_miner,
|
enable_mining: self.config.start_miner,
|
||||||
burn_reward: self.config.burn_mining_rewards,
|
burn_reward: self.config.burn_mining_rewards,
|
||||||
use_cuckoo_miner: false,
|
use_cuckoo_miner: false,
|
||||||
|
|
|
@ -18,6 +18,7 @@ extern crate grin_p2p as p2p;
|
||||||
extern crate grin_chain as chain;
|
extern crate grin_chain as chain;
|
||||||
extern crate grin_api as api;
|
extern crate grin_api as api;
|
||||||
extern crate grin_wallet as wallet;
|
extern crate grin_wallet as wallet;
|
||||||
|
extern crate grin_pow as pow;
|
||||||
extern crate secp256k1zkp as secp;
|
extern crate secp256k1zkp as secp;
|
||||||
|
|
||||||
extern crate env_logger;
|
extern crate env_logger;
|
||||||
|
@ -200,7 +201,7 @@ fn a_simulate_block_propagation() {
|
||||||
let mut evtlp = reactor::Core::new().unwrap();
|
let mut evtlp = reactor::Core::new().unwrap();
|
||||||
let handle = evtlp.handle();
|
let handle = evtlp.handle();
|
||||||
|
|
||||||
let miner_config = grin::MinerConfig {
|
let miner_config = pow::types::MinerConfig {
|
||||||
enable_mining: true,
|
enable_mining: true,
|
||||||
burn_reward: true,
|
burn_reward: true,
|
||||||
use_cuckoo_miner: false,
|
use_cuckoo_miner: false,
|
||||||
|
@ -267,7 +268,7 @@ fn simulate_full_sync() {
|
||||||
let mut evtlp = reactor::Core::new().unwrap();
|
let mut evtlp = reactor::Core::new().unwrap();
|
||||||
let handle = evtlp.handle();
|
let handle = evtlp.handle();
|
||||||
|
|
||||||
let miner_config = grin::MinerConfig {
|
let miner_config = pow::types::MinerConfig {
|
||||||
enable_mining: true,
|
enable_mining: true,
|
||||||
burn_reward: true,
|
burn_reward: true,
|
||||||
use_cuckoo_miner: false,
|
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 blake2;
|
||||||
|
|
||||||
use core::Proof;
|
use core::core::Proof;
|
||||||
use pow::siphash::siphash24;
|
use siphash::siphash24;
|
||||||
use pow::MiningWorker;
|
use MiningWorker;
|
||||||
|
|
||||||
const MAXPATHLEN: usize = 8192;
|
const MAXPATHLEN: usize = 8192;
|
||||||
|
|
||||||
|
@ -326,7 +326,7 @@ fn u8_to_u64(p:&[u8], i: usize) -> u64 {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use core::Proof;
|
use core::core::Proof;
|
||||||
|
|
||||||
|
|
||||||
static V1:[u32;42] = [0x1fe9, 0x2050, 0x4581, 0x6322, 0x65ab, 0xb3c1, 0xc1a4,
|
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
|
//! Note that this miner implementation is here mostly for tests and
|
||||||
//! reference. It's not optimized for speed.
|
//! 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;
|
mod siphash;
|
||||||
|
pub mod plugin;
|
||||||
pub mod cuckoo;
|
pub mod cuckoo;
|
||||||
|
pub mod types;
|
||||||
|
|
||||||
use time;
|
use core::consensus;
|
||||||
|
use core::core::BlockHeader;
|
||||||
use consensus::EASINESS;
|
use core::core::hash::Hashed;
|
||||||
use core::BlockHeader;
|
use core::core::Proof;
|
||||||
use core::hash::Hashed;
|
use core::core::target::Difficulty;
|
||||||
use core::Proof;
|
use core::global;
|
||||||
use core::target::Difficulty;
|
use core::genesis;
|
||||||
use pow::cuckoo::{Cuckoo, Error};
|
use cuckoo::{Cuckoo, Error};
|
||||||
|
|
||||||
|
|
||||||
/// Should be implemented by anything providing mining services
|
/// Should be implemented by anything providing mining services
|
||||||
///
|
///
|
||||||
|
@ -41,7 +64,7 @@ use pow::cuckoo::{Cuckoo, Error};
|
||||||
pub trait MiningWorker {
|
pub trait MiningWorker {
|
||||||
|
|
||||||
/// This only sets parameters and does initialisation work now
|
/// 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
|
/// Actually perform a mining attempt on the given input and
|
||||||
/// return a proof if found
|
/// 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() {
|
if bh.difficulty > bh.pow.clone().to_difficulty() {
|
||||||
return false;
|
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
|
/// 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)
|
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,
|
/// 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...
|
/// 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> {
|
diff: Difficulty, _: u32) -> Result<(), Error> {
|
||||||
let start_nonce = bh.nonce;
|
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
|
// try to find a cuckoo cycle on that header hash
|
||||||
loop {
|
loop {
|
||||||
// can be trivially optimized by avoiding re-serialization every time but this
|
// 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 {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use global;
|
use global;
|
||||||
use core::target::Difficulty;
|
use core::core::target::Difficulty;
|
||||||
use genesis;
|
use core::genesis;
|
||||||
use consensus::MINIMUM_DIFFICULTY;
|
use core::consensus::MINIMUM_DIFFICULTY;
|
||||||
use global::MiningParameterMode;
|
use core::global::MiningParameterMode;
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -114,7 +175,7 @@ mod test {
|
||||||
global::set_mining_mode(MiningParameterMode::AutomatedTesting);
|
global::set_mining_mode(MiningParameterMode::AutomatedTesting);
|
||||||
let mut b = genesis::genesis();
|
let mut b = genesis::genesis();
|
||||||
b.header.nonce = 310;
|
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();
|
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.nonce != 310);
|
||||||
assert!(b.header.pow.clone().to_difficulty() >= Difficulty::from_num(MINIMUM_DIFFICULTY));
|
assert!(b.header.pow.clone().to_difficulty() >= Difficulty::from_num(MINIMUM_DIFFICULTY));
|
|
@ -19,13 +19,13 @@
|
||||||
|
|
||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
use core::pow::cuckoo;
|
use cuckoo;
|
||||||
use core::pow::cuckoo::Error;
|
use cuckoo::Error;
|
||||||
use core::pow::MiningWorker;
|
use MiningWorker;
|
||||||
use core::global;
|
use core::global;
|
||||||
|
|
||||||
use core::core::Proof;
|
use core::core::Proof;
|
||||||
use types::{MinerConfig, ServerConfig};
|
use types::MinerConfig;
|
||||||
|
|
||||||
use std::sync::{Mutex};
|
use std::sync::{Mutex};
|
||||||
|
|
||||||
|
@ -64,12 +64,14 @@ impl Default for PluginMiner {
|
||||||
|
|
||||||
impl PluginMiner {
|
impl PluginMiner {
|
||||||
/// Init the plugin miner
|
/// 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
|
//Get directory of executable
|
||||||
let mut exe_path=env::current_exe().unwrap();
|
let mut exe_path=env::current_exe().unwrap();
|
||||||
exe_path.pop();
|
exe_path.pop();
|
||||||
let exe_path=exe_path.to_str().unwrap();
|
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 {
|
let plugin_install_path = match miner_config.cuckoo_miner_plugin_dir {
|
||||||
Some(s) => s,
|
Some(s) => s,
|
||||||
None => String::from(format!("{}/deps", exe_path))
|
None => String::from(format!("{}/deps", exe_path))
|
||||||
|
@ -86,7 +88,7 @@ impl PluginMiner {
|
||||||
//when packaging is more//thought out
|
//when packaging is more//thought out
|
||||||
|
|
||||||
let mut loaded_config_ref = LOADED_CONFIG.lock().unwrap();
|
let mut loaded_config_ref = LOADED_CONFIG.lock().unwrap();
|
||||||
|
|
||||||
//Load from here instead
|
//Load from here instead
|
||||||
if let Some(ref c) = *loaded_config_ref {
|
if let Some(ref c) = *loaded_config_ref {
|
||||||
debug!("Not re-loading plugin or directory.");
|
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