skeleton for proof checking
This commit is contained in:
@@ -25,6 +25,7 @@ use native_contracts::ValidatorReport as Provider;
|
||||
|
||||
use client::{Client, BlockChainClient};
|
||||
use engines::Call;
|
||||
use header::Header;
|
||||
|
||||
use super::ValidatorSet;
|
||||
use super::safe_contract::ValidatorSafeContract;
|
||||
@@ -65,6 +66,16 @@ impl ValidatorSet for ValidatorContract {
|
||||
self.validators.default_caller(id)
|
||||
}
|
||||
|
||||
fn proof_required(&self, header: &Header, block: Option<&[u8]>, receipts: Option<&[::receipt::Receipt]>)
|
||||
-> ::engines::RequiresProof
|
||||
{
|
||||
self.validators.proof_required(header, block, receipts)
|
||||
}
|
||||
|
||||
fn generate_proof(&self, header: &Header, caller: &Call) -> Result<Vec<u8>, String> {
|
||||
self.validators.generate_proof(header, caller)
|
||||
}
|
||||
|
||||
fn contains_with_caller(&self, bh: &H256, address: &Address, caller: &Call) -> bool {
|
||||
self.validators.contains_with_caller(bh, address, caller)
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ use ids::BlockId;
|
||||
use util::{Address, H256};
|
||||
use ethjson::spec::ValidatorSet as ValidatorSpec;
|
||||
use client::Client;
|
||||
use header::Header;
|
||||
|
||||
use self::simple_list::SimpleList;
|
||||
use self::contract::ValidatorContract;
|
||||
@@ -47,9 +48,10 @@ pub fn new_validator_set(spec: ValidatorSpec) -> Box<ValidatorSet> {
|
||||
}
|
||||
|
||||
/// A validator set.
|
||||
// TODO [keorn]: remove internal callers.
|
||||
pub trait ValidatorSet: Send + Sync {
|
||||
/// Get the default "Call" helper, for use in general operation.
|
||||
// TODO [keorn]: this is a hack intended to migrate off of
|
||||
// a strict dependency on state always being available.
|
||||
fn default_caller(&self, block_id: BlockId) -> Box<Call>;
|
||||
|
||||
/// Checks if a given address is a validator,
|
||||
@@ -63,12 +65,31 @@ pub trait ValidatorSet: Send + Sync {
|
||||
let default = self.default_caller(BlockId::Hash(*parent));
|
||||
self.get_with_caller(parent, nonce, &*default)
|
||||
}
|
||||
|
||||
/// Returns the current number of validators.
|
||||
fn count(&self, parent: &H256) -> usize {
|
||||
let default = self.default_caller(BlockId::Hash(*parent));
|
||||
self.count_with_caller(parent, &*default)
|
||||
}
|
||||
|
||||
/// Whether a validation proof is required at the given block.
|
||||
/// Usually indicates that the validator set changed at the given block.
|
||||
///
|
||||
/// Should not inspect state! This is used in situations where
|
||||
/// state is not generally available.
|
||||
///
|
||||
/// Return `Ok` with a flag indicating whether it changed at the given header,
|
||||
/// or `Unsure` indicating a need for more information.
|
||||
///
|
||||
/// This may or may not be called in a loop.
|
||||
fn proof_required(&self, header: &Header, block: Option<&[u8]>, receipts: Option<&[::receipt::Receipt]>)
|
||||
-> super::RequiresProof;
|
||||
|
||||
/// Generate a validation proof at the given header.
|
||||
/// Must interact with state only through the given caller!
|
||||
/// Otherwise, generated proofs may be wrong.
|
||||
fn generate_proof(&self, header: &Header, caller: &Call) -> Result<Vec<u8>, String>;
|
||||
|
||||
/// 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;
|
||||
|
||||
@@ -18,10 +18,10 @@
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::sync::Weak;
|
||||
use engines::Call;
|
||||
use engines::{Call, RequiresProof};
|
||||
use util::{H256, Address, RwLock};
|
||||
use ids::BlockId;
|
||||
use header::BlockNumber;
|
||||
use header::{BlockNumber, Header};
|
||||
use client::{Client, BlockChainClient};
|
||||
use super::ValidatorSet;
|
||||
|
||||
@@ -42,21 +42,9 @@ impl Multi {
|
||||
}
|
||||
|
||||
fn correct_set(&self, id: BlockId) -> Option<&ValidatorSet> {
|
||||
match self
|
||||
.block_number
|
||||
.read()(id)
|
||||
.map(|parent_block| self
|
||||
.sets
|
||||
.iter()
|
||||
.rev()
|
||||
.find(|&(block, _)| *block <= parent_block + 1)
|
||||
.expect("constructor validation ensures that there is at least one validator set for block 0;
|
||||
block 0 is less than any uint;
|
||||
qed")
|
||||
) {
|
||||
Ok((block, set)) => {
|
||||
trace!(target: "engine", "Multi ValidatorSet retrieved for block {}.", block);
|
||||
Some(&**set)
|
||||
match self.block_number.read()(id).map(|parent_block| self.correct_set_by_number(parent_block)) {
|
||||
Ok(set) => {
|
||||
Some(set)
|
||||
},
|
||||
Err(e) => {
|
||||
debug!(target: "engine", "ValidatorSet could not be recovered: {}", e);
|
||||
@@ -64,6 +52,18 @@ impl Multi {
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn correct_set_by_number(&self, parent_block: BlockNumber) -> &ValidatorSet {
|
||||
let (block, set) = self.sets.iter()
|
||||
.rev()
|
||||
.find(|&(block, _)| *block <= parent_block + 1)
|
||||
.expect("constructor validation ensures that there is at least one validator set for block 0;
|
||||
block 0 is less than any uint;
|
||||
qed");
|
||||
|
||||
trace!(target: "engine", "Multi ValidatorSet retrieved for block {}.", block);
|
||||
&**set
|
||||
}
|
||||
}
|
||||
|
||||
impl ValidatorSet for Multi {
|
||||
@@ -72,6 +72,16 @@ impl ValidatorSet for Multi {
|
||||
.unwrap_or(Box::new(|_, _| Err("No validator set for given ID.".into())))
|
||||
}
|
||||
|
||||
fn proof_required(&self, header: &Header, block: Option<&[u8]>, receipts: Option<&[::receipt::Receipt]>)
|
||||
-> RequiresProof
|
||||
{
|
||||
self.correct_set_by_number(header.number()).proof_required(header, block, receipts)
|
||||
}
|
||||
|
||||
fn generate_proof(&self, header: &Header, caller: &Call) -> Result<Vec<u8>, String> {
|
||||
self.correct_set_by_number(header.number()).generate_proof(header, caller)
|
||||
}
|
||||
|
||||
fn contains_with_caller(&self, bh: &H256, address: &Address, caller: &Call) -> bool {
|
||||
self.correct_set(BlockId::Hash(*bh))
|
||||
.map_or(false, |set| set.contains_with_caller(bh, address, caller))
|
||||
|
||||
@@ -26,6 +26,7 @@ use util::cache::MemoryLruCache;
|
||||
use engines::Call;
|
||||
use types::ids::BlockId;
|
||||
use client::{Client, BlockChainClient};
|
||||
use header::Header;
|
||||
|
||||
use super::ValidatorSet;
|
||||
use super::simple_list::SimpleList;
|
||||
@@ -74,6 +75,19 @@ impl ValidatorSet for ValidatorSafeContract {
|
||||
.and_then(|c| c.call_contract(id, addr, data)))
|
||||
}
|
||||
|
||||
fn proof_required(&self, header: &Header, block: Option<&[u8]>, receipts: Option<&[::receipt::Receipt]>)
|
||||
-> ::engines::RequiresProof
|
||||
{
|
||||
// TODO: check blooms first and then logs for the
|
||||
// ValidatorsChanged([parent_hash, nonce], new_validators) log event.
|
||||
::engines::RequiresProof::No
|
||||
}
|
||||
|
||||
fn generate_proof(&self, header: &Header, caller: &Call) -> Result<Vec<u8>, String> {
|
||||
self.get_list(caller).map(|list| ::rlp::encode_list(&list.into_inner()).to_vec())
|
||||
.ok_or_else(|| "Caller insufficient to get validator list.".into())
|
||||
}
|
||||
|
||||
fn contains_with_caller(&self, block_hash: &H256, address: &Address, caller: &Call) -> bool {
|
||||
let mut guard = self.validators.write();
|
||||
let maybe_existing = guard
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
use util::{H256, Address, HeapSizeOf};
|
||||
|
||||
use engines::Call;
|
||||
use header::Header;
|
||||
use super::ValidatorSet;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Default)]
|
||||
@@ -27,11 +28,17 @@ pub struct SimpleList {
|
||||
}
|
||||
|
||||
impl SimpleList {
|
||||
/// Create a new `SimpleList`.
|
||||
pub fn new(validators: Vec<Address>) -> Self {
|
||||
SimpleList {
|
||||
validators: validators,
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert into inner representation.
|
||||
pub fn into_inner(self) -> Vec<Address> {
|
||||
self.validators
|
||||
}
|
||||
}
|
||||
|
||||
impl HeapSizeOf for SimpleList {
|
||||
@@ -45,6 +52,16 @@ impl ValidatorSet for SimpleList {
|
||||
Box::new(|_, _| Err("Simple list doesn't require calls.".into()))
|
||||
}
|
||||
|
||||
fn proof_required(&self, _header: &Header, _block: Option<&[u8]>, _receipts: Option<&[::receipt::Receipt]>)
|
||||
-> ::engines::RequiresProof
|
||||
{
|
||||
::engines::RequiresProof::No
|
||||
}
|
||||
|
||||
fn generate_proof(&self, _header: &Header, _caller: &Call) -> Result<Vec<u8>, String> {
|
||||
Ok(Vec::new())
|
||||
}
|
||||
|
||||
fn contains_with_caller(&self, _bh: &H256, address: &Address, _: &Call) -> bool {
|
||||
self.validators.contains(address)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user