starting memoized validatorset

This commit is contained in:
Robert Habermeier 2017-04-12 12:46:25 +02:00
parent a254b2098f
commit 7723d6281b
4 changed files with 63 additions and 8 deletions

View File

@ -206,7 +206,7 @@ pub trait Engine : Sync + Send {
/// ///
/// Engines which do draw consensus information from the state may only do so /// Engines which do draw consensus information from the state may only do so
/// here. /// here.
fn generate_validation_proof(&self, _call: &Call) -> ValidationProof { fn generate_validation_proof(&self, header: &Header, _call: &Call) -> ValidationProof {
ValidationProof::default() ValidationProof::default()
} }

View File

@ -25,11 +25,15 @@ use std::sync::Weak;
use util::{Address, H256}; use util::{Address, H256};
use ethjson::spec::ValidatorSet as ValidatorSpec; use ethjson::spec::ValidatorSet as ValidatorSpec;
use client::Client; use client::Client;
use receipt::Receipt;
use self::simple_list::SimpleList; use self::simple_list::SimpleList;
use self::contract::ValidatorContract; use self::contract::ValidatorContract;
use self::safe_contract::ValidatorSafeContract; use self::safe_contract::ValidatorSafeContract;
use self::multi::Multi; use self::multi::Multi;
pub type Call = Fn(Address, Vec<u8>) -> Result<Vec<u8>, String>;
/// Creates a validator set from spec. /// Creates a validator set from spec.
pub fn new_validator_set(spec: ValidatorSpec) -> Box<ValidatorSet> { pub fn new_validator_set(spec: ValidatorSpec) -> Box<ValidatorSet> {
match spec { match spec {
@ -42,7 +46,12 @@ pub fn new_validator_set(spec: ValidatorSpec) -> Box<ValidatorSet> {
} }
} }
/// A validator set.
pub trait ValidatorSet: Send + Sync { pub trait ValidatorSet: Send + Sync {
/// Get this validator set as a flexible validator set.
/// Returning `None` indicates this is only usable for
/// full nodes.
fn as_memoized(&self) -> Option<&Memoized> { None }
/// Checks if a given address is a validator. /// Checks if a given address is a validator.
fn contains(&self, parent_block_hash: &H256, address: &Address) -> bool; fn contains(&self, parent_block_hash: &H256, address: &Address) -> bool;
/// Draws an validator nonce modulo number of validators. /// Draws an validator nonce modulo number of validators.
@ -56,3 +65,35 @@ pub trait ValidatorSet: Send + Sync {
/// Allows blockchain state access. /// Allows blockchain state access.
fn register_contract(&self, _client: Weak<Client>) {} fn register_contract(&self, _client: Weak<Client>) {}
} }
/// A flexible validator set can track its changes.
pub trait FlexibleValidatorSet: Send + Sync {
/// Whether a validator set may have changed at this header.
fn has_possibly_changed(&self, header: &Header) -> bool;
/// Whether a validator set has changed at this header, given the block receipts.
/// Called after `has_possibly_changed`.
/// `Some` indicates the validator set has changed at this header and the new
/// expected validator set.
/// `None` indicates no change.
fn has_changed(&self, header: &Header, receipts: &[Receipt]) -> Option<SimpleList>;
/// Fetch validators at a block synchronously.
fn fetch_validators(&self, header: &Header, call: &Call) -> Result<SimpleList, String>;
}
/// A memoized flexible validator set
pub struct Memoized {
inner: Box<FlexibleValidatorSet>,
memo: Mutex<(SimpleList, (H256, u64))>,
}
impl Memoized {
/// Denote that the
pub fn use_memo_at(&self, list: SimpleList)
}
impl ValidatorSet for Memoized {
fn as_memoized(&self) -> Option<&Memoized> { Some(self) }
}

View File

@ -40,7 +40,7 @@ impl Multi {
} }
} }
fn correct_set(&self, bh: &H256) -> Option<&Box<ValidatorSet>> { fn correct_set(&self, bh: &H256) -> Option<&ValidatorSet> {
match self match self
.block_number .block_number
.read()(bh) .read()(bh)
@ -55,7 +55,7 @@ impl Multi {
) { ) {
Ok((block, set)) => { Ok((block, set)) => {
trace!(target: "engine", "Multi ValidatorSet retrieved for block {}.", block); trace!(target: "engine", "Multi ValidatorSet retrieved for block {}.", block);
Some(set) Some(&*set)
}, },
Err(e) => { Err(e) => {
debug!(target: "engine", "ValidatorSet could not be recovered: {}", e); debug!(target: "engine", "ValidatorSet could not be recovered: {}", e);
@ -66,6 +66,21 @@ impl Multi {
} }
impl ValidatorSet for Multi { impl ValidatorSet for Multi {
fn has_possibly_changed(&self, header: &Header) -> bool {
// if the sets are the same for each header, compare those.
// otherwise, the sets have almost certainly changed.
match (self.correct_set(&header.hash()), self.correct_set(header.parent_hash())) {
(Some(a), Some(b)) if a as *const _ == b as *const _ => { a.has_possibly_changed(header) },
_ => true,
}
}
fn has_changed(&self, header: &Header, receipts: &[Receipt]) -> Option<Vec<Address>> {
}
fn fetch(&self) ->
fn contains(&self, bh: &H256, address: &Address) -> bool { fn contains(&self, bh: &H256, address: &Address) -> bool {
self.correct_set(bh).map_or(false, |set| set.contains(bh, address)) self.correct_set(bh).map_or(false, |set| set.contains(bh, address))
} }

View File

@ -22,13 +22,11 @@ use super::ValidatorSet;
#[derive(Debug, PartialEq, Eq, Default)] #[derive(Debug, PartialEq, Eq, Default)]
pub struct SimpleList { pub struct SimpleList {
validators: Vec<Address>, validators: Vec<Address>,
validator_n: usize,
} }
impl SimpleList { impl SimpleList {
pub fn new(validators: Vec<Address>) -> Self { pub fn new(validators: Vec<Address>) -> Self {
SimpleList { SimpleList {
validator_n: validators.len(),
validators: validators, validators: validators,
} }
} }
@ -36,7 +34,7 @@ impl SimpleList {
impl HeapSizeOf for SimpleList { impl HeapSizeOf for SimpleList {
fn heap_size_of_children(&self) -> usize { fn heap_size_of_children(&self) -> usize {
self.validators.heap_size_of_children() + self.validator_n.heap_size_of_children() self.validators.heap_size_of_children()
} }
} }
@ -46,11 +44,12 @@ impl ValidatorSet for SimpleList {
} }
fn get(&self, _bh: &H256, nonce: usize) -> Address { fn get(&self, _bh: &H256, nonce: usize) -> Address {
self.validators.get(nonce % self.validator_n).expect("There are validator_n authorities; taking number modulo validator_n gives number in validator_n range; qed").clone() let validator_n = self.validators.len();
self.validators.get(nonce % validator_n).expect("There are validator_n authorities; taking number modulo validator_n gives number in validator_n range; qed").clone()
} }
fn count(&self, _bh: &H256) -> usize { fn count(&self, _bh: &H256) -> usize {
self.validator_n self.validators.len()
} }
} }