diff --git a/ethcore/src/client.rs b/ethcore/src/client.rs index 422f1eaa2..6ae628f8b 100644 --- a/ethcore/src/client.rs +++ b/ethcore/src/client.rs @@ -16,6 +16,7 @@ //! Blockchain database client. +use std::marker::PhantomData; use util::*; use util::panics::*; use blockchain::{BlockChain, BlockProvider}; @@ -188,7 +189,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 { +pub struct Client where V: Verifier { chain: Arc>, engine: Arc>, state_db: Mutex, @@ -201,14 +202,22 @@ pub struct Client { sealing_block: Mutex>, author: RwLock
, extra_data: RwLock, + verifier: PhantomData } const HISTORY: u64 = 1000; const CLIENT_DB_VER_STR: &'static str = "4.0"; -impl Client { +impl Client { /// Create a new client with given spec and DB path. pub fn new(config: ClientConfig, spec: Spec, path: &Path, message_channel: IoChannel ) -> Result, Error> { + Client::::new_with_verifier(config, spec, path, message_channel) + } +} + +impl Client where V: Verifier { + /// Create a new client with given spec and DB path and custom verifier. + pub fn new_with_verifier(config: ClientConfig, spec: Spec, path: &Path, message_channel: IoChannel ) -> Result, Error> { let mut dir = path.to_path_buf(); dir.push(H64::from(spec.genesis_header().hash()).hex()); //TODO: sec/fat: pruned/full versioning @@ -240,6 +249,7 @@ impl Client { sealing_block: Mutex::new(None), author: RwLock::new(Address::new()), extra_data: RwLock::new(Vec::new()), + verifier: PhantomData })) } @@ -302,7 +312,7 @@ impl Client { // Final Verification let closed_block = enact_result.unwrap(); - if let Err(e) = verify_block_final(&header, closed_block.block().header()) { + if let Err(e) = V::verify_block_final(&header, closed_block.block().header()) { warn!(target: "client", "Stage 4 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); return Err(()); } @@ -503,7 +513,7 @@ impl Client { // TODO: need MinerService MinerIoHandler -impl BlockChainClient for Client { +impl BlockChainClient for Client where V: Verifier { fn block_header(&self, id: BlockId) -> Option { let chain = self.chain.read().unwrap(); Self::block_hash(&chain, id).and_then(|hash| chain.block(&hash).map(|bytes| BlockView::new(&bytes).rlp().at(0).as_raw().to_vec())) diff --git a/ethcore/src/verification/canon_verifier.rs b/ethcore/src/verification/canon_verifier.rs new file mode 100644 index 000000000..0d9cbc6b6 --- /dev/null +++ b/ethcore/src/verification/canon_verifier.rs @@ -0,0 +1,28 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +use error::Error; +use header::Header; +use super::Verifier; +use super::verification; + +pub struct CanonVerifier; + +impl Verifier for CanonVerifier { + fn verify_block_final(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 new file mode 100644 index 000000000..260121989 --- /dev/null +++ b/ethcore/src/verification/mod.rs @@ -0,0 +1,25 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +pub mod verification; +pub mod verifier; +mod canon_verifier; +mod noop_verifier; + +pub use self::verification::*; +pub use self::verifier::Verifier; +pub use self::canon_verifier::CanonVerifier; +pub use self::noop_verifier::NoopVerifier; diff --git a/ethcore/src/verification/noop_verifier.rs b/ethcore/src/verification/noop_verifier.rs new file mode 100644 index 000000000..8dfd64771 --- /dev/null +++ b/ethcore/src/verification/noop_verifier.rs @@ -0,0 +1,27 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +use error::Error; +use header::Header; +use super::Verifier; + +pub struct NoopVerifier; + +impl Verifier for NoopVerifier { + fn verify_block_final(_expected: &Header, _got: &Header) -> Result<(), Error> { + Ok(()) + } +} diff --git a/ethcore/src/verification.rs b/ethcore/src/verification/verification.rs similarity index 99% rename from ethcore/src/verification.rs rename to ethcore/src/verification/verification.rs index f52e2e1e4..fa540e7c6 100644 --- a/ethcore/src/verification.rs +++ b/ethcore/src/verification/verification.rs @@ -61,7 +61,7 @@ pub fn verify_block_unordered(header: Header, bytes: Bytes, engine: &Engine) -> for u in Rlp::new(&bytes).at(2).iter().map(|rlp| rlp.as_val::
()) { try!(engine.verify_block_unordered(&u, None)); } - // Verify transactions. + // Verify transactions. let mut transactions = Vec::new(); { let v = BlockView::new(&bytes); @@ -141,7 +141,7 @@ pub fn verify_block_family(header: &Header, bytes: &[u8], engine: &Engine, b let uncle_parent = try!(bc.block_header(&uncle.parent_hash).ok_or_else(|| Error::from(BlockError::UnknownUncleParent(uncle.parent_hash.clone())))); for _ in 0..depth { match bc.block_details(&expected_uncle_parent) { - Some(details) => { + Some(details) => { expected_uncle_parent = details.parent; }, None => break @@ -468,7 +468,7 @@ mod tests { header.number = 9; check_fail(family_test(&create_test_block_with_data(&header, &good_transactions, &good_uncles), engine.deref(), &bc), InvalidNumber(Mismatch { expected: parent.number + 1, found: header.number })); - + header = good.clone(); let mut bad_uncles = good_uncles.clone(); bad_uncles.push(good_uncle1.clone()); diff --git a/ethcore/src/verification/verifier.rs b/ethcore/src/verification/verifier.rs new file mode 100644 index 000000000..0ffbf3bdd --- /dev/null +++ b/ethcore/src/verification/verifier.rs @@ -0,0 +1,23 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +use error::Error; +use header::Header; + +/// Should be used to verify blocks. +pub trait Verifier: Send + Sync { + fn verify_block_final(expected: &Header, got: &Header) -> Result<(), Error>; +}