fix types and lifetimes
This commit is contained in:
parent
8da38fa98b
commit
74939a43d6
@ -25,7 +25,7 @@ use evm::Schedule;
|
|||||||
use ethjson;
|
use ethjson;
|
||||||
|
|
||||||
/// `BFT` params.
|
/// `BFT` params.
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug)]
|
||||||
pub struct BFTParams {
|
pub struct BFTParams {
|
||||||
/// Gas limit divisor.
|
/// Gas limit divisor.
|
||||||
pub gas_limit_bound_divisor: U256,
|
pub gas_limit_bound_divisor: U256,
|
||||||
@ -36,7 +36,7 @@ pub struct BFTParams {
|
|||||||
/// Number of validators.
|
/// Number of validators.
|
||||||
pub validator_n: usize,
|
pub validator_n: usize,
|
||||||
/// Precommit step votes.
|
/// Precommit step votes.
|
||||||
precommits: HashMap<H256, HashSet<H520>>
|
precommits: RwLock<HashMap<H256, HashSet<Signature>>>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ethjson::spec::BFTParams> for BFTParams {
|
impl From<ethjson::spec::BFTParams> for BFTParams {
|
||||||
@ -45,8 +45,9 @@ impl From<ethjson::spec::BFTParams> for BFTParams {
|
|||||||
BFTParams {
|
BFTParams {
|
||||||
gas_limit_bound_divisor: p.gas_limit_bound_divisor.into(),
|
gas_limit_bound_divisor: p.gas_limit_bound_divisor.into(),
|
||||||
duration_limit: p.duration_limit.into(),
|
duration_limit: p.duration_limit.into(),
|
||||||
validators: auth,
|
validator_n: val.len(),
|
||||||
validator_n: val.len()
|
validators: val,
|
||||||
|
precommits: RwLock::new(HashMap::new())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -68,17 +69,27 @@ impl BFT {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_precommit(&self, bare_hash: &H256, signature: &H520) -> result::Result<(), Error> {
|
fn add_precommit(&self, bare_hash: &H256, signature: &Signature) {
|
||||||
let signer = Address::from(try!(ec::recover(&sig, bare_hash)).sha3());
|
if let Some(mut precommits) = self.our_params.precommits.write().get_mut(bare_hash) {
|
||||||
if !self.our_params.validators.contains(&signer) {
|
precommits.insert(signature.clone());
|
||||||
return try!(Err(BlockError::InvalidSeal));
|
} else {
|
||||||
|
let mut new = HashSet::new();
|
||||||
|
new.insert(signature.clone());
|
||||||
|
assert!(self.our_params.precommits.write().insert(bare_hash.clone(), new).is_none());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_precommit(&self, bare_hash: &H256, signature: &Signature) -> result::Result<(), Error> {
|
||||||
|
let signer = Address::from(try!(ec::recover(&signature, bare_hash)).sha3());
|
||||||
|
match self.our_params.validators.contains(&signer) {
|
||||||
|
false => try!(Err(BlockError::InvalidSeal)),
|
||||||
|
true => Ok(()),
|
||||||
}
|
}
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn supermajority(&self) -> usize { 2*self.our_params.validator_n/3 }
|
fn supermajority(&self) -> usize { 2*self.our_params.validator_n/3 }
|
||||||
|
|
||||||
fn signatures_seal(&self, signatures: &HashSet<H520>) -> Vec<Bytes> {
|
fn signatures_seal(&self, signatures: &HashSet<Signature>) -> Vec<Bytes> {
|
||||||
signatures.iter().map(|sig| encode(&(&*sig as &[u8])).to_vec()).collect()
|
signatures.iter().map(|sig| encode(&(&*sig as &[u8])).to_vec()).collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -121,22 +132,23 @@ impl Engine for BFT {
|
|||||||
///
|
///
|
||||||
/// 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>> {
|
||||||
let hash = block.bare_hash();
|
let hash = block.header().bare_hash();
|
||||||
let signatures = self.our_params.precommits.entry(hash).or_insert(HashSet::new());
|
let guard = self.our_params.precommits.read();
|
||||||
|
let signatures = guard.get(&hash).unwrap_or(return None);
|
||||||
let threshold = self.supermajority();
|
let threshold = self.supermajority();
|
||||||
match (signatures.len(), accounts) {
|
match (signatures.len(), accounts) {
|
||||||
(threshold-1, Some(ap)) => {
|
(v, Some(ap)) if v == threshold-1 => {
|
||||||
// account should be pernamently unlocked, otherwise signing will fail
|
// account should be pernamently unlocked, otherwise signing will fail
|
||||||
if let Ok(signature) = ap.sign(*block.header().author(), hash) {
|
if let Ok(signature) = ap.sign(*block.header().author(), hash) {
|
||||||
*signatures.insert(signature);
|
self.add_precommit(&hash, &signature.into());
|
||||||
Some(self.signatures_seal(signatures));
|
Some(self.signatures_seal(signatures))
|
||||||
} else {
|
} else {
|
||||||
trace!(target: "bft", "generate_seal: FAIL: secret key unavailable");
|
trace!(target: "bft", "generate_seal: FAIL: secret key unavailable");
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
(0..threshold, _) => None,
|
(v, _) if v < threshold => None,
|
||||||
(threshold.., _) => Some(block.header().seal),
|
_ => Some(block.header().seal.clone()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,18 +166,19 @@ impl Engine for BFT {
|
|||||||
fn verify_block_unordered(&self, header: &Header, _block: Option<&[u8]>) -> result::Result<(), Error> {
|
fn verify_block_unordered(&self, header: &Header, _block: Option<&[u8]>) -> result::Result<(), Error> {
|
||||||
let hash = header.bare_hash();
|
let hash = header.bare_hash();
|
||||||
let threshold = self.supermajority();
|
let threshold = self.supermajority();
|
||||||
let signatures = self.our_params.precommits.entry(hash).or_insert(HashSet::new());
|
let guard = self.our_params.precommits.read();
|
||||||
|
let mut signatures = guard.get(&hash).unwrap_or(try!(Err(BlockError::InvalidSeal)));
|
||||||
if signatures.len() > threshold { return Ok(()) }
|
if signatures.len() > threshold { return Ok(()) }
|
||||||
// Count all valid precommits.
|
// Count all valid precommits.
|
||||||
for seal_field in header.seal {
|
for seal_field in header.seal() {
|
||||||
let sig = try!(UntrustedRlp::new(seal_field).as_val::<H520>());
|
let sig = try!(UntrustedRlp::new(&seal_field).as_val::<Signature>());
|
||||||
if !signatures.contains(sig) || self.check_precommit(hash, sig).is_ok() {
|
if !signatures.contains(&sig) || self.check_precommit(&hash, &sig).is_ok() {
|
||||||
trace!(target: "bft", "verify_block_unordered: new validator vote found");
|
trace!(target: "bft", "verify_block_unordered: new validator vote found");
|
||||||
*signatures.insert(sig);
|
self.add_precommit(&hash, &sig);
|
||||||
if signatures.len() > threshold { return Ok(()) }
|
if signatures.len() > threshold { return Ok(()) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(BlockError::InvalidSeal)
|
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::Result<(), Error> {
|
||||||
@ -197,12 +210,6 @@ impl Engine for BFT {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Header {
|
|
||||||
/// Get the none field of the header.
|
|
||||||
pub fn signature(&self) -> H520 {
|
|
||||||
decode(&self.seal()[0])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
@ -19,10 +19,12 @@
|
|||||||
mod null_engine;
|
mod null_engine;
|
||||||
mod instant_seal;
|
mod instant_seal;
|
||||||
mod basic_authority;
|
mod basic_authority;
|
||||||
|
mod bft;
|
||||||
|
|
||||||
pub use self::null_engine::NullEngine;
|
pub use self::null_engine::NullEngine;
|
||||||
pub use self::instant_seal::InstantSeal;
|
pub use self::instant_seal::InstantSeal;
|
||||||
pub use self::basic_authority::BasicAuthority;
|
pub use self::basic_authority::BasicAuthority;
|
||||||
|
pub use self::bft::BFT;
|
||||||
|
|
||||||
use common::*;
|
use common::*;
|
||||||
use account_provider::AccountProvider;
|
use account_provider::AccountProvider;
|
||||||
|
Loading…
Reference in New Issue
Block a user