Several bug fixes to the miner loop. Now builds the block properly and updates the shared head state.

This commit is contained in:
Ignotus Peverell 2016-12-20 17:36:48 -08:00
parent 57eb7ad0a9
commit 17104977de
No known key found for this signature in database
GPG key ID: 99CD25F39F8F8211

View file

@ -20,6 +20,7 @@ use std::sync::{Arc, Mutex};
use std::ops::Deref; use std::ops::Deref;
use time; use time;
use adapters::ChainToNetAdapter;
use core::consensus; use core::consensus;
use core::core; use core::core;
use core::core::hash::{Hash, Hashed}; use core::core::hash::{Hash, Hashed};
@ -31,15 +32,21 @@ use secp;
pub struct Miner { pub struct Miner {
chain_head: Arc<Mutex<chain::Tip>>, chain_head: Arc<Mutex<chain::Tip>>,
chain_store: Arc<chain::ChainStore>, chain_store: Arc<chain::ChainStore>,
/// chain adapter to net
chain_adapter: Arc<ChainToNetAdapter>,
} }
impl Miner { impl Miner {
/// Creates a new Miner. Needs references to the chain state and its /// Creates a new Miner. Needs references to the chain state and its
/// storage. /// storage.
pub fn new(chain_head: Arc<Mutex<chain::Tip>>, chain_store: Arc<chain::ChainStore>) -> Miner { pub fn new(chain_head: Arc<Mutex<chain::Tip>>,
chain_store: Arc<chain::ChainStore>,
chain_adapter: Arc<ChainToNetAdapter>)
-> Miner {
Miner { Miner {
chain_head: chain_head, chain_head: chain_head,
chain_store: chain_store, chain_store: chain_store,
chain_adapter: chain_adapter,
} }
} }
@ -55,15 +62,17 @@ impl Miner {
head = self.chain_store.head_header().unwrap(); head = self.chain_store.head_header().unwrap();
latest_hash = self.chain_head.lock().unwrap().last_block_h; latest_hash = self.chain_head.lock().unwrap().last_block_h;
} }
let b = self.build_block(&head); let mut b = self.build_block(&head);
let mut pow_header = pow::PowHeader::from_block(&b); let mut pow_header = pow::PowHeader::from_block(&b);
// 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 + 2;
let mut sol = None; let mut sol = None;
debug!("Mining at Cuckoo{} for at most 2 secs.", debug!("Mining at Cuckoo{} for at most 2 secs on block {}.",
b.header.cuckoo_len); b.header.cuckoo_len,
latest_hash);
let mut iter_count = 0;
while head.hash() == latest_hash && time::get_time().sec < deadline { while head.hash() == latest_hash && time::get_time().sec < deadline {
let pow_hash = pow_header.hash(); let pow_hash = pow_header.hash();
let mut miner = cuckoo::Miner::new(pow_hash.to_slice(), let mut miner = cuckoo::Miner::new(pow_hash.to_slice(),
@ -79,16 +88,28 @@ impl Miner {
{ {
latest_hash = self.chain_head.lock().unwrap().last_block_h; latest_hash = self.chain_head.lock().unwrap().last_block_h;
} }
iter_count += 1;
} }
// 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!("Found valid proof of work, adding block {}.", b.hash()); info!("Found valid proof of work, adding block {}.", b.hash());
if let Err(e) = chain::process_block(&b, self.chain_store.clone(), chain::NONE) { b.header.pow = proof;
b.header.nonce = pow_header.nonce;
let res = chain::process_block(&b,
self.chain_store.clone(),
self.chain_adapter.clone(),
chain::NONE);
if let Err(e) = res {
error!("Error validating mined block: {:?}", e); error!("Error validating mined block: {:?}", e);
} else if let Ok(Some(tip)) = res {
let chain_head = self.chain_head.clone();
let mut head = chain_head.lock().unwrap();
*head = tip;
} }
} else { } else {
debug!("No solution found, continuing...") debug!("No solution found after {} iterations, continuing...",
iter_count)
} }
} }
} }
@ -110,19 +131,11 @@ impl Miner {
let skey = secp::key::SecretKey::new(&secp_inst, &mut rng); let skey = secp::key::SecretKey::new(&secp_inst, &mut rng);
// TODO populate inputs and outputs from pool transactions // TODO populate inputs and outputs from pool transactions
core::Block { let mut b = core::Block::new(head, vec![], skey).unwrap();
header: core::BlockHeader { b.header.nonce = rng.gen();
height: head.height + 1, b.header.target = target;
previous: head.hash(), b.header.cuckoo_len = cuckoo_len;
timestamp: time::at(time::Timespec::new(now_sec, 0)), b.header.timestamp = time::at(time::Timespec::new(now_sec, 0));
cuckoo_len: cuckoo_len, b
target: target,
nonce: rng.gen(),
..Default::default()
},
inputs: vec![],
outputs: vec![],
proofs: vec![],
}
} }
} }