epoch verifier rename
This commit is contained in:
parent
e1fa4ab8ec
commit
f6f9816ef4
@ -579,11 +579,11 @@ impl Client {
|
|||||||
// generate validation proof if the engine requires them.
|
// generate validation proof if the engine requires them.
|
||||||
// TODO: make conditional?
|
// TODO: make conditional?
|
||||||
let generate_proof = {
|
let generate_proof = {
|
||||||
use engines::RequiresProof;
|
use engines::EpochChange;
|
||||||
match self.engine.proof_required(block.header(), Some(block_data), Some(&receipts)) {
|
match self.engine.is_epoch_end(block.header(), Some(block_data), Some(&receipts)) {
|
||||||
RequiresProof::Yes(_) => true,
|
EpochChange::Yes(_) => true,
|
||||||
RequiresProof::No => false,
|
EpochChange::No => false,
|
||||||
RequiresProof::Unsure(_) => {
|
EpochChange::Unsure(_) => {
|
||||||
warn!(target: "client", "Detected invalid engine implementation.");
|
warn!(target: "client", "Detected invalid engine implementation.");
|
||||||
warn!(target: "client", "Engine claims to require more block data, but everything provided.");
|
warn!(target: "client", "Engine claims to require more block data, but everything provided.");
|
||||||
false
|
false
|
||||||
|
@ -132,12 +132,14 @@ pub struct AuthorityRound {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// header-chain validator.
|
// header-chain validator.
|
||||||
struct ChainVerifier {
|
struct EpochVerifier {
|
||||||
|
epoch_number: U256,
|
||||||
step: Arc<Step>,
|
step: Arc<Step>,
|
||||||
subchain_validators: SimpleList,
|
subchain_validators: SimpleList,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl super::ChainVerifier for ChainVerifier {
|
impl super::EpochVerifier for EpochVerifier {
|
||||||
|
fn epoch_number(&self) -> U256 { self.epoch_number.clone() }
|
||||||
fn verify_light(&self, header: &Header) -> Result<(), Error> {
|
fn verify_light(&self, header: &Header) -> Result<(), Error> {
|
||||||
// always check the seal since it's fast.
|
// always check the seal since it's fast.
|
||||||
// nothing heavier to do.
|
// nothing heavier to do.
|
||||||
@ -398,22 +400,23 @@ impl Engine for AuthorityRound {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// the proofs we need just allow us to get the full validator set.
|
// the proofs we need just allow us to get the full validator set.
|
||||||
fn prove_with_caller(&self, header: &Header, caller: &Call) -> Result<Bytes, Error> {
|
fn epoch_proof(&self, header: &Header, caller: &Call) -> Result<Bytes, Error> {
|
||||||
self.validators.generate_proof(header, caller)
|
self.validators.epoch_proof(header, caller)
|
||||||
.map_err(|e| EngineError::InsufficientProof(e).into())
|
.map_err(|e| EngineError::InsufficientProof(e).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn proof_required(&self, header: &Header, block: Option<&[u8]>, receipts: Option<&[::receipt::Receipt]>)
|
fn is_epoch_end(&self, header: &Header, block: Option<&[u8]>, receipts: Option<&[::receipt::Receipt]>)
|
||||||
-> super::RequiresProof
|
-> super::EpochChange
|
||||||
{
|
{
|
||||||
self.validators.proof_required(header, block, receipts)
|
self.validators.is_epoch_end(header, block, receipts)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn chain_verifier(&self, header: &Header, proof: Bytes) -> Result<Box<super::ChainVerifier>, Error> {
|
fn epoch_verifier(&self, header: &Header, proof: &[u8]) -> Result<Box<super::EpochVerifier>, Error> {
|
||||||
// extract a simple list from the proof.
|
// extract a simple list from the proof.
|
||||||
let simple_list = self.validators.chain_verifier(header, proof)?;
|
let (num, simple_list) = self.validators.epoch_set(header, proof)?;
|
||||||
|
|
||||||
Ok(Box::new(ChainVerifier {
|
Ok(Box::new(EpochVerifier {
|
||||||
|
epoch_number: num,
|
||||||
step: self.step.clone(),
|
step: self.step.clone(),
|
||||||
subchain_validators: simple_list,
|
subchain_validators: simple_list,
|
||||||
}))
|
}))
|
||||||
|
@ -23,7 +23,7 @@ use account_provider::AccountProvider;
|
|||||||
use block::*;
|
use block::*;
|
||||||
use builtin::Builtin;
|
use builtin::Builtin;
|
||||||
use spec::CommonParams;
|
use spec::CommonParams;
|
||||||
use engines::{Engine, EngineError, Seal, Call, RequiresProof};
|
use engines::{Engine, EngineError, Seal, Call, EpochChange};
|
||||||
use env_info::EnvInfo;
|
use env_info::EnvInfo;
|
||||||
use error::{BlockError, Error};
|
use error::{BlockError, Error};
|
||||||
use evm::Schedule;
|
use evm::Schedule;
|
||||||
@ -51,11 +51,15 @@ impl From<ethjson::spec::BasicAuthorityParams> for BasicAuthorityParams {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ChainVerifier(SimpleList);
|
struct EpochVerifier {
|
||||||
|
epoch_number: U256,
|
||||||
|
list: SimpleList,
|
||||||
|
}
|
||||||
|
|
||||||
impl super::ChainVerifier for ChainVerifier {
|
impl super::EpochVerifier for EpochVerifier {
|
||||||
|
fn epoch_number(&self) -> U256 { self.epoch_number.clone() }
|
||||||
fn verify_light(&self, header: &Header) -> Result<(), Error> {
|
fn verify_light(&self, header: &Header) -> Result<(), Error> {
|
||||||
verify_external(header, &self.0)
|
verify_external(header, &self.list)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,22 +185,25 @@ impl Engine for BasicAuthority {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// the proofs we need just allow us to get the full validator set.
|
// the proofs we need just allow us to get the full validator set.
|
||||||
fn prove_with_caller(&self, header: &Header, caller: &Call) -> Result<Bytes, Error> {
|
fn epoch_proof(&self, header: &Header, caller: &Call) -> Result<Bytes, Error> {
|
||||||
self.validators.generate_proof(header, caller)
|
self.validators.epoch_proof(header, caller)
|
||||||
.map_err(|e| EngineError::InsufficientProof(e).into())
|
.map_err(|e| EngineError::InsufficientProof(e).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn proof_required(&self, header: &Header, block: Option<&[u8]>, receipts: Option<&[::receipt::Receipt]>)
|
fn is_epoch_end(&self, header: &Header, block: Option<&[u8]>, receipts: Option<&[::receipt::Receipt]>)
|
||||||
-> RequiresProof
|
-> EpochChange
|
||||||
{
|
{
|
||||||
self.validators.proof_required(header, block, receipts)
|
self.validators.is_epoch_end(header, block, receipts)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn chain_verifier(&self, header: &Header, proof: Bytes) -> Result<Box<super::ChainVerifier>, Error> {
|
fn epoch_verifier(&self, header: &Header, proof: &[u8]) -> Result<Box<super::EpochVerifier>, Error> {
|
||||||
// extract a simple list from the proof.
|
// extract a simple list from the proof.
|
||||||
let simple_list = self.validators.chain_verifier(header, proof)?;
|
let (num, simple_list) = self.validators.epoch_set(header, proof)?;
|
||||||
|
|
||||||
Ok(Box::new(ChainVerifier(simple_list)))
|
Ok(Box::new(EpochVerifier {
|
||||||
|
epoch_number: num,
|
||||||
|
list: simple_list,
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn register_client(&self, client: Weak<Client>) {
|
fn register_client(&self, client: Weak<Client>) {
|
||||||
|
@ -14,18 +14,21 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
// Chain verifiers.
|
// Epoch verifiers.
|
||||||
|
|
||||||
use error::Error;
|
use error::Error;
|
||||||
use header::Header;
|
use header::Header;
|
||||||
|
use util::U256;
|
||||||
|
|
||||||
/// Sequential chain verifier.
|
/// Verifier for all blocks within an epoch without accessing
|
||||||
///
|
///
|
||||||
/// See docs on `Engine` relating to proving functions for more details.
|
/// See docs on `Engine` relating to proving functions for more details.
|
||||||
/// Headers here will have already passed "basic" verification.
|
pub trait EpochVerifier: Sync {
|
||||||
pub trait ChainVerifier {
|
/// Get the epoch number.
|
||||||
|
fn epoch_number(&self) -> U256;
|
||||||
|
|
||||||
/// Lightly verify the next block header.
|
/// Lightly verify the next block header.
|
||||||
/// This may not be a header that requires a proof.
|
/// This may not be a header belonging to a different epoch.
|
||||||
fn verify_light(&self, header: &Header) -> Result<(), Error>;
|
fn verify_light(&self, header: &Header) -> Result<(), Error>;
|
||||||
|
|
||||||
/// Perform potentially heavier checks on the next block header.
|
/// Perform potentially heavier checks on the next block header.
|
||||||
@ -34,9 +37,10 @@ pub trait ChainVerifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// No-op chain verifier.
|
/// Special "no-op" verifier for stateless, epoch-less engines.
|
||||||
pub struct NoOp;
|
pub struct NoOp;
|
||||||
|
|
||||||
impl ChainVerifier for NoOp {
|
impl EpochVerifier for NoOp {
|
||||||
|
fn epoch_number(&self) -> U256 { 0.into() }
|
||||||
fn verify_light(&self, _header: &Header) -> Result<(), Error> { Ok(()) }
|
fn verify_light(&self, _header: &Header) -> Result<(), Error> { Ok(()) }
|
||||||
}
|
}
|
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
mod authority_round;
|
mod authority_round;
|
||||||
mod basic_authority;
|
mod basic_authority;
|
||||||
mod chain_verifier;
|
mod epoch_verifier;
|
||||||
mod instant_seal;
|
mod instant_seal;
|
||||||
mod null_engine;
|
mod null_engine;
|
||||||
mod signer;
|
mod signer;
|
||||||
@ -29,7 +29,7 @@ mod vote_collector;
|
|||||||
|
|
||||||
pub use self::authority_round::AuthorityRound;
|
pub use self::authority_round::AuthorityRound;
|
||||||
pub use self::basic_authority::BasicAuthority;
|
pub use self::basic_authority::BasicAuthority;
|
||||||
pub use self::chain_verifier::ChainVerifier;
|
pub use self::epoch_verifier::EpochVerifier;
|
||||||
pub use self::instant_seal::InstantSeal;
|
pub use self::instant_seal::InstantSeal;
|
||||||
pub use self::null_engine::NullEngine;
|
pub use self::null_engine::NullEngine;
|
||||||
pub use self::tendermint::Tendermint;
|
pub use self::tendermint::Tendermint;
|
||||||
@ -98,18 +98,19 @@ pub enum Seal {
|
|||||||
/// Type alias for a function we can make calls through synchronously.
|
/// Type alias for a function we can make calls through synchronously.
|
||||||
pub type Call = Fn(Address, Bytes) -> Result<Bytes, String>;
|
pub type Call = Fn(Address, Bytes) -> Result<Bytes, String>;
|
||||||
|
|
||||||
/// Results of a query of whether a validation proof is necessary at a block.
|
/// Results of a query of whether an epoch change occurred at the given block.
|
||||||
pub enum RequiresProof {
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub enum EpochChange {
|
||||||
/// Cannot determine until more data is passed.
|
/// Cannot determine until more data is passed.
|
||||||
Unsure(Unsure),
|
Unsure(Unsure),
|
||||||
/// Validation proof not required.
|
/// No epoch change.
|
||||||
No,
|
No,
|
||||||
/// Validation proof required, and the expected output
|
/// Validation proof required, and the expected output
|
||||||
/// if it can be recovered.
|
Yes(Bytes),
|
||||||
Yes(Option<Bytes>),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// More data required to determine if a validation proof is required.
|
/// More data required to determine if an epoch change occurred at a given block.
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
pub enum Unsure {
|
pub enum Unsure {
|
||||||
/// Needs the body.
|
/// Needs the body.
|
||||||
NeedsBody,
|
NeedsBody,
|
||||||
@ -219,37 +220,38 @@ pub trait Engine : Sync + Send {
|
|||||||
self.verify_block_basic(header, None).and_then(|_| self.verify_block_unordered(header, None))
|
self.verify_block_basic(header, None).and_then(|_| self.verify_block_unordered(header, None))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate validation proof.
|
/// Generate epoch change proof.
|
||||||
///
|
///
|
||||||
/// This will be used to generate proofs of validation as well as verify them.
|
/// This will be used to generate proofs of epoch change as well as verify them.
|
||||||
/// Must be called on blocks that have already passed basic verification.
|
/// Must be called on blocks that have already passed basic verification.
|
||||||
///
|
///
|
||||||
/// Return the "validation proof" generated.
|
/// Return the "epoch proof" generated.
|
||||||
/// This must be usable to generate a `ChainVerifier` for verifying all blocks
|
/// This must be usable to generate a `EpochVerifier` for verifying all blocks
|
||||||
/// from the supplied header up to the next one where proof is required.
|
/// from the supplied header up to the next one where proof is required.
|
||||||
///
|
///
|
||||||
/// For example, for PoA chains the proof will be a validator set,
|
/// For example, for PoA chains the proof will be a validator set,
|
||||||
/// and the corresponding `ChainVerifier` can be used to correctly validate
|
/// and the corresponding `EpochVerifier` can be used to correctly validate
|
||||||
/// all blocks produced under that `ValidatorSet`
|
/// all blocks produced under that `ValidatorSet`
|
||||||
fn prove_with_caller(&self, _header: &Header, _caller: &Call)
|
fn epoch_proof(&self, _header: &Header, _caller: &Call)
|
||||||
-> Result<Vec<u8>, Error>
|
-> Result<Vec<u8>, Error>
|
||||||
{
|
{
|
||||||
Ok(Vec::new())
|
Ok(Vec::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether a proof is required for the given header.
|
/// Whether an epoch change occurred at the given header.
|
||||||
fn proof_required(&self, _header: &Header, _block: Option<&[u8]>, _receipts: Option<&[Receipt]>)
|
/// Should not interact with state.
|
||||||
-> RequiresProof
|
fn is_epoch_end(&self, _header: &Header, _block: Option<&[u8]>, _receipts: Option<&[Receipt]>)
|
||||||
|
-> EpochChange
|
||||||
{
|
{
|
||||||
RequiresProof::No
|
EpochChange::No
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a subchain verifier from validation proof.
|
/// Create an epoch verifier from validation proof.
|
||||||
///
|
///
|
||||||
/// The proof should be one generated by `prove_with_caller`.
|
/// The proof should be one generated by `epoch_proof`.
|
||||||
/// See docs of `prove_with_caller` for description.
|
/// See docs of `epoch_proof` for description.
|
||||||
fn chain_verifier(&self, _header: &Header, _proof: Bytes) -> Result<Box<ChainVerifier>, Error> {
|
fn epoch_verifier(&self, _header: &Header, _proof: &[u8]) -> Result<Box<EpochVerifier>, Error> {
|
||||||
Ok(Box::new(self::chain_verifier::NoOp))
|
Ok(Box::new(self::epoch_verifier::NoOp))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Populate a header's fields based on its parent's header.
|
/// Populate a header's fields based on its parent's header.
|
||||||
|
@ -66,18 +66,18 @@ impl ValidatorSet for ValidatorContract {
|
|||||||
self.validators.default_caller(id)
|
self.validators.default_caller(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn proof_required(&self, header: &Header, block: Option<&[u8]>, receipts: Option<&[::receipt::Receipt]>)
|
fn is_epoch_end(&self, header: &Header, block: Option<&[u8]>, receipts: Option<&[::receipt::Receipt]>)
|
||||||
-> ::engines::RequiresProof
|
-> ::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> {
|
fn epoch_proof(&self, header: &Header, caller: &Call) -> Result<Vec<u8>, String> {
|
||||||
self.validators.generate_proof(header, caller)
|
self.validators.epoch_proof(header, caller)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn chain_verifier(&self, header: &Header, proof: Vec<u8>) -> Result<super::SimpleList, ::error::Error> {
|
fn epoch_set(&self, header: &Header, proof: &[u8]) -> Result<(U256, super::SimpleList), ::error::Error> {
|
||||||
self.validators.chain_verifier(header, proof)
|
self.validators.epoch_set(header, proof)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn contains_with_caller(&self, bh: &H256, address: &Address, caller: &Call) -> bool {
|
fn contains_with_caller(&self, bh: &H256, address: &Address, caller: &Call) -> bool {
|
||||||
|
@ -23,7 +23,7 @@ mod multi;
|
|||||||
|
|
||||||
use std::sync::Weak;
|
use std::sync::Weak;
|
||||||
use ids::BlockId;
|
use ids::BlockId;
|
||||||
use util::{Address, H256};
|
use util::{Address, H256, U256};
|
||||||
use ethjson::spec::ValidatorSet as ValidatorSpec;
|
use ethjson::spec::ValidatorSet as ValidatorSpec;
|
||||||
use client::Client;
|
use client::Client;
|
||||||
use header::Header;
|
use header::Header;
|
||||||
@ -72,26 +72,32 @@ pub trait ValidatorSet: Send + Sync {
|
|||||||
self.count_with_caller(parent, &*default)
|
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.
|
/// Usually indicates that the validator set changed at the given block.
|
||||||
///
|
///
|
||||||
/// Should not inspect state! This is used in situations where
|
/// Should not inspect state! This is used in situations where
|
||||||
/// state is not generally available.
|
/// 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.
|
/// or `Unsure` indicating a need for more information.
|
||||||
///
|
///
|
||||||
/// This may or may not be called in a loop.
|
/// If block or receipts are provided, do not return `Unsure` indicating
|
||||||
fn proof_required(&self, header: &Header, block: Option<&[u8]>, receipts: Option<&[::receipt::Receipt]>)
|
/// need for them.
|
||||||
-> super::RequiresProof;
|
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!
|
/// Must interact with state only through the given caller!
|
||||||
/// Otherwise, generated proofs may be wrong.
|
/// 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.
|
/// Recover the validator set for all
|
||||||
fn chain_verifier(&self, header: &Header, proof: Vec<u8>) -> Result<SimpleList, ::error::Error>;
|
///
|
||||||
|
/// 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
|
/// Checks if a given address is a validator, with the given function
|
||||||
/// for executing synchronous calls to contracts.
|
/// for executing synchronous calls to contracts.
|
||||||
|
@ -18,8 +18,8 @@
|
|||||||
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::sync::Weak;
|
use std::sync::Weak;
|
||||||
use engines::{Call, RequiresProof};
|
use engines::{Call, EpochChange};
|
||||||
use util::{H256, Address, RwLock};
|
use util::{H256, Address, RwLock, U256};
|
||||||
use ids::BlockId;
|
use ids::BlockId;
|
||||||
use header::{BlockNumber, Header};
|
use header::{BlockNumber, Header};
|
||||||
use client::{Client, BlockChainClient};
|
use client::{Client, BlockChainClient};
|
||||||
@ -43,9 +43,7 @@ impl Multi {
|
|||||||
|
|
||||||
fn correct_set(&self, id: BlockId) -> Option<&ValidatorSet> {
|
fn correct_set(&self, id: BlockId) -> Option<&ValidatorSet> {
|
||||||
match self.block_number.read()(id).map(|parent_block| self.correct_set_by_number(parent_block)) {
|
match self.block_number.read()(id).map(|parent_block| self.correct_set_by_number(parent_block)) {
|
||||||
Ok(set) => {
|
Ok((_, set)) => 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);
|
||||||
None
|
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()
|
let (block, set) = self.sets.iter()
|
||||||
.rev()
|
.rev()
|
||||||
.find(|&(block, _)| *block <= parent_block + 1)
|
.find(|&(block, _)| *block <= parent_block + 1)
|
||||||
@ -62,7 +62,7 @@ impl Multi {
|
|||||||
qed");
|
qed");
|
||||||
|
|
||||||
trace!(target: "engine", "Multi ValidatorSet retrieved for block {}.", block);
|
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())))
|
.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]>)
|
fn is_epoch_end(&self, header: &Header, block: Option<&[u8]>, receipts: Option<&[::receipt::Receipt]>)
|
||||||
-> RequiresProof
|
-> 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> {
|
fn epoch_proof(&self, header: &Header, caller: &Call) -> Result<Vec<u8>, String> {
|
||||||
self.correct_set_by_number(header.number()).generate_proof(header, caller)
|
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> {
|
fn epoch_set(&self, header: &Header, proof: &[u8]) -> Result<(U256, super::SimpleList), ::error::Error> {
|
||||||
self.correct_set_by_number(header.number()).chain_verifier(header, proof)
|
// "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 {
|
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)))
|
.and_then(|c| c.call_contract(id, addr, data)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn proof_required(&self, header: &Header, _block: Option<&[u8]>, receipts: Option<&[::receipt::Receipt]>)
|
fn is_epoch_end(&self, header: &Header, _block: Option<&[u8]>, receipts: Option<&[::receipt::Receipt]>)
|
||||||
-> ::engines::RequiresProof
|
-> ::engines::EpochChange
|
||||||
{
|
{
|
||||||
let bloom = self.expected_bloom(header);
|
let bloom = self.expected_bloom(header);
|
||||||
let header_bloom = header.log_bloom();
|
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 {
|
match receipts {
|
||||||
None => ::engines::RequiresProof::Unsure(::engines::Unsure::NeedsReceipts),
|
None => ::engines::EpochChange::Unsure(::engines::Unsure::NeedsReceipts),
|
||||||
Some(receipts) => {
|
Some(receipts) => {
|
||||||
let check_log = |log: &LogEntry| {
|
let check_log = |log: &LogEntry| {
|
||||||
log.address == self.address &&
|
log.address == self.address &&
|
||||||
@ -149,7 +149,11 @@ impl ValidatorSet for ValidatorSafeContract {
|
|||||||
.event("ValidatorsChanged".into())
|
.event("ValidatorsChanged".into())
|
||||||
.expect("Contract known ahead of time to have `ValidatorsChanged` event; qed");
|
.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()
|
let mut decoded_events = receipts.iter()
|
||||||
|
.rev()
|
||||||
.filter(|r| &bloom & &r.log_bloom == bloom)
|
.filter(|r| &bloom & &r.log_bloom == bloom)
|
||||||
.flat_map(|r| r.logs.iter())
|
.flat_map(|r| r.logs.iter())
|
||||||
.filter(move |l| check_log(l))
|
.filter(move |l| check_log(l))
|
||||||
@ -164,7 +168,7 @@ impl ValidatorSet for ValidatorSafeContract {
|
|||||||
|
|
||||||
// TODO: are multiple transitions per block possible?
|
// TODO: are multiple transitions per block possible?
|
||||||
match decoded_events.next() {
|
match decoded_events.next() {
|
||||||
None => ::engines::RequiresProof::No,
|
None => ::engines::EpochChange::No,
|
||||||
Some(matched_event) => {
|
Some(matched_event) => {
|
||||||
// decode log manually until the native contract generator is
|
// decode log manually until the native contract generator is
|
||||||
// good enough to do it for us.
|
// good enough to do it for us.
|
||||||
@ -181,10 +185,10 @@ impl ValidatorSet for ValidatorSafeContract {
|
|||||||
|
|
||||||
match (nonce, validators) {
|
match (nonce, validators) {
|
||||||
(Some(nonce), Some(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.");
|
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.
|
// the proof we generate is an RLP list containing two parts.
|
||||||
// (nonce, validators)
|
// (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)) {
|
match (self.get_nonce(caller), self.get_list(caller)) {
|
||||||
(Some(nonce), Some(list)) => Ok(encode_proof(nonce, &list.into_inner())),
|
(Some(nonce), Some(list)) => Ok(encode_proof(nonce, &list.into_inner())),
|
||||||
_ => Err("Caller insufficient to generate validator proof.".into()),
|
_ => 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;
|
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)?;
|
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 {
|
fn contains_with_caller(&self, block_hash: &H256, address: &Address, caller: &Call) -> bool {
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
/// Preconfigured validator list.
|
/// Preconfigured validator list.
|
||||||
|
|
||||||
use util::{H256, Address, HeapSizeOf};
|
use util::{H256, Address, HeapSizeOf, U256};
|
||||||
|
|
||||||
use engines::Call;
|
use engines::Call;
|
||||||
use header::Header;
|
use header::Header;
|
||||||
@ -53,18 +53,18 @@ impl ValidatorSet for SimpleList {
|
|||||||
Box::new(|_, _| Err("Simple list doesn't require calls.".into()))
|
Box::new(|_, _| Err("Simple list doesn't require calls.".into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn proof_required(&self, _header: &Header, _block: Option<&[u8]>, _receipts: Option<&[::receipt::Receipt]>)
|
fn is_epoch_end(&self, _header: &Header, _block: Option<&[u8]>, _receipts: Option<&[::receipt::Receipt]>)
|
||||||
-> ::engines::RequiresProof
|
-> ::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())
|
Ok(Vec::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn chain_verifier(&self, _header: &Header, _: Vec<u8>) -> Result<SimpleList, ::error::Error> {
|
fn epoch_set(&self, _header: &Header, _: &[u8]) -> Result<(U256, SimpleList), ::error::Error> {
|
||||||
Ok(self.clone())
|
Ok((0.into(), self.clone()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn contains_with_caller(&self, _bh: &H256, address: &Address, _: &Call) -> bool {
|
fn contains_with_caller(&self, _bh: &H256, address: &Address, _: &Call) -> bool {
|
||||||
|
@ -149,7 +149,16 @@ impl Ethash {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ::engines::ChainVerifier for Arc<Ethash> {
|
// TODO [rphmeier]
|
||||||
|
//
|
||||||
|
// for now, this is different than Ethash's own epochs, and signal
|
||||||
|
// "consensus epochs".
|
||||||
|
// in this sense, `Ethash` is epochless: the same `EpochVerifier` can be used
|
||||||
|
// for any block in the chain.
|
||||||
|
// in the future, we might move the Ethash epoch
|
||||||
|
// caching onto this mechanism as well.
|
||||||
|
impl ::engines::EpochVerifier for Arc<Ethash> {
|
||||||
|
fn epoch_number(&self) -> U256 { 0.into() }
|
||||||
fn verify_light(&self, _header: &Header) -> Result<(), Error> { Ok(()) }
|
fn verify_light(&self, _header: &Header) -> Result<(), Error> { Ok(()) }
|
||||||
fn verify_heavy(&self, header: &Header) -> Result<(), Error> {
|
fn verify_heavy(&self, header: &Header) -> Result<(), Error> {
|
||||||
self.verify_block_unordered(header, None)
|
self.verify_block_unordered(header, None)
|
||||||
@ -393,7 +402,7 @@ impl Engine for Arc<Ethash> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn chain_verifier(&self, _header: &Header, _proof: Vec<u8>) -> Result<Box<::engines::ChainVerifier>, Error> {
|
fn epoch_verifier(&self, _header: &Header, _proof: &[u8]) -> Result<Box<::engines::EpochVerifier>, Error> {
|
||||||
Ok(Box::new(self.clone()))
|
Ok(Box::new(self.clone()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user