diff --git a/Cargo.lock b/Cargo.lock index 467c385e0..be413453a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -418,8 +418,18 @@ dependencies = [ name = "client-traits" version = "0.1.0" dependencies = [ + "account-state 0.1.0", "common-types 0.1.0", + "ethcore-blockchain 0.1.0", + "ethcore-call-contract 0.1.0", + "ethcore-db 0.1.0", + "ethcore-miner 1.12.0", "ethereum-types 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "kvdb 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "stats 0.1.0", + "trace 0.1.0", + "vm 0.1.0", ] [[package]] @@ -748,6 +758,23 @@ dependencies = [ "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "engine" +version = "0.1.0" +dependencies = [ + "client-traits 0.1.0", + "common-types 0.1.0", + "ethcore-accounts 0.1.0", + "ethcore-blockchain 0.1.0", + "ethcore-builtin 0.1.0", + "ethereum-types 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethkey 0.3.0", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "machine 0.1.0", + "parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "vm 0.1.0", +] + [[package]] name = "enum_primitive" version = "0.1.1" @@ -861,6 +888,7 @@ dependencies = [ "common-types 0.1.0", "criterion 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "engine 0.1.0", "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi 8.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-contract 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1043,6 +1071,7 @@ dependencies = [ "client-traits 0.1.0", "common-types 0.1.0", "derive_more 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "engine 0.1.0", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore 1.12.0", "ethcore-blockchain 0.1.0", @@ -1238,6 +1267,7 @@ name = "ethcore-secretstore" version = "1.0.0" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "client-traits 0.1.0", "common-types 0.1.0", "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi 8.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1314,6 +1344,7 @@ version = "1.12.0" dependencies = [ "client-traits 0.1.0", "common-types 0.1.0", + "engine 0.1.0", "enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore 1.12.0", @@ -2524,6 +2555,7 @@ dependencies = [ name = "node-filter" version = "1.12.0" dependencies = [ + "client-traits 0.1.0", "common-types 0.1.0", "ethabi 8.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-contract 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2723,6 +2755,7 @@ dependencies = [ "ctrlc 1.1.1 (git+https://github.com/paritytech/rust-ctrlc.git)", "dir 0.1.2", "docopt 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "engine 0.1.0", "ethcore 1.12.0", "ethcore-accounts 0.1.0", "ethcore-blockchain 0.1.0", @@ -2813,6 +2846,7 @@ name = "parity-ipfs-api" version = "1.12.0" dependencies = [ "cid 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "client-traits 0.1.0", "common-types 0.1.0", "ethcore 1.12.0", "ethereum-types 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2876,6 +2910,7 @@ dependencies = [ "client-traits 0.1.0", "common-types 0.1.0", "eip-712 0.1.0", + "engine 0.1.0", "ethash 1.12.0", "ethcore 1.12.0", "ethcore-accounts 0.1.0", @@ -2997,6 +3032,7 @@ dependencies = [ name = "parity-updater" version = "1.12.0" dependencies = [ + "client-traits 0.1.0", "common-types 0.1.0", "ethabi 8.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-contract 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 4c5d4898e..69fe1f02a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,6 +33,7 @@ jsonrpc-core = "12.0.0" parity-bytes = "0.1" client-traits = { path = "ethcore/client-traits" } common-types = { path = "ethcore/types" } +engine = { path = "ethcore/engine" } ethcore = { path = "ethcore", features = ["parity"] } ethcore-accounts = { path = "accounts", optional = true } ethcore-blockchain = { path = "ethcore/blockchain" } diff --git a/ethash/src/lib.rs b/ethash/src/lib.rs index 47dd0688d..3225ceb9f 100644 --- a/ethash/src/lib.rs +++ b/ethash/src/lib.rs @@ -85,7 +85,7 @@ impl EthashManager { EthashManager { cache_dir: cache_dir.to_path_buf(), nodecache_builder: NodeCacheBuilder::new(optimize_for.into().unwrap_or_default(), progpow_transition), - progpow_transition: progpow_transition, + progpow_transition, cache: Mutex::new(LightCache { recent_epoch: None, recent: None, diff --git a/ethcore/Cargo.toml b/ethcore/Cargo.toml index 44118bbea..f896042aa 100644 --- a/ethcore/Cargo.toml +++ b/ethcore/Cargo.toml @@ -8,11 +8,13 @@ authors = ["Parity Technologies "] [dependencies] account-db = { path = "account-db" } +account-state = { path = "account-state" } ansi_term = "0.11" blooms-db = { path = "../util/blooms-db", optional = true } client-traits = { path = "./client-traits" } common-types = { path = "types" } crossbeam-utils = "0.6" +engine = { path = "./engine" } env_logger = { version = "0.5", optional = true } ethabi = "8.0" ethabi-contract = "8.0" @@ -30,7 +32,6 @@ ethereum-types = "0.6.0" ethjson = { path = "../json" } ethkey = { path = "../accounts/ethkey" } evm = { path = "evm" } -trie-vm-factories = { path = "trie-vm-factories" } futures = "0.1" hash-db = "0.15.0" parity-util-mem = "0.2.0" @@ -52,42 +53,43 @@ num_cpus = "1.2" parity-bytes = "0.1" parity-snappy = "0.1" parking_lot = "0.8" -pod = { path = "pod" } trie-db = "0.15.0" patricia-trie-ethereum = { path = "../util/patricia-trie-ethereum" } +pod = { path = "pod" } rand = "0.6" +rand_xorshift = "0.1.1" rayon = "1.1" rlp = "0.4.0" rlp_derive = { path = "../util/rlp-derive" } rustc-hex = "1.0" serde = "1.0" serde_derive = "1.0" -account-state = { path = "account-state" } -stats = { path = "../util/stats" } state-db = { path = "state-db" } +stats = { path = "../util/stats" } tempdir = { version = "0.3", optional = true } time-utils = { path = "../util/time-utils" } trace = { path = "trace" } trace-time = "0.1" +trie-vm-factories = { path = "trie-vm-factories" } triehash-ethereum = { version = "0.2", path = "../util/triehash-ethereum" } unexpected = { path = "../util/unexpected" } using_queue = { path = "../miner/using-queue" } vm = { path = "vm" } -rand_xorshift = "0.1.1" [dev-dependencies] blooms-db = { path = "../util/blooms-db" } criterion = "0.2" +engine = { path = "./engine", features = ["test-helpers"] } env_logger = "0.5" ethcore-accounts = { path = "../accounts" } fetch = { path = "../util/fetch" } kvdb-rocksdb = "0.1.3" +machine = { path = "./machine", features = ["test-helpers"] } parity-runtime = { path = "../util/runtime" } rlp_compress = { path = "../util/rlp-compress" } serde_json = "1.0" tempdir = "0.3" trie-standardmap = "0.15.0" -machine = { path = "./machine", features = ["test-helpers"] } [features] parity = ["work-notify", "price-info", "stratum"] diff --git a/ethcore/client-traits/Cargo.toml b/ethcore/client-traits/Cargo.toml index cbc5b1934..bc8b06f0f 100644 --- a/ethcore/client-traits/Cargo.toml +++ b/ethcore/client-traits/Cargo.toml @@ -7,6 +7,15 @@ edition = "2018" license = "GPL-3.0" [dependencies] -ethereum-types = "0.6.0" +account-state = { path = "../account-state" } +blockchain = { package = "ethcore-blockchain", path = "../blockchain" } +bytes = { package = "parity-bytes", version = "0.1.0" } +call-contract = { package = "ethcore-call-contract", path = "../call-contract" } common-types = { path = "../types" } - +ethcore-db = { path = "../db" } +ethcore-miner = { path = "../../miner" } +ethereum-types = "0.6.0" +kvdb = "0.1.0" +stats = { path = "../../util/stats" } +trace = { path = "../trace" } +vm = { path = "../vm" } diff --git a/ethcore/client-traits/src/lib.rs b/ethcore/client-traits/src/lib.rs index 84b418e3b..af68b9b3f 100644 --- a/ethcore/client-traits/src/lib.rs +++ b/ethcore/client-traits/src/lib.rs @@ -14,24 +14,412 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . -use ethereum_types::{Address, H256}; -use common_types::{ - header::Header, - encoded, - ids::BlockId, +use std::{ + collections::BTreeMap, + sync::Arc, }; +use account_state::state::StateInfo; +use blockchain::BlockProvider; +use bytes::Bytes; +use call_contract::{CallContract, RegistryInfo}; +use common_types::{ + basic_account::BasicAccount, + block_status::BlockStatus, + blockchain_info::BlockChainInfo, + BlockNumber, + call_analytics::CallAnalytics, + client_types::Mode, + encoded, + engines::{epoch::Transition as EpochTransition, machine::Executed}, + errors::EthcoreResult, + filter::Filter, + header::Header, + ids::{BlockId, TransactionId, TraceId, UncleId}, + log_entry::LocalizedLogEntry, + pruning_info::PruningInfo, + receipt::LocalizedReceipt, + trace_filter::Filter as TraceFilter, + transaction::{self, LocalizedTransaction, CallError, SignedTransaction}, + tree_route::TreeRoute, + verification::{VerificationQueueInfo, Unverified}, +}; +use ethereum_types::{Address, H256, U256}; +use ethcore_db::keys::BlockReceipts; +use ethcore_miner::pool::VerifiedTransaction; +use kvdb::DBValue; +use stats; +use trace::{ + FlatTrace, + localized::LocalizedTrace, + VMTrace, +}; +use vm::{LastHashes, Schedule}; + +/// State information to be used during client query +pub enum StateOrBlock { + /// State to be used, may be pending + State(Box), + + /// Id of an existing block from a chain to get state from + Block(BlockId) +} + +impl From> for StateOrBlock { + fn from(info: Box) -> StateOrBlock { + StateOrBlock::State(info) + } +} + +impl From for StateOrBlock { + fn from(id: BlockId) -> StateOrBlock { + StateOrBlock::Block(id) + } +} + +/// Provides `nonce` and `latest_nonce` methods +pub trait Nonce { + /// Attempt to get address nonce at given block. + /// May not fail on BlockId::Latest. + fn nonce(&self, address: &Address, id: BlockId) -> Option; + + /// Get address nonce at the latest block's state. + fn latest_nonce(&self, address: &Address) -> U256 { + self.nonce(address, BlockId::Latest) + .expect("nonce will return Some when given BlockId::Latest. nonce was given BlockId::Latest. \ + Therefore nonce has returned Some; qed") + } +} + +/// Provides `balance` and `latest_balance` methods +pub trait Balance { + /// Get address balance at the given block's state. + /// + /// May not return None if given BlockId::Latest. + /// Returns None if and only if the block's root hash has been pruned from the DB. + fn balance(&self, address: &Address, state: StateOrBlock) -> Option; + + /// Get address balance at the latest block's state. + fn latest_balance(&self, address: &Address) -> U256 { + self.balance(address, BlockId::Latest.into()) + .expect("balance will return Some if given BlockId::Latest. balance was given BlockId::Latest \ + Therefore balance has returned Some; qed") + } +} + +/// Provides methods to access account info +pub trait AccountData: Nonce + Balance {} + +/// Provides `chain_info` method +pub trait ChainInfo { + /// Get blockchain information. + fn chain_info(&self) -> BlockChainInfo; +} + /// Provides various information on a block by it's ID pub trait BlockInfo { - /// Get raw block header data by block id. - fn block_header(&self, id: BlockId) -> Option; + /// Get raw block header data by block id. + fn block_header(&self, id: BlockId) -> Option; - /// Get the best block header. - fn best_block_header(&self) -> Header; + /// Get the best block header. + fn best_block_header(&self) -> Header; - /// Get raw block data by block header hash. - fn block(&self, id: BlockId) -> Option; + /// Get raw block data by block header hash. + fn block(&self, id: BlockId) -> Option; - /// Get address code hash at given block's state. - fn code_hash(&self, address: &Address, id: BlockId) -> Option; + /// Get address code hash at given block's state. + fn code_hash(&self, address: &Address, id: BlockId) -> Option; +} + +/// Provides various information on a transaction by it's ID +pub trait TransactionInfo { + /// Get the hash of block that contains the transaction, if any. + fn transaction_block(&self, id: TransactionId) -> Option; +} + +/// Provides various blockchain information, like block header, chain state etc. +pub trait BlockChain: ChainInfo + BlockInfo + TransactionInfo {} + +/// Client facilities used by internally sealing Engines. +pub trait EngineClient: Sync + Send + ChainInfo { + /// Make a new block and seal it. + fn update_sealing(&self); + + /// Submit a seal for a block in the mining queue. + fn submit_seal(&self, block_hash: H256, seal: Vec); + + /// Broadcast a consensus message to the network. + fn broadcast_consensus_message(&self, message: Bytes); + + /// Get the transition to the epoch the given parent hash is part of + /// or transitions to. + /// This will give the epoch that any children of this parent belong to. + /// + /// The block corresponding the the parent hash must be stored already. + fn epoch_transition_for(&self, parent_hash: H256) -> Option; + + /// Attempt to cast the engine client to a full client. + fn as_full_client(&self) -> Option<&dyn BlockChainClient>; + + /// Get a block number by ID. + fn block_number(&self, id: BlockId) -> Option; + + /// Get raw block header data by block id. + fn block_header(&self, id: BlockId) -> Option; +} + +// FIXME Why these methods belong to BlockChainClient and not MiningBlockChainClient? +/// Provides methods to import block into blockchain +pub trait ImportBlock { + /// Import a block into the blockchain. + fn import_block(&self, block: Unverified) -> EthcoreResult; +} + +/// IO operations that should off-load heavy work to another thread. +pub trait IoClient: Sync + Send { + /// Queue transactions for importing. + fn queue_transactions(&self, transactions: Vec, peer_id: usize); + + /// Queue block import with transaction receipts. Does no sealing and transaction validation. + fn queue_ancient_block(&self, block_bytes: Unverified, receipts_bytes: Bytes) -> EthcoreResult; + + /// Queue consensus engine message. + fn queue_consensus_message(&self, message: Bytes); +} + +/// Provides recently seen bad blocks. +pub trait BadBlocks { + /// Returns a list of blocks that were recently not imported because they were invalid. + fn bad_blocks(&self) -> Vec<(Unverified, String)>; +} + + +/// Blockchain database client. Owns and manages a blockchain and a block queue. +pub trait BlockChainClient : Sync + Send + AccountData + BlockChain + CallContract + RegistryInfo + ImportBlock ++ IoClient + BadBlocks { + /// Look up the block number for the given block ID. + fn block_number(&self, id: BlockId) -> Option; + + /// Get raw block body data by block id. + /// Block body is an RLP list of two items: uncles and transactions. + fn block_body(&self, id: BlockId) -> Option; + + /// Get block status by block header hash. + fn block_status(&self, id: BlockId) -> BlockStatus; + + /// Get block total difficulty. + fn block_total_difficulty(&self, id: BlockId) -> Option; + + /// Attempt to get address storage root at given block. + /// May not fail on BlockId::Latest. + fn storage_root(&self, address: &Address, id: BlockId) -> Option; + + /// Get block hash. + fn block_hash(&self, id: BlockId) -> Option; + + /// Get address code at given block's state. + fn code(&self, address: &Address, state: StateOrBlock) -> Option>; + + /// Get address code at the latest block's state. + fn latest_code(&self, address: &Address) -> Option { + self.code(address, BlockId::Latest.into()) + .expect("code will return Some if given BlockId::Latest; qed") + } + + /// Get a reference to the `BlockProvider`. + fn chain(&self) -> Arc; + + /// Get block queue information. + fn queue_info(&self) -> VerificationQueueInfo; + + /// Get address code hash at given block's state. + + /// Get value of the storage at given position at the given block's state. + /// + /// May not return None if given BlockId::Latest. + /// Returns None if and only if the block's root hash has been pruned from the DB. + fn storage_at(&self, address: &Address, position: &H256, state: StateOrBlock) -> Option; + + /// Get value of the storage at given position at the latest block's state. + fn latest_storage_at(&self, address: &Address, position: &H256) -> H256 { + self.storage_at(address, position, BlockId::Latest.into()) + .expect("storage_at will return Some if given BlockId::Latest. storage_at was given BlockId::Latest. \ + Therefore storage_at has returned Some; qed") + } + + /// Get a list of all accounts in the block `id`, if fat DB is in operation, otherwise `None`. + /// If `after` is set the list starts with the following item. + fn list_accounts(&self, id: BlockId, after: Option<&Address>, count: u64) -> Option>; + + /// Get a list of all storage keys in the block `id`, if fat DB is in operation, otherwise `None`. + /// If `after` is set the list starts with the following item. + fn list_storage(&self, id: BlockId, account: &Address, after: Option<&H256>, count: u64) -> Option>; + + /// Get transaction with given hash. + fn transaction(&self, id: TransactionId) -> Option; + + /// Get uncle with given id. + fn uncle(&self, id: UncleId) -> Option; + + /// Get transaction receipt with given hash. + fn transaction_receipt(&self, id: TransactionId) -> Option; + + /// Get localized receipts for all transaction in given block. + fn localized_block_receipts(&self, id: BlockId) -> Option>; + + /// Get a tree route between `from` and `to`. + /// See `BlockChain::tree_route`. + fn tree_route(&self, from: &H256, to: &H256) -> Option; + + /// Get all possible uncle hashes for a block. + fn find_uncles(&self, hash: &H256) -> Option>; + + /// Get latest state node + fn state_data(&self, hash: &H256) -> Option; + + /// Get block receipts data by block header hash. + fn block_receipts(&self, hash: &H256) -> Option; + + /// Returns true if block queue is empty. + fn is_queue_empty(&self) -> bool { + self.queue_info().is_empty() + } + + /// Clear block queue and abort all import activity. + fn clear_queue(&self); + + /// Returns logs matching given filter. If one of the filtering block cannot be found, returns the block id that caused the error. + fn logs(&self, filter: Filter) -> Result, BlockId>; + + /// Replays a given transaction for inspection. + fn replay(&self, t: TransactionId, analytics: CallAnalytics) -> Result, CallError>; + + /// Replays all the transactions in a given block for inspection. + fn replay_block_transactions(&self, block: BlockId, analytics: CallAnalytics) -> Result)>>, CallError>; + + /// Returns traces matching given filter. + fn filter_traces(&self, filter: TraceFilter) -> Option>; + + /// Returns trace with given id. + fn trace(&self, trace: TraceId) -> Option; + + /// Returns traces created by transaction. + fn transaction_traces(&self, trace: TransactionId) -> Option>; + + /// Returns traces created by transaction from block. + fn block_traces(&self, trace: BlockId) -> Option>; + + /// Get last hashes starting from best block. + fn last_hashes(&self) -> LastHashes; + + /// List all ready transactions that should be propagated to other peers. + fn transactions_to_propagate(&self) -> Vec>; + + /// Sorted list of transaction gas prices from at least last sample_size blocks. + fn gas_price_corpus(&self, sample_size: usize) -> stats::Corpus { + let mut h = self.chain_info().best_block_hash; + let mut corpus = Vec::new(); + while corpus.is_empty() { + for _ in 0..sample_size { + let block = match self.block(BlockId::Hash(h)) { + Some(block) => block, + None => return corpus.into(), + }; + + if block.number() == 0 { + return corpus.into(); + } + for t in block.transaction_views().iter() { + corpus.push( t.gas_price() ) + } + h = block.parent_hash().clone(); + } + } + corpus.into() + } + + /// Get the preferred chain ID to sign on + fn signing_chain_id(&self) -> Option; + + /// Get the mode. + fn mode(&self) -> Mode; + + /// Set the mode. + fn set_mode(&self, mode: Mode); + + /// Get the chain spec name. + fn spec_name(&self) -> String; + + /// Set the chain via a spec name. + fn set_spec_name(&self, spec_name: String) -> Result<(), ()>; + + /// Disable the client from importing blocks. This cannot be undone in this session and indicates + /// that a subsystem has reason to believe this executable incapable of syncing the chain. + fn disable(&self); + + /// Returns engine-related extra info for `BlockId`. + fn block_extra_info(&self, id: BlockId) -> Option>; + + /// Returns engine-related extra info for `UncleId`. + fn uncle_extra_info(&self, id: UncleId) -> Option>; + + /// Returns information about pruning/data availability. + fn pruning_info(&self) -> PruningInfo; + + /// Schedule state-altering transaction to be executed on the next pending block. + fn transact_contract(&self, address: Address, data: Bytes) -> Result<(), transaction::Error>; + + /// Get the address of the registry itself. + fn registrar_address(&self) -> Option
; +} + +/// resets the blockchain +pub trait BlockChainReset { + /// reset to best_block - n + fn reset(&self, num: u32) -> Result<(), String>; +} + + +/// Provides `latest_schedule` method +pub trait ScheduleInfo { + /// Returns latest schedule. + fn latest_schedule(&self) -> Schedule; +} + +/// Provides methods to access chain state +pub trait StateClient { + /// Type representing chain state + type State: StateInfo; + + /// Get a copy of the best block's state. + fn latest_state(&self) -> Self::State; + + /// Attempt to get a copy of a specific block's final state. + /// + /// This will not fail if given BlockId::Latest. + /// Otherwise, this can fail (but may not) if the DB prunes state or the block + /// is unknown. + fn state_at(&self, id: BlockId) -> Option; +} + +/// Extended client interface for providing proofs of the state. +pub trait ProvingBlockChainClient: BlockChainClient { + /// Prove account storage at a specific block id. + /// + /// Both provided keys assume a secure trie. + /// Returns a vector of raw trie nodes (in order from the root) proving the storage query. + fn prove_storage(&self, key1: H256, key2: H256, id: BlockId) -> Option<(Vec, H256)>; + + /// Prove account existence at a specific block id. + /// The key is the keccak hash of the account's address. + /// Returns a vector of raw trie nodes (in order from the root) proving the query. + fn prove_account(&self, key1: H256, id: BlockId) -> Option<(Vec, BasicAccount)>; + + /// Prove execution of a transaction at the given block. + /// Returns the output of the call and a vector of database items necessary + /// to reproduce it. + fn prove_transaction(&self, transaction: SignedTransaction, id: BlockId) -> Option<(Bytes, Vec)>; + + /// Get an epoch change signal by block hash. + fn epoch_signal(&self, hash: H256) -> Option>; } diff --git a/ethcore/engine/Cargo.toml b/ethcore/engine/Cargo.toml new file mode 100644 index 000000000..28b2e5527 --- /dev/null +++ b/ethcore/engine/Cargo.toml @@ -0,0 +1,29 @@ +[package] +description = "Ethereum engine trait definition" +name = "engine" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0" + +[dependencies] +blockchain = { package = "ethcore-blockchain", path = "../blockchain" } +builtin = { path = "../builtin", package = "ethcore-builtin" } +bytes = { package = "parity-bytes", version = "0.1.0" } +client-traits = { path = "../client-traits" } +common-types = { path = "../types" } +ethereum-types = "0.6.0" +ethkey = { path = "../../accounts/ethkey" } +machine = { path = "../machine" } +vm = { path = "../vm" } + +# used from test-helpers +accounts = { package = "ethcore-accounts", path = "../../accounts", optional = true } +log = { version = "0.4.8", optional = true } + +[dev-dependencies] +accounts = { package = "ethcore-accounts", path = "../../accounts" } +log = "0.4.8" + +[features] +test-helpers = ["accounts", "log"] diff --git a/ethcore/engine/src/engine.rs b/ethcore/engine/src/engine.rs new file mode 100644 index 000000000..33c253357 --- /dev/null +++ b/ethcore/engine/src/engine.rs @@ -0,0 +1,418 @@ +// Copyright 2015-2019 Parity Technologies (UK) Ltd. +// This file is part of Parity Ethereum. + +// Parity Ethereum is free software: you can redistribute it and/or modify +// 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, +// 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 . + +//! Consensus engine specification and basic implementations. + +use std::sync::{Weak, Arc}; +use std::collections::BTreeMap; + +use builtin::Builtin; +use common_types::{ + BlockNumber, + ancestry_action::AncestryAction, + header::{Header, ExtendedHeader}, + engines::{ + Seal, SealingState, Headers, PendingTransitionStore, + params::CommonParams, + machine as machine_types, + machine::{AuxiliaryData, AuxiliaryRequest}, + }, + errors::{EthcoreError as Error, EngineError}, + transaction::{self, UnverifiedTransaction}, +}; +use client_traits::EngineClient; + +use ethereum_types::{H256, U256, Address}; +use ethkey::Signature; +use machine::{ + Machine, + executed_block::ExecutedBlock, +}; +use vm::{EnvInfo, Schedule, CallType, ActionValue}; + +use crate::{ + signer::EngineSigner, + snapshot::SnapshotComponents, +}; + +/// A system-calling closure. Enacts calls on a block's state from the system address. +pub type SystemCall<'a> = dyn FnMut(Address, Vec) -> Result, 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> = dyn FnMut(SystemOrCodeCallKind, Vec) -> Result, 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>, H256), +} + +/// Default SystemOrCodeCall implementation. +pub fn default_system_or_code_call<'a>(machine: &'a Machine, block: &'a mut ExecutedBlock) -> impl FnMut(SystemOrCodeCallKind, Vec) -> Result, 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)) + } +} + +/// Proof dependent on state. +pub trait StateDependentProof: Send + Sync { + /// Generate a proof, given the state. + fn generate_proof<'a>(&self, state: &machine_types::Call) -> Result, 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: &Machine, proof: &[u8]) -> Result<(), String>; +} + +/// Proof generated on epoch change. +pub enum Proof { + /// Known proof (extracted from signal) + Known(Vec), + /// State dependent proof. + WithState(Arc), +} + +/// Generated epoch verifier. +pub enum ConstructedVerifier<'a> { + /// Fully trusted verifier. + Trusted(Box), + /// Verifier unconfirmed. Check whether given finality proof finalizes given hash + /// under previous epoch. + Unconfirmed(Box, &'a [u8], H256), + /// Error constructing verifier. + Err(Error), +} + +impl<'a> ConstructedVerifier<'a> { + /// Convert to a result, indicating that any necessary confirmation has been done + /// already. + pub fn known_confirmed(self) -> Result, Error> { + match self { + ConstructedVerifier::Trusted(v) | ConstructedVerifier::Unconfirmed(v, _, _) => Ok(v), + ConstructedVerifier::Err(e) => Err(e), + } + } +} + +/// Results of a query of whether an epoch change occurred at the given block. +pub enum EpochChange { + /// Cannot determine until more data is passed. + Unsure(AuxiliaryRequest), + /// No epoch change. + No, + /// The epoch will change, with proof. + Yes(Proof), +} + +/// 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: Sync + Send { + /// The name of this engine. + fn name(&self) -> &str; + + /// Get access to the underlying state machine. + // TODO: decouple. + fn machine(&self) -> &Machine; + + /// The number of additional header fields required for this engine. + fn seal_fields(&self, _header: &Header) -> usize { 0 } + + /// Additional engine-specific information for the user/developer concerning `header`. + fn extra_info(&self, _header: &Header) -> BTreeMap { BTreeMap::new() } + + /// Maximum number of uncles a block is allowed to declare. + fn maximum_uncle_count(&self, _block: BlockNumber) -> usize { 0 } + + /// Optional maximum gas limit. + fn maximum_gas_limit(&self) -> Option { None } + + /// 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 ExecutedBlock, + _epoch_begin: bool, + ) -> Result<(), Error> { + Ok(()) + } + + /// Block transformation functions, after the transactions. + fn on_close_block( + &self, + _block: &mut ExecutedBlock, + _parent_header: &Header, + ) -> Result<(), Error> { + Ok(()) + } + + /// Allow mutating the header during seal generation. Currently only used by Clique. + fn on_seal_block(&self, _block: &mut ExecutedBlock) -> Result<(), Error> { Ok(()) } + + /// Returns the engine's current sealing state. + fn sealing_state(&self) -> SealingState { SealingState::External } + + /// 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: &ExecutedBlock, _parent: &Header) -> Seal { Seal::None } + + /// 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: &Header) -> Result<(), 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: &Header) -> Result<(), 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: &Header) -> Result<(), 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: &Header, _parent: &Header) -> Result<(), 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: &Header) -> Result<(), Error> { Ok(()) } + + /// Genesis epoch data. + fn genesis_epoch_data<'a>(&self, _header: &Header, _state: &machine_types::Call) -> Result, String> { Ok(Vec::new()) } + + /// 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. + /// + /// Should not interact with state. + fn signals_epoch_end<'a>(&self, _header: &Header, _aux: AuxiliaryData<'a>) -> EpochChange { + EpochChange::No + } + + /// 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: &Header, + _finalized: &[H256], + _chain: &Headers
, + _transition_store: &PendingTransitionStore, + ) -> Option> { + 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: &Header, + _chain: &Headers
, + _transition_store: &PendingTransitionStore, + ) -> Option> { + None + } + + /// Create an epoch verifier from validation proof and a flag indicating + /// whether finality is required. + fn epoch_verifier<'a>(&self, _header: &Header, _proof: &'a [u8]) -> ConstructedVerifier<'a> { + ConstructedVerifier::Trusted(Box::new(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 Header, _parent: &Header) { } + + /// 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) } + + /// Register a component which signs consensus messages. + fn set_signer(&self, _signer: Box) {} + + /// Sign using the EngineSigner, to be used for consensus tx signing. + fn sign(&self, _hash: H256) -> Result { unimplemented!() } + + /// Add Client which can be used for sealing, potentially querying the state and sending messages. + fn register_client(&self, _client: Weak) {} + + /// Trigger next step of the consensus engine. + fn step(&self) {} + + /// 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> { + None + } + + /// 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 + } + + /// 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: &Header, _ancestry: &mut dyn Iterator) -> Vec { + Vec::new() + } + + /// Returns author should used when executing tx's for this block. + fn executive_author(&self, header: &Header) -> Result { + Ok(*header.author()) + } + + /// Get the general parameters of the chain. + fn params(&self) -> &CommonParams; + + /// 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 { + 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.params().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 { + self.machine().signing_chain_id(env_info) + } + + /// 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) + } + + /// Performs pre-validation of RLP decoded transaction before other processing + fn decode_transaction(&self, transaction: &[u8]) -> Result { + self.machine().decode_transaction(transaction) + } +} + +/// Verifier for all blocks within an epoch with self-contained state. +pub trait EpochVerifier: Send + Sync { + /// Lightly verify the next block header. + /// This may not be a header belonging to a different epoch. + fn verify_light(&self, _header: &Header) -> Result<(), Error> { Ok(()) } + + /// Perform potentially heavier checks on the next block header. + fn verify_heavy(&self, header: &Header) -> Result<(), Error> { + self.verify_light(header) + } + + /// Check a finality proof against this epoch verifier. + /// Returns `Some(hashes)` if the proof proves finality of these hashes. + /// Returns `None` if the proof doesn't prove anything. + fn check_finality_proof(&self, _proof: &[u8]) -> Option> { + None + } +} + +/// Special "no-op" verifier for stateless, epoch-less engines. +pub struct NoOp; + +impl EpochVerifier for NoOp {} diff --git a/ethcore/engine/src/lib.rs b/ethcore/engine/src/lib.rs new file mode 100644 index 000000000..5b3c93bf6 --- /dev/null +++ b/ethcore/engine/src/lib.rs @@ -0,0 +1,37 @@ +// Copyright 2015-2019 Parity Technologies (UK) Ltd. +// This file is part of Parity Ethereum. + +// Parity Ethereum is free software: you can redistribute it and/or modify +// 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, +// 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 . + +//! This crate defines the Engine trait and related types. + +mod engine; +pub mod signer; +pub mod snapshot; + +pub use crate::engine::{ + Engine, + EpochVerifier, + StateDependentProof, + ConstructedVerifier, + EpochChange, + Proof, + SystemCall, + SystemOrCodeCall, + SystemOrCodeCallKind, + default_system_or_code_call, +}; + +#[cfg(any(test, feature = "test-helpers"))] +pub mod test_helpers; diff --git a/ethcore/src/engines/signer.rs b/ethcore/engine/src/signer.rs similarity index 62% rename from ethcore/src/engines/signer.rs rename to ethcore/engine/src/signer.rs index 196c535fe..1e932feef 100644 --- a/ethcore/src/engines/signer.rs +++ b/ethcore/engine/src/signer.rs @@ -44,36 +44,3 @@ impl EngineSigner for Signer { self.0.address() } } - -#[cfg(test)] -mod test_signer { - use std::sync::Arc; - - use ethkey::Password; - use accounts::{self, AccountProvider, SignError}; - - use super::*; - - impl EngineSigner for (Arc, Address, Password) { - fn sign(&self, hash: H256) -> Result { - match self.0.sign(self.1, Some(self.2.clone()), hash) { - Err(SignError::NotUnlocked) => unreachable!(), - Err(SignError::NotFound) => Err(ethkey::Error::InvalidAddress), - Err(SignError::SStore(accounts::Error::EthKey(err))) => Err(err), - Err(SignError::SStore(accounts::Error::EthKeyCrypto(err))) => { - warn!("Low level crypto error: {:?}", err); - Err(ethkey::Error::InvalidSecret) - }, - Err(SignError::SStore(err)) => { - warn!("Error signing for engine: {:?}", err); - Err(ethkey::Error::InvalidSignature) - }, - Ok(ok) => Ok(ok), - } - } - - fn address(&self) -> Address { - self.1 - } - } -} diff --git a/ethcore/engine/src/snapshot.rs b/ethcore/engine/src/snapshot.rs new file mode 100644 index 000000000..8499b97bf --- /dev/null +++ b/ethcore/engine/src/snapshot.rs @@ -0,0 +1,90 @@ +// Copyright 2015-2019 Parity Technologies (UK) Ltd. +// This file is part of Parity Ethereum. + +// Parity Ethereum is free software: you can redistribute it and/or modify +// 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, +// 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 . + +//! This module contains traits used while creating/restoring snapshots. They +//! are here because they use and are used by the Engine trait itself. + +use std::sync::{Arc, atomic::AtomicBool}; + +use ethereum_types::H256; + +use blockchain::{BlockChain, BlockChainDB}; +use common_types::{ + errors::{EthcoreError as Error, SnapshotError}, + snapshot::{ManifestData, ChunkSink, Progress}, +}; + +use crate::engine::Engine; + +/// Restore from secondary snapshot chunks. +pub trait Rebuilder: Send { + /// Feed a chunk, potentially out of order. + /// + /// Check `abort_flag` periodically while doing heavy work. If set to `false`, should bail with + /// `Error::RestorationAborted`. + fn feed( + &mut self, + chunk: &[u8], + engine: &dyn Engine, + abort_flag: &AtomicBool, + ) -> Result<(), Error>; + + /// Finalize the restoration. Will be done after all chunks have been + /// fed successfully. + /// + /// This should apply the necessary "glue" between chunks, + /// and verify against the restored state. + fn finalize(&mut self) -> Result<(), Error>; +} + +/// Components necessary for snapshot creation and restoration. +pub trait SnapshotComponents: Send { + /// Create secondary snapshot chunks; these corroborate the state data + /// in the state chunks. + /// + /// Chunks shouldn't exceed the given preferred size, and should be fed + /// uncompressed into the sink. + /// + /// This will vary by consensus engine, so it's exposed as a trait. + fn chunk_all( + &mut self, + chain: &BlockChain, + block_at: H256, + chunk_sink: &mut ChunkSink, + progress: &Progress, + preferred_size: usize, + ) -> Result<(), SnapshotError>; + + /// Create a rebuilder, which will have chunks fed into it in arbitrary + /// order and then be finalized. + /// + /// The manifest, a database, and fresh `BlockChain` are supplied. + /// + /// The engine passed to the `Rebuilder` methods will be the same instance + /// that created the `SnapshotComponents`. + fn rebuilder( + &self, + chain: BlockChain, + db: Arc, + manifest: &ManifestData, + ) -> Result, Error>; + + /// Minimum supported snapshot version number. + fn min_supported_version(&self) -> u64; + + /// Current version number + fn current_version(&self) -> u64; +} diff --git a/ethcore/engine/src/test_helpers.rs b/ethcore/engine/src/test_helpers.rs new file mode 100644 index 000000000..92ba66ff4 --- /dev/null +++ b/ethcore/engine/src/test_helpers.rs @@ -0,0 +1,49 @@ +// Copyright 2015-2019 Parity Technologies (UK) Ltd. +// This file is part of Parity Ethereum. + +// Parity Ethereum is free software: you can redistribute it and/or modify +// 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, +// 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 . + +//! Test helpers for engine related tests + +use std::sync::Arc; + +use ethereum_types::{Address, H256}; +use ethkey::{Password, Signature}; +use log::warn; +use accounts::{self, AccountProvider, SignError}; + +use crate::signer::EngineSigner; + +impl EngineSigner for (Arc, Address, Password) { + fn sign(&self, hash: H256) -> Result { + match self.0.sign(self.1, Some(self.2.clone()), hash) { + Err(SignError::NotUnlocked) => unreachable!(), + Err(SignError::NotFound) => Err(ethkey::Error::InvalidAddress), + Err(SignError::SStore(accounts::Error::EthKey(err))) => Err(err), + Err(SignError::SStore(accounts::Error::EthKeyCrypto(err))) => { + warn!("Low level crypto error: {:?}", err); + Err(ethkey::Error::InvalidSecret) + }, + Err(SignError::SStore(err)) => { + warn!("Error signing for engine: {:?}", err); + Err(ethkey::Error::InvalidSignature) + }, + Ok(ok) => Ok(ok), + } + } + + fn address(&self) -> Address { + self.1 + } +} diff --git a/ethcore/light/Cargo.toml b/ethcore/light/Cargo.toml index 83494b37a..19911db39 100644 --- a/ethcore/light/Cargo.toml +++ b/ethcore/light/Cargo.toml @@ -12,6 +12,7 @@ parity-bytes = "0.1" client-traits = { path = "../client-traits" } common-types = { path = "../types" } derive_more = "0.14.0" +engine = { path = "../engine" } ethcore = { path = ".."} ethcore-db = { path = "../db" } ethcore-blockchain = { path = "../blockchain" } diff --git a/ethcore/light/src/client/fetch.rs b/ethcore/light/src/client/fetch.rs index 602be8fc3..cbb5d3e22 100644 --- a/ethcore/light/src/client/fetch.rs +++ b/ethcore/light/src/client/fetch.rs @@ -18,10 +18,12 @@ use std::sync::Arc; -use common_types::encoded; -use common_types::header::Header; -use common_types::receipt::Receipt; -use ethcore::engines::{Engine, StateDependentProof}; +use common_types::{ + header::Header, + encoded, + receipt::Receipt, +}; +use engine::{Engine, StateDependentProof}; use ethereum_types::H256; use futures::future::IntoFuture; diff --git a/ethcore/light/src/client/header_chain.rs b/ethcore/light/src/client/header_chain.rs index 3b9d2beec..92207139a 100644 --- a/ethcore/light/src/client/header_chain.rs +++ b/ethcore/light/src/client/header_chain.rs @@ -33,11 +33,14 @@ use cht; use common_types::{ block_status::BlockStatus, encoded, + engines::epoch::{ + Transition as EpochTransition, + PendingTransition as PendingEpochTransition, + }, errors::{EthcoreError as Error, BlockError, EthcoreResult}, header::Header, ids::BlockId, }; -use ethcore::engines::epoch::{Transition as EpochTransition, PendingTransition as PendingEpochTransition}; use ethcore::spec::{Spec, SpecHardcodedSync}; use ethereum_types::{H256, H264, U256}; use parity_util_mem::{MallocSizeOf, MallocSizeOfOps}; diff --git a/ethcore/light/src/client/mod.rs b/ethcore/light/src/client/mod.rs index 6d4dd5a0b..73e512b10 100644 --- a/ethcore/light/src/client/mod.rs +++ b/ethcore/light/src/client/mod.rs @@ -18,8 +18,8 @@ use std::sync::{Weak, Arc}; +use engine::{Engine, EpochChange, Proof}; use ethcore::client::{ClientReport, EnvInfo, ClientIoMessage}; -use ethcore::engines::{epoch, Engine, EpochChange, EpochTransition, Proof}; use ethcore::verification::queue::{self, HeaderQueue}; use ethcore::spec::{Spec, SpecHardcodedSync}; use io::IoChannel; @@ -31,11 +31,12 @@ use common_types::{ block_status::BlockStatus, blockchain_info::BlockChainInfo, encoded, + engines::epoch::{Transition as EpochTransition, PendingTransition}, errors::EthcoreError as Error, errors::EthcoreResult, header::Header, ids::BlockId, - verification_queue_info::VerificationQueueInfo as BlockQueueInfo, + verification::VerificationQueueInfo as BlockQueueInfo, }; use kvdb::KeyValueDB; @@ -528,7 +529,7 @@ impl Client { }; let mut batch = self.db.transaction(); - self.chain.insert_pending_transition(&mut batch, header.hash(), &epoch::PendingTransition { + self.chain.insert_pending_transition(&mut batch, header.hash(), &PendingTransition { proof, }); self.db.write_buffered(batch); @@ -616,13 +617,13 @@ impl LightChainClient for Client { } } -impl ::ethcore::client::ChainInfo for Client { +impl client_traits::ChainInfo for Client { fn chain_info(&self) -> BlockChainInfo { Client::chain_info(self) } } -impl ::ethcore::client::EngineClient for Client { +impl client_traits::EngineClient for Client { fn update_sealing(&self) { } fn submit_seal(&self, _block_hash: H256, _seal: Vec>) { } fn broadcast_consensus_message(&self, _message: Vec) { } @@ -635,7 +636,7 @@ impl ::ethcore::client::EngineClient for Client { }) } - fn as_full_client(&self) -> Option<&dyn (::ethcore::client::BlockChainClient)> { + fn as_full_client(&self) -> Option<&dyn (client_traits::BlockChainClient)> { None } diff --git a/ethcore/light/src/lib.rs b/ethcore/light/src/lib.rs index 64b7f7d69..9b9c40533 100644 --- a/ethcore/light/src/lib.rs +++ b/ethcore/light/src/lib.rs @@ -56,6 +56,7 @@ extern crate log; extern crate bincode; extern crate client_traits; extern crate common_types; +extern crate engine; extern crate ethcore_blockchain; extern crate ethcore_db; extern crate ethcore_io as io; diff --git a/ethcore/light/src/on_demand/request.rs b/ethcore/light/src/on_demand/request.rs index f74d2e492..cff0b63fc 100644 --- a/ethcore/light/src/on_demand/request.rs +++ b/ethcore/light/src/on_demand/request.rs @@ -24,7 +24,7 @@ use common_types::basic_account::BasicAccount; use common_types::encoded; use common_types::receipt::Receipt; use common_types::transaction::SignedTransaction; -use ethcore::engines::{Engine, StateDependentProof}; +use engine::{Engine, StateDependentProof}; use ethcore::executive_state::{ProvedExecution, self}; use ethereum_types::{H256, U256, Address}; use ethtrie::{TrieError, TrieDB}; @@ -1099,8 +1099,8 @@ mod tests { use trie::Recorder; use hash::keccak; - use ethcore::client::{BlockChainClient, TestBlockChainClient, EachBlockWith}; - use client_traits::BlockInfo; + use ethcore::client::{TestBlockChainClient, EachBlockWith}; + use client_traits::{BlockInfo, BlockChainClient}; use common_types::header::Header; use common_types::encoded; use common_types::receipt::{Receipt, TransactionOutcome}; diff --git a/ethcore/light/src/provider.rs b/ethcore/light/src/provider.rs index 5e9533d5b..c44bf59b3 100644 --- a/ethcore/light/src/provider.rs +++ b/ethcore/light/src/provider.rs @@ -25,8 +25,12 @@ use common_types::{ ids::BlockId, transaction::PendingTransaction, }; -use ethcore::client::{BlockChainClient, ProvingBlockChainClient, ChainInfo}; -use client_traits::BlockInfo as ClientBlockInfo; +use client_traits::{ + BlockChainClient, + BlockInfo as ClientBlockInfo, + ChainInfo, + ProvingBlockChainClient, +}; use ethereum_types::H256; use parking_lot::RwLock; diff --git a/ethcore/machine/src/executed.rs b/ethcore/machine/src/executed.rs index 42c165bcb..b34f264ce 100644 --- a/ethcore/machine/src/executed.rs +++ b/ethcore/machine/src/executed.rs @@ -16,58 +16,14 @@ //! Transaction execution format module. -use ethereum_types::{U256, Address}; -use parity_bytes::Bytes; -use vm; use trace::{VMTrace, FlatTrace}; use common_types::{ - state_diff::StateDiff, - log_entry::LogEntry, + engines::machine, errors::ExecutionError, }; -/// Transaction execution receipt. -#[derive(Debug, PartialEq, Clone)] -pub struct Executed { - /// True if the outer call/create resulted in an exceptional exit. - pub exception: Option, - - /// Gas paid up front for execution of transaction. - pub gas: U256, - - /// Gas used during execution of transaction. - pub gas_used: U256, - - /// Gas refunded after the execution of transaction. - /// To get gas that was required up front, add `refunded` and `gas_used`. - pub refunded: U256, - - /// Cumulative gas used in current block so far. - /// - /// `cumulative_gas_used = gas_used(t0) + gas_used(t1) + ... gas_used(tn)` - /// - /// where `tn` is current transaction. - pub cumulative_gas_used: U256, - - /// Vector of logs generated by transaction. - pub logs: Vec, - - /// Addresses of contracts created during execution of transaction. - /// Ordered from earliest creation. - /// - /// eg. sender creates contract A and A in constructor creates contract B - /// - /// B creation ends first, and it will be the first element of the vector. - pub contracts_created: Vec
, - /// Transaction output. - pub output: Bytes, - /// The trace of this transaction. - pub trace: Vec, - /// The VM trace of this transaction. - pub vm_trace: Option, - /// The state diff, if we traced it. - pub state_diff: Option, -} +/// /// Transaction execution receipt, parametrised with convenient defaults. +pub type Executed = machine::Executed; /// Transaction execution result. pub type ExecutionResult = Result, ExecutionError>; diff --git a/ethcore/machine/src/executive.rs b/ethcore/machine/src/executive.rs index c49562dce..81b92599c 100644 --- a/ethcore/machine/src/executive.rs +++ b/ethcore/machine/src/executive.rs @@ -36,14 +36,14 @@ use trace::{self, Tracer, VMTracer}; use common_types::{ errors::ExecutionError, transaction::{Action, SignedTransaction}, + engines::machine::Executed, }; use crate::{ Machine, substate::Substate, - externalities::{Externalities, OutputPolicy, OriginInfo}, // todo: make explicit + externalities::{Externalities, OutputPolicy, OriginInfo}, transaction_ext::Transaction, - executed::Executed, }; #[cfg(debug_assertions)] diff --git a/ethcore/machine/src/test_helpers.rs b/ethcore/machine/src/test_helpers.rs index 49394d727..2182212b6 100644 --- a/ethcore/machine/src/test_helpers.rs +++ b/ethcore/machine/src/test_helpers.rs @@ -20,7 +20,6 @@ use common_types::engines::params::CommonParams; use ethjson; use crate::Machine; - pub fn load_machine(reader: &[u8]) -> Machine { let spec = ethjson::spec::Spec::load(reader).expect("chain spec is invalid"); diff --git a/ethcore/machine/src/tx_filter.rs b/ethcore/machine/src/tx_filter.rs index b688668d4..76a5d571a 100644 --- a/ethcore/machine/src/tx_filter.rs +++ b/ethcore/machine/src/tx_filter.rs @@ -153,12 +153,13 @@ mod test { use tempdir::TempDir; use ethereum_types::{U256, Address}; + use client_traits::BlockChainClient; use common_types::{ ids::BlockId, transaction::{Transaction, Action} }; use ethcore::{ - client::{BlockChainClient, Client, ClientConfig}, + client::{Client, ClientConfig}, spec::Spec, miner::Miner, test_helpers, diff --git a/ethcore/node-filter/Cargo.toml b/ethcore/node-filter/Cargo.toml index e174e6189..73a861252 100644 --- a/ethcore/node-filter/Cargo.toml +++ b/ethcore/node-filter/Cargo.toml @@ -7,6 +7,7 @@ version = "1.12.0" authors = ["Parity Technologies "] [dependencies] +client-traits = { path = "../client-traits" } common-types = { path = "../types" } ethcore = { path = ".."} ethcore-network = { path = "../../util/network" } diff --git a/ethcore/node-filter/src/lib.rs b/ethcore/node-filter/src/lib.rs index 2886a58e3..2c4313c37 100644 --- a/ethcore/node-filter/src/lib.rs +++ b/ethcore/node-filter/src/lib.rs @@ -16,6 +16,7 @@ //! Smart contract based node filter. +extern crate client_traits; extern crate common_types; extern crate ethabi; extern crate ethcore; @@ -25,8 +26,6 @@ extern crate ethereum_types; extern crate lru_cache; extern crate parking_lot; -#[macro_use] -extern crate ethabi_derive; #[macro_use] extern crate ethabi_contract; #[cfg(test)] @@ -42,7 +41,8 @@ use std::collections::{HashMap, VecDeque}; use std::sync::Weak; use common_types::ids::BlockId; -use ethcore::client::{BlockChainClient, ChainNotify, NewBlocks}; +use ethcore::client::{ChainNotify, NewBlocks}; +use client_traits::BlockChainClient; use ethereum_types::{H256, Address}; use ethabi::FunctionOutputDecoder; use network::{ConnectionFilter, ConnectionDirection}; @@ -54,7 +54,7 @@ use_contract!(peer_set, "res/peer_set.json"); /// Connection filter that uses a contract to manage permissions. pub struct NodeFilter { - client: Weak, + client: Weak, contract_address: Address, cache: RwLock } @@ -128,8 +128,10 @@ impl ChainNotify for NodeFilter { #[cfg(test)] mod test { use std::sync::{Arc, Weak}; + + use client_traits::BlockChainClient; use ethcore::spec::Spec; - use ethcore::client::{BlockChainClient, Client, ClientConfig}; + use ethcore::client::{Client, ClientConfig}; use ethcore::miner::Miner; use ethcore::test_helpers; use network::{ConnectionDirection, ConnectionFilter, NodeId}; diff --git a/ethcore/private-tx/src/encryptor.rs b/ethcore/private-tx/src/encryptor.rs index 323f44a69..d62ba546b 100644 --- a/ethcore/private-tx/src/encryptor.rs +++ b/ethcore/private-tx/src/encryptor.rs @@ -81,7 +81,7 @@ pub struct SecretStoreEncryptor { config: EncryptorConfig, client: FetchClient, sessions: Mutex>, - signer: Arc, + signer: Arc, } impl SecretStoreEncryptor { @@ -89,7 +89,7 @@ impl SecretStoreEncryptor { pub fn new( config: EncryptorConfig, client: FetchClient, - signer: Arc, + signer: Arc, ) -> Result { Ok(SecretStoreEncryptor { config, diff --git a/ethcore/private-tx/src/lib.rs b/ethcore/private-tx/src/lib.rs index ebbfb1918..283df9b7a 100644 --- a/ethcore/private-tx/src/lib.rs +++ b/ethcore/private-tx/src/lib.rs @@ -91,11 +91,12 @@ use ethkey::{Signature, recover, public_to_address}; use io::IoChannel; use machine::{ executive::{Executive, TransactOptions, contract_address as ethcore_contract_address}, - executed::Executed, + executed::Executed as FlatExecuted, }; use types::{ ids::BlockId, - transaction::{SignedTransaction, Transaction, Action, UnverifiedTransaction} + transaction::{SignedTransaction, Transaction, Action, UnverifiedTransaction}, + engines::machine::Executed, }; use ethcore::client::{ Client, ChainNotify, NewBlocks, ChainMessageType, ClientIoMessage, Call @@ -307,7 +308,7 @@ impl Provider { nonce_cache, engine, local_accounts, - None, // refuse_service_transactions = true + None, // refuse_service_transactions = true ) } @@ -456,7 +457,7 @@ impl Provider { } } - fn last_required_signature(&self, desc: &PrivateTransactionSigningDesc, sign: Signature) -> Result<(bool, Address), Error> { + fn last_required_signature(&self, desc: &PrivateTransactionSigningDesc, sign: Signature) -> Result<(bool, Address), Error> { let state_hash = self.calculate_state_hash(&desc.state, desc.contract_nonce); match recover(&sign, &state_hash) { Ok(public) => { @@ -702,7 +703,7 @@ impl Provider { } /// Call into private contract. - pub fn private_call(&self, block: BlockId, transaction: &SignedTransaction) -> Result { + pub fn private_call(&self, block: BlockId, transaction: &SignedTransaction) -> Result { let result = self.execute_private(transaction, TransactOptions::with_no_tracing(), block)?; Ok(result.result) } diff --git a/ethcore/private-tx/tests/private_contract.rs b/ethcore/private-tx/tests/private_contract.rs index 5d144e787..e4ee445df 100644 --- a/ethcore/private-tx/tests/private_contract.rs +++ b/ethcore/private-tx/tests/private_contract.rs @@ -16,6 +16,7 @@ //! Contract for private transactions tests. +extern crate client_traits; extern crate common_types as types; extern crate env_logger; extern crate ethcore; @@ -36,11 +37,11 @@ use types::ids::BlockId; use types::transaction::{Transaction, Action}; use ethcore::{ CreateContractAddress, - client::BlockChainClient, test_helpers::{generate_dummy_client, push_block_with_transactions}, miner::Miner, spec, }; +use client_traits::BlockChainClient; use ethkey::{Secret, KeyPair, Signature}; use machine::executive::contract_address; use hash::keccak; diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index 2e4d050f6..2ed86bb66 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -37,7 +37,7 @@ use std::sync::Arc; use bytes::Bytes; use ethereum_types::{H256, U256, Address, Bloom}; -use engines::Engine; +use engine::Engine; use trie_vm_factories::Factories; use state_db::StateDB; use account_state::State; @@ -485,17 +485,19 @@ pub fn enact_verified( mod tests { use test_helpers::get_temp_state_db; use super::*; - use engines::Engine; + use engine::Engine; use vm::LastHashes; use trie_vm_factories::Factories; use state_db::StateDB; use ethereum_types::Address; use std::sync::Arc; - use verification::queue::kind::blocks::Unverified; - use types::transaction::SignedTransaction; use types::{ - header::Header, view, views::BlockView, errors::EthcoreError as Error, + header::Header, + transaction::SignedTransaction, + view, + views::BlockView, + verification::Unverified, }; use hash_db::EMPTY_PREFIX; use crate::spec; diff --git a/ethcore/src/client/ancient_import.rs b/ethcore/src/client/ancient_import.rs index 22f13ff53..c25c5a599 100644 --- a/ethcore/src/client/ancient_import.rs +++ b/ethcore/src/client/ancient_import.rs @@ -18,7 +18,7 @@ use std::sync::Arc; -use engines::{Engine, EpochVerifier}; +use engine::{Engine, EpochVerifier}; use blockchain::BlockChain; use parking_lot::RwLock; diff --git a/ethcore/src/client/bad_blocks.rs b/ethcore/src/client/bad_blocks.rs index 6af24cc40..5df225c5b 100644 --- a/ethcore/src/client/bad_blocks.rs +++ b/ethcore/src/client/bad_blocks.rs @@ -21,7 +21,7 @@ use ethereum_types::H256; use itertools::Itertools; use memory_cache::MemoryLruCache; use parking_lot::RwLock; -use verification::queue::kind::blocks::Unverified; +use types::verification::Unverified; /// Recently seen bad blocks. pub struct BadBlocks { diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 670038399..f2a03144d 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -39,20 +39,18 @@ use hash_db::EMPTY_PREFIX; use block::{LockedBlock, Drain, ClosedBlock, OpenBlock, enact_verified, SealedBlock}; use client::ancient_import::AncientVerifier; use client::{ - Nonce, Balance, ChainInfo, TransactionInfo, - ReopenBlock, PrepareOpenBlock, ScheduleInfo, ImportSealedBlock, - BroadcastProposalBlock, ImportBlock, StateOrBlock, StateInfo, StateClient, Call, - AccountData, BlockChain as BlockChainTrait, BlockProducer, SealedBlockImporter, - BlockChainReset + ReopenBlock, PrepareOpenBlock, ImportSealedBlock, BroadcastProposalBlock, StateInfo, + Call, BlockProducer, SealedBlockImporter, ChainNotify, EngineInfo, + ClientConfig, NewBlocks, ChainRoute, ChainMessageType, bad_blocks, ClientIoMessage, }; -use client::{ - ClientConfig, BlockChainClient, - TraceFilter, CallAnalytics, Mode, - ChainNotify, NewBlocks, ChainRoute, PruningInfo, ProvingBlockChainClient, EngineInfo, ChainMessageType, - IoClient, BadBlocks, bad_blocks, ClientIoMessage, +use client_traits::{ + BlockInfo, ScheduleInfo, StateClient, BlockChainReset, + Nonce, Balance, ChainInfo, TransactionInfo, ImportBlock, + AccountData, BlockChain as BlockChainTrait, BlockChainClient, + IoClient, BadBlocks, ProvingBlockChainClient, + StateOrBlock }; -use client_traits::BlockInfo; -use engines::{Engine, EpochTransition, ForkChoice}; +use engine::Engine; use machine::{ executed::Executed, executive::{Executive, TransactOptions, contract_address}, @@ -70,11 +68,14 @@ use types::{ ancestry_action::AncestryAction, BlockNumber, block::PreverifiedBlock, + block_status::BlockStatus, + blockchain_info::BlockChainInfo, encoded, engines::{ + ForkChoice, SealingState, MAX_UNCLE_AGE, - epoch::PendingTransition, + epoch::{PendingTransition, Transition as EpochTransition}, machine::{AuxiliaryData, Call as MachineCall}, }, errors::{EngineError, ExecutionError, BlockError, EthcoreError, SnapshotError, ImportError, EthcoreResult}, @@ -84,10 +85,15 @@ use types::{ log_entry::LocalizedLogEntry, receipt::{Receipt, LocalizedReceipt}, header::Header, + snapshot::Progress, + trace_filter::Filter as TraceFilter, + pruning_info::PruningInfo, + call_analytics::CallAnalytics, + client_types::Mode, + verification::{Unverified, VerificationQueueInfo as BlockQueueInfo}, }; use verification::queue::kind::BlockLike; -use verification::queue::kind::blocks::Unverified; use verification::{Verifier, BlockQueue}; use verification; use ansi_term::Colour; @@ -95,9 +101,6 @@ use ethtrie::Layout; // re-export pub use blockchain::CacheSize as BlockChainCacheSize; use db::{Writable, Readable, keys::BlockDetails}; -pub use types::blockchain_info::BlockChainInfo; -pub use types::block_status::BlockStatus; -pub use types::verification_queue_info::VerificationQueueInfo as BlockQueueInfo; use_contract!(registry, "res/contracts/registrar.json"); @@ -604,7 +607,7 @@ impl Importer { state_db: &StateDB, client: &Client, ) -> EthcoreResult> { - use engines::EpochChange; + use engine::EpochChange; let hash = header.hash(); let auxiliary = AuxiliaryData { @@ -614,7 +617,7 @@ impl Importer { match self.engine.signals_epoch_end(header, auxiliary) { EpochChange::Yes(proof) => { - use engines::Proof; + use engine::Proof; let proof = match proof { Proof::Known(proof) => proof, @@ -1163,7 +1166,7 @@ impl Client { &self, writer: W, at: BlockId, - p: &snapshot::Progress, + p: &Progress, ) -> Result<(), EthcoreError> { let db = self.state_db.read().journal_db().boxed_clone(); let best_block_number = self.chain_info().best_block_number; @@ -1275,6 +1278,7 @@ impl Client { t: &SignedTransaction, analytics: CallAnalytics, ) -> Result { + use types::engines::machine::Executed as RawExecuted; fn call( state: &mut State, env_info: &EnvInfo, @@ -1282,7 +1286,7 @@ impl Client { state_diff: bool, transaction: &SignedTransaction, options: TransactOptions, - ) -> Result, CallError> where + ) -> Result, CallError> where T: trace::Tracer, V: trace::VMTracer, { @@ -2507,7 +2511,7 @@ impl SealedBlockImporter for Client {} impl ::miner::TransactionVerifierClient for Client {} impl ::miner::BlockChainClient for Client {} -impl super::traits::EngineClient for Client { +impl client_traits::EngineClient for Client { fn update_sealing(&self) { self.importer.miner.update_sealing(self) } @@ -2523,7 +2527,7 @@ impl super::traits::EngineClient for Client { self.notify(|notify| notify.broadcast(ChainMessageType::Consensus(message.clone()))); } - fn epoch_transition_for(&self, parent_hash: H256) -> Option<::engines::EpochTransition> { + fn epoch_transition_for(&self, parent_hash: H256) -> Option { self.chain.read().epoch_transition_for(parent_hash) } @@ -2657,9 +2661,10 @@ impl IoChannelQueue { #[cfg(test)] mod tests { use ethereum_types::{H256, Address}; - use client::{BlockChainClient, ChainInfo}; + use client_traits::{BlockChainClient, ChainInfo}; use types::{ encoded, + engines::ForkChoice, ids::{BlockId, TransactionId}, log_entry::{LogEntry, LocalizedLogEntry}, receipt::{Receipt, LocalizedReceipt, TransactionOutcome}, @@ -2690,7 +2695,7 @@ mod tests { thread::spawn(move || { let mut batch = DBTransaction::new(); another_client.chain.read().insert_block(&mut batch, encoded::Block::new(new_block), Vec::new(), ExtrasInsert { - fork_choice: ::engines::ForkChoice::New, + fork_choice: ForkChoice::New, is_finalized: false, }); go_thread.store(true, Ordering::SeqCst); diff --git a/ethcore/src/client/config.rs b/ethcore/src/client/config.rs index 59fc4f813..8397344a2 100644 --- a/ethcore/src/client/config.rs +++ b/ethcore/src/client/config.rs @@ -15,11 +15,11 @@ // along with Parity Ethereum. If not, see . use std::str::FromStr; -use std::fmt::{Display, Formatter, Error as FmtError}; use verification::{VerifierType, QueueConfig}; use journaldb; use snapshot::SnapshotConfiguration; +use types::client_types::Mode; pub use std::time::Duration; pub use blockchain::Config as BlockChainConfig; @@ -56,32 +56,6 @@ impl FromStr for DatabaseCompactionProfile { } } -/// Operating mode for the client. -#[derive(Debug, Eq, PartialEq, Clone)] -pub enum Mode { - /// Always on. - Active, - /// Goes offline after client is inactive for some (given) time, but - /// comes back online after a while of inactivity. - Passive(Duration, Duration), - /// Goes offline after client is inactive for some (given) time and - /// stays inactive. - Dark(Duration), - /// Always off. - Off, -} - -impl Display for Mode { - fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { - match *self { - Mode::Active => write!(f, "active"), - Mode::Passive(..) => write!(f, "passive"), - Mode::Dark(..) => write!(f, "dark"), - Mode::Off => write!(f, "offline"), - } - } -} - /// Client configuration. Includes configs for all sub-systems. #[derive(Debug, PartialEq, Clone)] pub struct ClientConfig { diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index 8ac833f0d..cd5dd4735 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -26,8 +26,8 @@ mod io_message; #[cfg(any(test, feature = "test-helpers"))] mod test_client; -pub use self::client::*; -pub use self::config::{Mode, ClientConfig, DatabaseCompactionProfile, BlockChainConfig, VMType}; +pub use self::client::{Client, ClientReport}; +pub use self::config::{ClientConfig, DatabaseCompactionProfile, BlockChainConfig, VMType}; #[cfg(any(test, feature = "test-helpers"))] pub use self::evm_test_client::{EvmTestClient, EvmTestError, TransactErr, TransactSuccess}; pub use self::io_message::ClientIoMessage; @@ -35,17 +35,11 @@ pub use self::io_message::ClientIoMessage; pub use self::test_client::{TestBlockChainClient, EachBlockWith, TestState}; pub use self::chain_notify::{ChainNotify, NewBlocks, ChainRoute, ChainRouteType, ChainMessageType}; pub use self::traits::{ - Nonce, Balance, ChainInfo, ReopenBlock, PrepareOpenBlock, TransactionInfo, ScheduleInfo, ImportSealedBlock, BroadcastProposalBlock, ImportBlock, - StateOrBlock, StateClient, Call, EngineInfo, AccountData, BlockChain, BlockProducer, SealedBlockImporter, BadBlocks, - BlockChainReset, BlockChainClient, EngineClient, ProvingBlockChainClient, IoClient + ReopenBlock, PrepareOpenBlock, ImportSealedBlock, BroadcastProposalBlock, + Call, EngineInfo, BlockProducer, SealedBlockImporter, }; pub use account_state::state::StateInfo; -use types::{ - trace_filter::Filter as TraceFilter, - pruning_info::PruningInfo, - call_analytics::CallAnalytics, -}; pub use vm::{LastHashes, EnvInfo}; diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index 801215cb2..42d30bbc2 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -40,6 +40,7 @@ use rustc_hex::FromHex; use types::{ BlockNumber, encoded, + engines::epoch::Transition as EpochTransition, ids::{BlockId, TransactionId, UncleId, TraceId}, basic_account::BasicAccount, errors::{EthcoreError as Error, EthcoreResult}, @@ -53,20 +54,26 @@ use types::{ receipt::{Receipt, LocalizedReceipt, TransactionOutcome}, view, views::BlockView, + verification::Unverified, + client_types::Mode, + blockchain_info::BlockChainInfo, + block_status::BlockStatus, }; use vm::Schedule; use block::{OpenBlock, SealedBlock, ClosedBlock}; use call_contract::{CallContract, RegistryInfo}; use client::{ - Nonce, Balance, ChainInfo, ReopenBlock, TransactionInfo, - PrepareOpenBlock, BlockChainClient, BlockChainInfo, BlockStatus, Mode, - LastHashes, ProvingBlockChainClient, ScheduleInfo, ImportSealedBlock, BroadcastProposalBlock, - ImportBlock, StateOrBlock, Call, StateClient, EngineInfo, AccountData, BlockChain, BlockProducer, - SealedBlockImporter, IoClient, BadBlocks + ReopenBlock, PrepareOpenBlock, ImportSealedBlock, BroadcastProposalBlock, Call, + EngineInfo, BlockProducer, SealedBlockImporter, + LastHashes, }; -use client_traits::BlockInfo; -use engines::Engine; +use client_traits::{ + BlockInfo, Nonce, Balance, ChainInfo, TransactionInfo, BlockChainClient, ImportBlock, + AccountData, BlockChain, IoClient, BadBlocks, ScheduleInfo, StateClient, ProvingBlockChainClient, + StateOrBlock +}; +use engine::Engine; use machine::executed::Executed; use journaldb; use miner::{self, Miner, MinerService}; @@ -75,7 +82,6 @@ use account_state::state::StateInfo; use state_db::StateDB; use trace::LocalizedTrace; use verification::queue::QueueInfo as BlockQueueInfo; -use verification::queue::kind::blocks::Unverified; /// Test client. pub struct TestBlockChainClient { @@ -945,7 +951,7 @@ impl ProvingBlockChainClient for TestBlockChainClient { } } -impl super::traits::EngineClient for TestBlockChainClient { +impl client_traits::EngineClient for TestBlockChainClient { fn update_sealing(&self) { self.miner.update_sealing(self) } @@ -959,7 +965,7 @@ impl super::traits::EngineClient for TestBlockChainClient { fn broadcast_consensus_message(&self, _message: Bytes) {} - fn epoch_transition_for(&self, _block_hash: H256) -> Option<::engines::EpochTransition> { + fn epoch_transition_for(&self, _block_hash: H256) -> Option { None } diff --git a/ethcore/src/client/traits.rs b/ethcore/src/client/traits.rs index ccb7d38a7..36ce41444 100644 --- a/ethcore/src/client/traits.rs +++ b/ethcore/src/client/traits.rs @@ -14,138 +14,20 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . -use std::collections::BTreeMap; -use std::sync::Arc; - -use blockchain::{BlockReceipts, TreeRoute, BlockProvider}; use bytes::Bytes; -use call_contract::{CallContract, RegistryInfo}; -use client_traits::BlockInfo; -use ethcore_miner::pool::VerifiedTransaction; use ethereum_types::{H256, U256, Address}; -use evm::Schedule; -use itertools::Itertools; -use kvdb::DBValue; use types::{ - transaction::{self, LocalizedTransaction, SignedTransaction, CallError}, - BlockNumber, - basic_account::BasicAccount, - block_status::BlockStatus, - blockchain_info::BlockChainInfo, + transaction::{SignedTransaction, CallError}, call_analytics::CallAnalytics, - encoded, errors::EthcoreError as Error, errors::EthcoreResult, - filter::Filter, header::Header, - ids::*, - log_entry::LocalizedLogEntry, - pruning_info::PruningInfo, - receipt::LocalizedReceipt, - trace_filter::Filter as TraceFilter, - verification_queue_info::VerificationQueueInfo as BlockQueueInfo, }; -use vm::LastHashes; use block::{OpenBlock, SealedBlock, ClosedBlock}; -use client::Mode; -use engines::Engine; +use engine::Engine; use machine::executed::Executed; use account_state::state::StateInfo; -use trace::LocalizedTrace; -use verification::queue::kind::blocks::Unverified; // todo this is reexported from common_types - -/// State information to be used during client query -pub enum StateOrBlock { - /// State to be used, may be pending - State(Box), - - /// Id of an existing block from a chain to get state from - Block(BlockId) -} - -impl From> for StateOrBlock { - fn from(info: Box) -> StateOrBlock { - StateOrBlock::State(info) - } -} - -impl From for StateOrBlock { - fn from(id: BlockId) -> StateOrBlock { - StateOrBlock::Block(id) - } -} - -/// Provides `nonce` and `latest_nonce` methods -pub trait Nonce { - /// Attempt to get address nonce at given block. - /// May not fail on BlockId::Latest. - fn nonce(&self, address: &Address, id: BlockId) -> Option; - - /// Get address nonce at the latest block's state. - fn latest_nonce(&self, address: &Address) -> U256 { - self.nonce(address, BlockId::Latest) - .expect("nonce will return Some when given BlockId::Latest. nonce was given BlockId::Latest. \ - Therefore nonce has returned Some; qed") - } -} - -/// Provides `balance` and `latest_balance` methods -pub trait Balance { - /// Get address balance at the given block's state. - /// - /// May not return None if given BlockId::Latest. - /// Returns None if and only if the block's root hash has been pruned from the DB. - fn balance(&self, address: &Address, state: StateOrBlock) -> Option; - - /// Get address balance at the latest block's state. - fn latest_balance(&self, address: &Address) -> U256 { - self.balance(address, BlockId::Latest.into()) - .expect("balance will return Some if given BlockId::Latest. balance was given BlockId::Latest \ - Therefore balance has returned Some; qed") - } -} - -/// Provides methods to access account info -pub trait AccountData: Nonce + Balance {} - -/// Provides `chain_info` method -pub trait ChainInfo { - /// Get blockchain information. - fn chain_info(&self) -> BlockChainInfo; -} - -/// Provides various information on a transaction by it's ID -pub trait TransactionInfo { - /// Get the hash of block that contains the transaction, if any. - fn transaction_block(&self, id: TransactionId) -> Option; -} - -/// Provides methods to access chain state -pub trait StateClient { - /// Type representing chain state - type State: StateInfo; - - /// Get a copy of the best block's state. - fn latest_state(&self) -> Self::State; - - /// Attempt to get a copy of a specific block's final state. - /// - /// This will not fail if given BlockId::Latest. - /// Otherwise, this can fail (but may not) if the DB prunes state or the block - /// is unknown. - fn state_at(&self, id: BlockId) -> Option; -} - -/// Provides various blockchain information, like block header, chain state etc. -pub trait BlockChain: ChainInfo + BlockInfo + TransactionInfo {} - -// FIXME Why these methods belong to BlockChainClient and not MiningBlockChainClient? -/// Provides methods to import block into blockchain -pub trait ImportBlock { - /// Import a block into the blockchain. - fn import_block(&self, block: Unverified) -> EthcoreResult; -} /// Provides `call` and `call_many` methods pub trait Call { @@ -169,201 +51,6 @@ pub trait EngineInfo { fn engine(&self) -> &dyn Engine; } -/// IO operations that should off-load heavy work to another thread. -pub trait IoClient: Sync + Send { - /// Queue transactions for importing. - fn queue_transactions(&self, transactions: Vec, peer_id: usize); - - /// Queue block import with transaction receipts. Does no sealing and transaction validation. - fn queue_ancient_block(&self, block_bytes: Unverified, receipts_bytes: Bytes) -> EthcoreResult; - - /// Queue consensus engine message. - fn queue_consensus_message(&self, message: Bytes); -} - -/// Provides recently seen bad blocks. -pub trait BadBlocks { - /// Returns a list of blocks that were recently not imported because they were invalid. - fn bad_blocks(&self) -> Vec<(Unverified, String)>; -} - -/// Blockchain database client. Owns and manages a blockchain and a block queue. -pub trait BlockChainClient : Sync + Send + AccountData + BlockChain + CallContract + RegistryInfo + ImportBlock -+ IoClient + BadBlocks { - /// Look up the block number for the given block ID. - fn block_number(&self, id: BlockId) -> Option; - - /// Get raw block body data by block id. - /// Block body is an RLP list of two items: uncles and transactions. - fn block_body(&self, id: BlockId) -> Option; - - /// Get block status by block header hash. - fn block_status(&self, id: BlockId) -> BlockStatus; - - /// Get block total difficulty. - fn block_total_difficulty(&self, id: BlockId) -> Option; - - /// Attempt to get address storage root at given block. - /// May not fail on BlockId::Latest. - fn storage_root(&self, address: &Address, id: BlockId) -> Option; - - /// Get block hash. - fn block_hash(&self, id: BlockId) -> Option; - - /// Get address code at given block's state. - fn code(&self, address: &Address, state: StateOrBlock) -> Option>; - - /// Get address code at the latest block's state. - fn latest_code(&self, address: &Address) -> Option { - self.code(address, BlockId::Latest.into()) - .expect("code will return Some if given BlockId::Latest; qed") - } - - /// Get a reference to the `BlockProvider`. - fn chain(&self) -> Arc; - - /// Get block queue information. - fn queue_info(&self) -> BlockQueueInfo; - - /// Get address code hash at given block's state. - - /// Get value of the storage at given position at the given block's state. - /// - /// May not return None if given BlockId::Latest. - /// Returns None if and only if the block's root hash has been pruned from the DB. - fn storage_at(&self, address: &Address, position: &H256, state: StateOrBlock) -> Option; - - /// Get value of the storage at given position at the latest block's state. - fn latest_storage_at(&self, address: &Address, position: &H256) -> H256 { - self.storage_at(address, position, BlockId::Latest.into()) - .expect("storage_at will return Some if given BlockId::Latest. storage_at was given BlockId::Latest. \ - Therefore storage_at has returned Some; qed") - } - - /// Get a list of all accounts in the block `id`, if fat DB is in operation, otherwise `None`. - /// If `after` is set the list starts with the following item. - fn list_accounts(&self, id: BlockId, after: Option<&Address>, count: u64) -> Option>; - - /// Get a list of all storage keys in the block `id`, if fat DB is in operation, otherwise `None`. - /// If `after` is set the list starts with the following item. - fn list_storage(&self, id: BlockId, account: &Address, after: Option<&H256>, count: u64) -> Option>; - - /// Get transaction with given hash. - fn transaction(&self, id: TransactionId) -> Option; - - /// Get uncle with given id. - fn uncle(&self, id: UncleId) -> Option; - - /// Get transaction receipt with given hash. - fn transaction_receipt(&self, id: TransactionId) -> Option; - - /// Get localized receipts for all transaction in given block. - fn localized_block_receipts(&self, id: BlockId) -> Option>; - - /// Get a tree route between `from` and `to`. - /// See `BlockChain::tree_route`. - fn tree_route(&self, from: &H256, to: &H256) -> Option; - - /// Get all possible uncle hashes for a block. - fn find_uncles(&self, hash: &H256) -> Option>; - - /// Get latest state node - fn state_data(&self, hash: &H256) -> Option; - - /// Get block receipts data by block header hash. - fn block_receipts(&self, hash: &H256) -> Option; - - /// Returns true if block queue is empty. - fn is_queue_empty(&self) -> bool { - self.queue_info().is_empty() - } - - /// Clear block queue and abort all import activity. - fn clear_queue(&self); - - /// Returns logs matching given filter. If one of the filtering block cannot be found, returns the block id that caused the error. - fn logs(&self, filter: Filter) -> Result, BlockId>; - - /// Replays a given transaction for inspection. - fn replay(&self, t: TransactionId, analytics: CallAnalytics) -> Result; - - /// Replays all the transactions in a given block for inspection. - fn replay_block_transactions(&self, block: BlockId, analytics: CallAnalytics) -> Result>, CallError>; - - /// Returns traces matching given filter. - fn filter_traces(&self, filter: TraceFilter) -> Option>; - - /// Returns trace with given id. - fn trace(&self, trace: TraceId) -> Option; - - /// Returns traces created by transaction. - fn transaction_traces(&self, trace: TransactionId) -> Option>; - - /// Returns traces created by transaction from block. - fn block_traces(&self, trace: BlockId) -> Option>; - - /// Get last hashes starting from best block. - fn last_hashes(&self) -> LastHashes; - - /// List all ready transactions that should be propagated to other peers. - fn transactions_to_propagate(&self) -> Vec>; - - /// Sorted list of transaction gas prices from at least last sample_size blocks. - fn gas_price_corpus(&self, sample_size: usize) -> ::stats::Corpus { - let mut h = self.chain_info().best_block_hash; - let mut corpus = Vec::new(); - while corpus.is_empty() { - for _ in 0..sample_size { - let block = match self.block(BlockId::Hash(h)) { - Some(block) => block, - None => return corpus.into(), - }; - - if block.number() == 0 { - return corpus.into(); - } - block.transaction_views().iter().foreach(|t| corpus.push(t.gas_price())); - h = block.parent_hash().clone(); - } - } - corpus.into() - } - - /// Get the preferred chain ID to sign on - fn signing_chain_id(&self) -> Option; - - /// Get the mode. - fn mode(&self) -> Mode; - - /// Set the mode. - fn set_mode(&self, mode: Mode); - - /// Get the chain spec name. - fn spec_name(&self) -> String; - - /// Set the chain via a spec name. - fn set_spec_name(&self, spec_name: String) -> Result<(), ()>; - - /// Disable the client from importing blocks. This cannot be undone in this session and indicates - /// that a subsystem has reason to believe this executable incapable of syncing the chain. - fn disable(&self); - - /// Returns engine-related extra info for `BlockId`. - fn block_extra_info(&self, id: BlockId) -> Option>; - - /// Returns engine-related extra info for `UncleId`. - fn uncle_extra_info(&self, id: UncleId) -> Option>; - - /// Returns information about pruning/data availability. - fn pruning_info(&self) -> PruningInfo; - - /// Schedule state-altering transaction to be executed on the next pending block. - fn transact_contract(&self, address: Address, data: Bytes) -> Result<(), transaction::Error>; - - /// Get the address of the registry itself. - fn registrar_address(&self) -> Option
; -} - /// Provides `reopen_block` method pub trait ReopenBlock { /// Reopens an OpenBlock and updates uncles. @@ -383,12 +70,6 @@ pub trait PrepareOpenBlock { /// Provides methods used for sealing new state pub trait BlockProducer: PrepareOpenBlock + ReopenBlock {} -/// Provides `latest_schedule` method -pub trait ScheduleInfo { - /// Returns latest schedule. - fn latest_schedule(&self) -> Schedule; -} - ///Provides `import_sealed_block` method pub trait ImportSealedBlock { /// Import sealed block. Skips all verifications. @@ -403,59 +84,3 @@ pub trait BroadcastProposalBlock { /// Provides methods to import sealed block and broadcast a block proposal pub trait SealedBlockImporter: ImportSealedBlock + BroadcastProposalBlock {} - -/// Client facilities used by internally sealing Engines. -pub trait EngineClient: Sync + Send + ChainInfo { - /// Make a new block and seal it. - fn update_sealing(&self); - - /// Submit a seal for a block in the mining queue. - fn submit_seal(&self, block_hash: H256, seal: Vec); - - /// Broadcast a consensus message to the network. - fn broadcast_consensus_message(&self, message: Bytes); - - /// Get the transition to the epoch the given parent hash is part of - /// or transitions to. - /// This will give the epoch that any children of this parent belong to. - /// - /// The block corresponding the the parent hash must be stored already. - fn epoch_transition_for(&self, parent_hash: H256) -> Option<::engines::EpochTransition>; - - /// Attempt to cast the engine client to a full client. - fn as_full_client(&self) -> Option<&dyn BlockChainClient>; - - /// Get a block number by ID. - fn block_number(&self, id: BlockId) -> Option; - - /// Get raw block header data by block id. - fn block_header(&self, id: BlockId) -> Option; -} - -/// Extended client interface for providing proofs of the state. -pub trait ProvingBlockChainClient: BlockChainClient { - /// Prove account storage at a specific block id. - /// - /// Both provided keys assume a secure trie. - /// Returns a vector of raw trie nodes (in order from the root) proving the storage query. - fn prove_storage(&self, key1: H256, key2: H256, id: BlockId) -> Option<(Vec, H256)>; - - /// Prove account existence at a specific block id. - /// The key is the keccak hash of the account's address. - /// Returns a vector of raw trie nodes (in order from the root) proving the query. - fn prove_account(&self, key1: H256, id: BlockId) -> Option<(Vec, BasicAccount)>; - - /// Prove execution of a transaction at the given block. - /// Returns the output of the call and a vector of database items necessary - /// to reproduce it. - fn prove_transaction(&self, transaction: SignedTransaction, id: BlockId) -> Option<(Bytes, Vec)>; - - /// Get an epoch change signal by block hash. - fn epoch_signal(&self, hash: H256) -> Option>; -} - -/// resets the blockchain -pub trait BlockChainReset { - /// reset to best_block - n - fn reset(&self, num: u32) -> Result<(), String>; -} diff --git a/ethcore/src/engines/authority_round/mod.rs b/ethcore/src/engines/authority_round/mod.rs index d4523ffbf..dae24e9ef 100644 --- a/ethcore/src/engines/authority_round/mod.rs +++ b/ethcore/src/engines/authority_round/mod.rs @@ -24,17 +24,18 @@ use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering as AtomicOrdering}; use std::sync::{Weak, Arc}; use std::time::{UNIX_EPOCH, Duration}; -use client::EngineClient; -use engines::{Engine, Seal, ConstructedVerifier}; +use client_traits::EngineClient; +use engine::{Engine,ConstructedVerifier}; use engines::block_reward; use engines::block_reward::{BlockRewardContract, RewardKind}; +use engine::snapshot::SnapshotComponents; use ethjson; use machine::{ ExecutedBlock, Machine, }; use hash::keccak; -use super::signer::EngineSigner; +use engine::signer::EngineSigner; use super::validator_set::{ValidatorSet, SimpleList, new_validator_set}; use self::finality::RollingFinality; use ethkey::{self, Signature}; @@ -49,7 +50,10 @@ use types::{ BlockNumber, header::{Header, ExtendedHeader}, engines::{ + Headers, params::CommonParams, + PendingTransitionStore, + Seal, SealingState, machine::{Call, AuxiliaryData}, }, @@ -459,7 +463,7 @@ struct EpochVerifier { empty_steps_transition: u64, } -impl super::EpochVerifier for EpochVerifier { +impl engine::EpochVerifier for EpochVerifier { fn verify_light(&self, header: &Header) -> Result<(), Error> { // Validate the timestamp verify_timestamp(&self.step.inner, header_step(header, self.empty_steps_transition)?)?; @@ -1273,7 +1277,7 @@ impl Engine for AuthorityRound { let rewards: Vec<_> = match self.block_reward_contract { Some(ref c) if block.header.number() >= self.block_reward_contract_transition => { - let mut call = super::default_system_or_code_call(&self.machine, block); + let mut call = engine::default_system_or_code_call(&self.machine, block); let rewards = c.reward(beneficiaries, &mut call)?; rewards.into_iter().map(|(author, amount)| (author, RewardKind::External, amount)).collect() @@ -1429,8 +1433,8 @@ impl Engine for AuthorityRound { .map(|set_proof| combine_proofs(0, &set_proof, &[])) } - fn signals_epoch_end(&self, header: &Header, aux: AuxiliaryData) -> super::EpochChange { - if self.immediate_transitions { return super::EpochChange::No } + fn signals_epoch_end(&self, header: &Header, aux: AuxiliaryData) -> engine::EpochChange { + if self.immediate_transitions { return engine::EpochChange::No } let first = header.number() == 0; self.validators.signals_epoch_end(first, header, aux) @@ -1439,8 +1443,8 @@ impl Engine for AuthorityRound { fn is_epoch_end_light( &self, chain_head: &Header, - chain: &super::Headers
, - transition_store: &super::PendingTransitionStore, + chain: &Headers
, + transition_store: &PendingTransitionStore, ) -> Option> { // epochs only matter if we want to support light clients. if self.immediate_transitions { return None } @@ -1483,8 +1487,8 @@ impl Engine for AuthorityRound { &self, chain_head: &Header, finalized: &[H256], - chain: &super::Headers
, - transition_store: &super::PendingTransitionStore, + chain: &Headers
, + transition_store: &PendingTransitionStore, ) -> Option> { // epochs only matter if we want to support light clients. if self.immediate_transitions { return None } @@ -1591,7 +1595,7 @@ impl Engine for AuthorityRound { ) } - fn snapshot_components(&self) -> Option> { + fn snapshot_components(&self) -> Option> { if self.immediate_transitions { None } else { @@ -1628,7 +1632,7 @@ mod tests { use ethkey::Signature; use types::{ header::Header, - engines::params::CommonParams, + engines::{Seal, params::CommonParams}, errors::{EthcoreError as Error, EngineError}, transaction::{Action, Transaction}, }; @@ -1639,7 +1643,7 @@ mod tests { TestNotify }; use crate::spec::{Spec, self}; - use engines::{Seal, Engine}; + use engine::Engine; use engines::validator_set::{TestSet, SimpleList}; use super::{AuthorityRoundParams, AuthorityRound, EmptyStep, SealedEmptyStep, calculate_score}; use machine::Machine; diff --git a/ethcore/src/engines/basic_authority.rs b/ethcore/src/engines/basic_authority.rs index 632e2a0e8..55c8ab5e7 100644 --- a/ethcore/src/engines/basic_authority.rs +++ b/ethcore/src/engines/basic_authority.rs @@ -20,10 +20,14 @@ use std::sync::Weak; use ethereum_types::{H256, H520}; use parking_lot::RwLock; use ethkey::{self, Signature}; -use engines::{Engine, Seal, ConstructedVerifier}; -use engines::signer::EngineSigner; +use engine::{ + Engine, + ConstructedVerifier, + snapshot::SnapshotComponents, + signer::EngineSigner, +}; use ethjson; -use client::EngineClient; +use client_traits::EngineClient; use machine::{ Machine, executed_block::ExecutedBlock, @@ -31,7 +35,10 @@ use machine::{ use types::{ header::Header, engines::{ + Headers, + PendingTransitionStore, SealingState, + Seal, params::CommonParams, machine::{AuxiliaryData, Call}, }, @@ -59,7 +66,7 @@ struct EpochVerifier { list: SimpleList, } -impl super::EpochVerifier for EpochVerifier { +impl engine::EpochVerifier for EpochVerifier { fn verify_light(&self, header: &Header) -> Result<(), Error> { verify_external(header, &self.list) } @@ -144,13 +151,13 @@ impl Engine for BasicAuthority { } #[cfg(not(test))] - fn signals_epoch_end(&self, _header: &Header, _auxiliary: AuxiliaryData) -> super::EpochChange { + fn signals_epoch_end(&self, _header: &Header, _auxiliary: AuxiliaryData) -> engine::EpochChange { // don't bother signalling even though a contract might try. - super::EpochChange::No + engine::EpochChange::No } #[cfg(test)] - fn signals_epoch_end(&self, header: &Header, auxiliary: AuxiliaryData) -> super::EpochChange { + fn signals_epoch_end(&self, header: &Header, auxiliary: AuxiliaryData) -> engine::EpochChange { // in test mode, always signal even though they don't be finalized. let first = header.number() == 0; self.validators.signals_epoch_end(first, header, auxiliary) @@ -160,8 +167,8 @@ impl Engine for BasicAuthority { &self, chain_head: &Header, _finalized: &[H256], - _chain: &super::Headers
, - _transition_store: &super::PendingTransitionStore, + _chain: &Headers
, + _transition_store: &PendingTransitionStore, ) -> Option> { let first = chain_head.number() == 0; @@ -172,8 +179,8 @@ impl Engine for BasicAuthority { fn is_epoch_end_light( &self, chain_head: &Header, - chain: &super::Headers
, - transition_store: &super::PendingTransitionStore, + chain: &Headers
, + transition_store: &PendingTransitionStore, ) -> Option> { self.is_epoch_end(chain_head, &[], chain, transition_store) } @@ -183,7 +190,7 @@ impl Engine for BasicAuthority { match self.validators.epoch_set(first, &self.machine, header.number(), proof) { Ok((list, finalize)) => { - let verifier = Box::new(EpochVerifier { list: list }); + let verifier = Box::new(EpochVerifier { list }); // our epoch verifier will ensure no unverified verifier is ever verified. match finalize { @@ -211,7 +218,7 @@ impl Engine for BasicAuthority { ) } - fn snapshot_components(&self) -> Option> { + fn snapshot_components(&self) -> Option> { None } @@ -230,7 +237,7 @@ mod tests { use accounts::AccountProvider; use types::header::Header; use spec::Spec; - use engines::{Seal, SealingState}; + use types::engines::{Seal, SealingState}; use tempdir::TempDir; /// Create a new test chain spec with `BasicAuthority` consensus engine. diff --git a/ethcore/src/engines/block_reward.rs b/ethcore/src/engines/block_reward.rs index 3429a28ce..c2f66c13e 100644 --- a/ethcore/src/engines/block_reward.rs +++ b/ethcore/src/engines/block_reward.rs @@ -28,7 +28,7 @@ use types::{ BlockNumber, errors::{EngineError, EthcoreError as Error}, }; -use super::{SystemOrCodeCall, SystemOrCodeCallKind}; +use engine::{SystemOrCodeCall, SystemOrCodeCallKind}; use trace::{Tracer, ExecutiveTracer, Tracing}; use_contract!(block_reward_contract, "res/contracts/block_reward.json"); @@ -166,7 +166,7 @@ mod test { use crate::spec; use test_helpers::generate_dummy_client_with_spec; - use engines::SystemOrCodeCallKind; + use engine::SystemOrCodeCallKind; use super::{BlockRewardContract, RewardKind}; #[test] diff --git a/ethcore/src/engines/clique/mod.rs b/ethcore/src/engines/clique/mod.rs index 8dea9d997..3f249f42a 100644 --- a/ethcore/src/engines/clique/mod.rs +++ b/ethcore/src/engines/clique/mod.rs @@ -65,9 +65,15 @@ use std::thread; use std::time; use std::time::{Instant, Duration, SystemTime, UNIX_EPOCH}; -use client::EngineClient; -use engines::clique::util::{extract_signers, recover_creator}; -use engines::{Engine, Seal, SealingState, EthashSeal}; +use client_traits::EngineClient; +use engines::{ + clique::util::{extract_signers, recover_creator}, + EthashSeal, +}; +use engine::{ + Engine, + signer::EngineSigner, +}; use ethereum_types::{Address, H64, H160, H256, U256}; use ethkey::Signature; use hash::KECCAK_EMPTY_LIST_RLP; @@ -79,7 +85,6 @@ use machine::{ }; use parking_lot::RwLock; use rand::Rng; -use super::signer::EngineSigner; use unexpected::{Mismatch, OutOfBounds}; use time_utils::CheckedSystemTime; use types::{ @@ -87,6 +92,8 @@ use types::{ ids::BlockId, header::Header, engines::{ + Seal, + SealingState, params::CommonParams, machine::Call, }, diff --git a/ethcore/src/engines/clique/tests.rs b/ethcore/src/engines/clique/tests.rs index 46e9506f1..e1954a13f 100644 --- a/ethcore/src/engines/clique/tests.rs +++ b/ethcore/src/engines/clique/tests.rs @@ -17,7 +17,7 @@ //! Consensus tests for `PoA Clique Engine`, see http://eips.ethereum.org/EIPS/eip-225 for more information use block::*; -use engines::Engine; +use engine::Engine; use ethereum_types::{Address, H256}; use ethkey::{Secret, KeyPair}; use state_db::StateDB; diff --git a/ethcore/src/engines/ethash.rs b/ethcore/src/engines/ethash.rs index 22f81804f..df75ae816 100644 --- a/ethcore/src/engines/ethash.rs +++ b/ethcore/src/engines/ethash.rs @@ -19,6 +19,7 @@ use std::collections::BTreeMap; use std::path::Path; use std::sync::Arc; +use engine::snapshot::SnapshotComponents; use ethereum_types::{H256, H64, U256}; use ethjson; use hash::{KECCAK_EMPTY_LIST_RLP}; @@ -33,7 +34,7 @@ use types::{ use unexpected::{OutOfBounds, Mismatch}; use engines::block_reward::{self, BlockRewardContract, RewardKind}; -use engines::{self, Engine}; +use engine::Engine; use ethash::{self, quick_get_difficulty, slow_hash_block_number, EthashManager, OptimizeFor}; use machine::{ ExecutedBlock, @@ -179,7 +180,7 @@ impl From for EthashParams { /// mainnet chains in the Olympic, Frontier and Homestead eras. pub struct Ethash { ethash_params: EthashParams, - pow: EthashManager, + pow: Arc, machine: Machine, } @@ -190,17 +191,48 @@ impl Ethash { ethash_params: EthashParams, machine: Machine, optimize_for: T, - ) -> Arc { + ) -> Self { let progpow_transition = ethash_params.progpow_transition; - Arc::new(Ethash { + Ethash { ethash_params, machine, - pow: EthashManager::new(cache_dir.as_ref(), optimize_for.into(), progpow_transition), - }) + pow: Arc::new(EthashManager::new( + cache_dir.as_ref(), + optimize_for.into(), + progpow_transition + )), + } } } +fn verify_block_unordered(pow: &Arc, header: &Header) -> Result<(), Error> { + let seal = Seal::parse_seal(header.seal())?; + + let result = pow.compute_light( + header.number() as u64, + &header.bare_hash().0, + seal.nonce.to_low_u64_be() + ); + let mix = H256(result.mix_hash); + let difficulty = ethash::boundary_to_difficulty(&H256(result.value)); + trace!(target: "miner", "num: {num}, seed: {seed}, h: {h}, non: {non}, mix: {mix}, res: {res}", + num = header.number() as u64, + seed = H256(slow_hash_block_number(header.number() as u64)), + h = header.bare_hash(), + non = seal.nonce.to_low_u64_be(), + mix = H256(result.mix_hash), + res = H256(result.value)); + if mix != seal.mix_hash { + return Err(From::from(BlockError::MismatchedH256SealElement(Mismatch { expected: mix, found: seal.mix_hash }))); + } + if &difficulty < header.difficulty() { + return Err(From::from(BlockError::InvalidProofOfWork(OutOfBounds { min: Some(header.difficulty().clone()), max: None, found: difficulty }))); + } + Ok(()) +} + + // TODO [rphmeier] // // for now, this is different than Ethash's own epochs, and signal @@ -209,17 +241,17 @@ impl Ethash { // for any block in the chain. // in the future, we might move the Ethash epoch // caching onto this mechanism as well. -// NOTE[dvdplm]: the reason we impl this for Arc and not plain Ethash is the -// way `epoch_verifier()` works. This means `new()` returns an `Arc` which is -// then re-wrapped in an Arc in `spec::engine()`. -impl engines::EpochVerifier for Arc { - fn verify_light(&self, _header: &Header) -> Result<(), Error> { Ok(()) } +struct EpochVerifier { + pow: Arc +} + +impl engine::EpochVerifier for EpochVerifier { fn verify_heavy(&self, header: &Header) -> Result<(), Error> { - self.verify_block_unordered(header).into() + verify_block_unordered(&self.pow, header) } } -impl Engine for Arc { +impl Engine for Ethash { fn name(&self) -> &str { "Ethash" } fn machine(&self) -> &Machine { &self.machine } @@ -241,11 +273,6 @@ impl Engine for Arc { fn maximum_gas_limit(&self) -> Option { Some(0x7fff_ffff_ffff_ffffu64.into()) } - fn populate_from_parent(&self, header: &mut Header, parent: &Header) { - let difficulty = self.calculate_difficulty(header, parent); - header.set_difficulty(difficulty); - } - /// Apply the block reward on finalisation of the block. /// This assumes that all uncles are valid uncles (i.e. of at least one generation before the current). fn on_close_block(&self, block: &mut ExecutedBlock, _parent_header: &Header) -> Result<(), Error> { @@ -264,7 +291,7 @@ impl Engine for Arc { beneficiaries.push((*uncle_author, RewardKind::uncle(number, u.number()))); } - let mut call = engines::default_system_or_code_call(&self.machine, block); + let mut call = engine::default_system_or_code_call(&self.machine, block); let rewards = c.reward(beneficiaries, &mut call)?; rewards.into_iter().map(|(author, amount)| (author, RewardKind::External, amount)).collect() @@ -346,25 +373,7 @@ impl Engine for Arc { } fn verify_block_unordered(&self, header: &Header) -> Result<(), Error> { - let seal = Seal::parse_seal(header.seal())?; - - let result = self.pow.compute_light(header.number() as u64, &header.bare_hash().0, seal.nonce.to_low_u64_be()); - let mix = H256(result.mix_hash); - let difficulty = ethash::boundary_to_difficulty(&H256(result.value)); - trace!(target: "miner", "num: {num}, seed: {seed}, h: {h}, non: {non}, mix: {mix}, res: {res}", - num = header.number() as u64, - seed = H256(slow_hash_block_number(header.number() as u64)), - h = header.bare_hash(), - non = seal.nonce.to_low_u64_be(), - mix = H256(result.mix_hash), - res = H256(result.value)); - if mix != seal.mix_hash { - return Err(From::from(BlockError::MismatchedH256SealElement(Mismatch { expected: mix, found: seal.mix_hash }))); - } - if &difficulty < header.difficulty() { - return Err(From::from(BlockError::InvalidProofOfWork(OutOfBounds { min: Some(header.difficulty().clone()), max: None, found: difficulty }))); - } - Ok(()) + verify_block_unordered(&self.pow, header) } fn verify_block_family(&self, header: &Header, parent: &Header) -> Result<(), Error> { @@ -382,11 +391,17 @@ impl Engine for Arc { Ok(()) } - fn epoch_verifier<'a>(&self, _header: &Header, _proof: &'a [u8]) -> engines::ConstructedVerifier<'a> { - engines::ConstructedVerifier::Trusted(Box::new(self.clone())) + fn epoch_verifier<'a>(&self, _header: &Header, _proof: &'a [u8]) -> engine::ConstructedVerifier<'a> { + let v = EpochVerifier{pow: self.pow.clone()}; + engine::ConstructedVerifier::Trusted(Box::new(v)) } - fn snapshot_components(&self) -> Option> { + fn populate_from_parent(&self, header: &mut Header, parent: &Header) { + let difficulty = self.calculate_difficulty(header, parent); + header.set_difficulty(difficulty); + } + + fn snapshot_components(&self) -> Option> { Some(Box::new(::snapshot::PowSnapshot::new(SNAPSHOT_BLOCKS, MAX_SNAPSHOT_BLOCKS))) } @@ -502,7 +517,7 @@ mod tests { errors::{BlockError, EthcoreError as Error}, }; use spec::Spec; - use engines::Engine; + use engine::Engine; use crate::spec::{new_morden, new_mcip3_test, new_homestead_test_machine}; use super::{Ethash, EthashParams, ecip1017_eras_block_reward}; use rlp; diff --git a/ethcore/src/engines/instant_seal.rs b/ethcore/src/engines/instant_seal.rs index 8b2be4865..d786176bd 100644 --- a/ethcore/src/engines/instant_seal.rs +++ b/ethcore/src/engines/instant_seal.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . -use engines::{Engine, Seal}; +use engine::Engine; use machine::{ ExecutedBlock, Machine @@ -22,6 +22,7 @@ use machine::{ use types::{ header::Header, engines::{ + Seal, SealingState, params::CommonParams, }, @@ -110,9 +111,11 @@ mod tests { use ethereum_types::{H520, Address}; use test_helpers::get_temp_state_db; use crate::spec; - use types::header::Header; + use types::{ + header::Header, + engines::Seal, + }; use block::*; - use engines::Seal; #[test] fn instant_can_seal() { diff --git a/ethcore/src/engines/mod.rs b/ethcore/src/engines/mod.rs index b5391c0b2..780a6a063 100644 --- a/ethcore/src/engines/mod.rs +++ b/ethcore/src/engines/mod.rs @@ -25,425 +25,10 @@ mod null_engine; mod validator_set; pub mod block_reward; -pub mod signer; pub use self::authority_round::AuthorityRound; pub use self::basic_authority::BasicAuthority; pub use self::instant_seal::{InstantSeal, InstantSealParams}; pub use self::null_engine::NullEngine; -pub use self::signer::EngineSigner; pub use self::clique::Clique; pub use self::ethash::{Ethash, Seal as EthashSeal}; - -// TODO [ToDr] Remove re-export (#10130) -pub use types::engines::ForkChoice; -pub use types::engines::epoch::{self, Transition as EpochTransition}; - -use std::sync::{Weak, Arc}; -use std::collections::BTreeMap; - -use builtin::Builtin; -use vm::{EnvInfo, Schedule, CallType, ActionValue}; -use types::{ - BlockNumber, - ancestry_action::AncestryAction, - header::{Header, ExtendedHeader}, - engines::{ - SealingState, Headers, PendingTransitionStore, - params::CommonParams, - machine as machine_types, - machine::{AuxiliaryData, AuxiliaryRequest}, - }, - errors::{EthcoreError as Error, EngineError}, - transaction::{self, UnverifiedTransaction}, -}; -use snapshot::SnapshotComponents; -use client::EngineClient; - -use ethkey::Signature; -use machine::{ - Machine, - executed_block::ExecutedBlock, -}; -use ethereum_types::{H256, U256, Address}; -use bytes::Bytes; - -/// Seal type. -#[derive(Debug, PartialEq, Eq)] -pub enum Seal { - /// Regular block seal; should be part of the blockchain. - Regular(Vec), - /// Engine does not 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> = dyn FnMut(Address, Vec) -> Result, 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> = dyn FnMut(SystemOrCodeCallKind, Vec) -> Result, 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>, H256), -} - -/// Default SystemOrCodeCall implementation. -pub fn default_system_or_code_call<'a>(machine: &'a Machine, block: &'a mut ExecutedBlock) -> impl FnMut(SystemOrCodeCallKind, Vec) -> Result, 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)) - } -} - -/// Proof dependent on state. -pub trait StateDependentProof: Send + Sync { - /// Generate a proof, given the state. - fn generate_proof<'a>(&self, state: &machine_types::Call) -> Result, 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: &Machine, proof: &[u8]) -> Result<(), String>; -} - -/// Proof generated on epoch change. -pub enum Proof { - /// Known proof (extracted from signal) - Known(Vec), - /// State dependent proof. - WithState(Arc), -} - -/// Generated epoch verifier. -pub enum ConstructedVerifier<'a> { - /// Fully trusted verifier. - Trusted(Box), - /// Verifier unconfirmed. Check whether given finality proof finalizes given hash - /// under previous epoch. - Unconfirmed(Box, &'a [u8], H256), - /// Error constructing verifier. - Err(Error), -} - -impl<'a> ConstructedVerifier<'a> { - /// Convert to a result, indicating that any necessary confirmation has been done - /// already. - pub fn known_confirmed(self) -> Result, Error> { - match self { - ConstructedVerifier::Trusted(v) | ConstructedVerifier::Unconfirmed(v, _, _) => Ok(v), - ConstructedVerifier::Err(e) => Err(e), - } - } -} - -/// Results of a query of whether an epoch change occurred at the given block. -pub enum EpochChange { - /// Cannot determine until more data is passed. - Unsure(AuxiliaryRequest), - /// No epoch change. - No, - /// The epoch will change, with proof. - Yes(Proof), -} - -/// 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: Sync + Send { - /// The name of this engine. - fn name(&self) -> &str; - - /// Get access to the underlying state machine. - // TODO: decouple. - fn machine(&self) -> &Machine; - - /// The number of additional header fields required for this engine. - fn seal_fields(&self, _header: &Header) -> usize { 0 } - - /// Additional engine-specific information for the user/developer concerning `header`. - fn extra_info(&self, _header: &Header) -> BTreeMap { BTreeMap::new() } - - /// Maximum number of uncles a block is allowed to declare. - fn maximum_uncle_count(&self, _block: BlockNumber) -> usize { 0 } - - /// Optional maximum gas limit. - fn maximum_gas_limit(&self) -> Option { None } - - /// 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 ExecutedBlock, - _epoch_begin: bool, - ) -> Result<(), Error> { - Ok(()) - } - - /// Block transformation functions, after the transactions. - fn on_close_block( - &self, - _block: &mut ExecutedBlock, - _parent_header: &Header, - ) -> Result<(), Error> { - Ok(()) - } - - /// Allow mutating the header during seal generation. Currently only used by Clique. - fn on_seal_block(&self, _block: &mut ExecutedBlock) -> Result<(), Error> { Ok(()) } - - /// Returns the engine's current sealing state. - fn sealing_state(&self) -> SealingState { SealingState::External } - - /// 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: &ExecutedBlock, _parent: &Header) -> Seal { Seal::None } - - /// 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: &Header) -> Result<(), 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: &Header) -> Result<(), 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: &Header) -> Result<(), 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: &Header, _parent: &Header) -> Result<(), 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: &Header) -> Result<(), Error> { Ok(()) } - - /// Genesis epoch data. - fn genesis_epoch_data<'a>(&self, _header: &Header, _state: &machine_types::Call) -> Result, String> { Ok(Vec::new()) } - - /// 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. - /// - /// Should not interact with state. - fn signals_epoch_end<'a>(&self, _header: &Header, _aux: AuxiliaryData<'a>) -> EpochChange { - EpochChange::No - } - - /// 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: &Header, - _finalized: &[H256], - _chain: &Headers
, - _transition_store: &PendingTransitionStore, - ) -> Option> { - 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: &Header, - _chain: &Headers
, - _transition_store: &PendingTransitionStore, - ) -> Option> { - None - } - - /// Create an epoch verifier from validation proof and a flag indicating - /// whether finality is required. - fn epoch_verifier<'a>(&self, _header: &Header, _proof: &'a [u8]) -> ConstructedVerifier<'a> { - ConstructedVerifier::Trusted(Box::new(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 Header, _parent: &Header) { } - - /// 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) } - - /// Register a component which signs consensus messages. - fn set_signer(&self, _signer: Box) {} - - /// Sign using the EngineSigner, to be used for consensus tx signing. - fn sign(&self, _hash: H256) -> Result { unimplemented!() } - - /// Add Client which can be used for sealing, potentially querying the state and sending messages. - fn register_client(&self, _client: Weak) {} - - /// Trigger next step of the consensus engine. - fn step(&self) {} - - /// 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> { - None - } - - /// 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 - } - - /// 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: &Header, _ancestry: &mut dyn Iterator) -> Vec { - Vec::new() - } - - /// Returns author should used when executing tx's for this block. - fn executive_author(&self, header: &Header) -> Result { - Ok(*header.author()) - } - - /// Get the general parameters of the chain. - fn params(&self) -> &CommonParams; - - /// 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 { - 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.params().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 { - self.machine().signing_chain_id(env_info) - } - - /// 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) - } - - /// Performs pre-validation of RLP decoded transaction before other processing - fn decode_transaction(&self, transaction: &[u8]) -> Result { - self.machine().decode_transaction(transaction) - } -} - -/// Verifier for all blocks within an epoch with self-contained state. -pub trait EpochVerifier: Send + Sync { - /// Lightly verify the next block header. - /// This may not be a header belonging to a different epoch. - fn verify_light(&self, header: &Header) -> Result<(), Error>; - - /// Perform potentially heavier checks on the next block header. - fn verify_heavy(&self, header: &Header) -> Result<(), Error> { - self.verify_light(header) - } - - /// Check a finality proof against this epoch verifier. - /// Returns `Some(hashes)` if the proof proves finality of these hashes. - /// Returns `None` if the proof doesn't prove anything. - fn check_finality_proof(&self, _proof: &[u8]) -> Option> { - None - } -} - -/// Special "no-op" verifier for stateless, epoch-less engines. -pub struct NoOp; - -impl EpochVerifier for NoOp { - fn verify_light(&self, _header: &Header) -> Result<(), Error> { Ok(()) } -} diff --git a/ethcore/src/engines/null_engine.rs b/ethcore/src/engines/null_engine.rs index 549bf22e0..37e4e2ce6 100644 --- a/ethcore/src/engines/null_engine.rs +++ b/ethcore/src/engines/null_engine.rs @@ -14,7 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . -use engines::Engine; +use engine::snapshot::SnapshotComponents; +use engine::Engine; use engines::block_reward::{self, RewardKind}; use ethereum_types::U256; use machine::{ @@ -103,7 +104,7 @@ impl Engine for NullEngine { Ok(()) } - fn snapshot_components(&self) -> Option> { + fn snapshot_components(&self) -> Option> { Some(Box::new(::snapshot::PowSnapshot::new(10000, 10000))) } diff --git a/ethcore/src/engines/validator_set/contract.rs b/ethcore/src/engines/validator_set/contract.rs index b680bdeeb..bf9769556 100644 --- a/ethcore/src/engines/validator_set/contract.rs +++ b/ethcore/src/engines/validator_set/contract.rs @@ -30,9 +30,10 @@ use types::{ engines::machine::{Call, AuxiliaryData}, }; -use client::EngineClient; +use client_traits::EngineClient; +use engine::SystemCall; -use super::{ValidatorSet, SimpleList, SystemCall}; +use super::{ValidatorSet, SimpleList}; use super::safe_contract::ValidatorSafeContract; use_contract!(validator_report, "res/contracts/validator_report.json"); @@ -93,7 +94,7 @@ impl ValidatorSet for ValidatorContract { first: bool, header: &Header, aux: AuxiliaryData, - ) -> ::engines::EpochChange { + ) -> engine::EpochChange { self.validators.signals_epoch_end(first, header, aux) } @@ -145,14 +146,15 @@ mod tests { use bytes::ToPretty; use rlp::encode; use crate::spec; - use types::header::Header; + use types::{ + header::Header, + ids::BlockId, + }; use accounts::AccountProvider; use miner::{self, MinerService}; - use types::ids::BlockId; use test_helpers::generate_dummy_client_with_spec; use call_contract::CallContract; - use client::{BlockChainClient, ChainInfo}; - use client_traits::BlockInfo; + use client_traits::{BlockChainClient, ChainInfo, BlockInfo}; use super::super::ValidatorSet; use super::ValidatorContract; diff --git a/ethcore/src/engines/validator_set/mod.rs b/ethcore/src/engines/validator_set/mod.rs index 3a7255427..27f11f4e2 100644 --- a/ethcore/src/engines/validator_set/mod.rs +++ b/ethcore/src/engines/validator_set/mod.rs @@ -26,6 +26,8 @@ mod multi; use std::sync::Weak; use bytes::Bytes; +use client_traits::EngineClient; +use engine::SystemCall; use ethereum_types::{H256, Address}; use ethjson::spec::ValidatorSet as ValidatorSpec; use machine::Machine; @@ -37,15 +39,13 @@ use types::{ engines::machine::{Call, AuxiliaryData}, }; -use client::EngineClient; - #[cfg(test)] pub use self::test::TestSet; pub use self::simple_list::SimpleList; + use self::contract::ValidatorContract; use self::safe_contract::ValidatorSafeContract; use self::multi::Multi; -use super::SystemCall; /// Creates a validator set from spec. pub fn new_validator_set(spec: ValidatorSpec) -> Box { @@ -117,7 +117,7 @@ pub trait ValidatorSet: Send + Sync + 'static { first: bool, header: &Header, aux: AuxiliaryData, - ) -> ::engines::EpochChange; + ) -> engine::EpochChange; /// Recover the validator set from the given proof, the block number, and /// whether this header is first in its set. diff --git a/ethcore/src/engines/validator_set/multi.rs b/ethcore/src/engines/validator_set/multi.rs index 48b00b9cf..9e44430f4 100644 --- a/ethcore/src/engines/validator_set/multi.rs +++ b/ethcore/src/engines/validator_set/multi.rs @@ -30,7 +30,7 @@ use types::{ engines::machine::{Call, AuxiliaryData}, }; -use client::EngineClient; +use client_traits::EngineClient; use machine::Machine; use super::{SystemCall, ValidatorSet}; @@ -100,7 +100,7 @@ impl ValidatorSet for Multi { } fn signals_epoch_end(&self, _first: bool, header: &Header, aux: AuxiliaryData) - -> ::engines::EpochChange + -> engine::EpochChange { let (set_block, set) = self.correct_set_by_number(header.number()); let first = set_block == header.number(); @@ -155,18 +155,19 @@ mod tests { use std::collections::BTreeMap; use hash::keccak; use accounts::AccountProvider; - use client::{BlockChainClient, ChainInfo, ImportBlock}; - use client_traits::BlockInfo; - use engines::EpochChange; + use client_traits::{BlockChainClient, BlockInfo, ChainInfo, ImportBlock, EngineClient}; + use engine::EpochChange; use engines::validator_set::ValidatorSet; use ethkey::Secret; use types::header::Header; use miner::{self, MinerService}; use crate::spec; use test_helpers::{generate_dummy_client_with_spec, generate_dummy_client_with_spec_and_data}; - use types::ids::BlockId; + use types::{ + ids::BlockId, + verification::Unverified, + }; use ethereum_types::Address; - use verification::queue::kind::blocks::Unverified; use super::Multi; @@ -186,24 +187,24 @@ mod tests { let signer = Box::new((tap.clone(), v1, "".into())); client.miner().set_author(miner::Author::Sealer(signer)); client.transact_contract(Default::default(), Default::default()).unwrap(); - ::client::EngineClient::update_sealing(&*client); + EngineClient::update_sealing(&*client); assert_eq!(client.chain_info().best_block_number, 0); // Right signer for the first block. let signer = Box::new((tap.clone(), v0, "".into())); client.miner().set_author(miner::Author::Sealer(signer)); - ::client::EngineClient::update_sealing(&*client); + EngineClient::update_sealing(&*client); assert_eq!(client.chain_info().best_block_number, 1); // This time v0 is wrong. client.transact_contract(Default::default(), Default::default()).unwrap(); - ::client::EngineClient::update_sealing(&*client); + EngineClient::update_sealing(&*client); assert_eq!(client.chain_info().best_block_number, 1); let signer = Box::new((tap.clone(), v1, "".into())); client.miner().set_author(miner::Author::Sealer(signer)); - ::client::EngineClient::update_sealing(&*client); + EngineClient::update_sealing(&*client); assert_eq!(client.chain_info().best_block_number, 2); // v1 is still good. client.transact_contract(Default::default(), Default::default()).unwrap(); - ::client::EngineClient::update_sealing(&*client); + EngineClient::update_sealing(&*client); assert_eq!(client.chain_info().best_block_number, 3); // Check syncing. diff --git a/ethcore/src/engines/validator_set/safe_contract.rs b/ethcore/src/engines/validator_set/safe_contract.rs index 68c9575c6..08f03c7a4 100644 --- a/ethcore/src/engines/validator_set/safe_contract.rs +++ b/ethcore/src/engines/validator_set/safe_contract.rs @@ -36,7 +36,7 @@ use types::{ }; use unexpected::Mismatch; -use client::EngineClient; +use client_traits::EngineClient; use machine::Machine; use super::{SystemCall, ValidatorSet}; use super::simple_list::SimpleList; @@ -59,7 +59,7 @@ struct StateProof { header: Header, } -impl ::engines::StateDependentProof for StateProof { +impl engine::StateDependentProof for StateProof { fn generate_proof(&self, caller: &Call) -> Result, String> { prove_initial(self.contract_address, &self.header, caller) } @@ -314,7 +314,7 @@ impl ValidatorSet for ValidatorSafeContract { } fn signals_epoch_end(&self, first: bool, header: &Header, aux: AuxiliaryData) - -> ::engines::EpochChange + -> engine::EpochChange { let receipts = aux.receipts; @@ -325,27 +325,27 @@ impl ValidatorSet for ValidatorSafeContract { contract_address: self.contract_address, header: header.clone(), }); - return ::engines::EpochChange::Yes(::engines::Proof::WithState(state_proof as Arc<_>)); + return engine::EpochChange::Yes(engine::Proof::WithState(state_proof as Arc<_>)); } // otherwise, we're checking for logs. let bloom = self.expected_bloom(header); let header_bloom = header.log_bloom(); - if &bloom & header_bloom != bloom { return ::engines::EpochChange::No } + if &bloom & header_bloom != bloom { return engine::EpochChange::No } trace!(target: "engine", "detected epoch change event bloom"); match receipts { - None => ::engines::EpochChange::Unsure(AuxiliaryRequest::Receipts), + None => engine::EpochChange::Unsure(AuxiliaryRequest::Receipts), Some(receipts) => match self.extract_from_event(bloom, header, receipts) { - None => ::engines::EpochChange::No, + None => engine::EpochChange::No, Some(list) => { info!(target: "engine", "Signal for transition within contract. New validator list: {:?}", &*list); let proof = encode_proof(&header, receipts); - ::engines::EpochChange::Yes(::engines::Proof::Known(proof)) + engine::EpochChange::Yes(engine::Proof::Known(proof)) } }, } @@ -452,19 +452,24 @@ mod tests { use std::sync::Arc; use rustc_hex::FromHex; use hash::keccak; + use engine::{EpochChange, Proof}; use ethereum_types::Address; - use types::ids::BlockId; use crate::spec; use accounts::AccountProvider; - use types::transaction::{Transaction, Action}; - use client::{ChainInfo, ImportBlock}; - use client_traits::BlockInfo; + use types::{ + ids::BlockId, + engines::machine::AuxiliaryRequest, + header::Header, + log_entry::LogEntry, + transaction::{Transaction, Action}, + verification::Unverified, + }; + use client_traits::{BlockInfo, ChainInfo, ImportBlock, EngineClient}; use ethkey::Secret; use miner::{self, MinerService}; use test_helpers::{generate_dummy_client_with_spec, generate_dummy_client_with_spec_and_data}; use super::super::ValidatorSet; use super::{ValidatorSafeContract, EVENT_NAME_HASH}; - use verification::queue::kind::blocks::Unverified; #[test] fn fetches_validators() { @@ -500,7 +505,7 @@ mod tests { data: "bfc708a000000000000000000000000082a978b3f5962a5b0957d9ee9eef472ee55b42f1".from_hex().unwrap(), }.sign(&s0, Some(chain_id)); client.miner().import_own_transaction(client.as_ref(), tx.into()).unwrap(); - ::client::EngineClient::update_sealing(&*client); + EngineClient::update_sealing(&*client); assert_eq!(client.chain_info().best_block_number, 1); // Add "1" validator back in. let tx = Transaction { @@ -512,14 +517,14 @@ mod tests { data: "4d238c8e00000000000000000000000082a978b3f5962a5b0957d9ee9eef472ee55b42f1".from_hex().unwrap(), }.sign(&s0, Some(chain_id)); client.miner().import_own_transaction(client.as_ref(), tx.into()).unwrap(); - ::client::EngineClient::update_sealing(&*client); + EngineClient::update_sealing(&*client); // The transaction is not yet included so still unable to seal. assert_eq!(client.chain_info().best_block_number, 1); // Switch to the validator that is still there. let signer = Box::new((tap.clone(), v0, "".into())); client.miner().set_author(miner::Author::Sealer(signer)); - ::client::EngineClient::update_sealing(&*client); + EngineClient::update_sealing(&*client); assert_eq!(client.chain_info().best_block_number, 2); // Switch back to the added validator, since the state is updated. let signer = Box::new((tap.clone(), v1, "".into())); @@ -533,7 +538,7 @@ mod tests { data: Vec::new(), }.sign(&s0, Some(chain_id)); client.miner().import_own_transaction(client.as_ref(), tx.into()).unwrap(); - ::client::EngineClient::update_sealing(&*client); + EngineClient::update_sealing(&*client); // Able to seal again. assert_eq!(client.chain_info().best_block_number, 3); @@ -549,13 +554,6 @@ mod tests { #[test] fn detects_bloom() { - use engines::EpochChange; - use types::{ - header::Header, - log_entry::LogEntry, - engines::machine::AuxiliaryRequest, - }; - let client = generate_dummy_client_with_spec(spec::new_validator_safe_contract); let engine = client.engine().clone(); let validator_contract = "0000000000000000000000000000000000000005".parse::
().unwrap(); @@ -590,9 +588,6 @@ mod tests { #[test] fn initial_contract_is_signal() { - use types::header::Header; - use engines::{EpochChange, Proof}; - let client = generate_dummy_client_with_spec(spec::new_validator_safe_contract); let engine = client.engine().clone(); diff --git a/ethcore/src/engines/validator_set/simple_list.rs b/ethcore/src/engines/validator_set/simple_list.rs index 5ec08b286..d3d14f009 100644 --- a/ethcore/src/engines/validator_set/simple_list.rs +++ b/ethcore/src/engines/validator_set/simple_list.rs @@ -77,9 +77,9 @@ impl ValidatorSet for SimpleList { } fn signals_epoch_end(&self, _: bool, _: &Header, _: AuxiliaryData) - -> ::engines::EpochChange + -> engine::EpochChange { - ::engines::EpochChange::No + engine::EpochChange::No } fn epoch_set(&self, _first: bool, _: &Machine, _: BlockNumber, _: &[u8]) -> Result<(SimpleList, Option), EthcoreError> { diff --git a/ethcore/src/engines/validator_set/test.rs b/ethcore/src/engines/validator_set/test.rs index 7abb294bc..c4572a75c 100644 --- a/ethcore/src/engines/validator_set/test.rs +++ b/ethcore/src/engines/validator_set/test.rs @@ -71,9 +71,9 @@ impl ValidatorSet for TestSet { fn is_epoch_end(&self, _first: bool, _chain_head: &Header) -> Option> { None } fn signals_epoch_end(&self, _: bool, _: &Header, _: AuxiliaryData) - -> ::engines::EpochChange + -> engine::EpochChange { - ::engines::EpochChange::No + engine::EpochChange::No } fn epoch_set(&self, _: bool, _: &Machine, _: BlockNumber, _: &[u8]) -> Result<(SimpleList, Option), EthcoreError> { diff --git a/ethcore/src/executive_state.rs b/ethcore/src/executive_state.rs index d045102ce..7d440e26a 100644 --- a/ethcore/src/executive_state.rs +++ b/ethcore/src/executive_state.rs @@ -25,6 +25,7 @@ use machine::{ }; use vm::EnvInfo; use types::{ + engines::machine::Executed as RawExecuted, errors::{ExecutionError, EthcoreError as Error}, transaction::SignedTransaction, receipt::{TransactionOutcome, Receipt}, @@ -242,7 +243,7 @@ fn execute( t: &SignedTransaction, options: TransactOptions, virt: bool -) -> Result, ExecutionError> +) -> Result, ExecutionError> where B: Backend, T: trace::Tracer, diff --git a/ethcore/src/json_tests/chain.rs b/ethcore/src/json_tests/chain.rs index 1e9861f61..4bfe3c7c9 100644 --- a/ethcore/src/json_tests/chain.rs +++ b/ethcore/src/json_tests/chain.rs @@ -16,13 +16,14 @@ use std::path::Path; use std::sync::Arc; -use client::{EvmTestClient, Client, ClientConfig, ChainInfo, ImportBlock}; +use client::{EvmTestClient, Client, ClientConfig}; +use client_traits::{ImportBlock, ChainInfo}; use spec::Genesis; use ethjson; use miner::Miner; use io::IoChannel; use test_helpers; -use verification::queue::kind::blocks::Unverified; +use types::verification::Unverified; use verification::VerifierType; use super::SKIP_TEST_STATE; use super::HookType; diff --git a/ethcore/src/json_tests/executive.rs b/ethcore/src/json_tests/executive.rs index aaac509c4..234cd557d 100644 --- a/ethcore/src/json_tests/executive.rs +++ b/ethcore/src/json_tests/executive.rs @@ -29,7 +29,6 @@ use machine::{ externalities::{OutputPolicy, OriginInfo, Externalities}, substate::Substate, executive::contract_address, - test_helpers::new_frontier_test_machine, }; use test_helpers::get_temp_state; diff --git a/ethcore/src/lib.rs b/ethcore/src/lib.rs index 7802dc4da..d1936aa9d 100644 --- a/ethcore/src/lib.rs +++ b/ethcore/src/lib.rs @@ -59,6 +59,7 @@ extern crate ansi_term; extern crate client_traits; extern crate common_types as types; extern crate crossbeam_utils; +extern crate engine; extern crate ethabi; extern crate ethash; extern crate ethcore_blockchain as blockchain; @@ -102,7 +103,6 @@ extern crate parity_util_mem as malloc_size_of; extern crate rustc_hex; extern crate serde; extern crate state_db; -extern crate stats; extern crate time_utils; extern crate trace; extern crate triehash_ethereum as triehash; diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index 6157e8d28..e7e066d45 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -49,7 +49,7 @@ use types::{ block::Block, header::Header, ids::BlockId, - engines::{SealingState}, + engines::{Seal, SealingState}, errors::{EthcoreError as Error, ExecutionError}, receipt::RichReceipt, }; @@ -57,9 +57,15 @@ use using_queue::{UsingQueue, GetAction}; use block::{ClosedBlock, SealedBlock}; use client::{ - BlockChain, ChainInfo, BlockProducer, SealedBlockImporter, Nonce, TransactionInfo, ClientIoMessage, + BlockProducer, SealedBlockImporter, ClientIoMessage, +}; +use client_traits::{ + BlockChain, ChainInfo, Nonce, TransactionInfo, +}; +use engine::{ + Engine, + signer::EngineSigner }; -use engines::{Engine, Seal, EngineSigner}; use machine::executive::contract_address; use spec::Spec; use account_state::State; @@ -1483,12 +1489,15 @@ mod tests { use ethkey::{Generator, Random}; use hash::keccak; use rustc_hex::FromHex; - use types::BlockNumber; - use client::{TestBlockChainClient, EachBlockWith, ChainInfo, ImportSealedBlock}; + use client::{TestBlockChainClient, EachBlockWith, ImportSealedBlock}; + use client_traits::ChainInfo; use miner::{MinerService, PendingOrdering}; use test_helpers::{generate_dummy_client, generate_dummy_client_with_spec}; - use types::transaction::{Transaction}; + use types::{ + BlockNumber, + transaction::Transaction + }; use crate::spec; #[test] diff --git a/ethcore/src/miner/mod.rs b/ethcore/src/miner/mod.rs index c9f4c0d1f..0de939025 100644 --- a/ethcore/src/miner/mod.rs +++ b/ethcore/src/miner/mod.rs @@ -47,11 +47,8 @@ use types::{ use block::SealedBlock; use call_contract::{CallContract, RegistryInfo}; -use client::{ - ScheduleInfo, - BlockChain, BlockProducer, SealedBlockImporter, ChainInfo, - AccountData, Nonce, -}; +use client::{BlockProducer, SealedBlockImporter}; +use client_traits::{BlockChain, ChainInfo, AccountData, Nonce, ScheduleInfo}; use account_state::state::StateInfo; /// Provides methods to verify incoming external transactions diff --git a/ethcore/src/miner/pool_client.rs b/ethcore/src/miner/pool_client.rs index 4a9852409..97a4d004d 100644 --- a/ethcore/src/miner/pool_client.rs +++ b/ethcore/src/miner/pool_client.rs @@ -39,9 +39,8 @@ use types::{ use parking_lot::RwLock; use call_contract::CallContract; -use client::Nonce; -use client_traits::BlockInfo; -use engines::Engine; +use client_traits::{BlockInfo, Nonce}; +use engine::Engine; use machine::transaction_ext::Transaction; use miner; diff --git a/ethcore/src/snapshot/account.rs b/ethcore/src/snapshot/account.rs index 7bf2f4829..62d9ac71d 100644 --- a/ethcore/src/snapshot/account.rs +++ b/ethcore/src/snapshot/account.rs @@ -17,14 +17,17 @@ //! Account state encoding and decoding use account_db::{AccountDB, AccountDBMut}; -use types::basic_account::BasicAccount; +use types::{ + basic_account::BasicAccount, + snapshot::Progress, + errors::SnapshotError as Error, +}; use bytes::Bytes; use ethereum_types::{H256, U256}; use ethtrie::{TrieDB, TrieDBMut}; use hash::{KECCAK_EMPTY, KECCAK_NULL_RLP}; use hash_db::HashDB; use rlp::{RlpStream, Rlp}; -use snapshot::{Error, Progress}; use std::collections::HashSet; use trie::{Trie, TrieMut}; use std::sync::atomic::Ordering; diff --git a/ethcore/src/snapshot/consensus/authority.rs b/ethcore/src/snapshot/consensus/authority.rs index 341c70d34..19f46bb14 100644 --- a/ethcore/src/snapshot/consensus/authority.rs +++ b/ethcore/src/snapshot/consensus/authority.rs @@ -19,14 +19,14 @@ //! //! The chunks here contain state proofs of transitions, along with validator proofs. -use super::{SnapshotComponents, Rebuilder, ChunkSink}; - use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; -use engines::{Engine, EpochVerifier, EpochTransition}; -use snapshot::{ManifestData, Progress}; - +use engine::{ + Engine, + EpochVerifier, + snapshot::{SnapshotComponents, Rebuilder} +}; use blockchain::{BlockChain, BlockChainDB, BlockProvider}; use bytes::Bytes; use ethereum_types::{H256, U256}; @@ -35,10 +35,12 @@ use kvdb::KeyValueDB; use rlp::{RlpStream, Rlp}; use types::{ encoded, + engines::epoch::Transition as EpochTransition, header::Header, ids::BlockId, errors::{SnapshotError, EthcoreError}, receipt::Receipt, + snapshot::{ChunkSink, Progress, ManifestData} }; /// Snapshot creation and restoration for PoA chains. @@ -189,7 +191,7 @@ impl ChunkRebuilder { transition_rlp: Rlp, engine: &dyn Engine, ) -> Result { - use engines::ConstructedVerifier; + use engine::ConstructedVerifier; // decode. let header: Header = transition_rlp.val_at(0)?; diff --git a/ethcore/src/snapshot/consensus/mod.rs b/ethcore/src/snapshot/consensus/mod.rs index 102acdeca..3623d008d 100644 --- a/ethcore/src/snapshot/consensus/mod.rs +++ b/ethcore/src/snapshot/consensus/mod.rs @@ -17,81 +17,8 @@ //! Secondary chunk creation and restoration, implementations for different consensus //! engines. -use std::sync::atomic::AtomicBool; -use std::sync::Arc; - -use blockchain::{BlockChain, BlockChainDB}; -use engines::Engine; -use snapshot::{ManifestData, Progress}; -use types::errors::{SnapshotError, EthcoreError}; - -use ethereum_types::H256; - mod authority; mod work; pub use self::authority::*; pub use self::work::*; - -/// A sink for produced chunks. -pub type ChunkSink<'a> = dyn FnMut(&[u8]) -> ::std::io::Result<()> + 'a; - -/// Components necessary for snapshot creation and restoration. -pub trait SnapshotComponents: Send { - /// Create secondary snapshot chunks; these corroborate the state data - /// in the state chunks. - /// - /// Chunks shouldn't exceed the given preferred size, and should be fed - /// uncompressed into the sink. - /// - /// This will vary by consensus engine, so it's exposed as a trait. - fn chunk_all( - &mut self, - chain: &BlockChain, - block_at: H256, - chunk_sink: &mut ChunkSink, - progress: &Progress, - preferred_size: usize, - ) -> Result<(), SnapshotError>; - - /// Create a rebuilder, which will have chunks fed into it in aribtrary - /// order and then be finalized. - /// - /// The manifest, a database, and fresh `BlockChain` are supplied. - /// - /// The engine passed to the `Rebuilder` methods will be the same instance - /// that created the `SnapshotComponents`. - fn rebuilder( - &self, - chain: BlockChain, - db: Arc, - manifest: &ManifestData, - ) -> Result, EthcoreError>; - - /// Minimum supported snapshot version number. - fn min_supported_version(&self) -> u64; - - /// Current version number - fn current_version(&self) -> u64; -} - -/// Restore from secondary snapshot chunks. -pub trait Rebuilder: Send { - /// Feed a chunk, potentially out of order. - /// - /// Check `abort_flag` periodically while doing heavy work. If set to `false`, should bail with - /// `Error::RestorationAborted`. - fn feed( - &mut self, - chunk: &[u8], - engine: &dyn Engine, - abort_flag: &AtomicBool, - ) -> Result<(), EthcoreError>; - - /// Finalize the restoration. Will be done after all chunks have been - /// fed successfully. - /// - /// This should apply the necessary "glue" between chunks, - /// and verify against the restored state. - fn finalize(&mut self) -> Result<(), EthcoreError>; -} diff --git a/ethcore/src/snapshot/consensus/work.rs b/ethcore/src/snapshot/consensus/work.rs index f286006a9..f9c4faec3 100644 --- a/ethcore/src/snapshot/consensus/work.rs +++ b/ethcore/src/snapshot/consensus/work.rs @@ -20,15 +20,13 @@ //! The secondary chunks in this instance are 30,000 "abridged blocks" from the head //! of the chain, which serve as an indication of valid chain. -use super::{SnapshotComponents, Rebuilder, ChunkSink}; - use std::collections::VecDeque; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; use blockchain::{BlockChain, BlockChainDB, BlockProvider}; -use engines::Engine; -use snapshot::{ManifestData, Progress}; +use engine::Engine; +use engine::snapshot::{SnapshotComponents, Rebuilder}; use snapshot::block::AbridgedBlock; use ethereum_types::H256; use kvdb::KeyValueDB; @@ -37,7 +35,9 @@ use rlp::{RlpStream, Rlp}; use rand::rngs::OsRng; use types::{ encoded, + engines::epoch::Transition as EpochTransition, errors::{SnapshotError, EthcoreError}, + snapshot::{ChunkSink, ManifestData, Progress}, }; /// Snapshot creation and restoration for PoW chains. @@ -84,7 +84,12 @@ impl SnapshotComponents for PowSnapshot { db: Arc, manifest: &ManifestData, ) -> Result, EthcoreError> { - PowRebuilder::new(chain, db.key_value().clone(), manifest, self.max_restore_blocks).map(|r| Box::new(r) as Box<_>) + PowRebuilder::new( + chain, + db.key_value().clone(), + manifest, + self.max_restore_blocks + ).map(|r| Box::new(r) as Box<_>) } fn min_supported_version(&self) -> u64 { ::snapshot::MIN_SUPPORTED_STATE_CHUNK_VERSION } @@ -314,7 +319,7 @@ impl Rebuilder for PowRebuilder { } let genesis_hash = self.chain.genesis_hash(); - self.chain.insert_epoch_transition(&mut batch, 0, ::engines::EpochTransition { + self.chain.insert_epoch_transition(&mut batch, 0, EpochTransition { block_number: 0, block_hash: genesis_hash, proof: vec![], diff --git a/ethcore/src/snapshot/mod.rs b/ethcore/src/snapshot/mod.rs index 256db1d94..3dab15d4f 100644 --- a/ethcore/src/snapshot/mod.rs +++ b/ethcore/src/snapshot/mod.rs @@ -22,16 +22,16 @@ use std::collections::{HashMap, HashSet}; use std::cmp; use std::sync::Arc; -use std::sync::atomic::{AtomicBool, AtomicU64, AtomicUsize, Ordering}; +use std::sync::atomic::{AtomicBool, Ordering}; use hash::{keccak, KECCAK_NULL_RLP, KECCAK_EMPTY}; use account_db::{AccountDB, AccountDBMut}; use blockchain::{BlockChain, BlockProvider}; -use engines::Engine; use types::{ ids::BlockId, header::Header, errors::{SnapshotError as Error, EthcoreError}, + snapshot::Progress, }; use ethereum_types::{H256, U256}; use hash_db::HashDB; @@ -51,6 +51,10 @@ use self::io::SnapshotWriter; use super::state_db::StateDB; use account_state::Account as StateAccount; +use engine::{ + Engine, + snapshot::SnapshotComponents +}; use crossbeam_utils::thread; use rand::{Rng, rngs::OsRng}; @@ -59,7 +63,7 @@ pub use self::consensus::*; pub use self::service::{SnapshotClient, Service, DatabaseRestore}; pub use self::traits::SnapshotService; pub use self::watcher::Watcher; -pub use types::snapshot_manifest::ManifestData; +pub use types::snapshot::ManifestData; pub use types::restoration_status::RestorationStatus; pub use types::basic_account::BasicAccount; @@ -111,42 +115,6 @@ impl Default for SnapshotConfiguration { } } -/// A progress indicator for snapshots. -#[derive(Debug, Default)] -pub struct Progress { - accounts: AtomicUsize, - blocks: AtomicUsize, - size: AtomicU64, - done: AtomicBool, - abort: AtomicBool, -} - -impl Progress { - /// Reset the progress. - pub fn reset(&self) { - self.accounts.store(0, Ordering::Release); - self.blocks.store(0, Ordering::Release); - self.size.store(0, Ordering::Release); - self.abort.store(false, Ordering::Release); - - // atomic fence here to ensure the others are written first? - // logs might very rarely get polluted if not. - self.done.store(false, Ordering::Release); - } - - /// Get the number of accounts snapshotted thus far. - pub fn accounts(&self) -> usize { self.accounts.load(Ordering::Acquire) } - - /// Get the number of blocks snapshotted thus far. - pub fn blocks(&self) -> usize { self.blocks.load(Ordering::Acquire) } - - /// Get the written size of the snapshot in bytes. - pub fn size(&self) -> u64 { self.size.load(Ordering::Acquire) } - - /// Whether the snapshot is complete. - pub fn done(&self) -> bool { self.done.load(Ordering::Acquire) } - -} /// Take a snapshot using the given blockchain, starting block hash, and database, writing into the given writer. pub fn take_snapshot( chunker: Box, diff --git a/ethcore/src/snapshot/service.rs b/ethcore/src/snapshot/service.rs index 79bdb902c..3c1a3afea 100644 --- a/ethcore/src/snapshot/service.rs +++ b/ethcore/src/snapshot/service.rs @@ -24,17 +24,21 @@ use std::sync::Arc; use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; use std::cmp; -use super::{ManifestData, StateRebuilder, Rebuilder, RestorationStatus, SnapshotService, MAX_CHUNK_SIZE}; +use super::{StateRebuilder, RestorationStatus, SnapshotService, MAX_CHUNK_SIZE}; use super::io::{SnapshotReader, LooseReader, SnapshotWriter, LooseWriter}; use blockchain::{BlockChain, BlockChainDB, BlockChainDBHandler}; -use client::{BlockChainClient, Client, ChainInfo, ClientIoMessage}; -use client_traits::BlockInfo; -use engines::Engine; +use client::{Client, ClientIoMessage}; +use client_traits::{ + BlockInfo, BlockChainClient, ChainInfo +}; +use engine::Engine; +use engine::snapshot::Rebuilder; use hash::keccak; use types::{ errors::{EthcoreError as Error, SnapshotError, SnapshotError::UnlinkedAncientBlockChain}, ids::BlockId, + snapshot::{ManifestData, Progress}, }; use io::IoChannel; @@ -245,7 +249,7 @@ pub struct Service { state_chunks: AtomicUsize, block_chunks: AtomicUsize, client: Arc, - progress: super::Progress, + progress: Progress, taking_snapshot: AtomicBool, restoring_snapshot: AtomicBool, } diff --git a/ethcore/src/snapshot/tests/helpers.rs b/ethcore/src/snapshot/tests/helpers.rs index 053e8813f..d1931d911 100644 --- a/ethcore/src/snapshot/tests/helpers.rs +++ b/ethcore/src/snapshot/tests/helpers.rs @@ -25,8 +25,9 @@ use hash::{KECCAK_NULL_RLP}; use account_db::AccountDBMut; use types::basic_account::BasicAccount; use blockchain::{BlockChain, BlockChainDB}; -use client::{Client, ChainInfo}; -use engines::Engine; +use client::Client; +use client_traits::ChainInfo; +use engine::Engine; use snapshot::{StateRebuilder}; use snapshot::io::{SnapshotReader, PackedWriter, PackedReader}; diff --git a/ethcore/src/snapshot/tests/proof_of_authority.rs b/ethcore/src/snapshot/tests/proof_of_authority.rs index f16357b0f..a0161acdf 100644 --- a/ethcore/src/snapshot/tests/proof_of_authority.rs +++ b/ethcore/src/snapshot/tests/proof_of_authority.rs @@ -21,7 +21,8 @@ use std::sync::Arc; use std::str::FromStr; use accounts::AccountProvider; -use client::{Client, BlockChainClient, ChainInfo}; +use client::Client; +use client_traits::{BlockChainClient, ChainInfo}; use ethkey::Secret; use snapshot::tests::helpers as snapshot_helpers; use spec::Spec; diff --git a/ethcore/src/snapshot/tests/proof_of_work.rs b/ethcore/src/snapshot/tests/proof_of_work.rs index eee12a0c2..6e7726a6a 100644 --- a/ethcore/src/snapshot/tests/proof_of_work.rs +++ b/ethcore/src/snapshot/tests/proof_of_work.rs @@ -18,7 +18,10 @@ use std::sync::atomic::AtomicBool; use tempdir::TempDir; -use types::errors::EthcoreError as Error; +use types::{ + errors::EthcoreError as Error, + engines::ForkChoice, +}; use blockchain::generator::{BlockGenerator, BlockBuilder}; use blockchain::{BlockChain, ExtrasInsert}; @@ -50,7 +53,7 @@ fn chunk_and_restore(amount: u64) { let mut batch = DBTransaction::new(); for block in generator { bc.insert_block(&mut batch, block.encoded(), vec![], ExtrasInsert { - fork_choice: ::engines::ForkChoice::New, + fork_choice: ForkChoice::New, is_finalized: false, }); bc.commit(); diff --git a/ethcore/src/snapshot/tests/service.rs b/ethcore/src/snapshot/tests/service.rs index 13ab94214..e9bc3b92b 100644 --- a/ethcore/src/snapshot/tests/service.rs +++ b/ethcore/src/snapshot/tests/service.rs @@ -21,19 +21,22 @@ use std::sync::Arc; use tempdir::TempDir; use blockchain::BlockProvider; -use client::{Client, ClientConfig, ImportBlock}; -use client_traits::BlockInfo; -use types::ids::BlockId; +use client::{Client, ClientConfig}; +use client_traits::{BlockInfo, ImportBlock}; +use types::{ + ids::BlockId, + snapshot::Progress, + verification::Unverified, +}; use snapshot::io::{PackedReader, PackedWriter, SnapshotReader, SnapshotWriter}; use snapshot::service::{Service, ServiceParams}; -use snapshot::{chunk_state, chunk_secondary, ManifestData, Progress, SnapshotService, RestorationStatus}; +use snapshot::{chunk_state, chunk_secondary, ManifestData, SnapshotService, RestorationStatus}; use crate::spec; use test_helpers::{new_db, new_temp_db, generate_dummy_client_with_spec_and_data, restoration_db_handler}; use parking_lot::Mutex; use io::IoChannel; use kvdb_rocksdb::DatabaseConfig; -use verification::queue::kind::blocks::Unverified; #[test] fn restored_is_equivalent() { diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index 773119b3f..f5ffd543e 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -39,8 +39,9 @@ use types::{ use vm::{EnvInfo, CallType, ActionValue, ActionParams, ParamsType}; use builtin::Builtin; +use engine::Engine; use engines::{ - Engine, NullEngine, InstantSeal, InstantSealParams, BasicAuthority, Clique, + NullEngine, InstantSeal, InstantSealParams, BasicAuthority, Clique, AuthorityRound, Ethash, }; use machine::{ diff --git a/ethcore/src/test_helpers.rs b/ethcore/src/test_helpers.rs index 2349b781c..32a5f7778 100644 --- a/ethcore/src/test_helpers.rs +++ b/ethcore/src/test_helpers.rs @@ -33,20 +33,24 @@ use kvdb_rocksdb::{self, Database, DatabaseConfig}; use parking_lot::RwLock; use rlp::{self, RlpStream}; use tempdir::TempDir; -use types::transaction::{Action, Transaction, SignedTransaction}; -use types::encoded; -use types::header::Header; -use types::view; -use types::views::BlockView; +use types::{ + transaction::{Action, Transaction, SignedTransaction}, + encoded, + engines::ForkChoice, + header::Header, + view, + views::BlockView, + verification::Unverified, +}; use block::{OpenBlock, Drain}; -use client::{Client, ClientConfig, ChainInfo, ImportBlock, ChainNotify, ChainMessageType, PrepareOpenBlock}; +use client::{Client, ClientConfig, ChainNotify, ChainMessageType, PrepareOpenBlock}; +use client_traits::{ChainInfo, ImportBlock}; use trie_vm_factories::Factories; use miner::Miner; use spec::{Spec, self}; use account_state::*; use state_db::StateDB; -use verification::queue::kind::blocks::Unverified; /// Creates test block with corresponding header pub fn create_test_block(header: &Header) -> Bytes { @@ -375,7 +379,7 @@ pub fn generate_dummy_blockchain(block_number: u32) -> BlockChain { for block_order in 1..block_number { // Total difficulty is always 0 here. bc.insert_block(&mut batch, encoded::Block::new(create_unverifiable_block(block_order, bc.best_block_hash())), vec![], ExtrasInsert { - fork_choice: ::engines::ForkChoice::New, + fork_choice: ForkChoice::New, is_finalized: false, }); bc.commit(); @@ -393,7 +397,7 @@ pub fn generate_dummy_blockchain_with_extra(block_number: u32) -> BlockChain { for block_order in 1..block_number { // Total difficulty is always 0 here. bc.insert_block(&mut batch, encoded::Block::new(create_unverifiable_block_with_extra(block_order, bc.best_block_hash(), None)), vec![], ExtrasInsert { - fork_choice: ::engines::ForkChoice::New, + fork_choice: ForkChoice::New, is_finalized: false, }); bc.commit(); diff --git a/ethcore/src/tests/client.rs b/ethcore/src/tests/client.rs index 7c7b4c1d3..ea2aff7ae 100644 --- a/ethcore/src/tests/client.rs +++ b/ethcore/src/tests/client.rs @@ -26,12 +26,13 @@ use types::{ ids::BlockId, transaction::{PendingTransaction, Transaction, Action, Condition}, filter::Filter, + verification::Unverified, view, views::BlockView, }; -use client::{BlockChainClient, BlockChainReset, Client, ClientConfig, ChainInfo, PrepareOpenBlock, ImportSealedBlock, ImportBlock}; -use client_traits::BlockInfo; +use client::{Client, ClientConfig, PrepareOpenBlock, ImportSealedBlock}; +use client_traits::{BlockInfo, BlockChainClient, BlockChainReset, ChainInfo, ImportBlock}; use crate::spec; use machine::executive::{Executive, TransactOptions}; use miner::{Miner, PendingOrdering, MinerService}; @@ -41,7 +42,6 @@ use test_helpers::{ generate_dummy_client, push_blocks_to_client, get_test_client_with_blocks, get_good_dummy_block_seq, generate_dummy_client_with_data, get_good_dummy_block, get_bad_state_dummy_block }; -use verification::queue::kind::blocks::Unverified; #[test] fn imports_from_empty() { @@ -210,7 +210,7 @@ fn can_generate_gas_price_histogram() { let client = generate_dummy_client_with_data(20, 1, slice_into![6354,8593,6065,4842,7845,7002,689,4958,4250,6098,5804,4320,643,8895,2296,8589,7145,2000,2512,1408]); let hist = client.gas_price_corpus(20).histogram(5).unwrap(); - let correct_hist = ::stats::Histogram { bucket_bounds: vec_into![643, 2294, 3945, 5596, 7247, 8898], counts: vec![4,2,4,6,4] }; + let correct_hist = stats::Histogram { bucket_bounds: vec_into![643, 2294, 3945, 5596, 7247, 8898], counts: vec![4,2,4,6,4] }; assert_eq!(hist, correct_hist); } @@ -327,7 +327,7 @@ fn does_not_propagate_delayed_transactions() { #[test] fn transaction_proof() { - use ::client::ProvingBlockChainClient; + use client_traits::ProvingBlockChainClient; let client = generate_dummy_client(0); let address = Address::random(); diff --git a/ethcore/src/tests/trace.rs b/ethcore/src/tests/trace.rs index 9f1326b49..dd6fb8464 100644 --- a/ethcore/src/tests/trace.rs +++ b/ethcore/src/tests/trace.rs @@ -22,21 +22,21 @@ use block::*; use ethereum_types::{U256, Address}; use io::*; use crate::spec; -use client::*; use test_helpers::get_temp_state_db; -use client::{BlockChainClient, Client, ClientConfig}; +use client::{Client, ClientConfig}; +use client_traits::{BlockChainClient, ImportBlock}; use std::sync::Arc; use std::str::FromStr; use miner::Miner; use trace::{RewardType, LocalizedTrace}; use trace::trace::Action::Reward; use test_helpers; -use verification::queue::kind::blocks::Unverified; use types::{ ids::BlockId, transaction::{Action, Transaction}, trace_filter::Filter as TraceFilter, header::Header, + verification::Unverified, view, views::BlockView, }; diff --git a/ethcore/src/verification/canon_verifier.rs b/ethcore/src/verification/canon_verifier.rs index acf42b451..c0c607097 100644 --- a/ethcore/src/verification/canon_verifier.rs +++ b/ethcore/src/verification/canon_verifier.rs @@ -18,7 +18,7 @@ use call_contract::CallContract; use client_traits::BlockInfo; -use engines::Engine; +use engine::Engine; use types::{ header::Header, errors::EthcoreError as Error, diff --git a/ethcore/src/verification/noop_verifier.rs b/ethcore/src/verification/noop_verifier.rs index 8bcbe1532..3f9a6210f 100644 --- a/ethcore/src/verification/noop_verifier.rs +++ b/ethcore/src/verification/noop_verifier.rs @@ -18,7 +18,7 @@ use call_contract::CallContract; use client_traits::BlockInfo; -use engines::Engine; +use engine::Engine; use types::{ header::Header, errors::EthcoreError as Error diff --git a/ethcore/src/verification/queue/kind.rs b/ethcore/src/verification/queue/kind.rs index 106759ca3..937d05abd 100644 --- a/ethcore/src/verification/queue/kind.rs +++ b/ethcore/src/verification/queue/kind.rs @@ -16,7 +16,7 @@ //! Definition of valid items for the verification queue. -use engines::Engine; +use engine::Engine; use parity_util_mem::MallocSizeOf; use ethereum_types::{H256, U256}; @@ -69,18 +69,15 @@ pub trait Kind: 'static + Sized + Send + Sync { pub mod blocks { use super::{Kind, BlockLike}; - use engines::Engine; + use engine::Engine; use types::{ block::PreverifiedBlock, - header::Header, errors::{EthcoreError as Error, BlockError}, - transaction::UnverifiedTransaction + verification::Unverified, }; use verification::{verify_block_basic, verify_block_unordered}; - use parity_util_mem::MallocSizeOf; use ethereum_types::{H256, U256}; - use bytes::Bytes; /// A mode for verifying blocks. pub struct Blocks; @@ -116,40 +113,6 @@ pub mod blocks { } } - /// An unverified block. - #[derive(PartialEq, Debug, MallocSizeOf)] - pub struct Unverified { - /// Unverified block header. - pub header: Header, - /// Unverified block transactions. - pub transactions: Vec, - /// Unverified block uncles. - pub uncles: Vec
, - /// Raw block bytes. - pub bytes: Bytes, - } - - impl Unverified { - /// Create an `Unverified` from raw bytes. - pub fn from_rlp(bytes: Bytes) -> Result { - use rlp::Rlp; - let (header, transactions, uncles) = { - let rlp = Rlp::new(&bytes); - let header = rlp.val_at(0)?; - let transactions = rlp.list_at(1)?; - let uncles = rlp.list_at(2)?; - (header, transactions, uncles) - }; - - Ok(Unverified { - header, - transactions, - uncles, - bytes, - }) - } - } - impl BlockLike for Unverified { fn hash(&self) -> H256 { self.header.hash() @@ -183,7 +146,7 @@ pub mod blocks { pub mod headers { use super::{Kind, BlockLike}; - use engines::Engine; + use engine::Engine; use types::{ header::Header, errors::EthcoreError as Error, diff --git a/ethcore/src/verification/queue/mod.rs b/ethcore/src/verification/queue/mod.rs index 9b736807d..5bd96442a 100644 --- a/ethcore/src/verification/queue/mod.rs +++ b/ethcore/src/verification/queue/mod.rs @@ -26,14 +26,14 @@ use parity_util_mem::{MallocSizeOf, MallocSizeOfExt}; use ethereum_types::{H256, U256}; use parking_lot::{Condvar, Mutex, RwLock}; use io::*; -use engines::Engine; +use engine::Engine; use client::ClientIoMessage; use len_caching_lock::LenCachingMutex; use types::errors::{BlockError, EthcoreError as Error, ImportError}; use self::kind::{BlockLike, Kind}; -pub use types::verification_queue_info::VerificationQueueInfo as QueueInfo; +pub use types::verification::VerificationQueueInfo as QueueInfo; pub mod kind; @@ -735,13 +735,13 @@ impl Drop for VerificationQueue { mod tests { use io::*; use super::{BlockQueue, Config, State}; - use super::kind::blocks::Unverified; use test_helpers::{get_good_dummy_block_seq, get_good_dummy_block}; use bytes::Bytes; use types::{ + errors::{EthcoreError, ImportError}, + verification::Unverified, view, views::BlockView, - errors::{EthcoreError, ImportError}, }; use crate::spec; diff --git a/ethcore/src/verification/verification.rs b/ethcore/src/verification/verification.rs index 2042e70af..28cc87e5e 100644 --- a/ethcore/src/verification/verification.rs +++ b/ethcore/src/verification/verification.rs @@ -32,15 +32,15 @@ use unexpected::{Mismatch, OutOfBounds}; use blockchain::*; use call_contract::CallContract; use client_traits::BlockInfo; -use engines::Engine; +use engine::Engine; use types::{ BlockNumber, header::Header, errors::{EthcoreError as Error, BlockError}, engines::MAX_UNCLE_AGE, block::PreverifiedBlock, + verification::Unverified, }; -use verification::queue::kind::blocks::Unverified; use time_utils::CheckedSystemTime; @@ -370,7 +370,7 @@ mod tests { use blockchain::{BlockDetails, TransactionAddress, BlockReceipts}; use bytes::Bytes; use hash::keccak; - use engines::Engine; + use engine::Engine; use ethkey::{Random, Generator}; use crate::spec; use test_helpers::{create_test_block_with_data, create_test_block}; diff --git a/ethcore/src/verification/verifier.rs b/ethcore/src/verification/verifier.rs index 17bb96a2c..ced7f5649 100644 --- a/ethcore/src/verification/verifier.rs +++ b/ethcore/src/verification/verifier.rs @@ -18,7 +18,7 @@ use call_contract::CallContract; use client_traits::BlockInfo; -use engines::Engine; +use engine::Engine; use types::{ header::Header, errors::EthcoreError as Error, diff --git a/ethcore/sync/Cargo.toml b/ethcore/sync/Cargo.toml index 5e2cf1cad..df35a4bab 100644 --- a/ethcore/sync/Cargo.toml +++ b/ethcore/sync/Cargo.toml @@ -10,6 +10,7 @@ authors = ["Parity Technologies "] [dependencies] client-traits = { path = "../client-traits" } common-types = { path = "../types" } +engine = { path = "../engine" } enum_primitive = "0.1.1" ethcore = { path = ".." } ethcore-io = { path = "../../util/io" } diff --git a/ethcore/sync/src/api.rs b/ethcore/sync/src/api.rs index 9a8c6a8bf..3a662f8cb 100644 --- a/ethcore/sync/src/api.rs +++ b/ethcore/sync/src/api.rs @@ -32,7 +32,8 @@ use futures::sync::mpsc as futures_mpsc; use futures::Stream; use io::{TimerToken}; use ethkey::Secret; -use ethcore::client::{BlockChainClient, ChainNotify, NewBlocks, ChainMessageType}; +use ethcore::client::{ChainNotify, NewBlocks, ChainMessageType}; +use client_traits::BlockChainClient; use ethcore::snapshot::SnapshotService; use types::BlockNumber; use sync_io::NetSyncIo; diff --git a/ethcore/sync/src/blocks.rs b/ethcore/sync/src/blocks.rs index e5b892536..0dd672786 100644 --- a/ethcore/sync/src/blocks.rs +++ b/ethcore/sync/src/blocks.rs @@ -22,9 +22,11 @@ use triehash_ethereum::ordered_trie_root; use bytes::Bytes; use rlp::{Rlp, RlpStream, DecoderError}; use network; -use ethcore::verification::queue::kind::blocks::Unverified; -use types::transaction::UnverifiedTransaction; -use types::header::Header as BlockHeader; +use types::{ + transaction::UnverifiedTransaction, + header::Header as BlockHeader, + verification::Unverified, +}; malloc_size_of_is_0!(HeaderId); @@ -541,12 +543,13 @@ impl BlockCollection { #[cfg(test)] mod test { use super::{BlockCollection, SyncHeader}; - use ethcore::client::{TestBlockChainClient, EachBlockWith, BlockChainClient}; + use client_traits::BlockChainClient; + use ethcore::client::{TestBlockChainClient, EachBlockWith}; use types::{ ids::BlockId, - BlockNumber + BlockNumber, + verification::Unverified, }; - use ethcore::verification::queue::kind::blocks::Unverified; use rlp::*; fn is_empty(bc: &BlockCollection) -> bool { diff --git a/ethcore/sync/src/chain/handler.rs b/ethcore/sync/src/chain/handler.rs index 15fd65e0f..659720e3f 100644 --- a/ethcore/sync/src/chain/handler.rs +++ b/ethcore/sync/src/chain/handler.rs @@ -19,7 +19,6 @@ use block_sync::{BlockDownloaderImportError as DownloaderImportError, DownloadAc use bytes::Bytes; use enum_primitive::FromPrimitive; use ethcore::snapshot::{ManifestData, RestorationStatus}; -use ethcore::verification::queue::kind::blocks::Unverified; use ethereum_types::{H256, U256}; use hash::keccak; use network::PeerId; @@ -34,6 +33,7 @@ use types::{ block_status::BlockStatus, ids::BlockId, errors::{EthcoreError, ImportError, BlockError}, + verification::Unverified, }; use super::sync_packet::{PacketInfo, SyncPacket}; @@ -742,9 +742,10 @@ impl SyncHandler { #[cfg(test)] mod tests { - use ethcore::client::{ChainInfo, EachBlockWith, TestBlockChainClient}; + use client_traits::ChainInfo; + use ethcore::client::{EachBlockWith, TestBlockChainClient}; use parking_lot::RwLock; - use rlp::{Rlp}; + use rlp::Rlp; use std::collections::{VecDeque}; use tests::helpers::{TestIo}; use tests::snapshot::TestSnapshotService; diff --git a/ethcore/sync/src/chain/mod.rs b/ethcore/sync/src/chain/mod.rs index 1ca7fe0a7..1b40649ec 100644 --- a/ethcore/sync/src/chain/mod.rs +++ b/ethcore/sync/src/chain/mod.rs @@ -108,7 +108,7 @@ use bytes::Bytes; use rlp::{RlpStream, DecoderError}; use network::{self, PeerId, PacketId}; use network::client_version::ClientVersion; -use ethcore::client::{BlockChainClient, BlockStatus, BlockChainInfo, BlockQueueInfo}; +use client_traits::BlockChainClient; use ethcore::snapshot::RestorationStatus; use sync_io::SyncIo; use super::{WarpSync, SyncConfig}; @@ -121,7 +121,10 @@ use transactions_stats::{TransactionsStats, Stats as TransactionStats}; use types::{ BlockNumber, ids::BlockId, - transaction::UnverifiedTransaction + transaction::UnverifiedTransaction, + verification::VerificationQueueInfo as BlockQueueInfo, + blockchain_info::BlockChainInfo, + block_status::BlockStatus, }; use self::handler::SyncHandler; @@ -1373,8 +1376,8 @@ pub mod tests { use super::*; use ::SyncConfig; use super::{PeerInfo, PeerAsking}; - use ethcore::client::{BlockChainClient, EachBlockWith, TestBlockChainClient, ChainInfo}; - use client_traits::BlockInfo; + use ethcore::client::{EachBlockWith, TestBlockChainClient}; + use client_traits::{BlockInfo, BlockChainClient, ChainInfo}; use ethcore::miner::{MinerService, PendingOrdering}; use types::header::Header; diff --git a/ethcore/sync/src/chain/propagator.rs b/ethcore/sync/src/chain/propagator.rs index eb554cd5d..e347d81c8 100644 --- a/ethcore/sync/src/chain/propagator.rs +++ b/ethcore/sync/src/chain/propagator.rs @@ -335,8 +335,8 @@ impl SyncPropagator { #[cfg(test)] mod tests { - use ethcore::client::{ChainInfo, EachBlockWith, TestBlockChainClient}; - use client_traits::BlockInfo; + use client_traits::{BlockInfo, ChainInfo}; + use ethcore::client::{EachBlockWith, TestBlockChainClient}; use parking_lot::RwLock; use rlp::Rlp; use std::collections::VecDeque; diff --git a/ethcore/sync/src/chain/supplier.rs b/ethcore/sync/src/chain/supplier.rs index 34cb71617..e802cb0e0 100644 --- a/ethcore/sync/src/chain/supplier.rs +++ b/ethcore/sync/src/chain/supplier.rs @@ -376,7 +376,8 @@ mod test { use rlp::{Rlp, RlpStream}; use super::{*, super::tests::*}; use blocks::SyncHeader; - use ethcore::client::{BlockChainClient, EachBlockWith, TestBlockChainClient}; + use client_traits::BlockChainClient; + use ethcore::client::{EachBlockWith, TestBlockChainClient}; use std::str::FromStr; #[test] diff --git a/ethcore/sync/src/lib.rs b/ethcore/sync/src/lib.rs index 4f71170bc..674f0db44 100644 --- a/ethcore/sync/src/lib.rs +++ b/ethcore/sync/src/lib.rs @@ -21,6 +21,7 @@ //! https://github.com/ethereum/wiki/wiki/Ethereum-Wire-Protocol //! +extern crate client_traits; extern crate common_types as types; extern crate ethcore; extern crate ethcore_io as io; @@ -46,8 +47,8 @@ extern crate ethcore_light as light; #[cfg(test)] extern crate kvdb_memorydb; #[cfg(test)] extern crate rustc_hex; #[cfg(test)] extern crate rand_xorshift; -#[cfg(test)] extern crate client_traits; #[cfg(test)] extern crate machine; +#[cfg(test)] extern crate engine; #[macro_use] extern crate enum_primitive; diff --git a/ethcore/sync/src/sync_io.rs b/ethcore/sync/src/sync_io.rs index 73f95caf9..b7a25bafd 100644 --- a/ethcore/sync/src/sync_io.rs +++ b/ethcore/sync/src/sync_io.rs @@ -19,7 +19,7 @@ use chain::sync_packet::{PacketInfo, SyncPacket}; use network::{NetworkContext, PeerId, PacketId, Error, SessionInfo, ProtocolId}; use network::client_version::ClientVersion; use bytes::Bytes; -use ethcore::client::BlockChainClient; +use client_traits::BlockChainClient; use types::BlockNumber; use ethcore::snapshot::SnapshotService; use parking_lot::RwLock; diff --git a/ethcore/sync/src/tests/chain.rs b/ethcore/sync/src/tests/chain.rs index 1ae9922a5..0f67321df 100644 --- a/ethcore/sync/src/tests/chain.rs +++ b/ethcore/sync/src/tests/chain.rs @@ -16,7 +16,8 @@ use std::sync::Arc; use types::ids::BlockId; -use ethcore::client::{TestBlockChainClient, BlockChainClient, EachBlockWith, ChainInfo}; +use client_traits::{BlockChainClient, ChainInfo}; +use ethcore::client::{TestBlockChainClient, EachBlockWith}; use client_traits::BlockInfo; use chain::SyncState; use super::helpers::*; diff --git a/ethcore/sync/src/tests/consensus.rs b/ethcore/sync/src/tests/consensus.rs index 8f17ecb15..f991d4692 100644 --- a/ethcore/sync/src/tests/consensus.rs +++ b/ethcore/sync/src/tests/consensus.rs @@ -18,8 +18,9 @@ use std::sync::Arc; use hash::keccak; use ethereum_types::{U256, Address}; use io::{IoHandler, IoChannel}; -use ethcore::client::{ChainInfo, ClientIoMessage}; -use ethcore::engines; +use client_traits::ChainInfo; +use engine::signer; +use ethcore::client::{ClientIoMessage}; use ethcore::spec; use ethcore::miner::{self, MinerService}; use ethkey::{KeyPair, Secret}; @@ -49,8 +50,8 @@ fn authority_round() { let io_handler0: Arc> = Arc::new(TestIoHandler::new(net.peer(0).chain.clone())); let io_handler1: Arc> = Arc::new(TestIoHandler::new(net.peer(1).chain.clone())); // Push transaction to both clients. Only one of them gets lucky to produce a block. - net.peer(0).miner.set_author(miner::Author::Sealer(engines::signer::from_keypair(s0.clone()))); - net.peer(1).miner.set_author(miner::Author::Sealer(engines::signer::from_keypair(s1.clone()))); + net.peer(0).miner.set_author(miner::Author::Sealer(signer::from_keypair(s0.clone()))); + net.peer(1).miner.set_author(miner::Author::Sealer(signer::from_keypair(s1.clone()))); net.peer(0).chain.engine().register_client(Arc::downgrade(&net.peer(0).chain) as _); net.peer(1).chain.engine().register_client(Arc::downgrade(&net.peer(1).chain) as _); net.peer(0).chain.set_io_channel(IoChannel::to_handler(Arc::downgrade(&io_handler1))); diff --git a/ethcore/sync/src/tests/helpers.rs b/ethcore/sync/src/tests/helpers.rs index 135161a38..017e8b3ee 100644 --- a/ethcore/sync/src/tests/helpers.rs +++ b/ethcore/sync/src/tests/helpers.rs @@ -22,7 +22,8 @@ use bytes::Bytes; use network::{self, PeerId, ProtocolId, PacketId, SessionInfo}; use network::client_version::ClientVersion; use tests::snapshot::*; -use ethcore::client::{TestBlockChainClient, BlockChainClient, Client as EthcoreClient, +use client_traits::BlockChainClient; +use ethcore::client::{TestBlockChainClient, Client as EthcoreClient, ClientConfig, ChainNotify, NewBlocks, ChainMessageType, ClientIoMessage}; use ethcore::snapshot::SnapshotService; use ethcore::spec::{self, Spec}; diff --git a/ethcore/sync/src/tests/private.rs b/ethcore/sync/src/tests/private.rs index c62a4ae35..1d91e2124 100644 --- a/ethcore/sync/src/tests/private.rs +++ b/ethcore/sync/src/tests/private.rs @@ -19,10 +19,11 @@ use hash::keccak; use io::{IoHandler, IoChannel}; use types::transaction::{Transaction, Action}; use types::ids::BlockId; +use client_traits::BlockChainClient; +use engine::signer; use ethcore::{ CreateContractAddress, - client::{ClientIoMessage, BlockChainClient}, - engines, + client::ClientIoMessage, miner::{self, MinerService}, spec::Spec, test_helpers::push_block_with_transactions, @@ -54,8 +55,8 @@ fn send_private_transaction() { let io_handler0: Arc> = Arc::new(TestIoHandler::new(net.peer(0).chain.clone())); let io_handler1: Arc> = Arc::new(TestIoHandler::new(net.peer(1).chain.clone())); - net.peer(0).miner.set_author(miner::Author::Sealer(engines::signer::from_keypair(s0.clone()))); - net.peer(1).miner.set_author(miner::Author::Sealer(engines::signer::from_keypair(s1.clone()))); + net.peer(0).miner.set_author(miner::Author::Sealer(signer::from_keypair(s0.clone()))); + net.peer(1).miner.set_author(miner::Author::Sealer(signer::from_keypair(s1.clone()))); net.peer(0).chain.engine().register_client(Arc::downgrade(&net.peer(0).chain) as _); net.peer(1).chain.engine().register_client(Arc::downgrade(&net.peer(1).chain) as _); net.peer(0).chain.set_io_channel(IoChannel::to_handler(Arc::downgrade(&io_handler0))); diff --git a/ethcore/types/src/client_types.rs b/ethcore/types/src/client_types.rs new file mode 100644 index 000000000..ad90e0db0 --- /dev/null +++ b/ethcore/types/src/client_types.rs @@ -0,0 +1,49 @@ +// Copyright 2015-2019 Parity Technologies (UK) Ltd. +// This file is part of Parity Ethereum. + +// Parity Ethereum is free software: you can redistribute it and/or modify +// 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, +// 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 . + +//! Client related types. + +use std::{ + fmt::{Display, Formatter, Error as FmtError}, + time::Duration, +}; + +/// Operating mode for the client. +#[derive(Debug, Eq, PartialEq, Clone)] +pub enum Mode { + /// Always on. + Active, + /// Goes offline after client is inactive for some (given) time, but + /// comes back online after a while of inactivity. + Passive(Duration, Duration), + /// Goes offline after client is inactive for some (given) time and + /// stays inactive. + Dark(Duration), + /// Always off. + Off, +} + +impl Display for Mode { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { + match *self { + Mode::Active => write!(f, "active"), + Mode::Passive(..) => write!(f, "passive"), + Mode::Dark(..) => write!(f, "dark"), + Mode::Off => write!(f, "offline"), + } + } +} + diff --git a/ethcore/types/src/engines/machine.rs b/ethcore/types/src/engines/machine.rs index be0a5ef9c..db952aebc 100644 --- a/ethcore/types/src/engines/machine.rs +++ b/ethcore/types/src/engines/machine.rs @@ -16,9 +16,14 @@ //! State machine types -use ethereum_types::Address; +use ethereum_types::{Address, U256}; +use bytes::Bytes; -use crate::receipt; +use crate::{ + log_entry::LogEntry, + receipt, + state_diff::StateDiff, +}; /// Type alias for a function we can make calls through synchronously. /// Returns the call result and state proof for each call. @@ -44,3 +49,47 @@ pub struct AuxiliaryData<'a> { /// The block receipts. pub receipts: Option<&'a [receipt::Receipt]>, } + + +/// Transaction execution receipt. +#[derive(Debug, PartialEq, Clone)] +pub struct Executed { + /// True if the outer call/create resulted in an exceptional exit. + pub exception: Option, + + /// Gas paid up front for execution of transaction. + pub gas: U256, + + /// Gas used during execution of transaction. + pub gas_used: U256, + + /// Gas refunded after the execution of transaction. + /// To get gas that was required up front, add `refunded` and `gas_used`. + pub refunded: U256, + + /// Cumulative gas used in current block so far. + /// + /// `cumulative_gas_used = gas_used(t0) + gas_used(t1) + ... gas_used(tn)` + /// + /// where `tn` is current transaction. + pub cumulative_gas_used: U256, + + /// Vector of logs generated by transaction. + pub logs: Vec, + + /// Addresses of contracts created during execution of transaction. + /// Ordered from earliest creation. + /// + /// eg. sender creates contract A and A in constructor creates contract B + /// + /// B creation ends first, and it will be the first element of the vector. + pub contracts_created: Vec
, + /// Transaction output. + pub output: Bytes, + /// The trace of this transaction. + pub trace: Vec, + /// The VM trace of this transaction. + pub vm_trace: Option, + /// The state diff, if we traced it. + pub state_diff: Option, +} diff --git a/ethcore/types/src/engines/mod.rs b/ethcore/types/src/engines/mod.rs index ac8a20d29..3a1564b9a 100644 --- a/ethcore/types/src/engines/mod.rs +++ b/ethcore/types/src/engines/mod.rs @@ -17,6 +17,7 @@ //! Engine-specific types. use ethereum_types::{Address, H256}; +use bytes::Bytes; use ethjson; use crate::BlockNumber; @@ -25,6 +26,15 @@ pub mod epoch; pub mod params; pub mod machine; +/// Seal type. +#[derive(Debug, PartialEq, Eq)] +pub enum Seal { + /// Regular block seal; should be part of the blockchain. + Regular(Vec), + /// Engine does not generate seal for this block right now. + None, +} + /// The type of sealing the engine is currently able to perform. #[derive(Debug, PartialEq, Eq)] pub enum SealingState { diff --git a/ethcore/types/src/lib.rs b/ethcore/types/src/lib.rs index d209b3d25..99153a205 100644 --- a/ethcore/types/src/lib.rs +++ b/ethcore/types/src/lib.rs @@ -64,6 +64,7 @@ pub mod block; pub mod block_status; pub mod blockchain_info; pub mod call_analytics; +pub mod client_types; pub mod encoded; pub mod engines; pub mod errors; @@ -75,12 +76,12 @@ pub mod pruning_info; pub mod receipt; pub mod restoration_status; pub mod security_level; -pub mod snapshot_manifest; +pub mod snapshot; pub mod state_diff; pub mod trace_filter; pub mod transaction; pub mod tree_route; -pub mod verification_queue_info; +pub mod verification; /// Type for block number. pub type BlockNumber = u64; diff --git a/ethcore/types/src/snapshot_manifest.rs b/ethcore/types/src/snapshot.rs similarity index 57% rename from ethcore/types/src/snapshot_manifest.rs rename to ethcore/types/src/snapshot.rs index 8ed19fcfc..dd58279e2 100644 --- a/ethcore/types/src/snapshot_manifest.rs +++ b/ethcore/types/src/snapshot.rs @@ -14,12 +14,55 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . -//! Snapshot manifest type definition +//! Snapshot type definitions + +use std::sync::atomic::{AtomicBool, AtomicUsize, AtomicU64, Ordering}; use ethereum_types::H256; use rlp::{Rlp, RlpStream, DecoderError}; use bytes::Bytes; +/// A progress indicator for snapshots. +#[derive(Debug, Default)] +pub struct Progress { + /// Number of accounts processed so far + pub accounts: AtomicUsize, + /// Number of blocks processed so far + pub blocks: AtomicUsize, + /// Size in bytes of a all compressed chunks processed so far + pub size: AtomicU64, + /// Signals that the snapshotting process is completed + pub done: AtomicBool, + /// Signal snapshotting process to abort + pub abort: AtomicBool, +} + +impl Progress { + /// Reset the progress. + pub fn reset(&self) { + self.accounts.store(0, Ordering::Release); + self.blocks.store(0, Ordering::Release); + self.size.store(0, Ordering::Release); + self.abort.store(false, Ordering::Release); + + // atomic fence here to ensure the others are written first? + // logs might very rarely get polluted if not. + self.done.store(false, Ordering::Release); + } + + /// Get the number of accounts snapshotted thus far. + pub fn accounts(&self) -> usize { self.accounts.load(Ordering::Acquire) } + + /// Get the number of blocks snapshotted thus far. + pub fn blocks(&self) -> usize { self.blocks.load(Ordering::Acquire) } + + /// Get the written size of the snapshot in bytes. + pub fn size(&self) -> u64 { self.size.load(Ordering::Acquire) } + + /// Whether the snapshot is complete. + pub fn done(&self) -> bool { self.done.load(Ordering::Acquire) } +} + /// Manifest data. #[derive(Debug, Clone, PartialEq, Eq)] pub struct ManifestData { @@ -67,12 +110,15 @@ impl ManifestData { let block_hash: H256 = decoder.val_at(start + 4)?; Ok(ManifestData { - version: version, - state_hashes: state_hashes, - block_hashes: block_hashes, - state_root: state_root, - block_number: block_number, - block_hash: block_hash, + version, + state_hashes, + block_hashes, + state_root, + block_number, + block_hash, }) } } + +/// A sink for produced chunks. +pub type ChunkSink<'a> = dyn FnMut(&[u8]) -> std::io::Result<()> + 'a; diff --git a/ethcore/types/src/verification_queue_info.rs b/ethcore/types/src/verification.rs similarity index 67% rename from ethcore/types/src/verification_queue_info.rs rename to ethcore/types/src/verification.rs index b89cfe20c..dedf45492 100644 --- a/ethcore/types/src/verification_queue_info.rs +++ b/ethcore/types/src/verification.rs @@ -14,7 +14,14 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . -//! Verification queue info types +//! Verification types + +use crate::{ + header::Header, + transaction::UnverifiedTransaction, +}; +use bytes::Bytes; +use parity_util_mem::MallocSizeOf; /// Verification queue status #[derive(Debug, Clone)] @@ -48,3 +55,38 @@ impl VerificationQueueInfo { self.unverified_queue_size + self.verified_queue_size + self.verifying_queue_size == 0 } } + +/// An unverified block. +#[derive(PartialEq, Debug, MallocSizeOf)] +pub struct Unverified { + /// Unverified block header. + pub header: Header, + /// Unverified block transactions. + pub transactions: Vec, + /// Unverified block uncles. + pub uncles: Vec
, + /// Raw block bytes. + pub bytes: Bytes, +} + +impl Unverified { + /// Create an `Unverified` from raw bytes. + pub fn from_rlp(bytes: Bytes) -> Result { + use rlp::Rlp; + let (header, transactions, uncles) = { + let rlp = Rlp::new(&bytes); + let header = rlp.val_at(0)?; + let transactions = rlp.list_at(1)?; + let uncles = rlp.list_at(2)?; + (header, transactions, uncles) + }; + + Ok(Unverified { + header, + transactions, + uncles, + bytes, + }) + } +} + diff --git a/ipfs/Cargo.toml b/ipfs/Cargo.toml index 3df59d012..44902200e 100644 --- a/ipfs/Cargo.toml +++ b/ipfs/Cargo.toml @@ -6,6 +6,7 @@ license = "GPL-3.0" authors = ["Parity Technologies "] [dependencies] +client-traits = { path = "../ethcore/client-traits" } common-types = { path = "../ethcore/types" } ethcore = { path = "../ethcore" } parity-bytes = "0.1" diff --git a/ipfs/src/lib.rs b/ipfs/src/lib.rs index 635fd4c76..40ff2bd18 100644 --- a/ipfs/src/lib.rs +++ b/ipfs/src/lib.rs @@ -19,6 +19,7 @@ extern crate cid; extern crate unicase; extern crate rlp; +extern crate client_traits; extern crate common_types; extern crate ethcore; extern crate parity_bytes as bytes; @@ -35,7 +36,7 @@ use std::net::{SocketAddr, IpAddr}; use core::futures::future::{self, FutureResult}; use core::futures::{self, Future}; -use ethcore::client::BlockChainClient; +use client_traits::BlockChainClient; use http::hyper::{self, server, Method, StatusCode, Body, header::{self, HeaderValue}, }; diff --git a/miner/src/pool/local_transactions.rs b/miner/src/pool/local_transactions.rs index 346877d03..a83af5b72 100644 --- a/miner/src/pool/local_transactions.rs +++ b/miner/src/pool/local_transactions.rs @@ -66,7 +66,7 @@ pub struct LocalTransactionsList { max_old: usize, transactions: LinkedHashMap, pending: usize, - in_chain: Option bool + Send + Sync>>, + in_chain: Option bool + Send + Sync>>, } impl fmt::Debug for LocalTransactionsList { diff --git a/parity/account_utils.rs b/parity/account_utils.rs index 88a8dcfd4..9c380c2f5 100644 --- a/parity/account_utils.rs +++ b/parity/account_utils.rs @@ -133,7 +133,7 @@ mod accounts { } pub fn miner_author(spec: &SpecType, dirs: &Directories, account_provider: &Arc, engine_signer: Address, passwords: &[Password]) -> Result, String> { - use ethcore::engines::EngineSigner; + use engine::signer::EngineSigner; // Check if engine signer exists if !account_provider.has_account(engine_signer) { diff --git a/parity/blockchain.rs b/parity/blockchain.rs index 7d19333be..d5e666768 100644 --- a/parity/blockchain.rs +++ b/parity/blockchain.rs @@ -26,13 +26,12 @@ use hash::{keccak, KECCAK_NULL_RLP}; use ethereum_types::{U256, H256, Address}; use bytes::ToPretty; use rlp::PayloadInfo; -use client_traits::BlockInfo; -use ethcore::client::{ - Mode, DatabaseCompactionProfile, VMType, Nonce, Balance, BlockChainClient, ImportBlock, BlockChainReset +use client_traits::{BlockInfo, BlockChainReset, Nonce, Balance, BlockChainClient, ImportBlock}; +use ethcore::{ + client::{DatabaseCompactionProfile, VMType}, + miner::Miner, + verification::queue::VerifierSettings, }; -use ethcore::miner::Miner; -use ethcore::verification::queue::VerifierSettings; -use ethcore::verification::queue::kind::blocks::Unverified; use ethcore_service::ClientService; use cache::CacheConfig; use informant::{Informant, FullNodeInformantData, MillisecondDuration}; @@ -45,7 +44,9 @@ use db; use ansi_term::Colour; use types::{ ids::BlockId, - errors::{ImportError, EthcoreError} + errors::{ImportError, EthcoreError}, + client_types::Mode, + verification::Unverified, }; #[derive(Debug, PartialEq)] diff --git a/parity/helpers.rs b/parity/helpers.rs index 1c9494e3d..ebcdf87bc 100644 --- a/parity/helpers.rs +++ b/parity/helpers.rs @@ -21,7 +21,7 @@ use std::fs::File; use std::collections::HashSet; use ethereum_types::{U256, Address}; use journaldb::Algorithm; -use ethcore::client::{Mode, VMType, DatabaseCompactionProfile, ClientConfig, VerifierType}; +use ethcore::client::{VMType, DatabaseCompactionProfile, ClientConfig, VerifierType}; use ethcore::miner::{PendingSet, Penalization}; use miner::pool::PrioritizationStrategy; use cache::CacheConfig; @@ -32,7 +32,10 @@ use sync::{validate_node_url, self}; use db::migrate; use path; use ethkey::Password; -use types::ids::BlockId; +use types::{ + ids::BlockId, + client_types::Mode, +}; pub fn to_duration(s: &str) -> Result { to_seconds(s).map(Duration::from_secs) @@ -348,10 +351,12 @@ mod tests { use std::collections::HashSet; use tempdir::TempDir; use ethereum_types::U256; - use ethcore::client::Mode; use ethcore::miner::PendingSet; use ethkey::Password; - use types::ids::BlockId; + use types::{ + ids::BlockId, + client_types::Mode, + }; use super::{to_duration, to_mode, to_block_id, to_u256, to_pending_set, to_address, to_addresses, to_price, geth_ipc_path, to_bootnodes, join_set, password_from_file}; #[test] diff --git a/parity/informant.rs b/parity/informant.rs index cd2690b23..683c67c4b 100644 --- a/parity/informant.rs +++ b/parity/informant.rs @@ -24,13 +24,14 @@ use std::time::{Instant, Duration}; use atty; use ethcore::client::{ - ChainInfo, BlockChainInfo, BlockChainClient, - BlockQueueInfo, ChainNotify, NewBlocks, ClientReport, Client, ClientIoMessage + ChainNotify, NewBlocks, ClientReport, Client, ClientIoMessage }; -use client_traits::BlockInfo; +use client_traits::{BlockInfo, ChainInfo, BlockChainClient}; use types::{ BlockNumber, ids::BlockId, + blockchain_info::BlockChainInfo, + verification::VerificationQueueInfo as BlockQueueInfo, }; use ethcore::snapshot::{RestorationStatus, SnapshotService as SS}; use ethcore::snapshot::service::Service as SnapshotService; diff --git a/parity/ipfs.rs b/parity/ipfs.rs index 0923a1e7d..f8062f52a 100644 --- a/parity/ipfs.rs +++ b/parity/ipfs.rs @@ -17,7 +17,7 @@ use std::sync::Arc; use parity_ipfs_api::{self, AccessControlAllowOrigin, Host, Listening}; use parity_ipfs_api::error::ServerError; -use ethcore::client::BlockChainClient; +use client_traits::BlockChainClient; #[derive(Debug, PartialEq, Clone)] pub struct Configuration { diff --git a/parity/lib.rs b/parity/lib.rs index 2e5e5c1b8..86abde9da 100644 --- a/parity/lib.rs +++ b/parity/lib.rs @@ -44,6 +44,7 @@ extern crate cli_signer; extern crate client_traits; extern crate common_types as types; +extern crate engine; extern crate ethcore; extern crate ethcore_call_contract as call_contract; extern crate ethcore_db; diff --git a/parity/light_helpers/epoch_fetch.rs b/parity/light_helpers/epoch_fetch.rs index 95eea5858..f73aec57d 100644 --- a/parity/light_helpers/epoch_fetch.rs +++ b/parity/light_helpers/epoch_fetch.rs @@ -16,11 +16,13 @@ use std::sync::{Arc, Weak}; -use ethcore::engines::{Engine, StateDependentProof}; +use engine::{Engine, StateDependentProof}; use sync::{LightSync, LightNetworkDispatcher}; -use types::encoded; -use types::header::Header; -use types::receipt::Receipt; +use types::{ + header::Header, + encoded, + receipt::Receipt, +}; use futures::{future, Future}; use futures::future::Either; diff --git a/parity/modules.rs b/parity/modules.rs index 8c86cda9b..f8607b827 100644 --- a/parity/modules.rs +++ b/parity/modules.rs @@ -16,7 +16,7 @@ use std::sync::{Arc, mpsc}; -use ethcore::client::BlockChainClient; +use client_traits::BlockChainClient; use sync::{self, SyncConfig, NetworkConfiguration, Params, ConnectionFilter}; use ethcore::snapshot::SnapshotService; use light::Provider; diff --git a/parity/params.rs b/parity/params.rs index 65b8d77ee..e4d1e7548 100644 --- a/parity/params.rs +++ b/parity/params.rs @@ -18,7 +18,6 @@ use std::collections::HashSet; use std::time::Duration; use std::{str, fs, fmt}; -use ethcore::client::Mode; use ethcore::spec::{Spec, SpecParams, self}; use ethereum_types::{U256, Address}; use parity_runtime::Executor; @@ -28,6 +27,7 @@ use miner::gas_pricer::GasPricer; use miner::gas_price_calibrator::{GasPriceCalibratorOptions, GasPriceCalibrator}; use parity_version::version_data; use user_defaults::UserDefaults; +use types::client_types::Mode; #[derive(Debug, PartialEq)] pub enum SpecType { diff --git a/parity/rpc_apis.rs b/parity/rpc_apis.rs index b3aec40dc..0b9d4d9f5 100644 --- a/parity/rpc_apis.rs +++ b/parity/rpc_apis.rs @@ -25,7 +25,7 @@ use account_utils::{self, AccountProvider}; use ethcore::client::Client; use ethcore::miner::Miner; use ethcore::snapshot::SnapshotService; -use ethcore::client::BlockChainClient; +use client_traits::BlockChainClient; use sync::SyncState; use ethcore_logger::RotatingLogger; use ethcore_private_tx::Provider as PrivateTransactionManager; diff --git a/parity/run.rs b/parity/run.rs index 6f1c441f1..82ae9694f 100644 --- a/parity/run.rs +++ b/parity/run.rs @@ -22,8 +22,8 @@ use std::thread; use ansi_term::Colour; use bytes::Bytes; use call_contract::CallContract; -use client_traits::BlockInfo; -use ethcore::client::{Client, Mode, DatabaseCompactionProfile, VMType, BlockChainClient}; +use client_traits::{BlockInfo, BlockChainClient}; +use ethcore::client::{Client, DatabaseCompactionProfile, VMType}; use ethcore::miner::{self, stratum, Miner, MinerService, MinerOptions}; use ethcore::snapshot::{self, SnapshotConfiguration}; use ethcore::spec::{SpecParams, OptimizeFor}; @@ -41,7 +41,10 @@ use miner::work_notify::WorkPoster; use node_filter::NodeFilter; use parity_runtime::Runtime; use sync::{self, SyncConfig, PrivateTxHandler}; -use types::ids::BlockId; +use types::{ + client_types::Mode, + ids::BlockId, +}; use parity_rpc::{ Origin, Metadata, NetworkSettings, informant, PubSubSession, FutureResult, FutureResponse, FutureOutput }; diff --git a/parity/snapshot.rs b/parity/snapshot.rs index c1d2a77e3..19cfb4897 100644 --- a/parity/snapshot.rs +++ b/parity/snapshot.rs @@ -21,13 +21,17 @@ use std::path::{Path, PathBuf}; use std::sync::Arc; use hash::keccak; -use ethcore::snapshot::{Progress, RestorationStatus, SnapshotConfiguration, SnapshotService as SS}; +use ethcore::snapshot::{RestorationStatus, SnapshotConfiguration, SnapshotService as SS}; use ethcore::snapshot::io::{SnapshotReader, PackedReader, PackedWriter}; use ethcore::snapshot::service::Service as SnapshotService; -use ethcore::client::{Mode, DatabaseCompactionProfile, VMType}; +use ethcore::client::{DatabaseCompactionProfile, VMType}; use ethcore::miner::Miner; use ethcore_service::ClientService; -use types::ids::BlockId; +use types::{ + ids::BlockId, + snapshot::Progress, + client_types::Mode, +}; use cache::CacheConfig; use params::{SpecType, Pruning, Switch, tracing_switch_to_bool, fatdb_switch_to_bool}; diff --git a/parity/user_defaults.rs b/parity/user_defaults.rs index bdd5d9efb..34e68dd82 100644 --- a/parity/user_defaults.rs +++ b/parity/user_defaults.rs @@ -22,7 +22,7 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde_json::de::from_reader; use serde_json::ser::to_string; use journaldb::Algorithm; -use ethcore::client::{Mode as ClientMode}; +use types::client_types::Mode as ClientMode; #[derive(Clone)] pub struct Seconds(Duration); diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index fc5baa868..507b821ef 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -35,7 +35,9 @@ jsonrpc-ws-server = "12.0.0" jsonrpc-ipc-server = "12.0.0" jsonrpc-pubsub = "12.0.0" +client-traits = { path = "../ethcore/client-traits" } common-types = { path = "../ethcore/types" } +engine = { path = "../ethcore/engine" } ethash = { path = "../ethash" } ethcore = { path = "../ethcore", features = ["test-helpers"] } ethcore-accounts = { path = "../accounts", optional = true } diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index 37749cf43..897df8d96 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -61,7 +61,9 @@ extern crate jsonrpc_http_server as http; extern crate jsonrpc_ipc_server as ipc; extern crate jsonrpc_pubsub; +extern crate client_traits; extern crate common_types as types; +extern crate engine; extern crate ethash; extern crate ethcore; extern crate fastmap; @@ -121,8 +123,6 @@ extern crate fake_fetch; #[cfg(test)] extern crate ethcore_io as io; -#[cfg(test)] -extern crate client_traits; pub extern crate jsonrpc_ws_server as ws; diff --git a/rpc/src/v1/helpers/block_import.rs b/rpc/src/v1/helpers/block_import.rs index 8e8dba28f..a062e1178 100644 --- a/rpc/src/v1/helpers/block_import.rs +++ b/rpc/src/v1/helpers/block_import.rs @@ -16,7 +16,7 @@ //! Block import analysis functions. -use ethcore::client::BlockQueueInfo; +use types::verification::VerificationQueueInfo as BlockQueueInfo; use sync::SyncState; /// Check if client is during major sync or during block import and allows defining whether 'waiting for peers' should diff --git a/rpc/src/v1/helpers/dispatch/full.rs b/rpc/src/v1/helpers/dispatch/full.rs index d958416cb..8c23f7208 100644 --- a/rpc/src/v1/helpers/dispatch/full.rs +++ b/rpc/src/v1/helpers/dispatch/full.rs @@ -16,7 +16,7 @@ use std::sync::Arc; -use ethcore::client::BlockChainClient; +use client_traits::BlockChainClient; use ethcore::miner::{self, MinerService}; use ethereum_types::{H256, U256, Address}; use types::transaction::{SignedTransaction, PendingTransaction}; diff --git a/rpc/src/v1/helpers/dispatch/mod.rs b/rpc/src/v1/helpers/dispatch/mod.rs index 3f247f0c6..fa8238508 100644 --- a/rpc/src/v1/helpers/dispatch/mod.rs +++ b/rpc/src/v1/helpers/dispatch/mod.rs @@ -75,7 +75,7 @@ use std::ops::Deref; use std::sync::Arc; use bytes::Bytes; -use ethcore::client::BlockChainClient; +use client_traits::BlockChainClient; use ethcore::miner::MinerService; use ethereum_types::{H520, H256, U256, Address}; use ethkey::{Password, Signature}; diff --git a/rpc/src/v1/helpers/engine_signer.rs b/rpc/src/v1/helpers/engine_signer.rs index 4cc3608cb..fd40dc95e 100644 --- a/rpc/src/v1/helpers/engine_signer.rs +++ b/rpc/src/v1/helpers/engine_signer.rs @@ -33,7 +33,7 @@ impl EngineSigner { } } -impl ethcore::engines::EngineSigner for EngineSigner { +impl engine::signer::EngineSigner for EngineSigner { fn sign(&self, message: ethkey::Message) -> Result { match self.accounts.sign(self.address, Some(self.password.clone()), message) { Ok(ok) => Ok(ok), diff --git a/rpc/src/v1/helpers/errors.rs b/rpc/src/v1/helpers/errors.rs index a9f8ab8fc..791d7e3b9 100644 --- a/rpc/src/v1/helpers/errors.rs +++ b/rpc/src/v1/helpers/errors.rs @@ -24,7 +24,7 @@ use types::transaction::Error as TransactionError; use ethcore_private_tx::Error as PrivateTransactionError; use vm::Error as VMError; use light::on_demand::error::{Error as OnDemandError}; -use ethcore::client::BlockChainClient; +use client_traits::BlockChainClient; use types::{ ids::BlockId, blockchain_info::BlockChainInfo, diff --git a/rpc/src/v1/helpers/light_fetch.rs b/rpc/src/v1/helpers/light_fetch.rs index 2a78f46f4..f2e67f86c 100644 --- a/rpc/src/v1/helpers/light_fetch.rs +++ b/rpc/src/v1/helpers/light_fetch.rs @@ -741,7 +741,7 @@ where tx: EthTransaction, hdr: encoded::Header, env_info: ::vm::EnvInfo, - engine: Arc<::ethcore::engines::Engine>, + engine: Arc, on_demand: Arc, sync: Arc, } diff --git a/rpc/src/v1/impls/debug.rs b/rpc/src/v1/impls/debug.rs index e46dd628d..64e2acac6 100644 --- a/rpc/src/v1/impls/debug.rs +++ b/rpc/src/v1/impls/debug.rs @@ -18,7 +18,7 @@ use std::sync::Arc; -use ethcore::client::BlockChainClient; +use client_traits::BlockChainClient; use types::header::Header; use types::transaction::LocalizedTransaction; diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 0511c5241..f50d79b5a 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -24,8 +24,9 @@ use rlp::Rlp; use ethereum_types::{Address, H64, H160, H256, U64, U256, BigEndianHash}; use parking_lot::Mutex; +use client_traits::{BlockChainClient, StateClient, ProvingBlockChainClient, StateOrBlock}; use ethash::{self, SeedHashCompute}; -use ethcore::client::{BlockChainClient, StateOrBlock, StateClient, StateInfo, Call, EngineInfo, ProvingBlockChainClient}; +use ethcore::client::{StateInfo, Call, EngineInfo}; use ethcore::miner::{self, MinerService}; use ethcore::snapshot::SnapshotService; use hash::keccak; diff --git a/rpc/src/v1/impls/eth_filter.rs b/rpc/src/v1/impls/eth_filter.rs index b205dde57..8bab90058 100644 --- a/rpc/src/v1/impls/eth_filter.rs +++ b/rpc/src/v1/impls/eth_filter.rs @@ -19,7 +19,7 @@ use std::sync::Arc; use std::collections::{BTreeSet, VecDeque}; -use ethcore::client::BlockChainClient; +use client_traits::BlockChainClient; use ethcore::miner::{self, MinerService}; use ethereum_types::{H256, U256}; use parking_lot::Mutex; diff --git a/rpc/src/v1/impls/eth_pubsub.rs b/rpc/src/v1/impls/eth_pubsub.rs index fd557b096..d9fe2329e 100644 --- a/rpc/src/v1/impls/eth_pubsub.rs +++ b/rpc/src/v1/impls/eth_pubsub.rs @@ -31,7 +31,8 @@ use v1::traits::EthPubSub; use v1::types::{pubsub, RichHeader, Log}; use sync::{SyncState, Notification}; -use ethcore::client::{BlockChainClient, ChainNotify, NewBlocks, ChainRouteType}; +use ethcore::client::{ChainNotify, NewBlocks, ChainRouteType}; +use client_traits::BlockChainClient; use ethereum_types::H256; use light::cache::Cache; use light::client::{LightChainClient, LightChainNotify}; diff --git a/rpc/src/v1/impls/parity.rs b/rpc/src/v1/impls/parity.rs index 305205644..75e69dcbf 100644 --- a/rpc/src/v1/impls/parity.rs +++ b/rpc/src/v1/impls/parity.rs @@ -20,7 +20,8 @@ use std::collections::BTreeMap; use crypto::DEFAULT_MAC; use ethereum_types::{H64, H160, H256, H512, U64, U256}; -use ethcore::client::{BlockChainClient, StateClient, Call}; +use ethcore::client::Call; +use client_traits::{BlockChainClient, StateClient}; use ethcore::miner::{self, MinerService, FilterOptions}; use ethcore::snapshot::{SnapshotService, RestorationStatus}; use account_state::state::StateInfo; @@ -30,7 +31,10 @@ use ethstore::random_phrase; use jsonrpc_core::futures::future; use jsonrpc_core::{BoxFuture, Result}; use sync::{SyncProvider, ManageNetwork}; -use types::ids::BlockId; +use types::{ + ids::BlockId, + verification::Unverified, +}; use updater::{Service as UpdateService}; use version::version_data; @@ -48,7 +52,6 @@ use v1::types::{ block_number_to_id }; use Host; -use ethcore::verification::queue::kind::blocks::Unverified; /// Parity implementation. pub struct ParityClient { diff --git a/rpc/src/v1/impls/parity_set.rs b/rpc/src/v1/impls/parity_set.rs index b7cef6c6b..25d06ed85 100644 --- a/rpc/src/v1/impls/parity_set.rs +++ b/rpc/src/v1/impls/parity_set.rs @@ -19,7 +19,8 @@ use std::io; use std::sync::Arc; use std::time::Duration; -use ethcore::client::{BlockChainClient, Mode}; +use client_traits::BlockChainClient; +use types::client_types::Mode; use ethcore::miner::{self, MinerService}; use ethereum_types::{H160, H256, U256}; use ethkey; @@ -161,7 +162,7 @@ impl ParitySet for ParitySetClient where fn set_engine_signer_secret(&self, secret: H256) -> Result { let keypair = ethkey::KeyPair::from_secret(secret.into()).map_err(|e| errors::account("Invalid secret", e))?; - self.miner.set_author(miner::Author::Sealer(ethcore::engines::signer::from_keypair(keypair))); + self.miner.set_author(miner::Author::Sealer(engine::signer::from_keypair(keypair))); Ok(true) } diff --git a/rpc/src/v1/impls/traces.rs b/rpc/src/v1/impls/traces.rs index b279c127d..4d0ccc1a9 100644 --- a/rpc/src/v1/impls/traces.rs +++ b/rpc/src/v1/impls/traces.rs @@ -18,7 +18,8 @@ use std::sync::Arc; -use ethcore::client::{BlockChainClient, StateClient, StateInfo, Call}; +use ethcore::client::{StateInfo, Call}; +use client_traits::{BlockChainClient, StateClient}; use ethereum_types::H256; use rlp::Rlp; use types::{ diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index c1981ce01..23aedbe50 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -19,12 +19,12 @@ use std::env; use std::sync::Arc; use accounts::AccountProvider; -use ethcore::client::{BlockChainClient, Client, ClientConfig, ChainInfo, ImportBlock}; +use client_traits::{BlockChainClient, ChainInfo, ImportBlock}; +use ethcore::client::{Client, ClientConfig}; use ethcore::miner::Miner; use ethcore::spec::{Genesis, Spec, self}; use ethcore::test_helpers; use ethcore::verification::VerifierType; -use ethcore::verification::queue::kind::blocks::Unverified; use ethereum_types::{Address, H256, U256}; use ethjson::blockchain::BlockChain; use ethjson::spec::ForkSpec; @@ -32,7 +32,10 @@ use io::IoChannel; use miner::external::ExternalMiner; use parity_runtime::Runtime; use parking_lot::Mutex; -use types::ids::BlockId; +use types::{ + ids::BlockId, + verification::Unverified, +}; use jsonrpc_core::IoHandler; use v1::helpers::dispatch::{self, FullDispatcher}; @@ -114,7 +117,7 @@ impl EthTester { let runtime = Runtime::with_thread_count(1); let account_provider = account_provider(); let ap = account_provider.clone(); - let accounts = Arc::new(move || ap.accounts().unwrap_or_default()) as _; + let accounts = Arc::new(move || ap.accounts().unwrap_or_default()) as _; let miner_service = miner_service(&spec); let snapshot_service = snapshot_service(); @@ -215,8 +218,7 @@ fn eth_get_proof() { }"#; let res_latest = r#","address":"0xaaaf5374fce5edbc8e2a8697c15331677e6ebaaa","balance":"0x9","codeHash":"0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470","nonce":"0x0","storageHash":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","storageProof":[]},"id":1}"#.to_owned(); - assert!(tester.handler.handle_request_sync(req_latest).unwrap().to_string().ends_with(res_latest.as_str())); - + assert!(tester.handler.handle_request_sync(req_latest).unwrap().to_string().ends_with(res_latest.as_str())); // non-existant account let req_new_acc = r#"{ "jsonrpc": "2.0", @@ -226,7 +228,7 @@ fn eth_get_proof() { }"#; let res_new_acc = r#","address":"0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","balance":"0x0","codeHash":"0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470","nonce":"0x0","storageHash":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","storageProof":[]},"id":3}"#.to_owned(); - assert!(tester.handler.handle_request_sync(req_new_acc).unwrap().to_string().ends_with(res_new_acc.as_str())); + assert!(tester.handler.handle_request_sync(req_new_acc).unwrap().to_string().ends_with(res_new_acc.as_str())); } #[test] diff --git a/rpc/src/v1/tests/helpers/miner_service.rs b/rpc/src/v1/tests/helpers/miner_service.rs index 5f7d3eed4..8bff84dc3 100644 --- a/rpc/src/v1/tests/helpers/miner_service.rs +++ b/rpc/src/v1/tests/helpers/miner_service.rs @@ -20,15 +20,15 @@ use std::sync::Arc; use std::collections::{BTreeMap, BTreeSet, HashMap}; use bytes::Bytes; +use client_traits::{Nonce, StateClient}; +use engine::{Engine, signer::EngineSigner}; use ethcore::block::SealedBlock; -use ethcore::client::{Nonce, PrepareOpenBlock, StateClient, EngineInfo, TestState}; -use ethcore::engines::{Engine, signer::EngineSigner}; +use ethcore::client::{PrepareOpenBlock, EngineInfo, TestState}; use ethcore::miner::{self, MinerService, AuthoringParams, FilterOptions}; use ethereum_types::{H256, U256, Address}; use miner::pool::local_transactions::Status as LocalTransactionStatus; use miner::pool::{verifier, VerifiedTransaction, QueueStatus}; use parking_lot::{RwLock, Mutex}; -use types::transaction::{self, UnverifiedTransaction, SignedTransaction, PendingTransaction}; use txpool; use types::{ BlockNumber, @@ -37,6 +37,7 @@ use types::{ errors::EthcoreError as Error, ids::BlockId, receipt::RichReceipt, + transaction::{self, UnverifiedTransaction, SignedTransaction, PendingTransaction}, }; /// Test miner service. diff --git a/rpc/src/v1/tests/mocked/eth.rs b/rpc/src/v1/tests/mocked/eth.rs index 34925ddce..7477eec69 100644 --- a/rpc/src/v1/tests/mocked/eth.rs +++ b/rpc/src/v1/tests/mocked/eth.rs @@ -20,7 +20,8 @@ use std::sync::Arc; use std::time::{Instant, Duration, SystemTime, UNIX_EPOCH}; use accounts::AccountProvider; -use ethcore::client::{BlockChainClient, EachBlockWith, TestBlockChainClient}; +use client_traits::BlockChainClient; +use ethcore::client::{EachBlockWith, TestBlockChainClient}; use ethcore::miner::{self, MinerService}; use ethereum_types::{H160, H256, U256, Address, Bloom}; use machine::executed::Executed; diff --git a/rpc/src/v1/types/histogram.rs b/rpc/src/v1/types/histogram.rs index d7f14c514..41ac87301 100644 --- a/rpc/src/v1/types/histogram.rs +++ b/rpc/src/v1/types/histogram.rs @@ -17,6 +17,7 @@ //! Gas prices histogram. use ethereum_types::U256; +use stats; /// Values of RPC settings. #[derive(Serialize, Deserialize)] @@ -25,12 +26,12 @@ use ethereum_types::U256; pub struct Histogram { /// Gas prices for bucket edges. pub bucket_bounds: Vec, - /// Transacion counts for each bucket. + /// Transaction counts for each bucket. pub counts: Vec, } -impl From<::stats::Histogram<::ethereum_types::U256>> for Histogram { - fn from(h: ::stats::Histogram<::ethereum_types::U256>) -> Self { +impl From> for Histogram { + fn from(h: stats::Histogram) -> Self { Histogram { bucket_bounds: h.bucket_bounds.into_iter().map(Into::into).collect(), counts: h.counts diff --git a/rpc/src/v1/types/trace_filter.rs b/rpc/src/v1/types/trace_filter.rs index 42bad70e8..4f11308c5 100644 --- a/rpc/src/v1/types/trace_filter.rs +++ b/rpc/src/v1/types/trace_filter.rs @@ -16,7 +16,6 @@ //! Trace filter deserialization. -use ethcore::client; use ethereum_types::H160; use types::{ ids::BlockId, diff --git a/secret-store/Cargo.toml b/secret-store/Cargo.toml index 06f13663f..76a0df44a 100644 --- a/secret-store/Cargo.toml +++ b/secret-store/Cargo.toml @@ -7,6 +7,7 @@ authors = ["Parity Technologies "] [dependencies] byteorder = "1.0" +client-traits = { path = "../ethcore/client-traits" } common-types = { path = "../ethcore/types" } ethabi = "8.0" ethabi-contract = "8.0" diff --git a/secret-store/src/helpers.rs b/secret-store/src/helpers.rs index 3dfe7ae8b..cdb235ac9 100644 --- a/secret-store/src/helpers.rs +++ b/secret-store/src/helpers.rs @@ -14,7 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . -use ethcore::client::{Client, BlockChainClient}; +use ethcore::client::Client; +use client_traits::BlockChainClient; use common_types::ids::BlockId; use ethereum_types::H256; diff --git a/secret-store/src/key_server_set.rs b/secret-store/src/key_server_set.rs index b57df0a8b..5ffaa7fb7 100644 --- a/secret-store/src/key_server_set.rs +++ b/secret-store/src/key_server_set.rs @@ -20,7 +20,8 @@ use std::collections::{BTreeMap, HashSet}; use parking_lot::Mutex; use call_contract::CallContract; use ethabi::FunctionOutputDecoder; -use ethcore::client::{Client, BlockChainClient, ChainNotify, NewBlocks}; +use ethcore::client::{Client, ChainNotify, NewBlocks}; +use client_traits::BlockChainClient; use common_types::ids::BlockId; use ethereum_types::{H256, Address}; use ethkey::public_to_address; diff --git a/secret-store/src/lib.rs b/secret-store/src/lib.rs index 025716704..2999b4ebd 100644 --- a/secret-store/src/lib.rs +++ b/secret-store/src/lib.rs @@ -15,6 +15,7 @@ // along with Parity Ethereum. If not, see . extern crate byteorder; +extern crate client_traits; extern crate common_types; extern crate ethabi; extern crate ethcore; diff --git a/secret-store/src/listener/service_contract.rs b/secret-store/src/listener/service_contract.rs index caac9065a..3d24ff798 100644 --- a/secret-store/src/listener/service_contract.rs +++ b/secret-store/src/listener/service_contract.rs @@ -20,7 +20,8 @@ use common_types::filter::Filter; use ethabi::RawLog; use ethabi::FunctionOutputDecoder; use call_contract::CallContract; -use ethcore::client::{Client, BlockChainClient}; +use ethcore::client::Client; +use client_traits::BlockChainClient; use common_types::ids::BlockId; use ethkey::{Public, public_to_address}; use hash::keccak; diff --git a/secret-store/src/trusted_client.rs b/secret-store/src/trusted_client.rs index 70ca6f420..a058f0564 100644 --- a/secret-store/src/trusted_client.rs +++ b/secret-store/src/trusted_client.rs @@ -22,7 +22,8 @@ use common_types::{ transaction::{Transaction, SignedTransaction, Action}, }; use ethereum_types::Address; -use ethcore::client::{Client, ChainInfo, Nonce}; +use ethcore::client::Client; +use client_traits::{ChainInfo, Nonce}; use ethcore::miner::{Miner, MinerService}; use sync::SyncProvider; use helpers::{get_confirmed_block_hash, REQUEST_CONFIRMATIONS_REQUIRED}; @@ -43,9 +44,9 @@ pub struct TrustedClient { impl TrustedClient { /// Create new trusted client. - pub fn new(self_key_pair: Arc, client: Arc, sync: Arc, miner: Arc) -> Self { + pub fn new(self_key_pair: Arc, client: Arc, sync: Arc, miner: Arc) -> Self { TrustedClient { - self_key_pair: self_key_pair, + self_key_pair, client: Arc::downgrade(&client), sync: Arc::downgrade(&sync), miner: Arc::downgrade(&miner), diff --git a/updater/Cargo.toml b/updater/Cargo.toml index 2229f376e..3ea95d598 100644 --- a/updater/Cargo.toml +++ b/updater/Cargo.toml @@ -6,6 +6,7 @@ license = "GPL-3.0" authors = ["Parity Technologies "] [dependencies] +client-traits = { path = "../ethcore/client-traits" } common-types = { path = "../ethcore/types" } ethabi = "8.0" ethabi-contract = "8.0" diff --git a/updater/src/lib.rs b/updater/src/lib.rs index f6fad1719..7bc4eab7d 100644 --- a/updater/src/lib.rs +++ b/updater/src/lib.rs @@ -18,6 +18,7 @@ #![warn(missing_docs)] +extern crate client_traits; extern crate common_types; extern crate ethabi; extern crate ethcore; diff --git a/updater/src/updater.rs b/updater/src/updater.rs index f9558876d..ec51ffd9a 100644 --- a/updater/src/updater.rs +++ b/updater/src/updater.rs @@ -30,7 +30,8 @@ use common_types::{ ids::BlockId, filter::Filter, }; -use ethcore::client::{BlockChainClient, ChainNotify, NewBlocks}; +use ethcore::client::{ChainNotify, NewBlocks}; +use client_traits::BlockChainClient; use ethereum_types::{H256, H160}; use hash_fetch::{self as fetch, HashFetch}; use parity_path::restrict_permissions_owner;