diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index b65bdfd4d..1a437bfac 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -16,7 +16,6 @@ //! Blockchain database client. -use std::marker::PhantomData; use std::path::PathBuf; use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrdering}; use util::*; @@ -30,7 +29,8 @@ use engine::Engine; use views::HeaderView; use service::{NetSyncMessage, SyncMessage}; use env_info::LastHashes; -use verification::*; +use verification; +use verification::{PreverifiedBlock, Verifier}; use block::*; use transaction::{LocalizedTransaction, SignedTransaction, Action}; use blockchain::extras::TransactionAddress; @@ -83,7 +83,7 @@ impl ClientReport { /// Blockchain database client backed by a persistent database. Owns and manages a blockchain and a block queue. /// Call `import_block()` to import a block asynchronously; `flush_queue()` flushes the queue. -pub struct Client where V: Verifier { +pub struct Client { chain: Arc, tracedb: Arc>, engine: Arc>, @@ -92,7 +92,7 @@ pub struct Client where V: Verifier { report: RwLock, import_lock: Mutex<()>, panic_handler: Arc, - verifier: PhantomData, + verifier: Box, vm_factory: Arc, miner: Arc, io_channel: IoChannel, @@ -107,13 +107,6 @@ const HISTORY: u64 = 1200; // of which you actually want force an upgrade. const CLIENT_DB_VER_STR: &'static str = "5.3"; -impl Client { - /// Create a new client with given spec and DB path. - pub fn new(config: ClientConfig, spec: Spec, path: &Path, miner: Arc, message_channel: IoChannel ) -> Result, ClientError> { - Client::::new_with_verifier(config, spec, path, miner, message_channel) - } -} - /// Get the path for the databases given the root path and information on the databases. pub fn get_db_path(path: &Path, pruning: journaldb::Algorithm, genesis_hash: H256) -> PathBuf { let mut dir = path.to_path_buf(); @@ -131,15 +124,15 @@ pub fn append_path(path: &Path, item: &str) -> String { p.to_str().unwrap().to_owned() } -impl Client where V: Verifier { +impl Client { /// Create a new client with given spec and DB path and custom verifier. - pub fn new_with_verifier( + pub fn new( config: ClientConfig, spec: Spec, path: &Path, miner: Arc, message_channel: IoChannel) - -> Result>, ClientError> + -> Result, ClientError> { let path = get_db_path(path, config.pruning, spec.genesis_header().hash()); let gb = spec.genesis_block(); @@ -180,7 +173,7 @@ impl Client where V: Verifier { report: RwLock::new(Default::default()), import_lock: Mutex::new(()), panic_handler: panic_handler, - verifier: PhantomData, + verifier: verification::new(config.verifier_type), vm_factory: Arc::new(EvmFactory::new(config.vm_type)), miner: miner, io_channel: message_channel, @@ -222,7 +215,7 @@ impl Client where V: Verifier { } // Verify Block Family - let verify_family_result = V::verify_block_family(&header, &block.bytes, engine, self.chain.deref()); + let verify_family_result = self.verifier.verify_block_family(&header, &block.bytes, engine, self.chain.deref()); if let Err(e) = verify_family_result { warn!(target: "client", "Stage 3 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); return Err(()); @@ -248,7 +241,7 @@ impl Client where V: Verifier { // Final Verification let locked_block = enact_result.unwrap(); - if let Err(e) = V::verify_block_final(&header, locked_block.block().header()) { + if let Err(e) = self.verifier.verify_block_final(&header, locked_block.block().header()) { warn!(target: "client", "Stage 4 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); return Err(()); } @@ -483,7 +476,7 @@ impl Client where V: Verifier { } } -impl BlockChainClient for Client where V: Verifier { +impl BlockChainClient for Client { fn call(&self, t: &SignedTransaction, analytics: CallAnalytics) -> Result { let header = self.block_header(BlockID::Latest).unwrap(); let view = HeaderView::new(&header); @@ -806,7 +799,7 @@ impl BlockChainClient for Client where V: Verifier { } } -impl MiningBlockChainClient for Client where V: Verifier { +impl MiningBlockChainClient for Client { fn prepare_open_block(&self, author: Address, gas_range_target: (U256, U256), extra_data: Bytes) -> OpenBlock { let engine = self.engine.deref().deref(); let h = self.chain.best_block_hash(); diff --git a/ethcore/src/client/config.rs b/ethcore/src/client/config.rs index 7d7f8e524..52a875a2f 100644 --- a/ethcore/src/client/config.rs +++ b/ethcore/src/client/config.rs @@ -18,6 +18,7 @@ pub use block_queue::BlockQueueConfig; pub use blockchain::Config as BlockChainConfig; pub use trace::{Config as TraceConfig, Switch}; pub use evm::VMType; +pub use verification::VerifierType; use util::journaldb; /// Client state db compaction profile @@ -52,4 +53,6 @@ pub struct ClientConfig { pub db_cache_size: Option, /// State db compaction profile pub db_compaction: DatabaseCompactionProfile, + /// Type of block verifier used by client. + pub verifier_type: VerifierType, } diff --git a/ethcore/src/verification/canon_verifier.rs b/ethcore/src/verification/canon_verifier.rs index 30e368f1b..e0ebf1b7c 100644 --- a/ethcore/src/verification/canon_verifier.rs +++ b/ethcore/src/verification/canon_verifier.rs @@ -24,11 +24,11 @@ use super::verification; pub struct CanonVerifier; impl Verifier for CanonVerifier { - fn verify_block_family(header: &Header, bytes: &[u8], engine: &Engine, bc: &BlockProvider) -> Result<(), Error> { + fn verify_block_family(&self, header: &Header, bytes: &[u8], engine: &Engine, bc: &BlockProvider) -> Result<(), Error> { verification::verify_block_family(header, bytes, engine, bc) } - fn verify_block_final(expected: &Header, got: &Header) -> Result<(), Error> { + fn verify_block_final(&self, expected: &Header, got: &Header) -> Result<(), Error> { verification::verify_block_final(expected, got) } } diff --git a/ethcore/src/verification/mod.rs b/ethcore/src/verification/mod.rs index fe1f406cc..10aee21f4 100644 --- a/ethcore/src/verification/mod.rs +++ b/ethcore/src/verification/mod.rs @@ -17,11 +17,32 @@ pub mod verification; pub mod verifier; mod canon_verifier; -#[cfg(test)] mod noop_verifier; pub use self::verification::*; pub use self::verifier::Verifier; pub use self::canon_verifier::CanonVerifier; -#[cfg(test)] pub use self::noop_verifier::NoopVerifier; + +/// Verifier type. +#[derive(Debug)] +pub enum VerifierType { + /// Verifies block normally. + Canon, + /// Does not verify block at all. + /// Used in tests. + Noop, +} + +impl Default for VerifierType { + fn default() -> Self { + VerifierType::Canon + } +} + +pub fn new(v: VerifierType) -> Box { + match v { + VerifierType::Canon => Box::new(CanonVerifier), + VerifierType::Noop => Box::new(NoopVerifier), + } +} diff --git a/ethcore/src/verification/noop_verifier.rs b/ethcore/src/verification/noop_verifier.rs index 20c15c3f1..99d1d594c 100644 --- a/ethcore/src/verification/noop_verifier.rs +++ b/ethcore/src/verification/noop_verifier.rs @@ -24,11 +24,11 @@ use super::Verifier; pub struct NoopVerifier; impl Verifier for NoopVerifier { - fn verify_block_family(_header: &Header, _bytes: &[u8], _engine: &Engine, _bc: &BlockProvider) -> Result<(), Error> { + fn verify_block_family(&self, _header: &Header, _bytes: &[u8], _engine: &Engine, _bc: &BlockProvider) -> Result<(), Error> { Ok(()) } - fn verify_block_final(_expected: &Header, _got: &Header) -> Result<(), Error> { + fn verify_block_final(&self, _expected: &Header, _got: &Header) -> Result<(), Error> { Ok(()) } } diff --git a/ethcore/src/verification/verifier.rs b/ethcore/src/verification/verifier.rs index cc5edce29..5db81a4eb 100644 --- a/ethcore/src/verification/verifier.rs +++ b/ethcore/src/verification/verifier.rs @@ -21,6 +21,6 @@ use header::Header; /// Should be used to verify blocks. pub trait Verifier: Send + Sync { - fn verify_block_family(header: &Header, bytes: &[u8], engine: &Engine, bc: &BlockProvider) -> Result<(), Error>; - fn verify_block_final(expected: &Header, got: &Header) -> Result<(), Error>; + fn verify_block_family(&self, header: &Header, bytes: &[u8], engine: &Engine, bc: &BlockProvider) -> Result<(), Error>; + fn verify_block_final(&self, expected: &Header, got: &Header) -> Result<(), Error>; }