From 7270bba43cca4bcbd369794fd6fa9b7941e2e2c8 Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 29 Nov 2016 17:03:59 +0100 Subject: [PATCH] verification flags --- db/src/lib.rs | 8 +++++ sync/src/synchronization_verifier.rs | 45 +++++----------------------- verification/src/chain_verifier.rs | 45 ++++++++++++++-------------- verification/src/task.rs | 6 ++-- 4 files changed, 43 insertions(+), 61 deletions(-) diff --git a/db/src/lib.rs b/db/src/lib.rs index e49d128b..cc04ad11 100644 --- a/db/src/lib.rs +++ b/db/src/lib.rs @@ -52,6 +52,14 @@ pub enum BlockLocation { Side(u32), } +impl BlockLocation { + pub fn height(&self) -> u32 { + match *self { + BlockLocation::Main(h) | BlockLocation::Side(h) => h, + } + } +} + pub type SharedStore = std::sync::Arc; pub use best_block::BestBlock; diff --git a/sync/src/synchronization_verifier.rs b/sync/src/synchronization_verifier.rs index 1f820151..6ec25810 100644 --- a/sync/src/synchronization_verifier.rs +++ b/sync/src/synchronization_verifier.rs @@ -3,9 +3,9 @@ use std::sync::Arc; use std::sync::mpsc::{channel, Sender, Receiver}; use parking_lot::Mutex; use chain::Transaction; -use network::{Magic, ConsensusParams}; +use network::Magic; use primitives::hash::H256; -use verification::{ChainVerifier, Verify as VerificationVerify}; +use verification::{ChainVerifier, Verify as VerificationVerify, Chain}; use synchronization_chain::ChainRef; use db::IndexedBlock; @@ -58,54 +58,25 @@ impl AsyncVerifier { verification_worker_thread: Some(thread::Builder::new() .name("Sync verification thread".to_string()) .spawn(move || { - AsyncVerifier::verification_worker_proc(sink, chain, network.consensus_params(), verifier, verification_work_receiver) + AsyncVerifier::verification_worker_proc(sink, verifier, verification_work_receiver) }) .expect("Error creating verification thread")) } } /// Thread procedure for handling verification tasks - fn verification_worker_proc(sink: Arc>, chain: ChainRef, consensus_params: ConsensusParams, mut verifier: ChainVerifier, work_receiver: Receiver) { - let bip16_time_border = consensus_params.bip16_time; - let mut is_bip16_active = false; - let mut parameters_change_steps = Some(0); - + fn verification_worker_proc(sink: Arc>, verifier: ChainVerifier, work_receiver: Receiver) { while let Ok(task) = work_receiver.recv() { match task { VerificationTask::VerifyBlock(block) => { - // for changes that are not relying on block# - let is_bip16_active_on_block = block.header().time >= bip16_time_border; - let force_parameters_change = is_bip16_active_on_block != is_bip16_active; - if force_parameters_change { - parameters_change_steps = Some(0); - } - - // change verifier parameters, if needed - if let Some(steps_left) = parameters_change_steps { - if steps_left == 0 { - let best_storage_block = chain.read().best_storage_block(); - - is_bip16_active = is_bip16_active_on_block; - verifier = verifier.verify_p2sh(is_bip16_active); - - let is_bip65_active = best_storage_block.number >= consensus_params.bip65_height; - verifier = verifier.verify_clocktimeverify(is_bip65_active); - - if is_bip65_active { - parameters_change_steps = None; - } else { - parameters_change_steps = Some(consensus_params.bip65_height - best_storage_block.number); - } - } else { - parameters_change_steps = Some(steps_left - 1); - } - } - // verify block match verifier.verify(&block) { - Ok(_chain) => { + Ok(Chain::Main) | Ok(Chain::Side) => { sink.lock().on_block_verification_success(block) }, + Ok(Chain::Orphan) => { + sink.lock().on_block_verification_error("Orphaned block", &block.hash()) + }, Err(e) => { sink.lock().on_block_verification_error(&format!("{:?}", e), &block.hash()) } diff --git a/verification/src/chain_verifier.rs b/verification/src/chain_verifier.rs index 2301f160..3fd5c3b2 100644 --- a/verification/src/chain_verifier.rs +++ b/verification/src/chain_verifier.rs @@ -18,8 +18,8 @@ const TRANSACTIONS_VERIFY_PARALLEL_THRESHOLD: usize = 16; pub struct ChainVerifier { store: db::SharedStore, - verify_p2sh: bool, - verify_clocktimeverify: bool, + //verify_p2sh: bool, + //verify_clocktimeverify: bool, skip_pow: bool, skip_sig: bool, network: Magic, @@ -30,8 +30,8 @@ impl ChainVerifier { pub fn new(store: db::SharedStore, network: Magic) -> Self { ChainVerifier { store: store, - verify_p2sh: false, - verify_clocktimeverify: false, + //verify_p2sh: false, + //verify_clocktimeverify: false, skip_pow: false, skip_sig: false, network: network, @@ -51,14 +51,12 @@ impl ChainVerifier { self } - pub fn verify_p2sh(mut self, verify: bool) -> Self { - self.verify_p2sh = verify; - self + pub fn verify_p2sh(&self, time: u32) -> bool { + time >= self.network.consensus_params().bip16_time } - pub fn verify_clocktimeverify(mut self, verify: bool) -> Self { - self.verify_clocktimeverify = verify; - self + pub fn verify_clocktimeverify(&self, height: u32) -> bool { + height >= self.network.consensus_params().bip65_height } /// Returns previous transaction output. @@ -102,7 +100,7 @@ impl ChainVerifier { fn block_sigops(&self, block: &db::IndexedBlock) -> usize { // strict pay-to-script-hash signature operations count toward block // signature operations limit is enforced with BIP16 - let bip16_active = block.header().time >= self.network.consensus_params().bip16_time; + let bip16_active = self.verify_p2sh(block.header().time); block.transactions().map(|(_, tx)| self.transaction_sigops(block, tx, bip16_active)).sum() } @@ -181,10 +179,11 @@ impl ChainVerifier { Ok(()) } - //block: &db::IndexedBlock, pub fn verify_transaction( &self, prevout_provider: &T, + height: u32, + time: u32, transaction: &chain::Transaction, sequence: usize ) -> Result<(), TransactionError> where T: PreviousTransactionOutputProvider { @@ -220,8 +219,8 @@ impl ChainVerifier { let output: Script = paired_output.script_pubkey.into(); let flags = VerificationFlags::default() - .verify_p2sh(self.verify_p2sh) - .verify_clocktimeverify(self.verify_clocktimeverify); + .verify_p2sh(self.verify_p2sh(time)) + .verify_clocktimeverify(self.verify_clocktimeverify(height)); // for tests only, skips as late as possible if self.skip_sig { continue; } @@ -292,6 +291,11 @@ impl ChainVerifier { return Err(Error::CoinbaseSignatureLength(coinbase_script_len)); } + let location = match self.store.accepted_location(block.header()) { + Some(location) => location, + None => return Ok(Chain::Orphan), + }; + if block.transaction_count() > TRANSACTIONS_VERIFY_PARALLEL_THRESHOLD { // todo: might use on-stack vector (smallvec/elastic array) let mut transaction_tasks: Vec = Vec::with_capacity(TRANSACTIONS_VERIFY_THREADS); @@ -300,7 +304,7 @@ impl ChainVerifier { let from = last; last = ::std::cmp::max(1, block.transaction_count() / TRANSACTIONS_VERIFY_THREADS); if num_task == TRANSACTIONS_VERIFY_THREADS - 1 { last = block.transaction_count(); }; - transaction_tasks.push(Task::new(block, from, last)); + transaction_tasks.push(Task::new(block, location.height(), from, last)); } self.pool.scoped(|scope| { @@ -318,22 +322,19 @@ impl ChainVerifier { } else { for (index, (_, tx)) in block.transactions().enumerate() { - if let Err(tx_err) = self.verify_transaction(block, tx, index) { + if let Err(tx_err) = self.verify_transaction(block, location.height(), block.header().time, tx, index) { return Err(Error::Transaction(index, tx_err)); } } } // todo: pre-process projected block number once verification is parallel! - match self.store.accepted_location(block.header()) { - None => { - Ok(Chain::Orphan) - }, - Some(BlockLocation::Main(block_number)) => { + match location { + BlockLocation::Main(block_number) => { try!(self.ordered_verify(block, block_number)); Ok(Chain::Main) }, - Some(BlockLocation::Side(block_number)) => { + BlockLocation::Side(block_number) => { try!(self.ordered_verify(block, block_number)); Ok(Chain::Side) }, diff --git a/verification/src/task.rs b/verification/src/task.rs index 340223fe..0a7d8bb3 100644 --- a/verification/src/task.rs +++ b/verification/src/task.rs @@ -4,6 +4,7 @@ use db::IndexedBlock; pub struct Task<'a> { block: &'a IndexedBlock, + block_height: u32, from: usize, to: usize, result: Result<(), TransactionCheckError>, @@ -12,9 +13,10 @@ pub struct Task<'a> { type TransactionCheckError = (usize, TransactionError); impl<'a> Task<'a> { - pub fn new(block: &'a IndexedBlock, from: usize, to: usize) -> Self { + pub fn new(block: &'a IndexedBlock, block_height: u32, from: usize, to: usize) -> Self { Task { block: block, + block_height: block_height, from: from, to: to, result: Ok(()), @@ -23,7 +25,7 @@ impl<'a> Task<'a> { pub fn progress(&mut self, verifier: &ChainVerifier) { for index in self.from..self.to { - if let Err(e) = verifier.verify_transaction(self.block, self.block.transaction_at(index).1, index) { + if let Err(e) = verifier.verify_transaction(self.block, self.block_height, self.block.header().time, self.block.transaction_at(index).1, index) { self.result = Err((index, e)) } }