seal generation and verificatio

This commit is contained in:
keorn 2016-09-06 12:26:06 +02:00
parent 91fbaf935c
commit 45e6b4ac9d

View File

@ -20,6 +20,7 @@ use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrdering};
use std::sync::Weak; use std::sync::Weak;
use common::*; use common::*;
use rlp::{UntrustedRlp, View, encode}; use rlp::{UntrustedRlp, View, encode};
use ethkey::{recover, public_to_address};
use account_provider::AccountProvider; use account_provider::AccountProvider;
use block::*; use block::*;
use spec::CommonParams; use spec::CommonParams;
@ -278,15 +279,9 @@ impl Engine for Tendermint {
/// ///
/// None is returned if not enough signatures can be collected. /// None is returned if not enough signatures can be collected.
fn generate_seal(&self, block: &ExecutedBlock, accounts: Option<&AccountProvider>) -> Option<Vec<Bytes>> { fn generate_seal(&self, block: &ExecutedBlock, accounts: Option<&AccountProvider>) -> Option<Vec<Bytes>> {
accounts.and_then(|ap| { self.s.try_read().and_then(|s| match *s {
let header = block.header(); Step::Commit(ref seal) => Some(seal.clone()),
if header.author() == &self.proposer() { _ => None,
ap.sign(*header.author(), header.bare_hash())
.ok()
.and_then(|signature| Some(vec![encode(&(&*signature as &[u8])).to_vec()]))
} else {
None
}
}) })
} }
@ -302,22 +297,35 @@ impl Engine for Tendermint {
} }
} }
fn verify_block_basic(&self, header: &Header, _block: Option<&[u8]>) -> result::Result<(), Error> { fn verify_block_basic(&self, header: &Header, _block: Option<&[u8]>) -> Result<(), Error> {
// check the seal fields. if header.seal().len() < self.threshold() {
// TODO: pull this out into common code. Err(From::from(BlockError::InvalidSealArity(
if header.seal().len() != self.seal_fields() { Mismatch { expected: self.threshold(), found: header.seal().len() }
return Err(From::from(BlockError::InvalidSealArity( )))
Mismatch { expected: self.seal_fields(), found: header.seal().len() } } else {
))); Ok(())
} }
Ok(())
} }
fn verify_block_unordered(&self, _header: &Header, _block: Option<&[u8]>) -> result::Result<(), Error> { fn verify_block_unordered(&self, header: &Header, _block: Option<&[u8]>) -> Result<(), Error> {
Ok(()) let to_address = |b: &Vec<u8>| {
let sig: H520 = try!(UntrustedRlp::new(b.as_slice()).as_val());
Ok(public_to_address(&try!(recover(&sig.into(), &header.bare_hash()))))
};
let validator_set = self.our_params.validators.iter().cloned().collect();
let seal_set = try!(header
.seal()
.iter()
.map(to_address)
.collect::<Result<HashSet<_>, Error>>());
if self.threshold() < seal_set.intersection(&validator_set).count() {
Ok(())
} else {
try!(Err(BlockError::InvalidSeal))
}
} }
fn verify_block_family(&self, header: &Header, parent: &Header, _block: Option<&[u8]>) -> result::Result<(), Error> { fn verify_block_family(&self, header: &Header, parent: &Header, _block: Option<&[u8]>) -> Result<(), Error> {
// we should not calculate difficulty for genesis blocks // we should not calculate difficulty for genesis blocks
if header.number() == 0 { if header.number() == 0 {
return Err(From::from(BlockError::RidiculousNumber(OutOfBounds { min: Some(1), max: None, found: header.number() }))); return Err(From::from(BlockError::RidiculousNumber(OutOfBounds { min: Some(1), max: None, found: header.number() })));
@ -336,7 +344,7 @@ impl Engine for Tendermint {
Ok(()) Ok(())
} }
fn verify_transaction_basic(&self, t: &SignedTransaction, _header: &Header) -> result::Result<(), Error> { fn verify_transaction_basic(&self, t: &SignedTransaction, _header: &Header) -> Result<(), Error> {
try!(t.check_low_s()); try!(t.check_low_s());
Ok(()) Ok(())
} }