From 7723d6281bcd11c7bd4da101c02fc70e78bbf303 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Wed, 12 Apr 2017 12:46:25 +0200 Subject: [PATCH] starting memoized validatorset --- ethcore/src/engines/mod.rs | 2 +- ethcore/src/engines/validator_set/mod.rs | 41 +++++++++++++++++++ ethcore/src/engines/validator_set/multi.rs | 19 ++++++++- .../src/engines/validator_set/simple_list.rs | 9 ++-- 4 files changed, 63 insertions(+), 8 deletions(-) diff --git a/ethcore/src/engines/mod.rs b/ethcore/src/engines/mod.rs index 76a0d790b..0ae353a56 100644 --- a/ethcore/src/engines/mod.rs +++ b/ethcore/src/engines/mod.rs @@ -206,7 +206,7 @@ pub trait Engine : Sync + Send { /// /// Engines which do draw consensus information from the state may only do so /// here. - fn generate_validation_proof(&self, _call: &Call) -> ValidationProof { + fn generate_validation_proof(&self, header: &Header, _call: &Call) -> ValidationProof { ValidationProof::default() } diff --git a/ethcore/src/engines/validator_set/mod.rs b/ethcore/src/engines/validator_set/mod.rs index cbbedfb33..a2f6d1075 100644 --- a/ethcore/src/engines/validator_set/mod.rs +++ b/ethcore/src/engines/validator_set/mod.rs @@ -25,11 +25,15 @@ use std::sync::Weak; use util::{Address, H256}; use ethjson::spec::ValidatorSet as ValidatorSpec; use client::Client; +use receipt::Receipt; + use self::simple_list::SimpleList; use self::contract::ValidatorContract; use self::safe_contract::ValidatorSafeContract; use self::multi::Multi; +pub type Call = Fn(Address, Vec) -> Result, String>; + /// Creates a validator set from spec. pub fn new_validator_set(spec: ValidatorSpec) -> Box { match spec { @@ -42,7 +46,12 @@ pub fn new_validator_set(spec: ValidatorSpec) -> Box { } } +/// A validator set. 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. fn contains(&self, parent_block_hash: &H256, address: &Address) -> bool; /// Draws an validator nonce modulo number of validators. @@ -56,3 +65,35 @@ pub trait ValidatorSet: Send + Sync { /// Allows blockchain state access. fn register_contract(&self, _client: Weak) {} } + +/// 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; + + /// Fetch validators at a block synchronously. + fn fetch_validators(&self, header: &Header, call: &Call) -> Result; +} + +/// A memoized flexible validator set +pub struct Memoized { + inner: Box, + 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) } +} + diff --git a/ethcore/src/engines/validator_set/multi.rs b/ethcore/src/engines/validator_set/multi.rs index 5027f23cd..8527a8aa9 100644 --- a/ethcore/src/engines/validator_set/multi.rs +++ b/ethcore/src/engines/validator_set/multi.rs @@ -40,7 +40,7 @@ impl Multi { } } - fn correct_set(&self, bh: &H256) -> Option<&Box> { + fn correct_set(&self, bh: &H256) -> Option<&ValidatorSet> { match self .block_number .read()(bh) @@ -55,7 +55,7 @@ impl Multi { ) { Ok((block, set)) => { trace!(target: "engine", "Multi ValidatorSet retrieved for block {}.", block); - Some(set) + Some(&*set) }, Err(e) => { debug!(target: "engine", "ValidatorSet could not be recovered: {}", e); @@ -66,6 +66,21 @@ impl 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> { + + } + + fn fetch(&self) -> + fn contains(&self, bh: &H256, address: &Address) -> bool { self.correct_set(bh).map_or(false, |set| set.contains(bh, address)) } diff --git a/ethcore/src/engines/validator_set/simple_list.rs b/ethcore/src/engines/validator_set/simple_list.rs index 2d7687979..cc4259fac 100644 --- a/ethcore/src/engines/validator_set/simple_list.rs +++ b/ethcore/src/engines/validator_set/simple_list.rs @@ -22,13 +22,11 @@ use super::ValidatorSet; #[derive(Debug, PartialEq, Eq, Default)] pub struct SimpleList { validators: Vec
, - validator_n: usize, } impl SimpleList { pub fn new(validators: Vec
) -> Self { SimpleList { - validator_n: validators.len(), validators: validators, } } @@ -36,7 +34,7 @@ impl SimpleList { impl HeapSizeOf for SimpleList { 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 { - 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 { - self.validator_n + self.validators.len() } }