openethereum/ethcore/src/engines/mod.rs

526 lines
21 KiB
Rust
Raw Normal View History

// Copyright 2015-2019 Parity Technologies (UK) Ltd.
// This file is part of Parity Ethereum.
2016-02-05 13:40:41 +01:00
// Parity Ethereum is free software: you can redistribute it and/or modify
2016-02-05 13:40:41 +01:00
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity Ethereum is distributed in the hope that it will be useful,
2016-02-05 13:40:41 +01:00
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
2016-02-05 13:40:41 +01:00
//! Consensus engine specification and basic implementations.
2016-09-08 12:12:24 +02:00
mod authority_round;
mod basic_authority;
mod instant_seal;
mod null_engine;
mod validator_set;
pub mod block_reward;
pub mod signer;
2016-09-08 12:12:24 +02:00
pub use self::authority_round::AuthorityRound;
pub use self::basic_authority::BasicAuthority;
pub use self::epoch::{EpochVerifier, Transition as EpochTransition};
pub use self::instant_seal::{InstantSeal, InstantSealParams};
pub use self::null_engine::NullEngine;
pub use self::signer::EngineSigner;
2016-05-16 18:16:56 +02:00
// TODO [ToDr] Remove re-export (#10130)
pub use types::engines::ForkChoice;
pub use types::engines::epoch;
2017-07-29 21:56:42 +02:00
use std::sync::{Weak, Arc};
2017-07-29 17:12:07 +02:00
use std::collections::{BTreeMap, HashMap};
use std::{fmt, error};
2017-04-11 17:07:04 +02:00
use builtin::Builtin;
use vm::{EnvInfo, Schedule, CreateContractAddress, CallType, ActionValue};
use error::Error;
use types::BlockNumber;
use types::header::{Header, ExtendedHeader};
2017-04-19 20:31:53 +02:00
use snapshot::SnapshotComponents;
use spec::CommonParams;
use types::transaction::{self, UnverifiedTransaction, SignedTransaction};
2017-04-11 17:07:04 +02:00
use ethkey::{Signature};
use parity_machine::{Machine, LocalizedMachine as Localized};
use ethereum_types::{H256, U256, Address};
use unexpected::{Mismatch, OutOfBounds};
use bytes::Bytes;
Fork choice and metadata framework for Engine (#8401) * Add light client TODO item * Move existing total-difficulty-based fork choice check to Engine * Abstract total difficulty and block provider as Machine::BlockMetadata and Machine::BlockProvider * Decouple "generate_metadata" logic to Engine * Use fixed BlockMetadata and BlockProvider type for null and instantseal In this way they can use total difficulty fork choice check * Extend blockdetails with metadatas and finalized info * Extra data update: mark_finalized and update_metadatas * Check finalized block in Blockchain * Fix a test constructor in verification mod * Add total difficulty trait * Fix type import * Db migration to V13 with metadata column * Address grumbles * metadatas -> metadata * Use generic type for update_metadata to avoid passing HashMap all around * Remove metadata in blockdetails * [WIP] Implement a generic metadata architecture * [WIP] Metadata insertion logic in BlockChain * typo: Value -> Self::Value * [WIP] Temporarily remove Engine::is_new_best interface So that we don't have too many type errors. * [WIP] Fix more type errors * [WIP] ExtendedHeader::PartialEq * [WIP] Change metadata type Option<Vec<u8>> to Vec<u8> * [WIP] Remove Metadata Error * [WIP] Clean up error conversion * [WIP] finalized -> is_finalized * [WIP] Mark all fields in ExtrasInsert as pub * [WIP] Remove unused import * [WIP] Keep only local metadata info * Mark metadata as optional * [WIP] Revert metadata db change in BlockChain * [WIP] Put finalization in unclosed state * Use metadata interface in BlockDetail * [WIP] Fix current build failures * [WIP] Remove unused blockmetadata struct * Remove DB migration info * [WIP] Typo * Use ExtendedHeader to implement fork choice check * Implement is_new_best using Ancestry iterator * Use expect instead of panic * [WIP] Add ancestry Engine support via on_new_block * Fix tests * Emission of ancestry actions * use_short_version should take account of metadata * Engine::is_new_best -> Engine::fork_choice * Use proper expect format as defined in #1026 * panic -> expect * ancestry_header -> ancestry_with_metadata * Boxed iterator -> &mut iterator * Fix tests * is_new_best -> primitive_fork_choice * Document how fork_choice works * Engine::fork_choice -> Engine::primitive_fork_choice * comment: clarify types of finalization where Engine::primitive_fork_choice works * Expose FinalizationInfo to Engine * Fix tests due to merging * Remove TotalDifficulty trait * Do not pass FinalizationInfo to Engine If there's finalized blocks in from route, choose the old branch without calling `Engine::fork_choice`. * Fix compile * Fix unused import * Remove is_to_route_finalized When no block reorg passes a finalized block, this variable is always false. * Address format grumbles * Fix docs: mark_finalized returns None if block hash is not found `blockchain` mod does not yet have an Error type, so we still temporarily use None here. * Fix inaccurate tree_route None expect description
2018-05-16 08:58:01 +02:00
use types::ancestry_action::AncestryAction;
/// Default EIP-210 contract code.
/// As defined in https://github.com/ethereum/EIPs/pull/210
pub const DEFAULT_BLOCKHASH_CONTRACT: &'static str = "73fffffffffffffffffffffffffffffffffffffffe33141561006a5760014303600035610100820755610100810715156100455760003561010061010083050761010001555b6201000081071515610064576000356101006201000083050761020001555b5061013e565b4360003512151561008457600060405260206040f361013d565b61010060003543031315156100a857610100600035075460605260206060f361013c565b6101006000350715156100c55762010000600035430313156100c8565b60005b156100ea576101006101006000350507610100015460805260206080f361013b565b620100006000350715156101095763010000006000354303131561010c565b60005b1561012f57610100620100006000350507610200015460a052602060a0f361013a565b600060c052602060c0f35b5b5b5b5b";
2016-08-24 15:55:47 +02:00
/// Voting errors.
#[derive(Debug)]
pub enum EngineError {
/// Signature or author field does not belong to an authority.
2016-12-08 12:03:34 +01:00
NotAuthorized(Address),
2016-11-29 13:51:27 +01:00
/// The same author issued different votes at the same step.
2016-12-08 12:03:34 +01:00
DoubleVote(Address),
2016-11-29 13:51:27 +01:00
/// The received block is from an incorrect proposer.
2016-12-08 12:03:34 +01:00
NotProposer(Mismatch<Address>),
2016-08-24 15:55:47 +02:00
/// Message was not expected.
2016-08-26 19:27:50 +02:00
UnexpectedMessage,
2016-12-02 14:32:00 +01:00
/// Seal field has an unexpected size.
BadSealFieldSize(OutOfBounds<usize>),
2017-04-12 18:55:38 +02:00
/// Validation proof insufficient.
InsufficientProof(String),
/// Failed system call.
FailedSystemCall(String),
/// Malformed consensus message.
MalformedMessage(String),
/// Requires client ref, but none registered.
RequiresClient,
/// Invalid engine specification or implementation.
InvalidEngine,
2016-11-29 13:51:27 +01:00
}
impl fmt::Display for EngineError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::EngineError::*;
let msg = match *self {
DoubleVote(ref address) => format!("Author {} issued too many blocks.", address),
NotProposer(ref mis) => format!("Author is not a current proposer: {}", mis),
NotAuthorized(ref address) => format!("Signer {} is not authorized.", address),
UnexpectedMessage => "This Engine should not be fed messages.".into(),
2016-12-02 14:32:00 +01:00
BadSealFieldSize(ref oob) => format!("Seal field has an unexpected length: {}", oob),
2017-04-12 18:55:38 +02:00
InsufficientProof(ref msg) => format!("Insufficient validation proof: {}", msg),
FailedSystemCall(ref msg) => format!("Failed to make system call: {}", msg),
MalformedMessage(ref msg) => format!("Received malformed consensus message: {}", msg),
RequiresClient => format!("Call requires client but none registered"),
InvalidEngine => format!("Invalid engine specification or implementation"),
2016-11-29 13:51:27 +01:00
};
f.write_fmt(format_args!("Engine error ({})", msg))
}
2016-08-24 15:55:47 +02:00
}
impl error::Error for EngineError {
fn description(&self) -> &str {
"Engine error"
}
}
2016-12-08 12:03:34 +01:00
/// Seal type.
#[derive(Debug, PartialEq, Eq)]
pub enum Seal {
/// Proposal seal; should be broadcasted, but not inserted into blockchain.
Proposal(Vec<Bytes>),
/// Regular block seal; should be part of the blockchain.
Regular(Vec<Bytes>),
/// Engine does generate seal for this block right now.
None,
}
/// A system-calling closure. Enacts calls on a block's state from the system address.
pub type SystemCall<'a> = FnMut(Address, Vec<u8>) -> Result<Vec<u8>, String> + 'a;
/// A system-calling closure. Enacts calls on a block's state with code either from an on-chain contract, or hard-coded EVM or WASM (if enabled on-chain) codes.
pub type SystemOrCodeCall<'a> = FnMut(SystemOrCodeCallKind, Vec<u8>) -> Result<Vec<u8>, String> + 'a;
/// Kind of SystemOrCodeCall, this is either an on-chain address, or code.
#[derive(PartialEq, Debug, Clone)]
pub enum SystemOrCodeCallKind {
/// On-chain address.
Address(Address),
/// Hard-coded code.
Code(Arc<Vec<u8>>, H256),
}
/// Default SystemOrCodeCall implementation.
pub fn default_system_or_code_call<'a>(machine: &'a ::machine::EthereumMachine, block: &'a mut ::block::ExecutedBlock) -> impl FnMut(SystemOrCodeCallKind, Vec<u8>) -> Result<Vec<u8>, String> + 'a {
move |to, data| {
let result = match to {
SystemOrCodeCallKind::Address(address) => {
machine.execute_as_system(
block,
address,
U256::max_value(),
Some(data),
)
},
SystemOrCodeCallKind::Code(code, code_hash) => {
machine.execute_code_as_system(
block,
None,
Some(code),
Some(code_hash),
Some(ActionValue::Apparent(U256::zero())),
U256::max_value(),
Some(data),
Some(CallType::StaticCall),
)
},
};
result.map_err(|e| format!("{}", e))
}
}
/// Type alias for a function we can get headers by hash through.
pub type Headers<'a, H> = Fn(H256) -> Option<H> + 'a;
/// Type alias for a function we can query pending transitions by block hash through.
pub type PendingTransitionStore<'a> = Fn(H256) -> Option<epoch::PendingTransition> + 'a;
/// Proof dependent on state.
pub trait StateDependentProof<M: Machine>: Send + Sync {
/// Generate a proof, given the state.
// TODO: make this into an &M::StateContext
fn generate_proof<'a>(&self, state: &<M as Localized<'a>>::StateContext) -> Result<Vec<u8>, String>;
/// Check a proof generated elsewhere (potentially by a peer).
// `engine` needed to check state proofs, while really this should
// just be state machine params.
fn check_proof(&self, machine: &M, proof: &[u8]) -> Result<(), String>;
}
/// Proof generated on epoch change.
pub enum Proof<M: Machine> {
/// Known proof (extracted from signal)
Known(Vec<u8>),
/// State dependent proof.
WithState(Arc<StateDependentProof<M>>),
}
/// Generated epoch verifier.
pub enum ConstructedVerifier<'a, M: Machine> {
/// Fully trusted verifier.
Trusted(Box<EpochVerifier<M>>),
/// Verifier unconfirmed. Check whether given finality proof finalizes given hash
/// under previous epoch.
Unconfirmed(Box<EpochVerifier<M>>, &'a [u8], H256),
/// Error constructing verifier.
Err(Error),
}
impl<'a, M: Machine> ConstructedVerifier<'a, M> {
/// Convert to a result, indicating that any necessary confirmation has been done
/// already.
pub fn known_confirmed(self) -> Result<Box<EpochVerifier<M>>, Error> {
match self {
ConstructedVerifier::Trusted(v) | ConstructedVerifier::Unconfirmed(v, _, _) => Ok(v),
ConstructedVerifier::Err(e) => Err(e),
}
}
}
2017-04-11 17:07:04 +02:00
2017-04-18 14:19:10 +02:00
/// Results of a query of whether an epoch change occurred at the given block.
pub enum EpochChange<M: Machine> {
2017-04-12 14:41:19 +02:00
/// Cannot determine until more data is passed.
Unsure(M::AuxiliaryRequest),
2017-04-18 14:19:10 +02:00
/// No epoch change.
2017-04-12 14:41:19 +02:00
No,
/// The epoch will change, with proof.
Yes(Proof<M>),
2017-04-12 14:41:19 +02:00
}
/// A consensus mechanism for the chain. Generally either proof-of-work or proof-of-stake-based.
/// Provides hooks into each of the major parts of block import.
pub trait Engine<M: Machine>: Sync + Send {
/// The name of this engine.
fn name(&self) -> &str;
/// Get access to the underlying state machine.
// TODO: decouple.
fn machine(&self) -> &M;
/// The number of additional header fields required for this engine.
Aura: Broadcast empty step messages instead of creating empty blocks (#7605) * aura: broadcast empty step message instead of sealing empty block * aura: add empty_step messages to seal * aura: include parent_hash in empty step message * aura: verify received empty step messages * aura: verify empty step messages in block * aura: fix dead lock on empty_steps * aura: fix EmptyStep Encodable * aura: take number of empty steps into account in chain score * aura: use empty step signers for finality * aura: add empty "empty step" messages to seal when reading from spec * aura: fix EmptyStep rlp encoding * aura: use Vec<u8> instead of Bytes * aura: fix block empty step verification * Update .gitlab-ci.yml fix lint * aura: fix accumulation of empty step signatures for finality * aura: include empty steps in seal signature * aura: configurable max number of empty steps * engine: pass block header to seal_fields method This is necessary to make the number of seal fields dynamic, e.g. activating a transition on a certain block number that changes the seal. * aura: add transition to enable empty step messages * aura: clear old empty step messages on verify_block_external * aura: ignore empty step messages from the future * aura: report skipped primaries when empty steps are not enabled * aura: fix tests * aura: report misbehavior * aura: add tests for rolling finality with multiple signatures * engine: fix validator set test In this test the block validation wasn't failing because the block was in the future (expected failure) but was instead failing because the author of the block isn't the expected authority. Since we added reporting of blocks produced by the wrong authority this test started failing. * aura: reward all the authors of empty step messages * aura: fix reward attribution for new blocks * aura: add tests for empty steps broadcasting and inclusion in blocks * aura: reduce size of empty step messages in seal * aura: add test for empty step inclusion in blocks * aura: add test for rewarding of empty steps * aura: add test for empty steps validation * aura: fix rlp encoding of sealed empty step * aura: fix grumbles
2018-02-15 01:39:29 +01:00
fn seal_fields(&self, _header: &M::Header) -> usize { 0 }
/// Additional engine-specific information for the user/developer concerning `header`.
fn extra_info(&self, _header: &M::Header) -> BTreeMap<String, String> { BTreeMap::new() }
2016-02-02 23:43:29 +01:00
/// Maximum number of uncles a block is allowed to declare.
fn maximum_uncle_count(&self, _block: BlockNumber) -> usize { 0 }
/// The number of generations back that uncles can be.
fn maximum_uncle_age(&self) -> usize { 6 }
/// Optional maximum gas limit.
fn maximum_gas_limit(&self) -> Option<U256> { None }
2016-02-02 23:43:29 +01:00
/// Block transformation functions, before the transactions.
/// `epoch_begin` set to true if this block kicks off an epoch.
fn on_new_block(
&self,
_block: &mut M::LiveBlock,
_epoch_begin: bool,
_ancestry: &mut Iterator<Item = ExtendedHeader>,
) -> Result<(), M::Error> {
Ok(())
}
2016-02-02 23:43:29 +01:00
/// Block transformation functions, after the transactions.
fn on_close_block(&self, _block: &mut M::LiveBlock) -> Result<(), M::Error> {
2017-08-10 12:36:29 +02:00
Ok(())
}
2017-02-20 16:35:53 +01:00
/// None means that it requires external input (e.g. PoW) to seal a block.
/// Some(true) means the engine is currently prime for seal generation (i.e. node is the current validator).
/// Some(false) means that the node might seal internally but is not qualified now.
fn seals_internally(&self) -> Option<bool> { None }
/// Attempt to seal the block internally.
///
/// If `Some` is returned, then you get a valid seal.
///
/// This operation is synchronous and may (quite reasonably) not be available, in which None will
/// be returned.
///
/// It is fine to require access to state or a full client for this function, since
/// light clients do not generate seals.
fn generate_seal(&self, _block: &M::LiveBlock, _parent: &M::Header) -> Seal { Seal::None }
2015-12-20 16:12:53 +01:00
/// Verify a locally-generated seal of a header.
///
/// If this engine seals internally,
/// no checks have to be done here, since all internally generated seals
/// should be valid.
///
/// Externally-generated seals (e.g. PoW) will need to be checked for validity.
///
/// It is fine to require access to state or a full client for this function, since
/// light clients do not generate seals.
fn verify_local_seal(&self, header: &M::Header) -> Result<(), M::Error>;
/// Phase 1 quick block verification. Only does checks that are cheap. Returns either a null `Ok` or a general error detailing the problem with import.
/// The verification module can optionally avoid checking the seal (`check_seal`), if seal verification is disabled this method won't be called.
fn verify_block_basic(&self, _header: &M::Header) -> Result<(), M::Error> { Ok(()) }
/// Phase 2 verification. Perform costly checks such as transaction signatures. Returns either a null `Ok` or a general error detailing the problem with import.
/// The verification module can optionally avoid checking the seal (`check_seal`), if seal verification is disabled this method won't be called.
fn verify_block_unordered(&self, _header: &M::Header) -> Result<(), M::Error> { Ok(()) }
/// Phase 3 verification. Check block information against parent. Returns either a null `Ok` or a general error detailing the problem with import.
fn verify_block_family(&self, _header: &M::Header, _parent: &M::Header) -> Result<(), M::Error> { Ok(()) }
/// Phase 4 verification. Verify block header against potentially external data.
/// Should only be called when `register_client` has been called previously.
fn verify_block_external(&self, _header: &M::Header) -> Result<(), M::Error> { Ok(()) }
/// Genesis epoch data.
fn genesis_epoch_data<'a>(&self, _header: &M::Header, _state: &<M as Localized<'a>>::StateContext) -> Result<Vec<u8>, String> { Ok(Vec::new()) }
2017-04-12 14:41:19 +02:00
/// Whether an epoch change is signalled at the given header but will require finality.
/// If a change can be enacted immediately then return `No` from this function but
/// `Yes` from `is_epoch_end`.
///
/// If auxiliary data of the block is required, return an auxiliary request and the function will be
/// called again with them.
/// Return `Yes` or `No` when the answer is definitively known.
///
2017-04-18 14:19:10 +02:00
/// Should not interact with state.
fn signals_epoch_end<'a>(&self, _header: &M::Header, _aux: <M as Localized<'a>>::AuxiliaryData)
-> EpochChange<M>
2017-04-12 14:41:19 +02:00
{
2017-04-18 14:19:10 +02:00
EpochChange::No
2017-04-11 17:07:04 +02:00
}
/// Whether a block is the end of an epoch.
///
/// This either means that an immediate transition occurs or a block signalling transition
/// has reached finality. The `Headers` given are not guaranteed to return any blocks
/// from any epoch other than the current. The client must keep track of finality and provide
/// the latest finalized headers to check against the transition store.
///
/// Return optional transition proof.
fn is_epoch_end(
&self,
_chain_head: &M::Header,
_finalized: &[H256],
_chain: &Headers<M::Header>,
_transition_store: &PendingTransitionStore,
) -> Option<Vec<u8>> {
None
}
/// Whether a block is the end of an epoch.
///
/// This either means that an immediate transition occurs or a block signalling transition
/// has reached finality. The `Headers` given are not guaranteed to return any blocks
/// from any epoch other than the current. This is a specialized method to use for light
/// clients since the light client doesn't track finality of all blocks, and therefore finality
/// for blocks in the current epoch is built inside this method by the engine.
///
/// Return optional transition proof.
fn is_epoch_end_light(
&self,
_chain_head: &M::Header,
_chain: &Headers<M::Header>,
_transition_store: &PendingTransitionStore,
) -> Option<Vec<u8>> {
None
}
/// Create an epoch verifier from validation proof and a flag indicating
/// whether finality is required.
fn epoch_verifier<'a>(&self, _header: &M::Header, _proof: &'a [u8]) -> ConstructedVerifier<'a, M> {
ConstructedVerifier::Trusted(Box::new(self::epoch::NoOp))
}
/// Populate a header's fields based on its parent's header.
/// Usually implements the chain scoring rule based on weight.
fn populate_from_parent(&self, _header: &mut M::Header, _parent: &M::Header) { }
2016-08-19 17:18:30 +02:00
/// Handle any potential consensus messages;
/// updating consensus state and potentially issuing a new one.
fn handle_message(&self, _message: &[u8]) -> Result<(), EngineError> { Err(EngineError::UnexpectedMessage) }
2015-12-23 12:56:38 +01:00
2016-12-08 12:03:34 +01:00
/// Find out if the block is a proposal block and should not be inserted into the DB.
/// Takes a header of a fully verified block.
fn is_proposal(&self, _verified_header: &M::Header) -> bool { false }
2016-12-08 12:03:34 +01:00
/// Register a component which signs consensus messages.
fn set_signer(&self, _signer: Box<EngineSigner>) {}
2016-12-05 18:08:16 +01:00
/// Sign using the EngineSigner, to be used for consensus tx signing.
fn sign(&self, _hash: H256) -> Result<Signature, M::Error> { unimplemented!() }
/// Add Client which can be used for sealing, potentially querying the state and sending messages.
fn register_client(&self, _client: Weak<M::EngineClient>) {}
2016-12-06 19:23:15 +01:00
/// Trigger next step of the consensus engine.
fn step(&self) {}
/// Stops any services that the may hold the Engine and makes it safe to drop.
fn stop(&self) {}
2017-04-19 20:31:53 +02:00
/// Create a factory for building snapshot chunks and restoring from them.
/// Returning `None` indicates that this engine doesn't support snapshot creation.
fn snapshot_components(&self) -> Option<Box<SnapshotComponents>> {
None
}
2017-05-05 16:00:40 +02:00
/// Whether this engine supports warp sync.
fn supports_warp(&self) -> bool {
self.snapshot_components().is_some()
}
/// Return a new open block header timestamp based on the parent timestamp.
fn open_block_header_timestamp(&self, parent_timestamp: u64) -> u64 {
use std::{time, cmp};
let now = time::SystemTime::now().duration_since(time::UNIX_EPOCH).unwrap_or_default();
cmp::max(now.as_secs() as u64, parent_timestamp + 1)
}
/// Check whether the parent timestamp is valid.
fn is_timestamp_valid(&self, header_timestamp: u64, parent_timestamp: u64) -> bool {
header_timestamp > parent_timestamp
}
Fork choice and metadata framework for Engine (#8401) * Add light client TODO item * Move existing total-difficulty-based fork choice check to Engine * Abstract total difficulty and block provider as Machine::BlockMetadata and Machine::BlockProvider * Decouple "generate_metadata" logic to Engine * Use fixed BlockMetadata and BlockProvider type for null and instantseal In this way they can use total difficulty fork choice check * Extend blockdetails with metadatas and finalized info * Extra data update: mark_finalized and update_metadatas * Check finalized block in Blockchain * Fix a test constructor in verification mod * Add total difficulty trait * Fix type import * Db migration to V13 with metadata column * Address grumbles * metadatas -> metadata * Use generic type for update_metadata to avoid passing HashMap all around * Remove metadata in blockdetails * [WIP] Implement a generic metadata architecture * [WIP] Metadata insertion logic in BlockChain * typo: Value -> Self::Value * [WIP] Temporarily remove Engine::is_new_best interface So that we don't have too many type errors. * [WIP] Fix more type errors * [WIP] ExtendedHeader::PartialEq * [WIP] Change metadata type Option<Vec<u8>> to Vec<u8> * [WIP] Remove Metadata Error * [WIP] Clean up error conversion * [WIP] finalized -> is_finalized * [WIP] Mark all fields in ExtrasInsert as pub * [WIP] Remove unused import * [WIP] Keep only local metadata info * Mark metadata as optional * [WIP] Revert metadata db change in BlockChain * [WIP] Put finalization in unclosed state * Use metadata interface in BlockDetail * [WIP] Fix current build failures * [WIP] Remove unused blockmetadata struct * Remove DB migration info * [WIP] Typo * Use ExtendedHeader to implement fork choice check * Implement is_new_best using Ancestry iterator * Use expect instead of panic * [WIP] Add ancestry Engine support via on_new_block * Fix tests * Emission of ancestry actions * use_short_version should take account of metadata * Engine::is_new_best -> Engine::fork_choice * Use proper expect format as defined in #1026 * panic -> expect * ancestry_header -> ancestry_with_metadata * Boxed iterator -> &mut iterator * Fix tests * is_new_best -> primitive_fork_choice * Document how fork_choice works * Engine::fork_choice -> Engine::primitive_fork_choice * comment: clarify types of finalization where Engine::primitive_fork_choice works * Expose FinalizationInfo to Engine * Fix tests due to merging * Remove TotalDifficulty trait * Do not pass FinalizationInfo to Engine If there's finalized blocks in from route, choose the old branch without calling `Engine::fork_choice`. * Fix compile * Fix unused import * Remove is_to_route_finalized When no block reorg passes a finalized block, this variable is always false. * Address format grumbles * Fix docs: mark_finalized returns None if block hash is not found `blockchain` mod does not yet have an Error type, so we still temporarily use None here. * Fix inaccurate tree_route None expect description
2018-05-16 08:58:01 +02:00
/// Gather all ancestry actions. Called at the last stage when a block is committed. The Engine must guarantee that
/// the ancestry exists.
fn ancestry_actions(&self, _header: &M::Header, _ancestry: &mut Iterator<Item = ExtendedHeader>) -> Vec<AncestryAction> {
Fork choice and metadata framework for Engine (#8401) * Add light client TODO item * Move existing total-difficulty-based fork choice check to Engine * Abstract total difficulty and block provider as Machine::BlockMetadata and Machine::BlockProvider * Decouple "generate_metadata" logic to Engine * Use fixed BlockMetadata and BlockProvider type for null and instantseal In this way they can use total difficulty fork choice check * Extend blockdetails with metadatas and finalized info * Extra data update: mark_finalized and update_metadatas * Check finalized block in Blockchain * Fix a test constructor in verification mod * Add total difficulty trait * Fix type import * Db migration to V13 with metadata column * Address grumbles * metadatas -> metadata * Use generic type for update_metadata to avoid passing HashMap all around * Remove metadata in blockdetails * [WIP] Implement a generic metadata architecture * [WIP] Metadata insertion logic in BlockChain * typo: Value -> Self::Value * [WIP] Temporarily remove Engine::is_new_best interface So that we don't have too many type errors. * [WIP] Fix more type errors * [WIP] ExtendedHeader::PartialEq * [WIP] Change metadata type Option<Vec<u8>> to Vec<u8> * [WIP] Remove Metadata Error * [WIP] Clean up error conversion * [WIP] finalized -> is_finalized * [WIP] Mark all fields in ExtrasInsert as pub * [WIP] Remove unused import * [WIP] Keep only local metadata info * Mark metadata as optional * [WIP] Revert metadata db change in BlockChain * [WIP] Put finalization in unclosed state * Use metadata interface in BlockDetail * [WIP] Fix current build failures * [WIP] Remove unused blockmetadata struct * Remove DB migration info * [WIP] Typo * Use ExtendedHeader to implement fork choice check * Implement is_new_best using Ancestry iterator * Use expect instead of panic * [WIP] Add ancestry Engine support via on_new_block * Fix tests * Emission of ancestry actions * use_short_version should take account of metadata * Engine::is_new_best -> Engine::fork_choice * Use proper expect format as defined in #1026 * panic -> expect * ancestry_header -> ancestry_with_metadata * Boxed iterator -> &mut iterator * Fix tests * is_new_best -> primitive_fork_choice * Document how fork_choice works * Engine::fork_choice -> Engine::primitive_fork_choice * comment: clarify types of finalization where Engine::primitive_fork_choice works * Expose FinalizationInfo to Engine * Fix tests due to merging * Remove TotalDifficulty trait * Do not pass FinalizationInfo to Engine If there's finalized blocks in from route, choose the old branch without calling `Engine::fork_choice`. * Fix compile * Fix unused import * Remove is_to_route_finalized When no block reorg passes a finalized block, this variable is always false. * Address format grumbles * Fix docs: mark_finalized returns None if block hash is not found `blockchain` mod does not yet have an Error type, so we still temporarily use None here. * Fix inaccurate tree_route None expect description
2018-05-16 08:58:01 +02:00
Vec::new()
}
/// Check whether the given new block is the best block, after finalization check.
fn fork_choice(&self, new: &ExtendedHeader, best: &ExtendedHeader) -> ForkChoice;
Fork choice and metadata framework for Engine (#8401) * Add light client TODO item * Move existing total-difficulty-based fork choice check to Engine * Abstract total difficulty and block provider as Machine::BlockMetadata and Machine::BlockProvider * Decouple "generate_metadata" logic to Engine * Use fixed BlockMetadata and BlockProvider type for null and instantseal In this way they can use total difficulty fork choice check * Extend blockdetails with metadatas and finalized info * Extra data update: mark_finalized and update_metadatas * Check finalized block in Blockchain * Fix a test constructor in verification mod * Add total difficulty trait * Fix type import * Db migration to V13 with metadata column * Address grumbles * metadatas -> metadata * Use generic type for update_metadata to avoid passing HashMap all around * Remove metadata in blockdetails * [WIP] Implement a generic metadata architecture * [WIP] Metadata insertion logic in BlockChain * typo: Value -> Self::Value * [WIP] Temporarily remove Engine::is_new_best interface So that we don't have too many type errors. * [WIP] Fix more type errors * [WIP] ExtendedHeader::PartialEq * [WIP] Change metadata type Option<Vec<u8>> to Vec<u8> * [WIP] Remove Metadata Error * [WIP] Clean up error conversion * [WIP] finalized -> is_finalized * [WIP] Mark all fields in ExtrasInsert as pub * [WIP] Remove unused import * [WIP] Keep only local metadata info * Mark metadata as optional * [WIP] Revert metadata db change in BlockChain * [WIP] Put finalization in unclosed state * Use metadata interface in BlockDetail * [WIP] Fix current build failures * [WIP] Remove unused blockmetadata struct * Remove DB migration info * [WIP] Typo * Use ExtendedHeader to implement fork choice check * Implement is_new_best using Ancestry iterator * Use expect instead of panic * [WIP] Add ancestry Engine support via on_new_block * Fix tests * Emission of ancestry actions * use_short_version should take account of metadata * Engine::is_new_best -> Engine::fork_choice * Use proper expect format as defined in #1026 * panic -> expect * ancestry_header -> ancestry_with_metadata * Boxed iterator -> &mut iterator * Fix tests * is_new_best -> primitive_fork_choice * Document how fork_choice works * Engine::fork_choice -> Engine::primitive_fork_choice * comment: clarify types of finalization where Engine::primitive_fork_choice works * Expose FinalizationInfo to Engine * Fix tests due to merging * Remove TotalDifficulty trait * Do not pass FinalizationInfo to Engine If there's finalized blocks in from route, choose the old branch without calling `Engine::fork_choice`. * Fix compile * Fix unused import * Remove is_to_route_finalized When no block reorg passes a finalized block, this variable is always false. * Address format grumbles * Fix docs: mark_finalized returns None if block hash is not found `blockchain` mod does not yet have an Error type, so we still temporarily use None here. * Fix inaccurate tree_route None expect description
2018-05-16 08:58:01 +02:00
}
/// Check whether a given block is the best block based on the default total difficulty rule.
pub fn total_difficulty_fork_choice(new: &ExtendedHeader, best: &ExtendedHeader) -> ForkChoice {
Fork choice and metadata framework for Engine (#8401) * Add light client TODO item * Move existing total-difficulty-based fork choice check to Engine * Abstract total difficulty and block provider as Machine::BlockMetadata and Machine::BlockProvider * Decouple "generate_metadata" logic to Engine * Use fixed BlockMetadata and BlockProvider type for null and instantseal In this way they can use total difficulty fork choice check * Extend blockdetails with metadatas and finalized info * Extra data update: mark_finalized and update_metadatas * Check finalized block in Blockchain * Fix a test constructor in verification mod * Add total difficulty trait * Fix type import * Db migration to V13 with metadata column * Address grumbles * metadatas -> metadata * Use generic type for update_metadata to avoid passing HashMap all around * Remove metadata in blockdetails * [WIP] Implement a generic metadata architecture * [WIP] Metadata insertion logic in BlockChain * typo: Value -> Self::Value * [WIP] Temporarily remove Engine::is_new_best interface So that we don't have too many type errors. * [WIP] Fix more type errors * [WIP] ExtendedHeader::PartialEq * [WIP] Change metadata type Option<Vec<u8>> to Vec<u8> * [WIP] Remove Metadata Error * [WIP] Clean up error conversion * [WIP] finalized -> is_finalized * [WIP] Mark all fields in ExtrasInsert as pub * [WIP] Remove unused import * [WIP] Keep only local metadata info * Mark metadata as optional * [WIP] Revert metadata db change in BlockChain * [WIP] Put finalization in unclosed state * Use metadata interface in BlockDetail * [WIP] Fix current build failures * [WIP] Remove unused blockmetadata struct * Remove DB migration info * [WIP] Typo * Use ExtendedHeader to implement fork choice check * Implement is_new_best using Ancestry iterator * Use expect instead of panic * [WIP] Add ancestry Engine support via on_new_block * Fix tests * Emission of ancestry actions * use_short_version should take account of metadata * Engine::is_new_best -> Engine::fork_choice * Use proper expect format as defined in #1026 * panic -> expect * ancestry_header -> ancestry_with_metadata * Boxed iterator -> &mut iterator * Fix tests * is_new_best -> primitive_fork_choice * Document how fork_choice works * Engine::fork_choice -> Engine::primitive_fork_choice * comment: clarify types of finalization where Engine::primitive_fork_choice works * Expose FinalizationInfo to Engine * Fix tests due to merging * Remove TotalDifficulty trait * Do not pass FinalizationInfo to Engine If there's finalized blocks in from route, choose the old branch without calling `Engine::fork_choice`. * Fix compile * Fix unused import * Remove is_to_route_finalized When no block reorg passes a finalized block, this variable is always false. * Address format grumbles * Fix docs: mark_finalized returns None if block hash is not found `blockchain` mod does not yet have an Error type, so we still temporarily use None here. * Fix inaccurate tree_route None expect description
2018-05-16 08:58:01 +02:00
if new.total_score() > best.total_score() {
ForkChoice::New
} else {
ForkChoice::Old
}
}
/// Common type alias for an engine coupled with an Ethereum-like state machine.
// TODO: make this a _trait_ alias when those exist.
// fortunately the effect is largely the same since engines are mostly used
// via trait objects.
pub trait EthEngine: Engine<::machine::EthereumMachine> {
/// Get the general parameters of the chain.
fn params(&self) -> &CommonParams {
self.machine().params()
}
/// Get the EVM schedule for the given block number.
fn schedule(&self, block_number: BlockNumber) -> Schedule {
self.machine().schedule(block_number)
}
/// Builtin-contracts for the chain..
fn builtins(&self) -> &BTreeMap<Address, Builtin> {
self.machine().builtins()
}
/// Attempt to get a handle to a built-in contract.
/// Only returns references to activated built-ins.
fn builtin(&self, a: &Address, block_number: BlockNumber) -> Option<&Builtin> {
self.machine().builtin(a, block_number)
}
/// Some intrinsic operation parameters; by default they take their value from the `spec()`'s `engine_params`.
fn maximum_extra_data_size(&self) -> usize {
self.machine().maximum_extra_data_size()
}
/// The nonce with which accounts begin at given block.
fn account_start_nonce(&self, block: BlockNumber) -> U256 {
self.machine().account_start_nonce(block)
}
/// The network ID that transactions should be signed with.
fn signing_chain_id(&self, env_info: &EnvInfo) -> Option<u64> {
self.machine().signing_chain_id(env_info)
}
2017-05-05 16:00:40 +02:00
/// Returns new contract address generation scheme at given block number.
fn create_address_scheme(&self, number: BlockNumber) -> CreateContractAddress {
self.machine().create_address_scheme(number)
}
/// Verify a particular transaction is valid.
New Transaction Queue implementation (#8074) * Implementation of Verifier, Scoring and Ready. * Queue in progress. * TransactionPool. * Prepare for txpool release. * Miner refactor [WiP] * WiP reworking miner. * Make it compile. * Add some docs. * Split blockchain access to a separate file. * Work on miner API. * Fix ethcore tests. * Refactor miner interface for sealing/work packages. * Implement next nonce. * RPC compiles. * Implement couple of missing methdods for RPC. * Add transaction queue listeners. * Compiles! * Clean-up and parallelize. * Get rid of RefCell in header. * Revert "Get rid of RefCell in header." This reverts commit 0f2424c9b7319a786e1565ea2a8a6d801a21b4fb. * Override Sync requirement. * Fix status display. * Unify logging. * Extract some cheap checks. * Measurements and optimizations. * Fix scoring bug, heap size of bug and add cache * Disable tx queueing and parallel verification. * Make ethcore and ethcore-miner compile again. * Make RPC compile again. * Bunch of txpool tests. * Migrate transaction queue tests. * Nonce Cap * Nonce cap cache and tests. * Remove stale future transactions from the queue. * Optimize scoring and write some tests. * Simple penalization. * Clean up and support for different scoring algorithms. * Add CLI parameters for the new queue. * Remove banning queue. * Disable debug build. * Change per_sender limit to be 1% instead of 5% * Avoid cloning when propagating transactions. * Remove old todo. * Post-review fixes. * Fix miner options default. * Implement back ready transactions for light client. * Get rid of from_pending_block * Pass rejection reason. * Add more details to drop. * Rollback heap size of. * Avoid cloning hashes when propagating and include more details on rejection. * Fix tests. * Introduce nonces cache. * Remove uneccessary hashes allocation. * Lower the mem limit. * Re-enable parallel verification. * Add miner log. Don't check the type if not below min_gas_price. * Add more traces, fix disabling miner. * Fix creating pending blocks twice on AuRa authorities. * Fix tests. * re-use pending blocks in AuRa * Use reseal_min_period to prevent too frequent update_sealing. * Fix log to contain hash not sender. * Optimize local transactions. * Fix aura tests. * Update locks comments. * Get rid of unsafe Sync impl. * Review fixes. * Remove excessive matches. * Fix compilation errors. * Use new pool in private transactions. * Fix private-tx test. * Fix secret store tests. * Actually use gas_floor_target * Fix config tests. * Fix pool tests. * Address grumbles.
2018-04-13 17:34:27 +02:00
///
/// Unordered verification doesn't rely on the transaction execution order,
/// i.e. it should only verify stuff that doesn't assume any previous transactions
/// has already been verified and executed.
///
/// NOTE This function consumes an `UnverifiedTransaction` and produces `SignedTransaction`
/// which implies that a heavy check of the signature is performed here.
fn verify_transaction_unordered(&self, t: UnverifiedTransaction, header: &Header) -> Result<SignedTransaction, transaction::Error> {
self.machine().verify_transaction_unordered(t, header)
}
New Transaction Queue implementation (#8074) * Implementation of Verifier, Scoring and Ready. * Queue in progress. * TransactionPool. * Prepare for txpool release. * Miner refactor [WiP] * WiP reworking miner. * Make it compile. * Add some docs. * Split blockchain access to a separate file. * Work on miner API. * Fix ethcore tests. * Refactor miner interface for sealing/work packages. * Implement next nonce. * RPC compiles. * Implement couple of missing methdods for RPC. * Add transaction queue listeners. * Compiles! * Clean-up and parallelize. * Get rid of RefCell in header. * Revert "Get rid of RefCell in header." This reverts commit 0f2424c9b7319a786e1565ea2a8a6d801a21b4fb. * Override Sync requirement. * Fix status display. * Unify logging. * Extract some cheap checks. * Measurements and optimizations. * Fix scoring bug, heap size of bug and add cache * Disable tx queueing and parallel verification. * Make ethcore and ethcore-miner compile again. * Make RPC compile again. * Bunch of txpool tests. * Migrate transaction queue tests. * Nonce Cap * Nonce cap cache and tests. * Remove stale future transactions from the queue. * Optimize scoring and write some tests. * Simple penalization. * Clean up and support for different scoring algorithms. * Add CLI parameters for the new queue. * Remove banning queue. * Disable debug build. * Change per_sender limit to be 1% instead of 5% * Avoid cloning when propagating transactions. * Remove old todo. * Post-review fixes. * Fix miner options default. * Implement back ready transactions for light client. * Get rid of from_pending_block * Pass rejection reason. * Add more details to drop. * Rollback heap size of. * Avoid cloning hashes when propagating and include more details on rejection. * Fix tests. * Introduce nonces cache. * Remove uneccessary hashes allocation. * Lower the mem limit. * Re-enable parallel verification. * Add miner log. Don't check the type if not below min_gas_price. * Add more traces, fix disabling miner. * Fix creating pending blocks twice on AuRa authorities. * Fix tests. * re-use pending blocks in AuRa * Use reseal_min_period to prevent too frequent update_sealing. * Fix log to contain hash not sender. * Optimize local transactions. * Fix aura tests. * Update locks comments. * Get rid of unsafe Sync impl. * Review fixes. * Remove excessive matches. * Fix compilation errors. * Use new pool in private transactions. * Fix private-tx test. * Fix secret store tests. * Actually use gas_floor_target * Fix config tests. * Fix pool tests. * Address grumbles.
2018-04-13 17:34:27 +02:00
/// Perform basic/cheap transaction verification.
///
/// This should include all cheap checks that can be done before
/// actually checking the signature, like chain-replay protection.
///
/// NOTE This is done before the signature is recovered so avoid
/// doing any state-touching checks that might be expensive.
///
/// TODO: Add flags for which bits of the transaction to check.
/// TODO: consider including State in the params.
fn verify_transaction_basic(&self, t: &UnverifiedTransaction, header: &Header) -> Result<(), transaction::Error> {
self.machine().verify_transaction_basic(t, header)
}
/// Additional information.
fn additional_params(&self) -> HashMap<String, String> {
self.machine().additional_params()
}
/// Performs pre-validation of RLP decoded transaction before other processing
fn decode_transaction(&self, transaction: &[u8]) -> Result<UnverifiedTransaction, transaction::Error> {
self.machine().decode_transaction(transaction)
}
}
// convenience wrappers for existing functions.
impl<T> EthEngine for T where T: Engine<::machine::EthereumMachine> { }