Merge branch 'master' into adaptive_queue_threads
This commit is contained in:
@@ -14,6 +14,8 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Canonical verifier.
|
||||
|
||||
use blockchain::BlockProvider;
|
||||
use engines::Engine;
|
||||
use error::Error;
|
||||
@@ -21,6 +23,7 @@ use header::Header;
|
||||
use super::Verifier;
|
||||
use super::verification;
|
||||
|
||||
/// A canonial verifier -- this does full verification.
|
||||
pub struct CanonVerifier;
|
||||
|
||||
impl Verifier for CanonVerifier {
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Block verification utilities.
|
||||
|
||||
pub mod verification;
|
||||
pub mod verifier;
|
||||
pub mod queue;
|
||||
@@ -31,6 +33,8 @@ pub use self::queue::{BlockQueue, Config as QueueConfig, VerificationQueue, Queu
|
||||
pub enum VerifierType {
|
||||
/// Verifies block normally.
|
||||
Canon,
|
||||
/// Verifies block normallly, but skips seal verification.
|
||||
CanonNoSeal,
|
||||
/// Does not verify block at all.
|
||||
/// Used in tests.
|
||||
Noop,
|
||||
@@ -42,9 +46,20 @@ impl Default for VerifierType {
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new verifier based on type.
|
||||
pub fn new(v: VerifierType) -> Box<Verifier> {
|
||||
match v {
|
||||
VerifierType::Canon => Box::new(CanonVerifier),
|
||||
VerifierType::Canon | VerifierType::CanonNoSeal => Box::new(CanonVerifier),
|
||||
VerifierType::Noop => Box::new(NoopVerifier),
|
||||
}
|
||||
}
|
||||
|
||||
impl VerifierType {
|
||||
/// Check if seal verification is enabled for this verifier type.
|
||||
pub fn verifying_seal(&self) -> bool {
|
||||
match *self {
|
||||
VerifierType::Canon => true,
|
||||
VerifierType::Noop | VerifierType::CanonNoSeal => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,12 +14,15 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! No-op verifier.
|
||||
|
||||
use blockchain::BlockProvider;
|
||||
use engines::Engine;
|
||||
use error::Error;
|
||||
use header::Header;
|
||||
use super::Verifier;
|
||||
|
||||
/// A no-op verifier -- this will verify everything it's given immediately.
|
||||
#[allow(dead_code)]
|
||||
pub struct NoopVerifier;
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ pub trait Kind: 'static + Sized + Send + Sync {
|
||||
fn create(input: Self::Input, engine: &Engine) -> Result<Self::Unverified, Error>;
|
||||
|
||||
/// Attempt to verify the `Unverified` item using the given engine.
|
||||
fn verify(unverified: Self::Unverified, engine: &Engine) -> Result<Self::Verified, Error>;
|
||||
fn verify(unverified: Self::Unverified, engine: &Engine, check_seal: bool) -> Result<Self::Verified, Error>;
|
||||
}
|
||||
|
||||
/// The blocks verification module.
|
||||
@@ -89,9 +89,9 @@ pub mod blocks {
|
||||
}
|
||||
}
|
||||
|
||||
fn verify(un: Self::Unverified, engine: &Engine) -> Result<Self::Verified, Error> {
|
||||
fn verify(un: Self::Unverified, engine: &Engine, check_seal: bool) -> Result<Self::Verified, Error> {
|
||||
let hash = un.hash();
|
||||
match verify_block_unordered(un.header, un.bytes, engine) {
|
||||
match verify_block_unordered(un.header, un.bytes, engine, check_seal) {
|
||||
Ok(verified) => Ok(verified),
|
||||
Err(e) => {
|
||||
warn!(target: "client", "Stage 2 block verification failed for {}: {:?}", hash, e);
|
||||
@@ -176,8 +176,11 @@ pub mod headers {
|
||||
verify_header_params(&input, engine).map(|_| input)
|
||||
}
|
||||
|
||||
fn verify(unverified: Self::Unverified, engine: &Engine) -> Result<Self::Verified, Error> {
|
||||
engine.verify_block_unordered(&unverified, None).map(|_| unverified)
|
||||
fn verify(unverified: Self::Unverified, engine: &Engine, check_seal: bool) -> Result<Self::Verified, Error> {
|
||||
match check_seal {
|
||||
true => engine.verify_block_unordered(&unverified, None).map(|_| unverified),
|
||||
false => Ok(unverified),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,6 +101,13 @@ pub enum Status {
|
||||
Unknown,
|
||||
}
|
||||
|
||||
// the internal queue sizes.
|
||||
struct Sizes {
|
||||
unverified: AtomicUsize,
|
||||
verifying: AtomicUsize,
|
||||
verified: AtomicUsize,
|
||||
}
|
||||
|
||||
/// A queue of items to be verified. Sits between network or other I/O and the `BlockChain`.
|
||||
/// Keeps them in the same order as inserted, minus invalid items.
|
||||
pub struct VerificationQueue<K: Kind> {
|
||||
@@ -121,19 +128,35 @@ pub struct VerificationQueue<K: Kind> {
|
||||
struct QueueSignal {
|
||||
deleting: Arc<AtomicBool>,
|
||||
signalled: AtomicBool,
|
||||
message_channel: IoChannel<ClientIoMessage>,
|
||||
message_channel: Mutex<IoChannel<ClientIoMessage>>,
|
||||
}
|
||||
|
||||
impl QueueSignal {
|
||||
#[cfg_attr(feature="dev", allow(bool_comparison))]
|
||||
fn set(&self) {
|
||||
fn set_sync(&self) {
|
||||
// Do not signal when we are about to close
|
||||
if self.deleting.load(AtomicOrdering::Relaxed) {
|
||||
return;
|
||||
}
|
||||
|
||||
if self.signalled.compare_and_swap(false, true, AtomicOrdering::Relaxed) == false {
|
||||
if let Err(e) = self.message_channel.send(ClientIoMessage::BlockVerified) {
|
||||
let channel = self.message_channel.lock().clone();
|
||||
if let Err(e) = channel.send_sync(ClientIoMessage::BlockVerified) {
|
||||
debug!("Error sending BlockVerified message: {:?}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature="dev", allow(bool_comparison))]
|
||||
fn set_async(&self) {
|
||||
// Do not signal when we are about to close
|
||||
if self.deleting.load(AtomicOrdering::Relaxed) {
|
||||
return;
|
||||
}
|
||||
|
||||
if self.signalled.compare_and_swap(false, true, AtomicOrdering::Relaxed) == false {
|
||||
let channel = self.message_channel.lock().clone();
|
||||
if let Err(e) = channel.send(ClientIoMessage::BlockVerified) {
|
||||
debug!("Error sending BlockVerified message: {:?}", e);
|
||||
}
|
||||
}
|
||||
@@ -147,36 +170,44 @@ impl QueueSignal {
|
||||
struct Verification<K: Kind> {
|
||||
// All locks must be captured in the order declared here.
|
||||
unverified: Mutex<VecDeque<K::Unverified>>,
|
||||
verified: Mutex<VecDeque<K::Verified>>,
|
||||
verifying: Mutex<VecDeque<Verifying<K>>>,
|
||||
verified: Mutex<VecDeque<K::Verified>>,
|
||||
bad: Mutex<HashSet<H256>>,
|
||||
more_to_verify: SMutex<()>,
|
||||
empty: SMutex<()>,
|
||||
verified_count: AtomicUsize,
|
||||
drained: AtomicUsize,
|
||||
imported: AtomicUsize,
|
||||
sizes: Sizes,
|
||||
check_seal: bool,
|
||||
}
|
||||
|
||||
impl<K: Kind> VerificationQueue<K> {
|
||||
/// Creates a new queue instance.
|
||||
pub fn new(config: Config, engine: Arc<Engine>, message_channel: IoChannel<ClientIoMessage>) -> Self {
|
||||
pub fn new(config: Config, engine: Arc<Engine>, message_channel: IoChannel<ClientIoMessage>, check_seal: bool) -> Self {
|
||||
let verification = Arc::new(Verification {
|
||||
unverified: Mutex::new(VecDeque::new()),
|
||||
verified: Mutex::new(VecDeque::new()),
|
||||
verifying: Mutex::new(VecDeque::new()),
|
||||
verified: Mutex::new(VecDeque::new()),
|
||||
bad: Mutex::new(HashSet::new()),
|
||||
more_to_verify: SMutex::new(()),
|
||||
empty: SMutex::new(()),
|
||||
verified_count: AtomicUsize::new(0),
|
||||
drained: AtomicUsize::new(0),
|
||||
imported: AtomicUsize::new(0),
|
||||
sizes: Sizes {
|
||||
unverified: AtomicUsize::new(0),
|
||||
verifying: AtomicUsize::new(0),
|
||||
verified: AtomicUsize::new(0),
|
||||
},
|
||||
check_seal: check_seal,
|
||||
});
|
||||
let more_to_verify = Arc::new(SCondvar::new());
|
||||
let deleting = Arc::new(AtomicBool::new(false));
|
||||
let ready_signal = Arc::new(QueueSignal {
|
||||
deleting: deleting.clone(),
|
||||
signalled: AtomicBool::new(false),
|
||||
message_channel: message_channel
|
||||
message_channel: Mutex::new(message_channel),
|
||||
});
|
||||
let empty = Arc::new(SCondvar::new());
|
||||
let panic_handler = PanicHandler::new_in_arc();
|
||||
@@ -232,18 +263,21 @@ impl<K: Kind> VerificationQueue<K> {
|
||||
None => continue,
|
||||
};
|
||||
|
||||
verification.sizes.unverified.fetch_sub(item.heap_size_of_children(), AtomicOrdering::SeqCst);
|
||||
verifying.push_back(Verifying { hash: item.hash(), output: None });
|
||||
item
|
||||
};
|
||||
|
||||
let hash = item.hash();
|
||||
match K::verify(item, &*engine) {
|
||||
let is_ready = match K::verify(item, &*engine, verification.check_seal) {
|
||||
Ok(verified) => {
|
||||
let mut verifying = verification.verifying.lock();
|
||||
let mut idx = None;
|
||||
for (i, e) in verifying.iter_mut().enumerate() {
|
||||
if e.hash == hash {
|
||||
idx = Some(i);
|
||||
|
||||
verification.sizes.verifying.fetch_add(verified.heap_size_of_children(), AtomicOrdering::SeqCst);
|
||||
e.output = Some(verified);
|
||||
break;
|
||||
}
|
||||
@@ -253,8 +287,10 @@ impl<K: Kind> VerificationQueue<K> {
|
||||
// we're next!
|
||||
let mut verified = verification.verified.lock();
|
||||
let mut bad = verification.bad.lock();
|
||||
VerificationQueue::drain_verifying(&mut verifying, &mut verified, &mut bad, &verification.verified_count);
|
||||
ready.set();
|
||||
VerificationQueue::drain_verifying(&mut verifying, &mut verified, &mut bad, &verification.verified_count, &verification.sizes);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
},
|
||||
Err(_) => {
|
||||
@@ -266,10 +302,16 @@ impl<K: Kind> VerificationQueue<K> {
|
||||
verifying.retain(|e| e.hash != hash);
|
||||
|
||||
if verifying.front().map_or(false, |x| x.output.is_some()) {
|
||||
VerificationQueue::drain_verifying(&mut verifying, &mut verified, &mut bad, &verification.verified_count);
|
||||
ready.set();
|
||||
VerificationQueue::drain_verifying(&mut verifying, &mut verified, &mut bad, &verification.verified_count, &verification.sizes);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
};
|
||||
if is_ready {
|
||||
// Import the block immediately
|
||||
ready.set_sync();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -278,20 +320,29 @@ impl<K: Kind> VerificationQueue<K> {
|
||||
verifying: &mut VecDeque<Verifying<K>>,
|
||||
verified: &mut VecDeque<K::Verified>,
|
||||
bad: &mut HashSet<H256>,
|
||||
v_count: &AtomicUsize
|
||||
v_count: &AtomicUsize,
|
||||
sizes: &Sizes,
|
||||
) {
|
||||
let start_len = verified.len();
|
||||
let mut removed_size = 0;
|
||||
let mut inserted_size = 0;
|
||||
|
||||
while let Some(output) = verifying.front_mut().and_then(|x| x.output.take()) {
|
||||
assert!(verifying.pop_front().is_some());
|
||||
let size = output.heap_size_of_children();
|
||||
removed_size += size;
|
||||
|
||||
if bad.contains(&output.parent_hash()) {
|
||||
bad.insert(output.hash());
|
||||
} else {
|
||||
inserted_size += size;
|
||||
verified.push_back(output);
|
||||
}
|
||||
}
|
||||
|
||||
v_count.fetch_add(verified.len() - start_len, AtomicOrdering::AcqRel);
|
||||
sizes.verifying.fetch_sub(removed_size, AtomicOrdering::SeqCst);
|
||||
sizes.verified.fetch_add(inserted_size, AtomicOrdering::SeqCst);
|
||||
}
|
||||
|
||||
/// Clear the queue and stop verification activity.
|
||||
@@ -302,6 +353,12 @@ impl<K: Kind> VerificationQueue<K> {
|
||||
unverified.clear();
|
||||
verifying.clear();
|
||||
verified.clear();
|
||||
|
||||
let sizes = &self.verification.sizes;
|
||||
sizes.unverified.store(0, AtomicOrdering::Release);
|
||||
sizes.verifying.store(0, AtomicOrdering::Release);
|
||||
sizes.verified.store(0, AtomicOrdering::Release);
|
||||
|
||||
self.processing.write().clear();
|
||||
}
|
||||
|
||||
@@ -345,6 +402,8 @@ impl<K: Kind> VerificationQueue<K> {
|
||||
|
||||
match K::create(input, &*self.engine) {
|
||||
Ok(item) => {
|
||||
self.verification.sizes.unverified.fetch_add(item.heap_size_of_children(), AtomicOrdering::SeqCst);
|
||||
|
||||
self.processing.write().insert(h.clone());
|
||||
self.verification.unverified.lock().push_back(item);
|
||||
self.verification.imported.fetch_add(1, AtomicOrdering::AcqRel);
|
||||
@@ -375,26 +434,32 @@ impl<K: Kind> VerificationQueue<K> {
|
||||
}
|
||||
|
||||
let mut new_verified = VecDeque::new();
|
||||
let mut removed_size = 0;
|
||||
for output in verified.drain(..) {
|
||||
if bad.contains(&output.parent_hash()) {
|
||||
removed_size += output.heap_size_of_children();
|
||||
bad.insert(output.hash());
|
||||
processing.remove(&output.hash());
|
||||
} else {
|
||||
new_verified.push_back(output);
|
||||
}
|
||||
}
|
||||
|
||||
self.verification.sizes.verified.fetch_sub(removed_size, AtomicOrdering::SeqCst);
|
||||
*verified = new_verified;
|
||||
}
|
||||
|
||||
/// Mark given item as processed
|
||||
pub fn mark_as_good(&self, hashes: &[H256]) {
|
||||
/// Mark given item as processed.
|
||||
/// Returns true if the queue becomes empty.
|
||||
pub fn mark_as_good(&self, hashes: &[H256]) -> bool {
|
||||
if hashes.is_empty() {
|
||||
return;
|
||||
return self.processing.read().is_empty();
|
||||
}
|
||||
let mut processing = self.processing.write();
|
||||
for hash in hashes {
|
||||
processing.remove(hash);
|
||||
}
|
||||
processing.is_empty()
|
||||
}
|
||||
|
||||
/// Removes up to `max` verified items from the queue
|
||||
@@ -403,28 +468,37 @@ impl<K: Kind> VerificationQueue<K> {
|
||||
let count = min(max, verified.len());
|
||||
let result = verified.drain(..count).collect::<Vec<_>>();
|
||||
|
||||
self.verification.drained.fetch_add(count, AtomicOrdering::AcqRel);
|
||||
self.verification.drained.fetch_add(result.len(), AtomicOrdering::AcqRel);
|
||||
|
||||
let drained_size = result.iter().map(HeapSizeOf::heap_size_of_children).fold(0, |a, c| a + c);
|
||||
self.verification.sizes.verified.fetch_sub(drained_size, AtomicOrdering::SeqCst);
|
||||
|
||||
self.ready_signal.reset();
|
||||
if !verified.is_empty() {
|
||||
self.ready_signal.set();
|
||||
self.ready_signal.set_async();
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
/// Get queue status.
|
||||
pub fn queue_info(&self) -> QueueInfo {
|
||||
use std::mem::size_of;
|
||||
|
||||
let (unverified_len, unverified_bytes) = {
|
||||
let v = self.verification.unverified.lock();
|
||||
(v.len(), v.heap_size_of_children())
|
||||
let len = self.verification.unverified.lock().len();
|
||||
let size = self.verification.sizes.unverified.load(AtomicOrdering::Acquire);
|
||||
|
||||
(len, size + len * size_of::<K::Unverified>())
|
||||
};
|
||||
let (verifying_len, verifying_bytes) = {
|
||||
let v = self.verification.verifying.lock();
|
||||
(v.len(), v.heap_size_of_children())
|
||||
let len = self.verification.verifying.lock().len();
|
||||
let size = self.verification.sizes.verifying.load(AtomicOrdering::Acquire);
|
||||
(len, size + len * size_of::<Verifying<K>>())
|
||||
};
|
||||
let (verified_len, verified_bytes) = {
|
||||
let v = self.verification.verified.lock();
|
||||
(v.len(), v.heap_size_of_children())
|
||||
let len = self.verification.verified.lock().len();
|
||||
let size = self.verification.sizes.verified.load(AtomicOrdering::Acquire);
|
||||
(len, size + len * size_of::<K::Verified>())
|
||||
};
|
||||
|
||||
QueueInfo {
|
||||
@@ -433,12 +507,9 @@ impl<K: Kind> VerificationQueue<K> {
|
||||
verified_queue_size: verified_len,
|
||||
max_queue_size: self.max_queue_size,
|
||||
max_mem_use: self.max_mem_use,
|
||||
mem_used:
|
||||
unverified_bytes
|
||||
+ verifying_bytes
|
||||
+ verified_bytes
|
||||
// TODO: https://github.com/servo/heapsize/pull/50
|
||||
//+ self.processing.read().heap_size_of_children(),
|
||||
mem_used: unverified_bytes
|
||||
+ verifying_bytes
|
||||
+ verified_bytes
|
||||
}
|
||||
}
|
||||
|
||||
@@ -593,7 +664,7 @@ mod tests {
|
||||
fn get_test_queue() -> BlockQueue {
|
||||
let spec = get_test_spec();
|
||||
let engine = spec.engine;
|
||||
BlockQueue::new(Config::default(), engine, IoChannel::disconnected())
|
||||
BlockQueue::new(Config::default(), engine, IoChannel::disconnected(), true)
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -601,7 +672,7 @@ mod tests {
|
||||
// TODO better test
|
||||
let spec = Spec::new_test();
|
||||
let engine = spec.engine;
|
||||
let _ = BlockQueue::new(Config::default(), engine, IoChannel::disconnected());
|
||||
let _ = BlockQueue::new(Config::default(), engine, IoChannel::disconnected(), true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -665,7 +736,7 @@ mod tests {
|
||||
let engine = spec.engine;
|
||||
let mut config = Config::default();
|
||||
config.max_mem_use = super::MIN_MEM_LIMIT; // empty queue uses about 15000
|
||||
let queue = BlockQueue::new(config, engine, IoChannel::disconnected());
|
||||
let queue = BlockQueue::new(config, engine, IoChannel::disconnected(), true);
|
||||
assert!(!queue.queue_info().is_full());
|
||||
let mut blocks = get_good_dummy_block_seq(50);
|
||||
for b in blocks.drain(..) {
|
||||
|
||||
@@ -14,17 +14,21 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/// Block and transaction verification functions
|
||||
///
|
||||
/// Block verification is done in 3 steps
|
||||
/// 1. Quick verification upon adding to the block queue
|
||||
/// 2. Signatures verification done in the queue.
|
||||
/// 3. Final verification against the blockchain done before enactment.
|
||||
//! Block and transaction verification functions
|
||||
//!
|
||||
//! Block verification is done in 3 steps
|
||||
//! 1. Quick verification upon adding to the block queue
|
||||
//! 2. Signatures verification done in the queue.
|
||||
//! 3. Final verification against the blockchain done before enactment.
|
||||
|
||||
use common::*;
|
||||
use util::*;
|
||||
use engines::Engine;
|
||||
use error::{BlockError, Error};
|
||||
use blockchain::*;
|
||||
use header::{BlockNumber, Header};
|
||||
use rlp::{UntrustedRlp, View};
|
||||
use transaction::SignedTransaction;
|
||||
use views::BlockView;
|
||||
|
||||
/// Preprocessed block data gathered in `verify_block_unordered` call
|
||||
pub struct PreverifiedBlock {
|
||||
@@ -66,10 +70,12 @@ pub fn verify_block_basic(header: &Header, bytes: &[u8], engine: &Engine) -> Res
|
||||
/// Phase 2 verification. Perform costly checks such as transaction signatures and block nonce for ethash.
|
||||
/// Still operates on a individual block
|
||||
/// Returns a `PreverifiedBlock` structure populated with transactions
|
||||
pub fn verify_block_unordered(header: Header, bytes: Bytes, engine: &Engine) -> Result<PreverifiedBlock, Error> {
|
||||
try!(engine.verify_block_unordered(&header, Some(&bytes)));
|
||||
for u in try!(UntrustedRlp::new(&bytes).at(2)).iter().map(|rlp| rlp.as_val::<Header>()) {
|
||||
try!(engine.verify_block_unordered(&try!(u), None));
|
||||
pub fn verify_block_unordered(header: Header, bytes: Bytes, engine: &Engine, check_seal: bool) -> Result<PreverifiedBlock, Error> {
|
||||
if check_seal {
|
||||
try!(engine.verify_block_unordered(&header, Some(&bytes)));
|
||||
for u in try!(UntrustedRlp::new(&bytes).at(2)).iter().map(|rlp| rlp.as_val::<Header>()) {
|
||||
try!(engine.verify_block_unordered(&try!(u), None));
|
||||
}
|
||||
}
|
||||
// Verify transactions.
|
||||
let mut transactions = Vec::new();
|
||||
@@ -108,7 +114,8 @@ pub fn verify_block_family(header: &Header, bytes: &[u8], engine: &Engine, bc: &
|
||||
match bc.block_details(&hash) {
|
||||
Some(details) => {
|
||||
excluded.insert(details.parent.clone());
|
||||
let b = bc.block(&hash).unwrap();
|
||||
let b = bc.block(&hash)
|
||||
.expect("parent already known to be stored; qed");
|
||||
excluded.extend(BlockView::new(&b).uncle_hashes());
|
||||
hash = details.parent;
|
||||
}
|
||||
@@ -296,7 +303,7 @@ mod tests {
|
||||
self.blocks.contains_key(hash)
|
||||
}
|
||||
|
||||
fn first_block(&self) -> H256 {
|
||||
fn first_block(&self) -> Option<H256> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
@@ -313,6 +320,10 @@ mod tests {
|
||||
self.block(hash).map(|b| BlockChain::block_to_body(&b))
|
||||
}
|
||||
|
||||
fn best_ancient_block(&self) -> Option<H256> {
|
||||
None
|
||||
}
|
||||
|
||||
/// Get the familial details concerning a block.
|
||||
fn block_details(&self, hash: &H256) -> Option<BlockDetails> {
|
||||
self.blocks.get(hash).map(|bytes| {
|
||||
@@ -384,7 +395,7 @@ mod tests {
|
||||
gas: U256::from(30_000),
|
||||
gas_price: U256::from(40_000),
|
||||
nonce: U256::one()
|
||||
}.sign(keypair.secret());
|
||||
}.sign(keypair.secret(), None);
|
||||
|
||||
let tr2 = Transaction {
|
||||
action: Action::Create,
|
||||
@@ -393,7 +404,7 @@ mod tests {
|
||||
gas: U256::from(30_000),
|
||||
gas_price: U256::from(40_000),
|
||||
nonce: U256::from(2)
|
||||
}.sign(keypair.secret());
|
||||
}.sign(keypair.secret(), None);
|
||||
|
||||
let good_transactions = [ tr1.clone(), tr2.clone() ];
|
||||
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! A generic verifier trait.
|
||||
|
||||
use blockchain::BlockProvider;
|
||||
use engines::Engine;
|
||||
use error::Error;
|
||||
@@ -21,6 +23,8 @@ use header::Header;
|
||||
|
||||
/// Should be used to verify blocks.
|
||||
pub trait Verifier: Send + Sync {
|
||||
/// Verify a block relative to its parent and uncles.
|
||||
fn verify_block_family(&self, header: &Header, bytes: &[u8], engine: &Engine, bc: &BlockProvider) -> Result<(), Error>;
|
||||
/// Do a final verification check for an enacted header vs its expected counterpart.
|
||||
fn verify_block_final(&self, expected: &Header, got: &Header) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user