Refactored and optimized signings.
This commit is contained in:
+36
-7
@@ -19,7 +19,6 @@ use std::cmp::max;
|
||||
use crate::blockchain::transaction::{ZoneData, DomainData};
|
||||
use std::ops::Deref;
|
||||
use crate::blockchain::types::MineResult::*;
|
||||
use crate::event::Event;
|
||||
|
||||
const DB_NAME: &str = "blockchain.db";
|
||||
const TEMP_DB_NAME: &str = "temp.db";
|
||||
@@ -57,6 +56,7 @@ pub struct Chain {
|
||||
max_height: u64,
|
||||
db: Connection,
|
||||
zones: RefCell<HashSet<String>>,
|
||||
signers: RefCell<SignersCache>,
|
||||
}
|
||||
|
||||
impl Chain {
|
||||
@@ -65,7 +65,7 @@ impl Chain {
|
||||
|
||||
let db = sqlite::open(DB_NAME).expect("Unable to open blockchain DB");
|
||||
let zones = RefCell::new(HashSet::new());
|
||||
let mut chain = Chain { origin, last_block: None, last_full_block: None, max_height: 0, db, zones };
|
||||
let mut chain = Chain { origin, last_block: None, last_full_block: None, max_height: 0, db, zones, signers: SignersCache::new() };
|
||||
chain.init_db();
|
||||
chain
|
||||
}
|
||||
@@ -262,7 +262,7 @@ impl Chain {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn update(&mut self, keystore: &Option<Keystore>) -> Option<Event> {
|
||||
pub fn get_sign_block(&self, keystore: &Option<Keystore>) -> Option<Block> {
|
||||
if self.get_height() < BLOCK_SIGNERS_START {
|
||||
trace!("Too early to start block signings");
|
||||
return None;
|
||||
@@ -292,6 +292,11 @@ impl Chain {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
let (last_hash, last_index) = match &self.last_block {
|
||||
Some(block) => (block.hash.clone(), block.index),
|
||||
None => { return None; }
|
||||
};
|
||||
|
||||
let keystore = keystore.clone().unwrap().clone();
|
||||
let signers: HashSet<Bytes> = self.get_block_signers(&block).into_iter().collect();
|
||||
if signers.contains(&keystore.get_public()) {
|
||||
@@ -304,10 +309,9 @@ impl Chain {
|
||||
}
|
||||
|
||||
info!("We have an honor to mine signing block!");
|
||||
let keystore = Box::new(keystore);
|
||||
// We start mining sign block after some time, not everyone in the same time
|
||||
let start = Utc::now().timestamp() + (rand::random::<i64>() % BLOCK_SIGNERS_START_RANDOM);
|
||||
return Some(Event::ActionMineSigning { start, index: block.index + 1, hash: block.hash, keystore });
|
||||
let mut block = Block::new(None, Bytes::default(), last_hash, SIGNER_DIFFICULTY);
|
||||
block.index = last_index + 1;
|
||||
return Some(block);
|
||||
} else if !signers.is_empty() {
|
||||
info!("Signing block must be mined by other nodes");
|
||||
}
|
||||
@@ -973,6 +977,12 @@ impl Chain {
|
||||
if block.index < BLOCK_SIGNERS_START || self.get_height() < block.index {
|
||||
return result;
|
||||
}
|
||||
|
||||
assert!(block.transaction.is_some());
|
||||
if self.signers.borrow().has_signers_for(block.index) {
|
||||
return self.signers.borrow().signers.clone();
|
||||
}
|
||||
|
||||
let mut set = HashSet::new();
|
||||
let tail = block.signature.get_tail_u64();
|
||||
let mut count = 1;
|
||||
@@ -988,6 +998,9 @@ impl Chain {
|
||||
count += 1;
|
||||
}
|
||||
trace!("Got signers for block {}: {:?}", block.index, &result);
|
||||
let mut signers = self.signers.borrow_mut();
|
||||
signers.index = block.index;
|
||||
signers.signers = result.clone();
|
||||
result
|
||||
}
|
||||
|
||||
@@ -1005,4 +1018,20 @@ impl Chain {
|
||||
let signature = Bytes::from_bytes(statement.read::<Vec<u8>>(10).unwrap().as_slice());
|
||||
Some(Block::from_all_params(index, timestamp, version, difficulty, random, nonce, prev_block_hash, hash, pub_key, signature, transaction))
|
||||
}
|
||||
}
|
||||
|
||||
struct SignersCache {
|
||||
index: u64,
|
||||
signers: Vec<Bytes>
|
||||
}
|
||||
|
||||
impl SignersCache {
|
||||
pub fn new() -> RefCell<SignersCache> {
|
||||
let cache = SignersCache { index: 0, signers: Vec::new() };
|
||||
RefCell::new(cache)
|
||||
}
|
||||
|
||||
pub fn has_signers_for(&self, index: u64) -> bool {
|
||||
self.index == index && !self.signers.is_empty()
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||
use crate::{Bytes, Keystore};
|
||||
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
pub enum Event {
|
||||
MinerStarted,
|
||||
@@ -13,7 +11,6 @@ pub enum Event {
|
||||
NewBlockReceived,
|
||||
BlockchainChanged { index: u64 },
|
||||
ActionStopMining,
|
||||
ActionMineSigning { start: i64, index: u64, hash: Bytes, keystore: Box<Keystore> },
|
||||
ActionQuit,
|
||||
NetworkStatus { nodes: usize, blocks: u64 },
|
||||
Syncing { have: u64, height: u64 },
|
||||
|
||||
+13
-17
@@ -9,13 +9,12 @@ use log::{debug, error, info, trace, warn};
|
||||
use num_cpus;
|
||||
|
||||
use crate::{Block, Bytes, Context, Keystore, setup_miner_thread};
|
||||
use crate::commons::{CHAIN_VERSION, SIGNER_DIFFICULTY, KEYSTORE_DIFFICULTY};
|
||||
use crate::commons::*;
|
||||
use crate::blockchain::types::BlockQuality;
|
||||
use crate::blockchain::hash_utils::*;
|
||||
use crate::keys::check_public_key_strength;
|
||||
use crate::event::Event;
|
||||
use blakeout::Blakeout;
|
||||
use std::ops::Deref;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct MineJob {
|
||||
@@ -74,7 +73,7 @@ impl Miner {
|
||||
let cond_var = self.cond_var.clone();
|
||||
thread::spawn(move || {
|
||||
running.store(true, Ordering::SeqCst);
|
||||
let delay = Duration::from_millis(1000);
|
||||
let delay = Duration::from_secs(30);
|
||||
while running.load(Ordering::SeqCst) {
|
||||
// If some transaction is being mined now, we yield
|
||||
if mining.load(Ordering::SeqCst) {
|
||||
@@ -92,16 +91,22 @@ impl Miner {
|
||||
} else {
|
||||
debug!("This job will wait for now");
|
||||
jobs.insert(0, job);
|
||||
let _ = cond_var.wait_timeout(jobs, delay).expect("Error in wait lock!");
|
||||
}
|
||||
} else {
|
||||
let _ = cond_var.wait(jobs).expect("Error in wait lock!");
|
||||
} else if !mining.load(Ordering::SeqCst) {
|
||||
if let Ok(context) = context.try_lock() {
|
||||
let keystore = context.get_keystore();
|
||||
if let Some(block) = context.chain.get_sign_block(&keystore) {
|
||||
info!("Got signing job, adding to queue");
|
||||
// We start mining sign block after some time, not everyone in the same time
|
||||
let start = Utc::now().timestamp() + (rand::random::<i64>() % BLOCK_SIGNERS_START_RANDOM);
|
||||
jobs.push(MineJob { start, block, keystore: keystore.unwrap() });
|
||||
}
|
||||
}
|
||||
}
|
||||
let _ = cond_var.wait_timeout(jobs, delay).expect("Error in wait lock!");
|
||||
}
|
||||
});
|
||||
let mining = self.mining.clone();
|
||||
let jobs = self.jobs.clone();
|
||||
let cond_var = self.cond_var.clone();
|
||||
self.context.lock().unwrap().bus.register(move |_uuid, e| {
|
||||
match e {
|
||||
Event::NewBlockReceived => {}
|
||||
@@ -109,15 +114,6 @@ impl Miner {
|
||||
Event::ActionStopMining => {
|
||||
mining.store(false, Ordering::SeqCst);
|
||||
}
|
||||
Event::ActionMineSigning { start, index, hash, keystore } => {
|
||||
if !mining.load(Ordering::SeqCst) {
|
||||
let mut block = Block::new(None, Bytes::default(), hash, SIGNER_DIFFICULTY);
|
||||
block.index = index;
|
||||
jobs.lock().unwrap().push(MineJob { start, block, keystore: keystore.deref().clone() });
|
||||
cond_var.notify_all();
|
||||
info!("Added a signing block to mine");
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
true
|
||||
|
||||
@@ -66,8 +66,6 @@ impl Network {
|
||||
let mut log_timer = Instant::now();
|
||||
let mut bootstrap_timer = Instant::now();
|
||||
let mut last_events_time = Instant::now();
|
||||
let mut sent_mining_event_index = 0u64;
|
||||
let mut sent_mining_event_time = Instant::now();
|
||||
loop {
|
||||
if peers.get_peers_count() == 0 && bootstrap_timer.elapsed().as_secs() > 60 {
|
||||
// Starting peer connections to bootstrap nodes
|
||||
@@ -166,16 +164,6 @@ impl Network {
|
||||
warn!("Last network events time {} seconds ago", elapsed);
|
||||
}
|
||||
log_timer = Instant::now();
|
||||
let mining = context.miner_state.mining;
|
||||
if !mining && (sent_mining_event_index < height || sent_mining_event_time.elapsed().as_secs() >= 600) {
|
||||
let keystore = context.keystore.clone();
|
||||
if let Some(event) = context.chain.update(&keystore) {
|
||||
context.bus.post(event);
|
||||
trace!("Posted an event to mine signing block");
|
||||
sent_mining_event_index = height;
|
||||
sent_mining_event_time = Instant::now();
|
||||
}
|
||||
}
|
||||
}
|
||||
(height, context.chain.last_hash())
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user