epoch verifier rename
This commit is contained in:
@@ -66,18 +66,18 @@ impl ValidatorSet for ValidatorContract {
|
||||
self.validators.default_caller(id)
|
||||
}
|
||||
|
||||
fn proof_required(&self, header: &Header, block: Option<&[u8]>, receipts: Option<&[::receipt::Receipt]>)
|
||||
-> ::engines::RequiresProof
|
||||
fn is_epoch_end(&self, header: &Header, block: Option<&[u8]>, receipts: Option<&[::receipt::Receipt]>)
|
||||
-> ::engines::EpochChange
|
||||
{
|
||||
self.validators.proof_required(header, block, receipts)
|
||||
self.validators.is_epoch_end(header, block, receipts)
|
||||
}
|
||||
|
||||
fn generate_proof(&self, header: &Header, caller: &Call) -> Result<Vec<u8>, String> {
|
||||
self.validators.generate_proof(header, caller)
|
||||
fn epoch_proof(&self, header: &Header, caller: &Call) -> Result<Vec<u8>, String> {
|
||||
self.validators.epoch_proof(header, caller)
|
||||
}
|
||||
|
||||
fn chain_verifier(&self, header: &Header, proof: Vec<u8>) -> Result<super::SimpleList, ::error::Error> {
|
||||
self.validators.chain_verifier(header, proof)
|
||||
fn epoch_set(&self, header: &Header, proof: &[u8]) -> Result<(U256, super::SimpleList), ::error::Error> {
|
||||
self.validators.epoch_set(header, proof)
|
||||
}
|
||||
|
||||
fn contains_with_caller(&self, bh: &H256, address: &Address, caller: &Call) -> bool {
|
||||
|
||||
@@ -23,7 +23,7 @@ mod multi;
|
||||
|
||||
use std::sync::Weak;
|
||||
use ids::BlockId;
|
||||
use util::{Address, H256};
|
||||
use util::{Address, H256, U256};
|
||||
use ethjson::spec::ValidatorSet as ValidatorSpec;
|
||||
use client::Client;
|
||||
use header::Header;
|
||||
@@ -72,26 +72,32 @@ pub trait ValidatorSet: Send + Sync {
|
||||
self.count_with_caller(parent, &*default)
|
||||
}
|
||||
|
||||
/// Whether a validation proof is required at the given block.
|
||||
/// Whether this block is the last one in its epoch.
|
||||
/// 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,
|
||||
/// Return `Yes` or `No` 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;
|
||||
/// If block or receipts are provided, do not return `Unsure` indicating
|
||||
/// need for them.
|
||||
fn is_epoch_end(&self, header: &Header, block: Option<&[u8]>, receipts: Option<&[::receipt::Receipt]>)
|
||||
-> super::EpochChange;
|
||||
|
||||
/// Generate a validation proof at the given header.
|
||||
/// Generate epoch proof.
|
||||
/// 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>;
|
||||
fn epoch_proof(&self, header: &Header, caller: &Call) -> Result<Vec<u8>, String>;
|
||||
|
||||
/// Create a fully self-contained validator set from the given proof.
|
||||
fn chain_verifier(&self, header: &Header, proof: Vec<u8>) -> Result<SimpleList, ::error::Error>;
|
||||
/// Recover the validator set for all
|
||||
///
|
||||
/// May fail if the given header doesn't kick off an epoch or
|
||||
/// the proof is invalid.
|
||||
///
|
||||
/// Returns the epoch number and proof.
|
||||
fn epoch_set(&self, header: &Header, proof: &[u8]) -> Result<(U256, SimpleList), ::error::Error>;
|
||||
|
||||
/// Checks if a given address is a validator, with the given function
|
||||
/// for executing synchronous calls to contracts.
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::sync::Weak;
|
||||
use engines::{Call, RequiresProof};
|
||||
use util::{H256, Address, RwLock};
|
||||
use engines::{Call, EpochChange};
|
||||
use util::{H256, Address, RwLock, U256};
|
||||
use ids::BlockId;
|
||||
use header::{BlockNumber, Header};
|
||||
use client::{Client, BlockChainClient};
|
||||
@@ -43,9 +43,7 @@ impl Multi {
|
||||
|
||||
fn correct_set(&self, id: BlockId) -> Option<&ValidatorSet> {
|
||||
match self.block_number.read()(id).map(|parent_block| self.correct_set_by_number(parent_block)) {
|
||||
Ok(set) => {
|
||||
Some(set)
|
||||
},
|
||||
Ok((_, set)) => Some(set),
|
||||
Err(e) => {
|
||||
debug!(target: "engine", "ValidatorSet could not be recovered: {}", e);
|
||||
None
|
||||
@@ -53,7 +51,9 @@ impl Multi {
|
||||
}
|
||||
}
|
||||
|
||||
fn correct_set_by_number(&self, parent_block: BlockNumber) -> &ValidatorSet {
|
||||
// get correct set by block number, along with block number at which
|
||||
// this set was activated.
|
||||
fn correct_set_by_number(&self, parent_block: BlockNumber) -> (BlockNumber, &ValidatorSet) {
|
||||
let (block, set) = self.sets.iter()
|
||||
.rev()
|
||||
.find(|&(block, _)| *block <= parent_block + 1)
|
||||
@@ -62,7 +62,7 @@ impl Multi {
|
||||
qed");
|
||||
|
||||
trace!(target: "engine", "Multi ValidatorSet retrieved for block {}.", block);
|
||||
&**set
|
||||
(*block, &**set)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,18 +72,22 @@ 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
|
||||
fn is_epoch_end(&self, header: &Header, block: Option<&[u8]>, receipts: Option<&[::receipt::Receipt]>)
|
||||
-> EpochChange
|
||||
{
|
||||
self.correct_set_by_number(header.number()).proof_required(header, block, receipts)
|
||||
self.correct_set_by_number(header.number()).1.is_epoch_end(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 epoch_proof(&self, header: &Header, caller: &Call) -> Result<Vec<u8>, String> {
|
||||
self.correct_set_by_number(header.number()).1.epoch_proof(header, caller)
|
||||
}
|
||||
|
||||
fn chain_verifier(&self, header: &Header, proof: Vec<u8>) -> Result<super::SimpleList, ::error::Error> {
|
||||
self.correct_set_by_number(header.number()).chain_verifier(header, proof)
|
||||
fn epoch_set(&self, header: &Header, proof: &[u8]) -> Result<(U256, super::SimpleList), ::error::Error> {
|
||||
// "multi" epoch is the inner set's epoch plus the transition block to that set.
|
||||
// ensures epoch increases monotonically.
|
||||
let (set_block, set) = self.correct_set_by_number(header.number());
|
||||
let (inner_epoch, list) = set.epoch_set(header, proof)?;
|
||||
Ok((U256::from(set_block) + inner_epoch, list))
|
||||
}
|
||||
|
||||
fn contains_with_caller(&self, bh: &H256, address: &Address, caller: &Call) -> bool {
|
||||
|
||||
@@ -126,16 +126,16 @@ 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
|
||||
fn is_epoch_end(&self, header: &Header, _block: Option<&[u8]>, receipts: Option<&[::receipt::Receipt]>)
|
||||
-> ::engines::EpochChange
|
||||
{
|
||||
let bloom = self.expected_bloom(header);
|
||||
let header_bloom = header.log_bloom();
|
||||
|
||||
if &bloom & header_bloom != bloom { return ::engines::RequiresProof::No }
|
||||
if &bloom & header_bloom != bloom { return ::engines::EpochChange::No }
|
||||
|
||||
match receipts {
|
||||
None => ::engines::RequiresProof::Unsure(::engines::Unsure::NeedsReceipts),
|
||||
None => ::engines::EpochChange::Unsure(::engines::Unsure::NeedsReceipts),
|
||||
Some(receipts) => {
|
||||
let check_log = |log: &LogEntry| {
|
||||
log.address == self.address &&
|
||||
@@ -149,7 +149,11 @@ impl ValidatorSet for ValidatorSafeContract {
|
||||
.event("ValidatorsChanged".into())
|
||||
.expect("Contract known ahead of time to have `ValidatorsChanged` event; qed");
|
||||
|
||||
// iterate in reverse because only the _last_ change in a given
|
||||
// block actually has any effect.
|
||||
// the contract should only increment the nonce once.
|
||||
let mut decoded_events = receipts.iter()
|
||||
.rev()
|
||||
.filter(|r| &bloom & &r.log_bloom == bloom)
|
||||
.flat_map(|r| r.logs.iter())
|
||||
.filter(move |l| check_log(l))
|
||||
@@ -164,7 +168,7 @@ impl ValidatorSet for ValidatorSafeContract {
|
||||
|
||||
// TODO: are multiple transitions per block possible?
|
||||
match decoded_events.next() {
|
||||
None => ::engines::RequiresProof::No,
|
||||
None => ::engines::EpochChange::No,
|
||||
Some(matched_event) => {
|
||||
// decode log manually until the native contract generator is
|
||||
// good enough to do it for us.
|
||||
@@ -181,10 +185,10 @@ impl ValidatorSet for ValidatorSafeContract {
|
||||
|
||||
match (nonce, validators) {
|
||||
(Some(nonce), Some(validators)) =>
|
||||
::engines::RequiresProof::Yes(Some(encode_proof(nonce, &validators))),
|
||||
::engines::EpochChange::Yes(encode_proof(nonce, &validators)),
|
||||
_ => {
|
||||
debug!(target: "engine", "Successfully decoded log turned out to be bad.");
|
||||
::engines::RequiresProof::No
|
||||
::engines::EpochChange::No
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -195,20 +199,21 @@ impl ValidatorSet for ValidatorSafeContract {
|
||||
|
||||
// the proof we generate is an RLP list containing two parts.
|
||||
// (nonce, validators)
|
||||
fn generate_proof(&self, _header: &Header, caller: &Call) -> Result<Vec<u8>, String> {
|
||||
fn epoch_proof(&self, _header: &Header, caller: &Call) -> Result<Vec<u8>, String> {
|
||||
match (self.get_nonce(caller), self.get_list(caller)) {
|
||||
(Some(nonce), Some(list)) => Ok(encode_proof(nonce, &list.into_inner())),
|
||||
_ => Err("Caller insufficient to generate validator proof.".into()),
|
||||
}
|
||||
}
|
||||
|
||||
fn chain_verifier(&self, _header: &Header, proof: Vec<u8>) -> Result<SimpleList, ::error::Error> {
|
||||
fn epoch_set(&self, _header: &Header, proof: &[u8]) -> Result<(U256, SimpleList), ::error::Error> {
|
||||
use rlp::UntrustedRlp;
|
||||
|
||||
let rlp = UntrustedRlp::new(&proof);
|
||||
let rlp = UntrustedRlp::new(proof);
|
||||
let nonce: U256 = rlp.val_at(0)?;
|
||||
let validators: Vec<Address> = rlp.list_at(1)?;
|
||||
|
||||
Ok(SimpleList::new(validators))
|
||||
Ok((nonce, SimpleList::new(validators)))
|
||||
}
|
||||
|
||||
fn contains_with_caller(&self, block_hash: &H256, address: &Address, caller: &Call) -> bool {
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
/// Preconfigured validator list.
|
||||
|
||||
use util::{H256, Address, HeapSizeOf};
|
||||
use util::{H256, Address, HeapSizeOf, U256};
|
||||
|
||||
use engines::Call;
|
||||
use header::Header;
|
||||
@@ -53,18 +53,18 @@ 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
|
||||
fn is_epoch_end(&self, _header: &Header, _block: Option<&[u8]>, _receipts: Option<&[::receipt::Receipt]>)
|
||||
-> ::engines::EpochChange
|
||||
{
|
||||
::engines::RequiresProof::No
|
||||
::engines::EpochChange::No
|
||||
}
|
||||
|
||||
fn generate_proof(&self, _header: &Header, _caller: &Call) -> Result<Vec<u8>, String> {
|
||||
fn epoch_proof(&self, _header: &Header, _caller: &Call) -> Result<Vec<u8>, String> {
|
||||
Ok(Vec::new())
|
||||
}
|
||||
|
||||
fn chain_verifier(&self, _header: &Header, _: Vec<u8>) -> Result<SimpleList, ::error::Error> {
|
||||
Ok(self.clone())
|
||||
fn epoch_set(&self, _header: &Header, _: &[u8]) -> Result<(U256, SimpleList), ::error::Error> {
|
||||
Ok((0.into(), self.clone()))
|
||||
}
|
||||
|
||||
fn contains_with_caller(&self, _bh: &H256, address: &Address, _: &Call) -> bool {
|
||||
|
||||
Reference in New Issue
Block a user