supply optional call context to validator sets
This commit is contained in:
parent
0f80c57dca
commit
ec922ee5e4
@ -18,12 +18,14 @@
|
|||||||
/// It can also report validators for misbehaviour with two levels: `reportMalicious` and `reportBenign`.
|
/// It can also report validators for misbehaviour with two levels: `reportMalicious` and `reportBenign`.
|
||||||
|
|
||||||
use std::sync::Weak;
|
use std::sync::Weak;
|
||||||
use futures::Future;
|
|
||||||
use util::*;
|
use util::*;
|
||||||
use client::{Client, BlockChainClient};
|
|
||||||
|
|
||||||
|
use futures::Future;
|
||||||
use native_contracts::ValidatorReport as Provider;
|
use native_contracts::ValidatorReport as Provider;
|
||||||
|
|
||||||
|
use client::{Client, BlockChainClient};
|
||||||
|
use engines::Call;
|
||||||
|
|
||||||
use super::ValidatorSet;
|
use super::ValidatorSet;
|
||||||
use super::safe_contract::ValidatorSafeContract;
|
use super::safe_contract::ValidatorSafeContract;
|
||||||
|
|
||||||
@ -48,7 +50,7 @@ impl ValidatorContract {
|
|||||||
// could be `impl Trait`.
|
// could be `impl Trait`.
|
||||||
// note: dispatches transactions to network as well as execute.
|
// note: dispatches transactions to network as well as execute.
|
||||||
// TODO [keorn]: Make more general.
|
// TODO [keorn]: Make more general.
|
||||||
fn transact(&self) -> Box<Fn(Address, Vec<u8>) -> Result<Vec<u8>, String>> {
|
fn transact(&self) -> Box<Call> {
|
||||||
let client = self.client.read().clone();
|
let client = self.client.read().clone();
|
||||||
Box::new(move |a, d| client.as_ref()
|
Box::new(move |a, d| client.as_ref()
|
||||||
.and_then(Weak::upgrade)
|
.and_then(Weak::upgrade)
|
||||||
@ -59,16 +61,20 @@ impl ValidatorContract {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ValidatorSet for ValidatorContract {
|
impl ValidatorSet for ValidatorContract {
|
||||||
fn contains(&self, bh: &H256, address: &Address) -> bool {
|
fn default_caller(&self, id: ::ids::BlockId) -> Box<Call> {
|
||||||
self.validators.contains(bh, address)
|
self.validators.default_caller(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get(&self, bh: &H256, nonce: usize) -> Address {
|
fn contains_with_caller(&self, bh: &H256, address: &Address, caller: &Call) -> bool {
|
||||||
self.validators.get(bh, nonce)
|
self.validators.contains_with_caller(bh, address, caller)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn count(&self, bh: &H256) -> usize {
|
fn get_with_caller(&self, bh: &H256, nonce: usize, caller: &Call) -> Address {
|
||||||
self.validators.count(bh)
|
self.validators.get_with_caller(bh, nonce, caller)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn count_with_caller(&self, bh: &H256, caller: &Call) -> usize {
|
||||||
|
self.validators.count_with_caller(bh, caller)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn report_malicious(&self, address: &Address) {
|
fn report_malicious(&self, address: &Address) {
|
||||||
|
@ -22,6 +22,7 @@ mod contract;
|
|||||||
mod multi;
|
mod multi;
|
||||||
|
|
||||||
use std::sync::Weak;
|
use std::sync::Weak;
|
||||||
|
use ids::BlockId;
|
||||||
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;
|
||||||
@ -31,6 +32,8 @@ use self::contract::ValidatorContract;
|
|||||||
use self::safe_contract::ValidatorSafeContract;
|
use self::safe_contract::ValidatorSafeContract;
|
||||||
use self::multi::Multi;
|
use self::multi::Multi;
|
||||||
|
|
||||||
|
use super::Call;
|
||||||
|
|
||||||
/// 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 {
|
||||||
@ -44,13 +47,39 @@ pub fn new_validator_set(spec: ValidatorSpec) -> Box<ValidatorSet> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A validator set.
|
/// A validator set.
|
||||||
|
// TODO [keorn]: remove internal callers.
|
||||||
pub trait ValidatorSet: Send + Sync {
|
pub trait ValidatorSet: Send + Sync {
|
||||||
/// Checks if a given address is a validator.
|
/// Get the default "Call" helper, for use in general operation.
|
||||||
fn contains(&self, parent_block_hash: &H256, address: &Address) -> bool;
|
fn default_caller(&self, block_id: BlockId) -> Box<Call>;
|
||||||
|
|
||||||
|
/// Checks if a given address is a validator,
|
||||||
|
/// using underlying, default call mechanism.
|
||||||
|
fn contains(&self, parent: &H256, address: &Address) -> bool {
|
||||||
|
let default = self.default_caller(BlockId::Hash(*parent));
|
||||||
|
self.contains_with_caller(parent, address, &*default)
|
||||||
|
}
|
||||||
/// Draws an validator nonce modulo number of validators.
|
/// Draws an validator nonce modulo number of validators.
|
||||||
fn get(&self, parent_block_hash: &H256, nonce: usize) -> Address;
|
fn get(&self, parent: &H256, nonce: usize) -> Address {
|
||||||
|
let default = self.default_caller(BlockId::Hash(*parent));
|
||||||
|
self.get_with_caller(parent, nonce, &*default)
|
||||||
|
}
|
||||||
/// Returns the current number of validators.
|
/// Returns the current number of validators.
|
||||||
fn count(&self, parent_block_hash: &H256) -> usize;
|
fn count(&self, parent: &H256) -> usize {
|
||||||
|
let default = self.default_caller(BlockId::Hash(*parent));
|
||||||
|
self.count_with_caller(parent, &*default)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Checks if a given address is a validator, with the given function
|
||||||
|
/// for executing synchronous calls to contracts.
|
||||||
|
fn contains_with_caller(&self, parent_block_hash: &H256, address: &Address, caller: &Call) -> bool;
|
||||||
|
|
||||||
|
/// Draws an validator nonce modulo number of validators.
|
||||||
|
///
|
||||||
|
fn get_with_caller(&self, parent_block_hash: &H256, nonce: usize, caller: &Call) -> Address;
|
||||||
|
|
||||||
|
/// Returns the current number of validators.
|
||||||
|
fn count_with_caller(&self, parent_block_hash: &H256, caller: &Call) -> usize;
|
||||||
|
|
||||||
/// Notifies about malicious behaviour.
|
/// Notifies about malicious behaviour.
|
||||||
fn report_malicious(&self, _validator: &Address) {}
|
fn report_malicious(&self, _validator: &Address) {}
|
||||||
/// Notifies about benign misbehaviour.
|
/// Notifies about benign misbehaviour.
|
||||||
|
@ -18,13 +18,14 @@
|
|||||||
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::sync::Weak;
|
use std::sync::Weak;
|
||||||
|
use engines::Call;
|
||||||
use util::{H256, Address, RwLock};
|
use util::{H256, Address, RwLock};
|
||||||
use ids::BlockId;
|
use ids::BlockId;
|
||||||
use header::BlockNumber;
|
use header::BlockNumber;
|
||||||
use client::{Client, BlockChainClient};
|
use client::{Client, BlockChainClient};
|
||||||
use super::ValidatorSet;
|
use super::ValidatorSet;
|
||||||
|
|
||||||
type BlockNumberLookup = Box<Fn(&H256) -> Result<BlockNumber, String> + Send + Sync + 'static>;
|
type BlockNumberLookup = Box<Fn(BlockId) -> Result<BlockNumber, String> + Send + Sync + 'static>;
|
||||||
|
|
||||||
pub struct Multi {
|
pub struct Multi {
|
||||||
sets: BTreeMap<BlockNumber, Box<ValidatorSet>>,
|
sets: BTreeMap<BlockNumber, Box<ValidatorSet>>,
|
||||||
@ -40,10 +41,10 @@ impl Multi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn correct_set(&self, bh: &H256) -> Option<&ValidatorSet> {
|
fn correct_set(&self, id: BlockId) -> Option<&ValidatorSet> {
|
||||||
match self
|
match self
|
||||||
.block_number
|
.block_number
|
||||||
.read()(bh)
|
.read()(id)
|
||||||
.map(|parent_block| self
|
.map(|parent_block| self
|
||||||
.sets
|
.sets
|
||||||
.iter()
|
.iter()
|
||||||
@ -66,16 +67,24 @@ impl Multi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ValidatorSet for Multi {
|
impl ValidatorSet for Multi {
|
||||||
fn contains(&self, bh: &H256, address: &Address) -> bool {
|
fn default_caller(&self, block_id: BlockId) -> Box<Call> {
|
||||||
self.correct_set(bh).map_or(false, |set| set.contains(bh, address))
|
self.correct_set(block_id).map(|set| set.default_caller(block_id))
|
||||||
|
.unwrap_or(Box::new(|_, _| Err("No validator set for given ID.".into())))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get(&self, bh: &H256, nonce: usize) -> Address {
|
fn contains_with_caller(&self, bh: &H256, address: &Address, caller: &Call) -> bool {
|
||||||
self.correct_set(bh).map_or_else(Default::default, |set| set.get(bh, nonce))
|
self.correct_set(BlockId::Hash(*bh))
|
||||||
|
.map_or(false, |set| set.contains_with_caller(bh, address, caller))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn count(&self, bh: &H256) -> usize {
|
fn get_with_caller(&self, bh: &H256, nonce: usize, caller: &Call) -> Address {
|
||||||
self.correct_set(bh).map_or_else(usize::max_value, |set| set.count(bh))
|
self.correct_set(BlockId::Hash(*bh))
|
||||||
|
.map_or_else(Default::default, |set| set.get_with_caller(bh, nonce, caller))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn count_with_caller(&self, bh: &H256, caller: &Call) -> usize {
|
||||||
|
self.correct_set(BlockId::Hash(*bh))
|
||||||
|
.map_or_else(usize::max_value, |set| set.count_with_caller(bh, caller))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn report_malicious(&self, validator: &Address) {
|
fn report_malicious(&self, validator: &Address) {
|
||||||
@ -94,10 +103,10 @@ impl ValidatorSet for Multi {
|
|||||||
for set in self.sets.values() {
|
for set in self.sets.values() {
|
||||||
set.register_contract(client.clone());
|
set.register_contract(client.clone());
|
||||||
}
|
}
|
||||||
*self.block_number.write() = Box::new(move |hash| client
|
*self.block_number.write() = Box::new(move |id| client
|
||||||
.upgrade()
|
.upgrade()
|
||||||
.ok_or("No client!".into())
|
.ok_or("No client!".into())
|
||||||
.and_then(|c| c.block_number(BlockId::Hash(*hash)).ok_or("Unknown block".into())));
|
.and_then(|c| c.block_number(id).ok_or("Unknown block".into())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ use native_contracts::ValidatorSet as Provider;
|
|||||||
use util::*;
|
use util::*;
|
||||||
use util::cache::MemoryLruCache;
|
use util::cache::MemoryLruCache;
|
||||||
|
|
||||||
|
use engines::Call;
|
||||||
use types::ids::BlockId;
|
use types::ids::BlockId;
|
||||||
use client::{Client, BlockChainClient};
|
use client::{Client, BlockChainClient};
|
||||||
|
|
||||||
@ -49,17 +50,9 @@ impl ValidatorSafeContract {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_call(&self, id: BlockId) -> Box<Fn(Address, Vec<u8>) -> Result<Vec<u8>, String>> {
|
|
||||||
let client = self.client.read().clone();
|
|
||||||
Box::new(move |addr, data| client.as_ref()
|
|
||||||
.and_then(Weak::upgrade)
|
|
||||||
.ok_or("No client!".into())
|
|
||||||
.and_then(|c| c.call_contract(id, addr, data)))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Queries the state and gets the set of validators.
|
/// Queries the state and gets the set of validators.
|
||||||
fn get_list(&self, block_hash: H256) -> Option<SimpleList> {
|
fn get_list(&self, caller: &Call) -> Option<SimpleList> {
|
||||||
match self.provider.get_validators(&*self.do_call(BlockId::Hash(block_hash))).wait() {
|
match self.provider.get_validators(caller).wait() {
|
||||||
Ok(new) => {
|
Ok(new) => {
|
||||||
debug!(target: "engine", "Set of validators obtained: {:?}", new);
|
debug!(target: "engine", "Set of validators obtained: {:?}", new);
|
||||||
Some(SimpleList::new(new))
|
Some(SimpleList::new(new))
|
||||||
@ -73,14 +66,22 @@ impl ValidatorSafeContract {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ValidatorSet for ValidatorSafeContract {
|
impl ValidatorSet for ValidatorSafeContract {
|
||||||
fn contains(&self, block_hash: &H256, address: &Address) -> bool {
|
fn default_caller(&self, id: BlockId) -> Box<Call> {
|
||||||
|
let client = self.client.read().clone();
|
||||||
|
Box::new(move |addr, data| client.as_ref()
|
||||||
|
.and_then(Weak::upgrade)
|
||||||
|
.ok_or("No client!".into())
|
||||||
|
.and_then(|c| c.call_contract(id, addr, data)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn contains_with_caller(&self, block_hash: &H256, address: &Address, caller: &Call) -> bool {
|
||||||
let mut guard = self.validators.write();
|
let mut guard = self.validators.write();
|
||||||
let maybe_existing = guard
|
let maybe_existing = guard
|
||||||
.get_mut(block_hash)
|
.get_mut(block_hash)
|
||||||
.map(|list| list.contains(block_hash, address));
|
.map(|list| list.contains(block_hash, address));
|
||||||
maybe_existing
|
maybe_existing
|
||||||
.unwrap_or_else(|| self
|
.unwrap_or_else(|| self
|
||||||
.get_list(block_hash.clone())
|
.get_list(caller)
|
||||||
.map_or(false, |list| {
|
.map_or(false, |list| {
|
||||||
let contains = list.contains(block_hash, address);
|
let contains = list.contains(block_hash, address);
|
||||||
guard.insert(block_hash.clone(), list);
|
guard.insert(block_hash.clone(), list);
|
||||||
@ -88,14 +89,14 @@ impl ValidatorSet for ValidatorSafeContract {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get(&self, block_hash: &H256, nonce: usize) -> Address {
|
fn get_with_caller(&self, block_hash: &H256, nonce: usize, caller: &Call) -> Address {
|
||||||
let mut guard = self.validators.write();
|
let mut guard = self.validators.write();
|
||||||
let maybe_existing = guard
|
let maybe_existing = guard
|
||||||
.get_mut(block_hash)
|
.get_mut(block_hash)
|
||||||
.map(|list| list.get(block_hash, nonce));
|
.map(|list| list.get(block_hash, nonce));
|
||||||
maybe_existing
|
maybe_existing
|
||||||
.unwrap_or_else(|| self
|
.unwrap_or_else(|| self
|
||||||
.get_list(block_hash.clone())
|
.get_list(caller)
|
||||||
.map_or_else(Default::default, |list| {
|
.map_or_else(Default::default, |list| {
|
||||||
let address = list.get(block_hash, nonce);
|
let address = list.get(block_hash, nonce);
|
||||||
guard.insert(block_hash.clone(), list);
|
guard.insert(block_hash.clone(), list);
|
||||||
@ -103,14 +104,14 @@ impl ValidatorSet for ValidatorSafeContract {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn count(&self, block_hash: &H256) -> usize {
|
fn count_with_caller(&self, block_hash: &H256, caller: &Call) -> usize {
|
||||||
let mut guard = self.validators.write();
|
let mut guard = self.validators.write();
|
||||||
let maybe_existing = guard
|
let maybe_existing = guard
|
||||||
.get_mut(block_hash)
|
.get_mut(block_hash)
|
||||||
.map(|list| list.count(block_hash));
|
.map(|list| list.count(block_hash));
|
||||||
maybe_existing
|
maybe_existing
|
||||||
.unwrap_or_else(|| self
|
.unwrap_or_else(|| self
|
||||||
.get_list(block_hash.clone())
|
.get_list(caller)
|
||||||
.map_or_else(usize::max_value, |list| {
|
.map_or_else(usize::max_value, |list| {
|
||||||
let address = list.count(block_hash);
|
let address = list.count(block_hash);
|
||||||
guard.insert(block_hash.clone(), list);
|
guard.insert(block_hash.clone(), list);
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
/// Preconfigured validator list.
|
/// Preconfigured validator list.
|
||||||
|
|
||||||
use util::{H256, Address, HeapSizeOf};
|
use util::{H256, Address, HeapSizeOf};
|
||||||
|
|
||||||
|
use engines::Call;
|
||||||
use super::ValidatorSet;
|
use super::ValidatorSet;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Default)]
|
#[derive(Debug, PartialEq, Eq, Default)]
|
||||||
@ -39,16 +41,20 @@ impl HeapSizeOf for SimpleList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ValidatorSet for SimpleList {
|
impl ValidatorSet for SimpleList {
|
||||||
fn contains(&self, _bh: &H256, address: &Address) -> bool {
|
fn default_caller(&self, _block_id: ::ids::BlockId) -> Box<Call> {
|
||||||
|
Box::new(|_, _| Err("Simple list doesn't require calls.".into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn contains_with_caller(&self, _bh: &H256, address: &Address, _: &Call) -> bool {
|
||||||
self.validators.contains(address)
|
self.validators.contains(address)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get(&self, _bh: &H256, nonce: usize) -> Address {
|
fn get_with_caller(&self, _bh: &H256, nonce: usize, _: &Call) -> Address {
|
||||||
let validator_n = self.validators.len();
|
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()
|
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_with_caller(&self, _bh: &H256, _: &Call) -> usize {
|
||||||
self.validators.len()
|
self.validators.len()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user