Genesis block for known chains, mine dev chains ()

Renamed mining parameter mode to chain type, with existing types
of CI testing, user testing, testnet1 or mainnet. The public
chains (testnet1 and mainnet) come with their fully pre-defined
genesis block.

Still need to set the nonce and cycle for testnet1 genesis.
This commit is contained in:
Ignotus Peverell 2017-11-15 16:49:15 -05:00 committed by GitHub
parent 6fb085a823
commit 91fdaa8320
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 167 additions and 190 deletions

View file

@ -33,7 +33,7 @@ use sumtree;
use types::*;
use util::LOGGER;
use core::global::{MiningParameterMode, MINING_PARAMETER_MODE};
use core::global;
const MAX_ORPHANS: usize = 20;
@ -184,16 +184,14 @@ impl Chain {
}
fn ctx_from_head(&self, head: Tip, opts: Options) -> pipe::BlockContext {
let opts_in = opts;
let param_ref = MINING_PARAMETER_MODE.read().unwrap();
let opts_in = match *param_ref {
MiningParameterMode::AutomatedTesting => opts_in | EASY_POW,
MiningParameterMode::UserTesting => opts_in | EASY_POW,
MiningParameterMode::Production => opts_in,
};
let opts = if global::is_production_mode() {
opts
} else {
opts | EASY_POW
};
pipe::BlockContext {
opts: opts_in,
opts: opts,
store: self.store.clone(),
head: head,
pow_verifier: self.pow_verifier,

View file

@ -30,7 +30,7 @@ use core::core::hash::Hashed;
use core::core::target::Difficulty;
use core::consensus;
use core::global;
use core::global::MiningParameterMode;
use core::global::ChainTypes;
use keychain::Keychain;
@ -43,7 +43,7 @@ fn clean_output_dir(dir_name: &str) {
fn setup(dir_name: &str) -> Chain {
let _ = env_logger::init();
clean_output_dir(dir_name);
global::set_mining_mode(MiningParameterMode::AutomatedTesting);
global::set_mining_mode(ChainTypes::AutomatedTesting);
let mut genesis_block = None;
if !chain::Chain::chain_exists(dir_name.to_string()) {
genesis_block = pow::mine_genesis_block(None);

View file

@ -28,7 +28,7 @@ use core::core::build;
use core::core::transaction;
use core::consensus;
use core::global;
use core::global::MiningParameterMode;
use core::global::ChainTypes;
use keychain::Keychain;
@ -42,7 +42,7 @@ fn clean_output_dir(dir_name: &str) {
fn test_coinbase_maturity() {
let _ = env_logger::init();
clean_output_dir(".grin");
global::set_mining_mode(MiningParameterMode::AutomatedTesting);
global::set_mining_mode(ChainTypes::AutomatedTesting);
let mut genesis_block = None;
if !chain::Chain::chain_exists(".grin".to_string()) {

View file

@ -17,18 +17,16 @@
use time;
use core;
use consensus::MINIMUM_DIFFICULTY;
use consensus;
use core::target::Difficulty;
use global;
/// Genesis block definition. It has no rewards, no inputs, no outputs, no
/// fees and a height of zero.
pub fn genesis() -> core::Block {
let proof_size = global::proofsize();
let empty_hash = core::hash::Hash([0x0; 32]);
/// Genesis block definition for development networks. The proof of work size
/// is small enough to mine it on the fly, so it does not contain its own
/// proof of work solution. Can also be easily mutated for different tests.
pub fn genesis_dev() -> core::Block {
core::Block {
header: core::BlockHeader {
version: 1,
height: 0,
previous: core::hash::Hash([0xff; 32]),
timestamp: time::Tm {
@ -37,13 +35,56 @@ pub fn genesis() -> core::Block {
tm_mday: 4,
..time::empty_tm()
},
difficulty: Difficulty::from_num(MINIMUM_DIFFICULTY),
total_difficulty: Difficulty::from_num(MINIMUM_DIFFICULTY),
utxo_root: empty_hash,
range_proof_root: empty_hash,
kernel_root: empty_hash,
nonce: global::get_genesis_nonce(),
pow: core::Proof::zero(proof_size), // TODO get actual PoW solution
..Default::default()
},
inputs: vec![],
outputs: vec![],
kernels: vec![],
}
}
/// First testnet genesis block, still subject to change (especially the date,
/// will hopefully come before Christmas).
pub fn genesis_testnet1() -> core::Block {
core::Block {
header: core::BlockHeader {
height: 0,
previous: core::hash::Hash([0xff; 32]),
timestamp: time::Tm {
tm_year: 2017 - 1900,
tm_mon: 12,
tm_mday: 25,
..time::empty_tm()
},
nonce: 1,
pow: core::Proof::zero(consensus::PROOFSIZE),
..Default::default()
},
inputs: vec![],
outputs: vec![],
kernels: vec![],
}
}
/// Placeholder for mainnet genesis block, will definitely change before
/// release so no use trying to pre-mine it.
pub fn genesis_main() -> core::Block {
core::Block {
header: core::BlockHeader {
height: 0,
previous: core::hash::Hash([0xff; 32]),
timestamp: time::Tm {
tm_year: 2018 - 1900,
tm_mon: 7,
tm_mday: 14,
..time::empty_tm()
},
difficulty: Difficulty::from_num(1000),
total_difficulty: Difficulty::from_num(1000),
nonce: global::get_genesis_nonce(),
pow: core::Proof::zero(consensus::PROOFSIZE),
..Default::default()
},
inputs: vec![],
outputs: vec![],

View file

@ -47,77 +47,85 @@ pub const AUTOMATED_TESTING_COINBASE_MATURITY: u64 = 3;
/// User testing coinbase maturity
pub const USER_TESTING_COINBASE_MATURITY: u64 = 3;
/// Mining parameter modes
/// Types of chain a server can run with, dictates the genesis block and
/// and mining parameters used.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum MiningParameterMode {
pub enum ChainTypes {
/// For CI testing
AutomatedTesting,
/// For User testing
UserTesting,
/// For production, use the values in consensus.rs
Production,
/// First test network
Testnet1,
/// Main production network
Mainnet,
}
lazy_static!{
/// The mining parameter mode
pub static ref MINING_PARAMETER_MODE: RwLock<MiningParameterMode> =
RwLock::new(MiningParameterMode::Production);
pub static ref CHAIN_TYPE: RwLock<ChainTypes> =
RwLock::new(ChainTypes::Mainnet);
}
/// Set the mining mode
pub fn set_mining_mode(mode: MiningParameterMode) {
let mut param_ref = MINING_PARAMETER_MODE.write().unwrap();
pub fn set_mining_mode(mode: ChainTypes) {
let mut param_ref = CHAIN_TYPE.write().unwrap();
*param_ref = mode;
}
/// The sizeshift
pub fn sizeshift() -> u8 {
let param_ref = MINING_PARAMETER_MODE.read().unwrap();
let param_ref = CHAIN_TYPE.read().unwrap();
match *param_ref {
MiningParameterMode::AutomatedTesting => AUTOMATED_TESTING_SIZESHIFT,
MiningParameterMode::UserTesting => USER_TESTING_SIZESHIFT,
MiningParameterMode::Production => DEFAULT_SIZESHIFT,
ChainTypes::AutomatedTesting => AUTOMATED_TESTING_SIZESHIFT,
ChainTypes::UserTesting => USER_TESTING_SIZESHIFT,
ChainTypes::Testnet1 => DEFAULT_SIZESHIFT,
ChainTypes::Mainnet => DEFAULT_SIZESHIFT,
}
}
/// The proofsize
pub fn proofsize() -> usize {
let param_ref = MINING_PARAMETER_MODE.read().unwrap();
let param_ref = CHAIN_TYPE.read().unwrap();
match *param_ref {
MiningParameterMode::AutomatedTesting => AUTOMATED_TESTING_PROOF_SIZE,
MiningParameterMode::UserTesting => USER_TESTING_PROOF_SIZE,
MiningParameterMode::Production => PROOFSIZE,
ChainTypes::AutomatedTesting => AUTOMATED_TESTING_PROOF_SIZE,
ChainTypes::UserTesting => USER_TESTING_PROOF_SIZE,
ChainTypes::Testnet1 => PROOFSIZE,
ChainTypes::Mainnet => PROOFSIZE,
}
}
/// Coinbase maturity
pub fn coinbase_maturity() -> u64 {
let param_ref = MINING_PARAMETER_MODE.read().unwrap();
let param_ref = CHAIN_TYPE.read().unwrap();
match *param_ref {
MiningParameterMode::AutomatedTesting => AUTOMATED_TESTING_COINBASE_MATURITY,
MiningParameterMode::UserTesting => USER_TESTING_COINBASE_MATURITY,
MiningParameterMode::Production => COINBASE_MATURITY,
ChainTypes::AutomatedTesting => AUTOMATED_TESTING_COINBASE_MATURITY,
ChainTypes::UserTesting => USER_TESTING_COINBASE_MATURITY,
ChainTypes::Testnet1 => COINBASE_MATURITY,
ChainTypes::Mainnet => COINBASE_MATURITY,
}
}
/// Are we in automated testing mode?
pub fn is_automated_testing_mode() -> bool {
let param_ref = MINING_PARAMETER_MODE.read().unwrap();
MiningParameterMode::AutomatedTesting == *param_ref
let param_ref = CHAIN_TYPE.read().unwrap();
ChainTypes::AutomatedTesting == *param_ref
}
/// Are we in user testing mode?
pub fn is_user_testing_mode() -> bool {
let param_ref = MINING_PARAMETER_MODE.read().unwrap();
MiningParameterMode::UserTesting == *param_ref
let param_ref = CHAIN_TYPE.read().unwrap();
ChainTypes::UserTesting == *param_ref
}
/// Are we in production mode?
/// Are we in production mode (a live public network)?
pub fn is_production_mode() -> bool {
let param_ref = MINING_PARAMETER_MODE.read().unwrap();
MiningParameterMode::Production == *param_ref
let param_ref = CHAIN_TYPE.read().unwrap();
ChainTypes::Testnet1 == *param_ref ||
ChainTypes::Mainnet == *param_ref
}
@ -126,78 +134,14 @@ pub fn is_production_mode() -> bool {
/// as the genesis block POW solution turns out to be the same for every new
/// block chain
/// at the moment
pub fn get_genesis_nonce() -> u64 {
let param_ref = MINING_PARAMETER_MODE.read().unwrap();
let param_ref = CHAIN_TYPE.read().unwrap();
match *param_ref {
// won't make a difference
MiningParameterMode::AutomatedTesting => 0,
ChainTypes::AutomatedTesting => 0,
// Magic nonce for current genesis block at cuckoo16
MiningParameterMode::UserTesting => 27944,
// Magic nonce for current genesis at cuckoo30
MiningParameterMode::Production => 1429942738856787200,
}
}
ChainTypes::UserTesting => 27944,
/// Returns the genesis POW for cuckoo16 (UserTesting) and cuckoo30 (Production)
pub fn get_genesis_pow() -> [u32; 42] {
let param_ref = MINING_PARAMETER_MODE.read().unwrap();
match *param_ref {
// pow solution for genesis block at cuckoo16
MiningParameterMode::UserTesting => [
0x37f, 0x9f6, 0x136d, 0x13d3, 0x155e, 0x16dd, 0x186b, 0x1b11, 0x208e, 0x23cd,
0x24d1, 0x278f, 0x2a1b, 0x2a28, 0x2a44, 0x2ae2, 0x2c37, 0x36af, 0x391d, 0x3c2e,
0x3d9a, 0x3f00, 0x429f, 0x45b2, 0x47ce, 0x47f1, 0x492f, 0x4bd8, 0x4fee, 0x51f0,
0x5207, 0x58e5, 0x5905, 0x5aca, 0x5dfb, 0x628d, 0x7310, 0x75e5, 0x76d4, 0x76df,
0x77bd, 0x7ab9
],
// pow solution for genesis block at cuckoo30
// TODO - likely this is no longer correct (block header changes)
MiningParameterMode::Production => [
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,
],
// TODO - for completeness do we provide one here for AutomatedTesting?
_ => panic!("unexpected"),
_ => panic!("Pre-set"),
}
}

View file

@ -32,13 +32,13 @@ seeding_type = "None"
#if seeding_type = List, the list of peers to connect to.
#seeds = ["192.168.0.1:8080","192.168.0.2:8080"]
#The mining parameter mode, which defines the set of cuckoo parameters
#used for mining. Can be:
#The chain type, which defines the genesis block and the set of cuckoo
#parameters used for mining. Can be:
#AutomatedTesting - For CI builds and instant blockchain creation
#UserTesting - For regular user testing (cuckoo 16)
#Production - Full production cuckoo parameter (cuckoo 30)
#Testnet1 - Full production cuckoo parameter (cuckoo 30)
mining_parameter_mode = "UserTesting"
chain_type = "UserTesting"
#7 = Bit flags for FULL_NODE, this structure needs to be changed
#internally to make it more configurable

View file

@ -21,6 +21,7 @@ use core::core::{self, Output};
use core::core::block::BlockHeader;
use core::core::hash::{Hash, Hashed};
use core::core::target::Difficulty;
use core::global;
use p2p::{self, NetAdapter, PeerData, PeerStore, Server, State};
use pool;
use util::secp::pedersen::Commitment;
@ -28,7 +29,6 @@ use util::OneTime;
use store;
use sync;
use util::LOGGER;
use core::global::{MiningParameterMode, MINING_PARAMETER_MODE};
/// Implementation of the NetAdapter for the blockchain. Gets notified when new
/// blocks and transactions are received and forwards to the chain and pool
@ -286,12 +286,11 @@ impl NetToChainAdapter {
} else {
chain::NONE
};
let param_ref = MINING_PARAMETER_MODE.read().unwrap();
let opts = match *param_ref {
MiningParameterMode::AutomatedTesting => opts | chain::EASY_POW,
MiningParameterMode::UserTesting => opts | chain::EASY_POW,
MiningParameterMode::Production => opts,
};
let opts = if global::is_production_mode() {
opts
} else {
opts | chain::EASY_POW
};
opts
}
}

View file

@ -28,6 +28,7 @@ use tokio_timer::Timer;
use adapters::*;
use api;
use chain;
use core::{global, genesis};
use miner;
use p2p;
use pool;
@ -37,7 +38,6 @@ use types::*;
use pow;
use util::LOGGER;
use core::global;
/// Grin server holding internal structures.
pub struct Server {
@ -91,7 +91,12 @@ impl Server {
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 chain_type = config.chain_type.clone().unwrap();
if chain_type == global::ChainTypes::Testnet1 {
genesis_block = Some(genesis::genesis_testnet1());
} else {
genesis_block = pow::mine_genesis_block(config.mining_config.clone());
}
}
let shared_chain = Arc::new(chain::Chain::init(

View file

@ -21,7 +21,7 @@ use pool;
use store;
use pow;
use wallet;
use core::global::MiningParameterMode;
use core::global::ChainTypes;
/// Error type wrapping underlying module errors.
#[derive(Debug)]
@ -91,8 +91,8 @@ pub struct ServerConfig {
/// Network address for the Rest API HTTP server.
pub api_http_addr: String,
/// Setup the server for tests and testnet
pub mining_parameter_mode: Option<MiningParameterMode>,
/// Setup the server for tests, testnet or mainnet
pub chain_type: Option<ChainTypes>,
/// Method used to get the list of seed nodes for initial bootstrap.
pub seeding_type: Seeding,
@ -125,7 +125,7 @@ impl Default for ServerConfig {
seeds: None,
p2p_config: Some(p2p::P2PConfig::default()),
mining_config: Some(pow::types::MinerConfig::default()),
mining_parameter_mode: Some(MiningParameterMode::Production),
chain_type: Some(ChainTypes::Testnet1),
pool_config: pool::PoolConfig::default(),
}
}

View file

@ -41,7 +41,7 @@ use tokio_timer::Timer;
use core::consensus;
use core::global;
use core::global::{MiningParameterMode, MINING_PARAMETER_MODE};
use core::global::ChainTypes;
use wallet::WalletConfig;
use framework::{LocalServerContainer, LocalServerContainerConfig, LocalServerContainerPool,
@ -51,7 +51,7 @@ use framework::{LocalServerContainer, LocalServerContainerConfig, LocalServerCon
/// Block and mining into a wallet for a bit
#[test]
fn basic_genesis_mine() {
global::set_mining_mode(MiningParameterMode::AutomatedTesting);
global::set_mining_mode(ChainTypes::AutomatedTesting);
let test_name_dir = "genesis_mine";
framework::clean_all_output(test_name_dir);
@ -80,7 +80,7 @@ fn basic_genesis_mine() {
/// messages they all end up connected.
#[test]
fn simulate_seeding() {
global::set_mining_mode(MiningParameterMode::AutomatedTesting);
global::set_mining_mode(ChainTypes::AutomatedTesting);
let test_name_dir = "simulate_seeding";
framework::clean_all_output(test_name_dir);
@ -133,7 +133,7 @@ fn simulate_seeding() {
//#[test]
#[allow(dead_code)]
fn simulate_parallel_mining() {
global::set_mining_mode(MiningParameterMode::AutomatedTesting);
global::set_mining_mode(ChainTypes::AutomatedTesting);
let test_name_dir = "simulate_parallel_mining";
// framework::clean_all_output(test_name_dir);
@ -187,7 +187,7 @@ fn simulate_parallel_mining() {
#[test]
fn a_simulate_block_propagation() {
util::init_test_logger();
global::set_mining_mode(MiningParameterMode::AutomatedTesting);
global::set_mining_mode(ChainTypes::AutomatedTesting);
let test_name_dir = "grin-prop";
framework::clean_all_output(test_name_dir);
@ -246,7 +246,7 @@ fn a_simulate_block_propagation() {
#[test]
fn simulate_full_sync() {
util::init_test_logger();
global::set_mining_mode(MiningParameterMode::AutomatedTesting);
global::set_mining_mode(ChainTypes::AutomatedTesting);
let test_name_dir = "grin-sync";
framework::clean_all_output(test_name_dir);

View file

@ -608,7 +608,7 @@ mod tests {
use keychain::Keychain;
use std::sync::{Arc, RwLock};
use blake2;
use core::global::MiningParameterMode;
use core::global::ChainTypes;
use core::core::SwitchCommitHash;
macro_rules! expect_output_parent {
@ -795,7 +795,7 @@ mod tests {
#[test]
fn test_immature_coinbase() {
global::set_mining_mode(MiningParameterMode::AutomatedTesting);
global::set_mining_mode(ChainTypes::AutomatedTesting);
let mut dummy_chain = DummyChainImpl::new();
let coinbase_output = test_coinbase_output(15);
dummy_chain.update_utxo_set(DummyUtxoSet::empty().with_output(coinbase_output));

View file

@ -94,12 +94,10 @@ pub fn pow20<T: MiningWorker>(
}
/// Mines a genesis block, using the config specified miner if specified.
/// Otherwise,
/// uses the internal miner
///
/// Otherwise, uses the internal miner
pub fn mine_genesis_block(miner_config: Option<types::MinerConfig>) -> Option<core::core::Block> {
info!(util::LOGGER, "Genesis block not found, initializing...");
let mut gen = genesis::genesis();
let mut gen = genesis::genesis_dev();
let diff = gen.header.difficulty.clone();
let sz = global::sizeshift() as u32;
@ -120,9 +118,8 @@ pub fn mine_genesis_block(miner_config: Option<types::MinerConfig>) -> Option<co
}
/// 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...
/// Mining Worker, until the required difficulty target is reached. May take a
/// while for a low target...
pub fn pow_size<T: MiningWorker + ?Sized>(
miner: &mut T,
bh: &mut BlockHeader,
@ -131,42 +128,36 @@ pub fn pow_size<T: MiningWorker + ?Sized>(
) -> Result<(), Error> {
let start_nonce = bh.nonce;
// try the pre-mined solution first for the genesis block (height 0)
if bh.height == 0 {
if global::is_production_mode() || global::is_user_testing_mode() {
let p = Proof::new(global::get_genesis_pow().to_vec());
if p.clone().to_difficulty() >= diff {
bh.pow = p;
return Ok(());
}
}
// set the nonce for faster solution finding in user testing
if bh.height == 0 && global::is_user_testing_mode() {
bh.nonce = global::get_genesis_nonce();
}
// try to find a cuckoo cycle on that header hash
loop {
// can be trivially optimized by avoiding re-serialization every time but this
// is not meant as a fast miner implementation
let pow_hash = bh.hash();
// try to find a cuckoo cycle on that header hash
loop {
// can be trivially optimized by avoiding re-serialization every time but this
// is not meant as a fast miner implementation
let pow_hash = bh.hash();
// if we found a cycle (not guaranteed) and the proof hash is higher that the
// diff, we're all good
// if we found a cycle (not guaranteed) and the proof hash is higher that the
// diff, we're all good
if let Ok(proof) = miner.mine(&pow_hash[..]) {
if proof.clone().to_difficulty() >= diff {
bh.pow = proof;
return Ok(());
}
}
if let Ok(proof) = miner.mine(&pow_hash[..]) {
if proof.clone().to_difficulty() >= diff {
bh.pow = proof;
return Ok(());
}
}
// otherwise increment the nonce
bh.nonce += 1;
// otherwise increment the nonce
bh.nonce += 1;
// and if we're back where we started, update the time (changes the hash as
// well)
if bh.nonce == start_nonce {
bh.timestamp = time::at_utc(time::Timespec { sec: 0, nsec: 0 });
}
}
// and if we're back where we started, update the time (changes the hash as
// well)
if bh.nonce == start_nonce {
bh.timestamp = time::at_utc(time::Timespec { sec: 0, nsec: 0 });
}
}
}
#[cfg(test)]
@ -176,14 +167,13 @@ mod test {
use core::core::target::Difficulty;
use core::genesis;
use core::consensus::MINIMUM_DIFFICULTY;
use core::global::MiningParameterMode;
use core::global::ChainTypes;
#[test]
fn genesis_pow() {
global::set_mining_mode(MiningParameterMode::AutomatedTesting);
let mut b = genesis::genesis();
b.header.nonce = 310;
global::set_mining_mode(ChainTypes::AutomatedTesting);
let mut b = genesis::genesis_dev();
b.header.nonce = 485;
let mut internal_miner = cuckoo::Miner::new(
consensus::EASINESS,
global::sizeshift() as u32,

View file

@ -57,7 +57,7 @@ fn start_from_config_file(mut global_config: GlobalConfig) {
.unwrap()
.server
.clone()
.mining_parameter_mode
.chain_type
.unwrap(),
);
@ -102,7 +102,7 @@ fn main() {
.unwrap()
.server
.clone()
.mining_parameter_mode
.chain_type
.unwrap(),
);
} else {