From f044b61f42025b81783768b225a2c9e1dcb2ee32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 11 Jan 2018 17:49:10 +0100 Subject: [PATCH] Extract some parts of miner from ethcore. (#7353) * Move miner away from ethcore. * Fix ethcore to use miner/transaction. * Fix tests and warnings. * fixed incorrect merge of the test in the documentation --- Cargo.lock | 51 ++++- Cargo.toml | 8 +- ethcore/Cargo.toml | 8 +- ethcore/light/Cargo.toml | 1 + ethcore/light/src/lib.rs | 1 + ethcore/light/src/net/mod.rs | 2 +- ethcore/light/src/net/tests/mod.rs | 2 +- ethcore/light/src/on_demand/request.rs | 2 +- ethcore/light/src/provider.rs | 6 +- ethcore/light/src/transaction_queue.rs | 21 +- ethcore/light/src/types/request/mod.rs | 10 +- ethcore/src/block.rs | 11 +- ethcore/src/client/client.rs | 6 +- ethcore/src/client/evm_test_client.rs | 2 +- ethcore/src/client/mod.rs | 2 +- ethcore/src/client/test_client.rs | 8 +- ethcore/src/client/traits.rs | 5 +- ethcore/src/error.rs | 93 +------- ethcore/src/json_tests/transaction.rs | 6 +- ethcore/src/lib.rs | 7 +- ethcore/src/machine.rs | 8 +- ethcore/src/miner/miner.rs | 91 +++++--- ethcore/src/miner/mod.rs | 22 +- ethcore/src/miner/stratum.rs | 20 +- ethcore/src/verification/verification.rs | 30 +-- ethcore/transaction/Cargo.toml | 21 ++ ethcore/transaction/src/error.rs | 114 ++++++++++ ethcore/transaction/src/lib.rs | 46 ++++ ethcore/{ => transaction}/src/transaction.rs | 55 ++--- ethcore/types/src/log_entry.rs | 6 +- evmbin/Cargo.toml | 9 +- evmbin/src/info.rs | 3 +- evmbin/src/main.rs | 1 + local-store/Cargo.toml | 7 +- local-store/src/lib.rs | 5 +- miner/Cargo.toml | 27 +++ .../src/miner => miner/src}/banning_queue.rs | 53 ++--- {ethcore/src/miner => miner/src}/external.rs | 2 + miner/src/lib.rs | 47 ++++ .../miner => miner/src}/local_transactions.rs | 27 ++- .../src}/service_transaction_checker.rs | 23 +- .../miner => miner/src}/transaction_queue.rs | 205 +++++++++--------- .../src/miner => miner/src}/work_notify.rs | 32 ++- parity/configuration.rs | 3 +- parity/dapps.rs | 4 +- parity/helpers.rs | 3 +- parity/main.rs | 4 +- parity/rpc_apis.rs | 7 +- parity/run.rs | 17 +- rpc/Cargo.toml | 25 ++- rpc/src/lib.rs | 2 + rpc/src/v1/helpers/dispatch.rs | 3 +- rpc/src/v1/helpers/errors.rs | 13 +- rpc/src/v1/helpers/fake_sign.rs | 2 +- rpc/src/v1/helpers/light_fetch.rs | 2 +- rpc/src/v1/impls/eth.rs | 5 +- rpc/src/v1/impls/light/eth.rs | 7 +- rpc/src/v1/impls/personal.rs | 6 +- rpc/src/v1/impls/signer.rs | 4 +- rpc/src/v1/impls/traces.rs | 2 +- rpc/src/v1/tests/eth.rs | 4 +- rpc/src/v1/tests/helpers/miner_service.rs | 17 +- rpc/src/v1/tests/mocked/eth.rs | 15 +- rpc/src/v1/tests/mocked/parity_set.rs | 2 +- rpc/src/v1/tests/mocked/personal.rs | 2 +- rpc/src/v1/tests/mocked/signer.rs | 2 +- rpc/src/v1/tests/mocked/signing.rs | 6 +- rpc/src/v1/types/transaction.rs | 2 +- rpc/src/v1/types/transaction_condition.rs | 23 +- sync/Cargo.toml | 3 +- sync/src/api.rs | 2 +- sync/src/chain.rs | 4 +- sync/src/lib.rs | 1 + sync/src/tests/consensus.rs | 2 +- 74 files changed, 778 insertions(+), 522 deletions(-) create mode 100644 ethcore/transaction/Cargo.toml create mode 100644 ethcore/transaction/src/error.rs create mode 100644 ethcore/transaction/src/lib.rs rename ethcore/{ => transaction}/src/transaction.rs (93%) create mode 100644 miner/Cargo.toml rename {ethcore/src/miner => miner/src}/banning_queue.rs (86%) rename {ethcore/src/miner => miner/src}/external.rs (98%) create mode 100644 miner/src/lib.rs rename {ethcore/src/miner => miner/src}/local_transactions.rs (87%) rename {ethcore/src/miner => miner/src}/service_transaction_checker.rs (76%) rename {ethcore/src/miner => miner/src}/transaction_queue.rs (94%) rename {ethcore/src/miner => miner/src}/work_notify.rs (82%) diff --git a/Cargo.lock b/Cargo.lock index 4e2be44c3..adf79b076 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -475,7 +475,9 @@ dependencies = [ "ethcore-devtools 1.9.0", "ethcore-io 1.9.0", "ethcore-logger 1.9.0", + "ethcore-miner 1.9.0", "ethcore-stratum 1.9.0", + "ethcore-transaction 0.1.0", "ethereum-types 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "ethjson 0.1.0", "ethkey 0.3.0", @@ -485,7 +487,6 @@ dependencies = [ "hardware-wallet 1.9.0", "hashdb 0.1.1", "heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.10.0-a.0 (git+https://github.com/paritytech/hyper)", "itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", "journaldb 0.1.0", "keccak-hash 0.1.0", @@ -493,7 +494,6 @@ dependencies = [ "kvdb-memorydb 0.1.0", "kvdb-rocksdb 0.1.0", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "linked-hash-map 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "macros 0.1.0", @@ -516,9 +516,7 @@ dependencies = [ "semantic_version 0.1.0", "snappy 0.1.0 (git+https://github.com/paritytech/rust-snappy)", "stats 0.1.0", - "table 0.1.0", "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", - "transient-hashmap 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "triehash 0.1.0", "unexpected 0.1.0", "using_queue 0.1.0", @@ -565,6 +563,7 @@ dependencies = [ "ethcore-bytes 0.1.0", "ethcore-io 1.9.0", "ethcore-network 1.9.0", + "ethcore-transaction 0.1.0", "ethereum-types 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "evm 0.1.0", "futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", @@ -609,6 +608,28 @@ dependencies = [ "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ethcore-miner" +version = "1.9.0" +dependencies = [ + "common-types 0.1.0", + "ethash 1.9.0", + "ethcore-transaction 0.1.0", + "ethereum-types 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ethkey 0.3.0", + "futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.10.0-a.0 (git+https://github.com/paritytech/hyper)", + "keccak-hash 0.1.0", + "linked-hash-map 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "native-contracts 0.1.0", + "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "table 0.1.0", + "transient-hashmap 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ethcore-network" version = "1.9.0" @@ -695,6 +716,21 @@ dependencies = [ "tokio-io 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ethcore-transaction" +version = "0.1.0" +dependencies = [ + "ethereum-types 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ethjson 0.1.0", + "ethkey 0.3.0", + "evm 0.1.0", + "heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak-hash 0.1.0", + "rlp 0.2.1", + "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unexpected 0.1.0", +] + [[package]] name = "ethcrypto" version = "0.1.0" @@ -811,6 +847,7 @@ dependencies = [ "ethcore-io 1.9.0", "ethcore-light 1.9.0", "ethcore-network 1.9.0", + "ethcore-transaction 0.1.0", "ethereum-types 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "ethkey 0.3.0", "heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -854,6 +891,7 @@ dependencies = [ "docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore 1.9.0", "ethcore-bytes 0.1.0", + "ethcore-transaction 0.1.0", "ethereum-types 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "ethjson 0.1.0", "evm 0.1.0", @@ -1897,9 +1935,11 @@ dependencies = [ "ethcore-io 1.9.0", "ethcore-light 1.9.0", "ethcore-logger 1.9.0", + "ethcore-miner 1.9.0", "ethcore-network 1.9.0", "ethcore-secretstore 1.0.0", "ethcore-stratum 1.9.0", + "ethcore-transaction 0.1.0", "ethereum-types 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "ethkey 0.3.0", "ethsync 1.9.0", @@ -2053,6 +2093,7 @@ version = "0.1.0" dependencies = [ "ethcore 1.9.0", "ethcore-io 1.9.0", + "ethcore-transaction 0.1.0", "ethkey 0.3.0", "kvdb 0.1.0", "kvdb-memorydb 0.1.0", @@ -2091,7 +2132,9 @@ dependencies = [ "ethcore-io 1.9.0", "ethcore-light 1.9.0", "ethcore-logger 1.9.0", + "ethcore-miner 1.9.0", "ethcore-network 1.9.0", + "ethcore-transaction 0.1.0", "ethcrypto 0.1.0", "ethereum-types 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "ethjson 0.1.0", diff --git a/Cargo.toml b/Cargo.toml index a3bfbd907..92b5498b0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,12 +35,14 @@ jsonrpc-core = { git = "https://github.com/paritytech/jsonrpc.git", branch = "pa ethsync = { path = "sync" } ethcore = { path = "ethcore" } ethcore-bytes = { path = "util/bytes" } -ethcore-io = { path = "util/io" } ethcore-devtools = { path = "devtools" } +ethcore-io = { path = "util/io" } ethcore-light = { path = "ethcore/light" } ethcore-logger = { path = "logger" } -ethcore-stratum = { path = "stratum" } +ethcore-miner = { path = "miner" } ethcore-network = { path = "util/network" } +ethcore-stratum = { path = "stratum" } +ethcore-transaction = { path = "ethcore/transaction" } ethereum-types = "0.1" node-filter = { path = "ethcore/node_filter" } ethkey = { path = "ethkey" } @@ -119,9 +121,11 @@ members = [ "chainspec", "dapps/js-glue", "ethcore/wasm/run", + "ethcore/types", "ethkey/cli", "ethstore/cli", "evmbin", + "miner", "transaction-pool", "whisper", ] diff --git a/ethcore/Cargo.toml b/ethcore/Cargo.toml index 2bf55117a..a1b865993 100644 --- a/ethcore/Cargo.toml +++ b/ethcore/Cargo.toml @@ -22,7 +22,9 @@ patricia-trie = { path = "../util/patricia_trie" } ethcore-devtools = { path = "../devtools" } ethcore-io = { path = "../util/io" } ethcore-logger = { path = "../logger" } +ethcore-miner = { path = "../miner" } ethcore-stratum = { path = "../stratum" } +ethcore-transaction = { path = "./transaction" } ethereum-types = "0.1" memory-cache = { path = "../util/memory_cache" } ethjson = { path = "../json" } @@ -32,10 +34,8 @@ evm = { path = "evm" } futures = "0.1" hardware-wallet = { path = "../hw" } heapsize = "0.4" -hyper = { git = "https://github.com/paritytech/hyper", default-features = false } itertools = "0.5" lazy_static = "0.2" -linked-hash-map = "0.5" log = "0.3" lru-cache = "0.1" native-contracts = { path = "native_contracts" } @@ -59,9 +59,7 @@ rust-crypto = "0.2.34" rustc-hex = "1.0" stats = { path = "../util/stats" } time = "0.1" -transient-hashmap = "0.4" using_queue = { path = "../util/using_queue" } -table = { path = "../util/table" } bloomable = { path = "../util/bloomable" } vm = { path = "vm" } wasm = { path = "wasm" } @@ -79,7 +77,7 @@ jit = ["evm/jit"] evm-debug = ["slow-blocks"] evm-debug-tests = ["evm-debug", "evm/evm-debug-tests"] slow-blocks = [] # Use SLOW_TX_DURATION="50" (compile time!) to track transactions over 50ms -json-tests = [] +json-tests = ["ethcore-transaction/json-tests"] test-heavy = [] default = [] benches = [] diff --git a/ethcore/light/Cargo.toml b/ethcore/light/Cargo.toml index 50b10d681..92a4adc6d 100644 --- a/ethcore/light/Cargo.toml +++ b/ethcore/light/Cargo.toml @@ -10,6 +10,7 @@ authors = ["Parity Technologies "] log = "0.3" ethcore = { path = ".."} ethcore-bytes = { path = "../../util/bytes" } +ethcore-transaction = { path = "../transaction" } ethereum-types = "0.1" memorydb = { path = "../../util/memorydb" } patricia-trie = { path = "../../util/patricia_trie" } diff --git a/ethcore/light/src/lib.rs b/ethcore/light/src/lib.rs index f04788cf4..c6ea7826a 100644 --- a/ethcore/light/src/lib.rs +++ b/ethcore/light/src/lib.rs @@ -57,6 +57,7 @@ extern crate bincode; extern crate ethcore_io as io; extern crate ethcore_network as network; extern crate ethcore_bytes as bytes; +extern crate ethcore_transaction as transaction; extern crate ethereum_types; extern crate ethcore; extern crate evm; diff --git a/ethcore/light/src/net/mod.rs b/ethcore/light/src/net/mod.rs index ac589b333..7166cae33 100644 --- a/ethcore/light/src/net/mod.rs +++ b/ethcore/light/src/net/mod.rs @@ -18,7 +18,7 @@ //! //! This uses a "Provider" to answer requests. -use ethcore::transaction::UnverifiedTransaction; +use transaction::UnverifiedTransaction; use io::TimerToken; use network::{HostInfo, NetworkProtocolHandler, NetworkContext, PeerId}; diff --git a/ethcore/light/src/net/tests/mod.rs b/ethcore/light/src/net/tests/mod.rs index 2102fd105..721aee13f 100644 --- a/ethcore/light/src/net/tests/mod.rs +++ b/ethcore/light/src/net/tests/mod.rs @@ -20,9 +20,9 @@ use ethcore::blockchain_info::BlockChainInfo; use ethcore::client::{EachBlockWith, TestBlockChainClient}; use ethcore::ids::BlockId; -use ethcore::transaction::{Action, PendingTransaction}; use ethcore::encoded; use network::{PeerId, NodeId}; +use transaction::{Action, PendingTransaction}; use net::context::IoContext; use net::status::{Capabilities, Status}; diff --git a/ethcore/light/src/on_demand/request.rs b/ethcore/light/src/on_demand/request.rs index 0c1ca2a13..4c023fbe4 100644 --- a/ethcore/light/src/on_demand/request.rs +++ b/ethcore/light/src/on_demand/request.rs @@ -24,7 +24,7 @@ use ethcore::engines::{EthEngine, StateDependentProof}; use ethcore::machine::EthereumMachine; use ethcore::receipt::Receipt; use ethcore::state::{self, ProvedExecution}; -use ethcore::transaction::SignedTransaction; +use transaction::SignedTransaction; use vm::EnvInfo; use hash::{KECCAK_NULL_RLP, KECCAK_EMPTY, KECCAK_EMPTY_LIST_RLP, keccak}; diff --git a/ethcore/light/src/provider.rs b/ethcore/light/src/provider.rs index 14046d774..70d04db9c 100644 --- a/ethcore/light/src/provider.rs +++ b/ethcore/light/src/provider.rs @@ -21,11 +21,11 @@ use std::sync::Arc; use ethcore::blockchain_info::BlockChainInfo; use ethcore::client::{BlockChainClient, ProvingBlockChainClient}; -use ethcore::transaction::PendingTransaction; -use ethcore::ids::BlockId; use ethcore::encoded; +use ethcore::ids::BlockId; use ethereum_types::H256; use parking_lot::RwLock; +use transaction::PendingTransaction; use cht::{self, BlockInfo}; use client::{LightChainClient, AsLightClient}; @@ -260,7 +260,7 @@ impl Provider for T { } fn transaction_proof(&self, req: request::CompleteExecutionRequest) -> Option { - use ethcore::transaction::Transaction; + use transaction::Transaction; let id = BlockId::Hash(req.block_hash); let nonce = match self.nonce(&req.from, id.clone()) { diff --git a/ethcore/light/src/transaction_queue.rs b/ethcore/light/src/transaction_queue.rs index b3f573772..ff4baf776 100644 --- a/ethcore/light/src/transaction_queue.rs +++ b/ethcore/light/src/transaction_queue.rs @@ -26,8 +26,7 @@ use std::collections::{BTreeMap, HashMap}; use std::collections::hash_map::Entry; -use ethcore::error::{TransactionError, TransactionImportResult}; -use ethcore::transaction::{Condition, PendingTransaction, SignedTransaction}; +use transaction::{self, Condition, PendingTransaction, SignedTransaction}; use ethereum_types::{H256, U256, Address}; use plain_hasher::H256FastMap; @@ -123,13 +122,13 @@ pub struct TransactionQueue { impl TransactionQueue { /// Import a pending transaction to be queued. - pub fn import(&mut self, tx: PendingTransaction) -> Result { + pub fn import(&mut self, tx: PendingTransaction) -> Result { let sender = tx.sender(); let hash = tx.hash(); let nonce = tx.nonce; let tx_info = TransactionInfo::from(&tx); - if self.by_hash.contains_key(&hash) { return Err(TransactionError::AlreadyImported) } + if self.by_hash.contains_key(&hash) { return Err(transaction::Error::AlreadyImported) } let res = match self.by_account.entry(sender) { Entry::Vacant(entry) => { @@ -139,14 +138,14 @@ impl TransactionQueue { future: BTreeMap::new(), }); - TransactionImportResult::Current + transaction::ImportResult::Current } Entry::Occupied(mut entry) => { let acct_txs = entry.get_mut(); if &nonce < acct_txs.cur_nonce.value() { // don't accept txs from before known current nonce. if acct_txs.cur_nonce.is_known() { - return Err(TransactionError::Old) + return Err(transaction::Error::Old) } // lower our assumption until corrected later. @@ -161,7 +160,7 @@ impl TransactionQueue { let old = ::std::mem::replace(&mut acct_txs.current[idx], tx_info); self.by_hash.remove(&old.hash); - TransactionImportResult::Current + transaction::ImportResult::Current } Err(idx) => { let cur_len = acct_txs.current.len(); @@ -183,13 +182,13 @@ impl TransactionQueue { acct_txs.future.insert(future_nonce, future); } - TransactionImportResult::Current + transaction::ImportResult::Current } else if idx == cur_len && acct_txs.current.last().map_or(false, |f| f.nonce + 1.into() != nonce) { trace!(target: "txqueue", "Queued future transaction for {}, nonce={}", sender, nonce); let future_nonce = nonce; acct_txs.future.insert(future_nonce, tx_info); - TransactionImportResult::Future + transaction::ImportResult::Future } else { trace!(target: "txqueue", "Queued current transaction for {}, nonce={}", sender, nonce); @@ -197,7 +196,7 @@ impl TransactionQueue { acct_txs.current.insert(idx, tx_info); acct_txs.adjust_future(); - TransactionImportResult::Current + transaction::ImportResult::Current } } } @@ -331,7 +330,7 @@ impl TransactionQueue { mod tests { use super::TransactionQueue; use ethereum_types::Address; - use ethcore::transaction::{Transaction, PendingTransaction, Condition}; + use transaction::{Transaction, PendingTransaction, Condition}; #[test] fn queued_senders() { diff --git a/ethcore/light/src/types/request/mod.rs b/ethcore/light/src/types/request/mod.rs index bd19d7e96..bd68c6a0a 100644 --- a/ethcore/light/src/types/request/mod.rs +++ b/ethcore/light/src/types/request/mod.rs @@ -1094,7 +1094,7 @@ pub mod block_body { impl Decodable for Response { fn decode(rlp: &UntrustedRlp) -> Result { use ethcore::header::Header as FullHeader; - use ethcore::transaction::UnverifiedTransaction; + use transaction::UnverifiedTransaction; // check body validity. let _: Vec = rlp.list_at(0)?; @@ -1410,7 +1410,7 @@ pub mod contract_code { /// A request for proof of execution. pub mod execution { use super::{Field, NoSuchOutput, OutputKind, Output}; - use ethcore::transaction::Action; + use transaction::Action; use rlp::{Encodable, Decodable, DecoderError, RlpStream, UntrustedRlp}; use ethereum_types::{H256, U256, Address}; use kvdb::DBValue; @@ -1755,7 +1755,7 @@ mod tests { #[test] fn body_roundtrip() { - use ethcore::transaction::{Transaction, UnverifiedTransaction}; + use transaction::{Transaction, UnverifiedTransaction}; let req = IncompleteBodyRequest { hash: Field::Scalar(Default::default()), }; @@ -1850,7 +1850,7 @@ mod tests { let req = IncompleteExecutionRequest { block_hash: Field::Scalar(Default::default()), from: Default::default(), - action: ::ethcore::transaction::Action::Create, + action: ::transaction::Action::Create, gas: 100_000.into(), gas_price: 0.into(), value: 100_000_001.into(), @@ -1880,7 +1880,7 @@ mod tests { let reqs: Vec<_> = (0..10).map(|_| IncompleteExecutionRequest { block_hash: Field::Scalar(Default::default()), from: Default::default(), - action: ::ethcore::transaction::Action::Create, + action: ::transaction::Action::Create, gas: 100_000.into(), gas_price: 0.into(), value: 100_000_001.into(), diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index 58f2d0484..79e9c3cdb 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -30,14 +30,14 @@ use unexpected::{Mismatch, OutOfBounds}; use basic_types::{LogBloom, Seal}; use vm::{EnvInfo, LastHashes}; use engines::EthEngine; -use error::{Error, BlockError, TransactionError}; +use error::{Error, BlockError}; use factory::Factories; use header::Header; use receipt::{Receipt, TransactionOutcome}; use state::State; use state_db::StateDB; use trace::FlatTrace; -use transaction::{UnverifiedTransaction, SignedTransaction}; +use transaction::{UnverifiedTransaction, SignedTransaction, Error as TransactionError}; use verification::PreverifiedBlock; use views::BlockView; @@ -737,7 +737,12 @@ mod tests { ) -> Result { let block = BlockView::new(block_bytes); let header = block.header(); - let transactions: Result, Error> = block.transactions().into_iter().map(SignedTransaction::new).collect(); + let transactions: Result, Error> = block + .transactions() + .into_iter() + .map(SignedTransaction::new) + .map(|r| r.map_err(Into::into)) + .collect(); let transactions = transactions?; { diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 1b8e084e9..c8b416f63 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -55,7 +55,7 @@ use futures::{future, Future}; use header::{BlockNumber, Header}; use io::*; use log_entry::LocalizedLogEntry; -use miner::{Miner, MinerService, TransactionImportResult}; +use miner::{Miner, MinerService}; use native_contracts::Registry; use parking_lot::{Mutex, RwLock, MutexGuard}; use rand::OsRng; @@ -69,7 +69,7 @@ use state::{self, State}; use trace; use trace::{TraceDB, ImportRequest as TraceImportRequest, LocalizedTrace, Database as TraceDatabase}; use trace::FlatTransactionTraces; -use transaction::{LocalizedTransaction, UnverifiedTransaction, SignedTransaction, Transaction, PendingTransaction, Action}; +use transaction::{self, LocalizedTransaction, UnverifiedTransaction, SignedTransaction, Transaction, PendingTransaction, Action}; use types::filter::Filter; use types::mode::Mode as IpcMode; use verification; @@ -1813,7 +1813,7 @@ impl BlockChainClient for Client { }) } - fn transact_contract(&self, address: Address, data: Bytes) -> Result { + fn transact_contract(&self, address: Address, data: Bytes) -> Result { let transaction = Transaction { nonce: self.latest_nonce(&self.miner.author()), action: Action::Call(address), diff --git a/ethcore/src/client/evm_test_client.rs b/ethcore/src/client/evm_test_client.rs index 27cf80d29..00f2af816 100644 --- a/ethcore/src/client/evm_test_client.rs +++ b/ethcore/src/client/evm_test_client.rs @@ -203,7 +203,7 @@ impl<'a> EvmTestClient<'a> { if let Err(error) = is_ok { return TransactResult::Err { state_root: *self.state.root(), - error, + error: error.into(), }; } diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index 2960f303d..0a7ff45b2 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -42,7 +42,7 @@ pub use types::call_analytics::CallAnalytics; pub use executive::{Executed, Executive, TransactOptions}; pub use vm::{LastHashes, EnvInfo}; -pub use error::{BlockImportError, TransactionImportError, TransactionImportResult}; +pub use error::{BlockImportError, TransactionImportError}; pub use verification::VerifierType; mod traits; diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index 62cedfb9d..b4ed7c0bd 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -32,7 +32,7 @@ use bytes::Bytes; use rlp::*; use ethkey::{Generator, Random}; use devtools::*; -use transaction::{Transaction, LocalizedTransaction, PendingTransaction, SignedTransaction, Action}; +use transaction::{self, Transaction, LocalizedTransaction, PendingTransaction, SignedTransaction, Action}; use blockchain::TreeRoute; use client::{ BlockChainClient, MiningBlockChainClient, BlockChainInfo, BlockStatus, BlockId, @@ -48,7 +48,7 @@ use blockchain::extras::BlockReceipts; use error::{ImportResult, Error as EthcoreError}; use evm::{Factory as EvmFactory, VMType}; use vm::Schedule; -use miner::{Miner, MinerService, TransactionImportResult}; +use miner::{Miner, MinerService}; use spec::Spec; use types::basic_account::BasicAccount; use types::mode::Mode; @@ -337,7 +337,7 @@ impl TestBlockChainClient { let hash = signed_tx.hash(); let res = self.miner.import_external_transactions(self, vec![signed_tx.into()]); let res = res.into_iter().next().unwrap().expect("Successful import"); - assert_eq!(res, TransactionImportResult::Current); + assert_eq!(res, transaction::ImportResult::Current); hash } @@ -771,7 +771,7 @@ impl BlockChainClient for TestBlockChainClient { fn call_contract(&self, _id: BlockId, _address: Address, _data: Bytes) -> Result { Ok(vec![]) } - fn transact_contract(&self, address: Address, data: Bytes) -> Result { + fn transact_contract(&self, address: Address, data: Bytes) -> Result { let transaction = Transaction { nonce: self.latest_nonce(&self.miner.author()), action: Action::Call(address), diff --git a/ethcore/src/client/traits.rs b/ethcore/src/client/traits.rs index 52622793d..bb35bcbae 100644 --- a/ethcore/src/client/traits.rs +++ b/ethcore/src/client/traits.rs @@ -21,8 +21,7 @@ use block::{OpenBlock, SealedBlock, ClosedBlock}; use blockchain::TreeRoute; use encoded; use vm::LastHashes; -use error::{ImportResult, CallError, Error as EthcoreError}; -use error::{TransactionImportResult, BlockImportError}; +use error::{ImportResult, CallError, Error as EthcoreError, BlockImportError}; use evm::{Factory as EvmFactory, Schedule}; use executive::Executed; use filter::Filter; @@ -30,7 +29,7 @@ use header::{BlockNumber}; use log_entry::LocalizedLogEntry; use receipt::LocalizedReceipt; use trace::LocalizedTrace; -use transaction::{LocalizedTransaction, PendingTransaction, SignedTransaction}; +use transaction::{LocalizedTransaction, PendingTransaction, SignedTransaction, ImportResult as TransactionImportResult}; use verification::queue::QueueInfo as BlockQueueInfo; use ethereum_types::{H256, U256, Address}; diff --git a/ethcore/src/error.rs b/ethcore/src/error.rs index 33e282447..c67bc03e0 100644 --- a/ethcore/src/error.rs +++ b/ethcore/src/error.rs @@ -31,92 +31,10 @@ use snapshot::Error as SnapshotError; use engines::EngineError; use ethkey::Error as EthkeyError; use account_provider::SignError as AccountsError; +use transaction::Error as TransactionError; pub use executed::{ExecutionError, CallError}; -#[derive(Debug, PartialEq, Clone, Copy)] -/// Errors concerning transaction processing. -pub enum TransactionError { - /// Transaction is already imported to the queue - AlreadyImported, - /// Transaction is not valid anymore (state already has higher nonce) - Old, - /// Transaction has too low fee - /// (there is already a transaction with the same sender-nonce but higher gas price) - TooCheapToReplace, - /// Transaction was not imported to the queue because limit has been reached. - LimitReached, - /// Transaction's gas price is below threshold. - InsufficientGasPrice { - /// Minimal expected gas price - minimal: U256, - /// Transaction gas price - got: U256, - }, - /// Transaction's gas is below currently set minimal gas requirement. - InsufficientGas { - /// Minimal expected gas - minimal: U256, - /// Transaction gas - got: U256, - }, - /// Sender doesn't have enough funds to pay for this transaction - InsufficientBalance { - /// Senders balance - balance: U256, - /// Transaction cost - cost: U256, - }, - /// Transactions gas is higher then current gas limit - GasLimitExceeded { - /// Current gas limit - limit: U256, - /// Declared transaction gas - got: U256, - }, - /// Transaction's gas limit (aka gas) is invalid. - InvalidGasLimit(OutOfBounds), - /// Transaction sender is banned. - SenderBanned, - /// Transaction receipient is banned. - RecipientBanned, - /// Contract creation code is banned. - CodeBanned, - /// Invalid chain ID given. - InvalidChainId, - /// Not enough permissions given by permission contract. - NotAllowed, -} - -impl fmt::Display for TransactionError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use self::TransactionError::*; - let msg = match *self { - AlreadyImported => "Already imported".into(), - Old => "No longer valid".into(), - TooCheapToReplace => "Gas price too low to replace".into(), - LimitReached => "Transaction limit reached".into(), - InsufficientGasPrice { minimal, got } => - format!("Insufficient gas price. Min={}, Given={}", minimal, got), - InsufficientGas { minimal, got } => - format!("Insufficient gas. Min={}, Given={}", minimal, got), - InsufficientBalance { balance, cost } => - format!("Insufficient balance for transaction. Balance={}, Cost={}", - balance, cost), - GasLimitExceeded { limit, got } => - format!("Gas limit exceeded. Limit={}, Given={}", limit, got), - InvalidGasLimit(ref err) => format!("Invalid gas limit. {}", err), - SenderBanned => "Sender is temporarily banned.".into(), - RecipientBanned => "Recipient is temporarily banned.".into(), - CodeBanned => "Contract code is temporarily banned.".into(), - InvalidChainId => "Transaction of this chain ID is not allowed on this chain.".into(), - NotAllowed => "Sender does not have permissions to execute this type of transction".into(), - }; - - f.write_fmt(format_args!("Transaction error ({})", msg)) - } -} - #[derive(Debug, PartialEq, Clone, Copy, Eq)] /// Errors concerning block processing. pub enum BlockError { @@ -270,15 +188,6 @@ impl From for BlockImportError { } } -/// Represents the result of importing transaction. -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum TransactionImportResult { - /// Transaction was imported to current queue. - Current, - /// Transaction was imported to future queue. - Future -} - /// Api-level error for transaction import #[derive(Debug, Clone)] pub enum TransactionImportError { diff --git a/ethcore/src/json_tests/transaction.rs b/ethcore/src/json_tests/transaction.rs index 6ae8123f1..b7445c51a 100644 --- a/ethcore/src/json_tests/transaction.rs +++ b/ethcore/src/json_tests/transaction.rs @@ -42,8 +42,10 @@ fn do_json_test(json_data: &[u8]) -> Vec { let rlp: Vec = test.rlp.into(); let res = UntrustedRlp::new(&rlp) .as_val() - .map_err(From::from) - .and_then(|t: UnverifiedTransaction| t.validate(schedule, schedule.have_delegate_call, allow_chain_id_of_one, allow_unsigned)); + .map_err(::error::Error::from) + .and_then(|t: UnverifiedTransaction| { + t.validate(schedule, schedule.have_delegate_call, allow_chain_id_of_one, allow_unsigned).map_err(Into::into) + }); fail_unless(test.transaction.is_none() == res.is_err(), "Validity different"); if let (Some(tx), Some(sender)) = (test.transaction, test.sender) { diff --git a/ethcore/src/lib.rs b/ethcore/src/lib.rs index 861ffe0a2..a767843ba 100644 --- a/ethcore/src/lib.rs +++ b/ethcore/src/lib.rs @@ -66,16 +66,16 @@ extern crate ethcore_devtools as devtools; extern crate ethcore_io as io; extern crate ethcore_bytes as bytes; extern crate ethcore_logger; +extern crate ethcore_miner; extern crate ethcore_stratum; +extern crate ethcore_transaction as transaction; extern crate ethereum_types; extern crate ethjson; extern crate ethkey; extern crate futures; extern crate hardware_wallet; extern crate hashdb; -extern crate hyper; extern crate itertools; -extern crate linked_hash_map; extern crate lru_cache; extern crate native_contracts; extern crate num_cpus; @@ -106,9 +106,7 @@ extern crate rlp_derive; extern crate rustc_hex; extern crate stats; extern crate time; -extern crate transient_hashmap; extern crate using_queue; -extern crate table; extern crate bloomable; extern crate vm; extern crate wasm; @@ -149,7 +147,6 @@ pub mod spec; pub mod state; pub mod timer; pub mod trace; -pub mod transaction; pub mod verification; pub mod views; diff --git a/ethcore/src/machine.rs b/ethcore/src/machine.rs index 1feb5d547..8bd8afac5 100644 --- a/ethcore/src/machine.rs +++ b/ethcore/src/machine.rs @@ -23,13 +23,13 @@ use std::sync::Arc; use block::ExecutedBlock; use builtin::Builtin; use client::BlockChainClient; -use error::{Error, TransactionError}; +use error::Error; use executive::Executive; use header::{BlockNumber, Header}; use spec::CommonParams; use state::{CleanupMode, Substate}; use trace::{NoopTracer, NoopVMTracer, Tracer, ExecutiveTracer, RewardType}; -use transaction::{SYSTEM_ADDRESS, UnverifiedTransaction, SignedTransaction}; +use transaction::{self, SYSTEM_ADDRESS, UnverifiedTransaction, SignedTransaction}; use tx_filter::TransactionFilter; use ethereum_types::{U256, Address}; @@ -341,7 +341,7 @@ impl EthereumMachine { /// Verify a particular transaction is valid, regardless of order. pub fn verify_transaction_unordered(&self, t: UnverifiedTransaction, _header: &Header) -> Result { - SignedTransaction::new(t) + Ok(SignedTransaction::new(t)?) } /// Does basic verification of the transaction. @@ -369,7 +369,7 @@ impl EthereumMachine { pub fn verify_transaction(&self, t: &SignedTransaction, header: &Header, client: &BlockChainClient) -> Result<(), Error> { if let Some(ref filter) = self.tx_filter.as_ref() { if !filter.transaction_allowed(header.parent_hash(), t, client) { - return Err(TransactionError::NotAllowed.into()) + return Err(transaction::Error::NotAllowed.into()) } } diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index aa91cce44..67567cc7d 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -18,32 +18,47 @@ use std::time::{Instant, Duration}; use std::collections::{BTreeMap, HashSet}; use std::sync::Arc; +use account_provider::{AccountProvider, SignError as AccountError}; +use ansi_term::Colour; use ethereum_types::{H256, U256, Address}; use parking_lot::{Mutex, RwLock}; use bytes::Bytes; -use timer::PerfTimer; -use using_queue::{UsingQueue, GetAction}; -use account_provider::{AccountProvider, SignError as AccountError}; -use state::State; -use client::{MiningBlockChainClient, BlockId, TransactionId}; -use client::TransactionImportResult; -use executive::contract_address; -use block::{ClosedBlock, IsBlock, Block}; +use engines::{EthEngine, Seal}; use error::*; -use transaction::{Action, UnverifiedTransaction, PendingTransaction, SignedTransaction, Condition as TransactionCondition}; +use ethcore_miner::banning_queue::{BanningTransactionQueue, Threshold}; +use ethcore_miner::local_transactions::{Status as LocalTransactionStatus}; +use ethcore_miner::transaction_queue::{ + TransactionQueue, + RemovalReason, + TransactionDetailsProvider as TransactionQueueDetailsProvider, + PrioritizationStrategy, + AccountDetails, + TransactionOrigin, +}; +use ethcore_miner::work_notify::{WorkPoster, NotifyWork}; +use ethcore_miner::service_transaction_checker::ServiceTransactionChecker; +use miner::{MinerService, MinerStatus}; +use price_info::fetch::Client as FetchClient; +use price_info::{Client as PriceInfoClient, PriceInfo}; +use timer::PerfTimer; +use transaction::{ + Action, + UnverifiedTransaction, + PendingTransaction, + SignedTransaction, + Condition as TransactionCondition, + ImportResult as TransactionImportResult, + Error as TransactionError, +}; +use using_queue::{UsingQueue, GetAction}; + +use block::{ClosedBlock, IsBlock, Block}; +use client::{MiningBlockChainClient, BlockId, TransactionId}; +use executive::contract_address; +use header::{Header, BlockNumber}; use receipt::{Receipt, RichReceipt}; use spec::Spec; -use engines::{EthEngine, Seal}; -use miner::{MinerService, MinerStatus, TransactionQueue, RemovalReason, TransactionQueueDetailsProvider, PrioritizationStrategy, - AccountDetails, TransactionOrigin}; -use miner::banning_queue::{BanningTransactionQueue, Threshold}; -use miner::work_notify::{WorkPoster, NotifyWork}; -use miner::local_transactions::{Status as LocalTransactionStatus}; -use miner::service_transaction_checker::ServiceTransactionChecker; -use price_info::{Client as PriceInfoClient, PriceInfo}; -use price_info::fetch::Client as FetchClient; -use header::{Header, BlockNumber}; -use ansi_term::Colour; +use state::State; /// Different possible definitions for pending transaction set. #[derive(Debug, PartialEq)] @@ -711,10 +726,10 @@ impl Miner { let details_provider = TransactionDetailsProvider::new(client, &self.service_transaction_action); match origin { TransactionOrigin::Local | TransactionOrigin::RetractedBlock => { - transaction_queue.add(transaction, origin, insertion_time, condition.clone(), &details_provider) + Ok(transaction_queue.add(transaction, origin, insertion_time, condition.clone(), &details_provider)?) }, TransactionOrigin::External => { - transaction_queue.add_with_banlist(transaction, insertion_time, &details_provider) + Ok(transaction_queue.add_with_banlist(transaction, insertion_time, &details_provider)?) }, } }, @@ -1218,18 +1233,28 @@ enum ServiceTransactionAction { impl ServiceTransactionAction { pub fn update_from_chain_client(&self, client: &MiningBlockChainClient) { if let ServiceTransactionAction::Check(ref checker) = *self { - checker.update_from_chain_client(client); + checker.update_from_chain_client(&client); } } pub fn check(&self, client: &MiningBlockChainClient, tx: &SignedTransaction) -> Result { match *self { ServiceTransactionAction::Refuse => Err("configured to refuse service transactions".to_owned()), - ServiceTransactionAction::Check(ref checker) => checker.check(client, tx), + ServiceTransactionAction::Check(ref checker) => checker.check(&client, tx), } } } +impl<'a> ::ethcore_miner::service_transaction_checker::ContractCaller for &'a MiningBlockChainClient { + fn registry_address(&self, name: &str) -> Option
{ + MiningBlockChainClient::registry_address(*self, name.into()) + } + + fn call_contract(&self, block: BlockId, address: Address, data: Vec) -> Result, String> { + MiningBlockChainClient::call_contract(*self, block, address, data) + } +} + struct TransactionDetailsProvider<'a> { client: &'a MiningBlockChainClient, service_transaction_action: &'a ServiceTransactionAction, @@ -1263,20 +1288,16 @@ impl<'a> TransactionQueueDetailsProvider for TransactionDetailsProvider<'a> { #[cfg(test)] mod tests { - - use std::sync::Arc; - use std::time::Duration; - use rustc_hex::FromHex; - use hash::keccak; - use super::super::{MinerService, PrioritizationStrategy}; use super::*; - use block::IsBlock; + use ethcore_miner::transaction_queue::PrioritizationStrategy; use ethereum_types::U256; use ethkey::{Generator, Random}; - use client::{BlockChainClient, TestBlockChainClient, EachBlockWith, TransactionImportResult}; - use header::BlockNumber; - use transaction::{SignedTransaction, Transaction, PendingTransaction, Action}; - use spec::Spec; + use hash::keccak; + use rustc_hex::FromHex; + use transaction::Transaction; + + use client::{BlockChainClient, TestBlockChainClient, EachBlockWith}; + use miner::MinerService; use tests::helpers::{generate_dummy_client, generate_dummy_client_with_spec_and_accounts}; #[test] diff --git a/ethcore/src/miner/mod.rs b/ethcore/src/miner/mod.rs index a26f03a06..34c416cc1 100644 --- a/ethcore/src/miner/mod.rs +++ b/ethcore/src/miner/mod.rs @@ -38,34 +38,24 @@ //! } //! ``` -mod banning_queue; -mod external; -mod local_transactions; mod miner; -mod service_transaction_checker; -mod transaction_queue; -mod work_notify; mod stratum; -pub use self::external::{ExternalMiner, ExternalMinerService}; - pub use self::miner::{Miner, MinerOptions, Banning, PendingSet, GasPricer, GasPriceCalibratorOptions, GasLimit}; -pub use self::transaction_queue::{TransactionQueue, RemovalReason, TransactionDetailsProvider as TransactionQueueDetailsProvider, - PrioritizationStrategy, AccountDetails, TransactionOrigin}; -pub use self::local_transactions::{Status as LocalTransactionStatus}; -pub use client::TransactionImportResult; -pub use self::work_notify::NotifyWork; pub use self::stratum::{Stratum, Error as StratumError, Options as StratumOptions}; +pub use ethcore_miner::local_transactions::Status as LocalTransactionStatus; + use std::collections::BTreeMap; use ethereum_types::{H256, U256, Address}; use bytes::Bytes; -use client::{MiningBlockChainClient}; + use block::ClosedBlock; +use client::{MiningBlockChainClient}; +use error::{Error}; use header::BlockNumber; use receipt::{RichReceipt, Receipt}; -use error::{Error}; -use transaction::{UnverifiedTransaction, PendingTransaction}; +use transaction::{UnverifiedTransaction, PendingTransaction, ImportResult as TransactionImportResult}; /// Miner client API pub trait MinerService : Send + Sync { diff --git a/ethcore/src/miner/stratum.rs b/ethcore/src/miner/stratum.rs index 5b9e306b5..80ec44ea4 100644 --- a/ethcore/src/miner/stratum.rs +++ b/ethcore/src/miner/stratum.rs @@ -16,22 +16,22 @@ //! Client-side stratum job dispatcher and mining notifier handler -use ethcore_stratum::{ - JobDispatcher, PushWorkHandler, - Stratum as StratumService, Error as StratumServiceError, -}; - use std::sync::{Arc, Weak}; use std::net::{SocketAddr, AddrParseError}; use std::fmt; +use block::IsBlock; +use client::Client; use ethereum_types::{H64, H256, clean_0x, U256}; use ethereum::ethash::Ethash; use ethash::SeedHashCompute; -use parking_lot::Mutex; +use ethcore_miner::work_notify::NotifyWork; +use ethcore_stratum::{ + JobDispatcher, PushWorkHandler, + Stratum as StratumService, Error as StratumServiceError, +}; use miner::{self, Miner, MinerService}; -use client::Client; -use block::IsBlock; +use parking_lot::Mutex; use rlp::encode; /// Configures stratum server options. @@ -213,7 +213,7 @@ impl From for Error { fn from(err: AddrParseError) -> Error { Error::Address(err) } } -impl super::work_notify::NotifyWork for Stratum { +impl NotifyWork for Stratum { fn notify(&self, pow_hash: H256, difficulty: U256, number: u64) { trace!(target: "stratum", "Notify work"); @@ -248,7 +248,7 @@ impl Stratum { /// Start STRATUM job dispatcher and register it in the miner pub fn register(cfg: &Options, miner: Arc, client: Weak) -> Result<(), Error> { let stratum = miner::Stratum::start(cfg, Arc::downgrade(&miner.clone()), client)?; - miner.push_notifier(Box::new(stratum) as Box); + miner.push_notifier(Box::new(stratum) as Box); Ok(()) } } diff --git a/ethcore/src/verification/verification.rs b/ethcore/src/verification/verification.rs index 7ceddad3d..672dee1db 100644 --- a/ethcore/src/verification/verification.rs +++ b/ethcore/src/verification/verification.rs @@ -332,27 +332,21 @@ fn verify_block_integrity(block: &[u8], transactions_root: &H256, uncles_hash: & #[cfg(test)] mod tests { + use super::*; + use std::collections::{BTreeMap, HashMap}; - use hash::keccak; use ethereum_types::{H256, H2048, U256}; - use triehash::ordered_trie_root; - use unexpected::{Mismatch, OutOfBounds}; - use bytes::Bytes; - use ethkey::{Random, Generator}; - use header::*; - use verification::*; - use blockchain::extras::*; - use error::*; - use error::BlockError::*; - use views::*; - use blockchain::*; - use engines::EthEngine; - use spec::*; - use transaction::*; - use tests::helpers::*; - use types::log_entry::{LogEntry, LocalizedLogEntry}; - use time::get_time; + use blockchain::extras::{BlockDetails, TransactionAddress, BlockReceipts}; use encoded; + use hash::keccak; + use engines::EthEngine; + use error::BlockError::*; + use ethkey::{Random, Generator}; + use spec::{CommonParams, Spec}; + use tests::helpers::{create_test_block_with_data, create_test_block}; + use time::get_time; + use transaction::{SignedTransaction, Transaction, UnverifiedTransaction, Action}; + use types::log_entry::{LogEntry, LocalizedLogEntry}; fn check_ok(result: Result<(), Error>) { result.unwrap_or_else(|e| panic!("Block verification failed: {:?}", e)); diff --git a/ethcore/transaction/Cargo.toml b/ethcore/transaction/Cargo.toml new file mode 100644 index 000000000..7cf5cc416 --- /dev/null +++ b/ethcore/transaction/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "ethcore-transaction" +description = "Transaction type" +version = "0.1.0" +authors = ["Parity Technologies "] + +[dependencies] +ethjson = { path = "../../json" } +ethkey = { path = "../../ethkey" } +evm = { path = "../evm" } +heapsize = "0.4" +keccak-hash = { path = "../../util/hash" } +rlp = { path = "../../util/rlp" } +unexpected = { path = "../../util/unexpected" } +ethereum-types = "0.1" + +[dev-dependencies] +rustc-hex= "1.0" + +[features] +json-tests = [] diff --git a/ethcore/transaction/src/error.rs b/ethcore/transaction/src/error.rs new file mode 100644 index 000000000..4578b88ac --- /dev/null +++ b/ethcore/transaction/src/error.rs @@ -0,0 +1,114 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity 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 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. If not, see . + +use std::fmt; + +use ethereum_types::U256; +use ethkey; +use unexpected::OutOfBounds; + +#[derive(Debug, PartialEq, Clone)] +/// Errors concerning transaction processing. +pub enum Error { + /// Transaction is already imported to the queue + AlreadyImported, + /// Transaction is not valid anymore (state already has higher nonce) + Old, + /// Transaction has too low fee + /// (there is already a transaction with the same sender-nonce but higher gas price) + TooCheapToReplace, + /// Transaction was not imported to the queue because limit has been reached. + LimitReached, + /// Transaction's gas price is below threshold. + InsufficientGasPrice { + /// Minimal expected gas price + minimal: U256, + /// Transaction gas price + got: U256, + }, + /// Transaction's gas is below currently set minimal gas requirement. + InsufficientGas { + /// Minimal expected gas + minimal: U256, + /// Transaction gas + got: U256, + }, + /// Sender doesn't have enough funds to pay for this transaction + InsufficientBalance { + /// Senders balance + balance: U256, + /// Transaction cost + cost: U256, + }, + /// Transactions gas is higher then current gas limit + GasLimitExceeded { + /// Current gas limit + limit: U256, + /// Declared transaction gas + got: U256, + }, + /// Transaction's gas limit (aka gas) is invalid. + InvalidGasLimit(OutOfBounds), + /// Transaction sender is banned. + SenderBanned, + /// Transaction receipient is banned. + RecipientBanned, + /// Contract creation code is banned. + CodeBanned, + /// Invalid chain ID given. + InvalidChainId, + /// Not enough permissions given by permission contract. + NotAllowed, + /// Signature error + InvalidSignature(String), +} + +impl From for Error { + fn from(err: ethkey::Error) -> Self { + Error::InvalidSignature(format!("{}", err)) + } +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use self::Error::*; + let msg = match *self { + AlreadyImported => "Already imported".into(), + Old => "No longer valid".into(), + TooCheapToReplace => "Gas price too low to replace".into(), + LimitReached => "Transaction limit reached".into(), + InsufficientGasPrice { minimal, got } => + format!("Insufficient gas price. Min={}, Given={}", minimal, got), + InsufficientGas { minimal, got } => + format!("Insufficient gas. Min={}, Given={}", minimal, got), + InsufficientBalance { balance, cost } => + format!("Insufficient balance for transaction. Balance={}, Cost={}", + balance, cost), + GasLimitExceeded { limit, got } => + format!("Gas limit exceeded. Limit={}, Given={}", limit, got), + InvalidGasLimit(ref err) => format!("Invalid gas limit. {}", err), + SenderBanned => "Sender is temporarily banned.".into(), + RecipientBanned => "Recipient is temporarily banned.".into(), + CodeBanned => "Contract code is temporarily banned.".into(), + InvalidChainId => "Transaction of this chain ID is not allowed on this chain.".into(), + InvalidSignature(ref err) => format!("Transaction has invalid signature: {}.", err), + NotAllowed => "Sender does not have permissions to execute this type of transction".into(), + }; + + f.write_fmt(format_args!("Transaction error ({})", msg)) + } +} + diff --git a/ethcore/transaction/src/lib.rs b/ethcore/transaction/src/lib.rs new file mode 100644 index 000000000..6d6c269f3 --- /dev/null +++ b/ethcore/transaction/src/lib.rs @@ -0,0 +1,46 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity 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 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. If not, see . + +//! Ethereum Transactions + +extern crate ethereum_types; +extern crate ethjson; +extern crate ethkey; +extern crate evm; +extern crate heapsize; +extern crate keccak_hash as hash; +extern crate rlp; +extern crate unexpected; + +#[cfg(test)] +extern crate rustc_hex; + +mod error; +mod transaction; + +pub use error::Error; +pub use transaction::*; + +// TODO [ToDr] Move to miner! + +/// Represents the result of importing transaction. +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum ImportResult { + /// Transaction was imported to current queue. + Current, + /// Transaction was imported to future queue. + Future +} diff --git a/ethcore/src/transaction.rs b/ethcore/transaction/src/transaction.rs similarity index 93% rename from ethcore/src/transaction.rs rename to ethcore/transaction/src/transaction.rs index 20f850efc..f206c549a 100644 --- a/ethcore/src/transaction.rs +++ b/ethcore/transaction/src/transaction.rs @@ -17,16 +17,18 @@ //! Transaction data structure. use std::ops::Deref; -use rlp::*; +use ethereum_types::{H256, H160, Address, U256}; +use error; +use ethjson; +use ethkey::{self, Signature, Secret, Public, recover, public_to_address}; +use evm::Schedule; use hash::keccak; use heapsize::HeapSizeOf; -use ethereum_types::{H256, H160, Address, U256}; -use bytes::Bytes; -use ethkey::{Signature, Secret, Public, recover, public_to_address, Error as EthkeyError}; -use error::*; -use evm::Schedule; -use header::BlockNumber; -use ethjson; +use rlp::{self, RlpStream, UntrustedRlp, DecoderError, Encodable}; +// use rlp::*; + +type Bytes = Vec; +type BlockNumber = u64; /// Fake address for unsigned transactions as defined by EIP-86. pub const UNSIGNED_SENDER: Address = H160([0xff; 20]); @@ -48,7 +50,7 @@ impl Default for Action { fn default() -> Action { Action::Create } } -impl Decodable for Action { +impl rlp::Decodable for Action { fn decode(rlp: &UntrustedRlp) -> Result { if rlp.is_empty() { Ok(Action::Create) @@ -58,7 +60,7 @@ impl Decodable for Action { } } -impl Encodable for Action { +impl rlp::Encodable for Action { fn rlp_append(&self, s: &mut RlpStream) { match *self { Action::Create => s.append_internal(&""), @@ -270,7 +272,7 @@ impl Deref for UnverifiedTransaction { } } -impl Decodable for UnverifiedTransaction { +impl rlp::Decodable for UnverifiedTransaction { fn decode(d: &UntrustedRlp) -> Result { if d.item_count()? != 9 { return Err(DecoderError::RlpIncorrectListLen); @@ -293,7 +295,7 @@ impl Decodable for UnverifiedTransaction { } } -impl Encodable for UnverifiedTransaction { +impl rlp::Encodable for UnverifiedTransaction { fn rlp_append(&self, s: &mut RlpStream) { self.rlp_append_sealed_transaction(s) } } @@ -350,9 +352,9 @@ impl UnverifiedTransaction { } /// Checks whether the signature has a low 's' value. - pub fn check_low_s(&self) -> Result<(), Error> { + pub fn check_low_s(&self) -> Result<(), ethkey::Error> { if !self.signature().is_low_s() { - Err(EthkeyError::InvalidSignature.into()) + Err(ethkey::Error::InvalidSignature.into()) } else { Ok(()) } @@ -364,39 +366,40 @@ impl UnverifiedTransaction { } /// Recovers the public key of the sender. - pub fn recover_public(&self) -> Result { + pub fn recover_public(&self) -> Result { Ok(recover(&self.signature(), &self.unsigned.hash(self.chain_id()))?) } /// Do basic validation, checking for valid signature and minimum gas, // TODO: consider use in block validation. - #[cfg(test)] #[cfg(feature = "json-tests")] - pub fn validate(self, schedule: &Schedule, require_low: bool, allow_chain_id_of_one: bool, allow_empty_signature: bool) -> Result { + pub fn validate(self, schedule: &Schedule, require_low: bool, allow_chain_id_of_one: bool, allow_empty_signature: bool) + -> Result + { let chain_id = if allow_chain_id_of_one { Some(1) } else { None }; self.verify_basic(require_low, chain_id, allow_empty_signature)?; if !allow_empty_signature || !self.is_unsigned() { self.recover_public()?; } if self.gas < U256::from(self.gas_required(&schedule)) { - return Err(TransactionError::InvalidGasLimit(::unexpected::OutOfBounds{min: Some(U256::from(self.gas_required(&schedule))), max: None, found: self.gas}).into()) + return Err(error::Error::InvalidGasLimit(::unexpected::OutOfBounds{min: Some(U256::from(self.gas_required(&schedule))), max: None, found: self.gas}).into()) } Ok(self) } /// Verify basic signature params. Does not attempt sender recovery. - pub fn verify_basic(&self, check_low_s: bool, chain_id: Option, allow_empty_signature: bool) -> Result<(), Error> { + pub fn verify_basic(&self, check_low_s: bool, chain_id: Option, allow_empty_signature: bool) -> Result<(), error::Error> { if check_low_s && !(allow_empty_signature && self.is_unsigned()) { self.check_low_s()?; } // EIP-86: Transactions of this form MUST have gasprice = 0, nonce = 0, value = 0, and do NOT increment the nonce of account 0. if allow_empty_signature && self.is_unsigned() && !(self.gas_price.is_zero() && self.value.is_zero() && self.nonce.is_zero()) { - return Err(EthkeyError::InvalidSignature.into()) + return Err(ethkey::Error::InvalidSignature.into()) } match (self.chain_id(), chain_id) { (None, _) => {}, (Some(n), Some(m)) if n == m => {}, - _ => return Err(TransactionError::InvalidChainId.into()), + _ => return Err(error::Error::InvalidChainId), }; Ok(()) } @@ -416,7 +419,7 @@ impl HeapSizeOf for SignedTransaction { } } -impl Encodable for SignedTransaction { +impl rlp::Encodable for SignedTransaction { fn rlp_append(&self, s: &mut RlpStream) { self.transaction.rlp_append_sealed_transaction(s) } } @@ -435,7 +438,7 @@ impl From for UnverifiedTransaction { impl SignedTransaction { /// Try to verify transaction and recover sender. - pub fn new(transaction: UnverifiedTransaction) -> Result { + pub fn new(transaction: UnverifiedTransaction) -> Result { if transaction.is_unsigned() { Ok(SignedTransaction { transaction: transaction, @@ -556,7 +559,7 @@ mod tests { #[test] fn sender_test() { - let t: UnverifiedTransaction = decode(&::rustc_hex::FromHex::from_hex("f85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804").unwrap()); + let t: UnverifiedTransaction = rlp::decode(&::rustc_hex::FromHex::from_hex("f85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804").unwrap()); assert_eq!(t.data, b""); assert_eq!(t.gas, U256::from(0x5208u64)); assert_eq!(t.gas_price, U256::from(0x01u64)); @@ -625,10 +628,10 @@ mod tests { use rustc_hex::FromHex; let test_vector = |tx_data: &str, address: &'static str| { - let signed = decode(&FromHex::from_hex(tx_data).unwrap()); + let signed = rlp::decode(&FromHex::from_hex(tx_data).unwrap()); let signed = SignedTransaction::new(signed).unwrap(); assert_eq!(signed.sender(), address.into()); - flushln!("chainid: {:?}", signed.chain_id()); + println!("chainid: {:?}", signed.chain_id()); }; test_vector("f864808504a817c800825208943535353535353535353535353535353535353535808025a0044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116da0044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d", "0xf0f6f18bca1b28cd68e4357452947e021241e9ce"); diff --git a/ethcore/types/src/log_entry.rs b/ethcore/types/src/log_entry.rs index 9caa7ff69..1bb072203 100644 --- a/ethcore/types/src/log_entry.rs +++ b/ethcore/types/src/log_entry.rs @@ -17,11 +17,11 @@ //! Log entry type definition. use std::ops::Deref; -use hash::keccak; -use heapsize::HeapSizeOf; -use bytes::Bytes; use ethereum_types::{H256, Address, LogBloom}; use bloomable::Bloomable; +use bytes::Bytes; +use hash::keccak; +use heapsize::HeapSizeOf; use {BlockNumber}; use ethjson; diff --git a/evmbin/Cargo.toml b/evmbin/Cargo.toml index 84486f370..849c06372 100644 --- a/evmbin/Cargo.toml +++ b/evmbin/Cargo.toml @@ -9,17 +9,18 @@ name = "parity-evm" path = "./src/main.rs" [dependencies] -rustc-hex = "1.0" docopt = "0.8" -serde = "1.0" -serde_derive = "1.0" ethcore = { path = "../ethcore" } ethjson = { path = "../json" } ethcore-bytes = { path = "../util/bytes" } +ethcore-transaction = { path = "../ethcore/transaction" } ethereum-types = "0.1" evm = { path = "../ethcore/evm" } -vm = { path = "../ethcore/vm" } panic_hook = { path = "../panic_hook" } +rustc-hex = "1.0" +serde = "1.0" +serde_derive = "1.0" +vm = { path = "../ethcore/vm" } [dev-dependencies] pretty_assertions = "0.1" diff --git a/evmbin/src/info.rs b/evmbin/src/info.rs index e3b5f3d23..3f3a66a8c 100644 --- a/evmbin/src/info.rs +++ b/evmbin/src/info.rs @@ -18,9 +18,10 @@ use std::time::{Instant, Duration}; use ethereum_types::{H256, U256}; -use ethcore::{trace, spec, transaction, pod_state}; use ethcore::client::{self, EvmTestClient, EvmTestError, TransactResult}; +use ethcore::{trace, spec, pod_state}; use ethjson; +use transaction; use vm::ActionParams; /// VM execution informant diff --git a/evmbin/src/main.rs b/evmbin/src/main.rs index f1dc91fc4..1a6bfdf22 100644 --- a/evmbin/src/main.rs +++ b/evmbin/src/main.rs @@ -25,6 +25,7 @@ extern crate serde; #[macro_use] extern crate serde_derive; extern crate docopt; +extern crate ethcore_transaction as transaction; extern crate ethcore_bytes as bytes; extern crate ethereum_types; extern crate vm; diff --git a/local-store/Cargo.toml b/local-store/Cargo.toml index 7dd73d464..6d09eb76f 100644 --- a/local-store/Cargo.toml +++ b/local-store/Cargo.toml @@ -5,14 +5,15 @@ version = "0.1.0" authors = ["Parity Technologies "] [dependencies] -ethcore-io = { path = "../util/io" } ethcore = { path = "../ethcore" } -rlp = { path = "../util/rlp" } +ethcore-io = { path = "../util/io" } +ethcore-transaction = { path = "../ethcore/transaction" } kvdb = { path = "../util/kvdb" } +log = "0.3" +rlp = { path = "../util/rlp" } serde = "1.0" serde_derive = "1.0" serde_json = "1.0" -log = "0.3" [dev-dependencies] ethkey = { path = "../ethkey" } diff --git a/local-store/src/lib.rs b/local-store/src/lib.rs index ccd2b11b7..d61bdec85 100644 --- a/local-store/src/lib.rs +++ b/local-store/src/lib.rs @@ -19,7 +19,7 @@ use std::sync::Arc; use std::fmt; -use ethcore::transaction::{ +use transaction::{ SignedTransaction, PendingTransaction, UnverifiedTransaction, Condition as TransactionCondition }; @@ -29,6 +29,7 @@ use rlp::UntrustedRlp; use kvdb::KeyValueDB; extern crate ethcore; +extern crate ethcore_transaction as transaction; extern crate ethcore_io as io; extern crate rlp; extern crate serde_json; @@ -231,7 +232,7 @@ mod tests { use super::NodeInfo; use std::sync::Arc; - use ethcore::transaction::{Transaction, Condition, PendingTransaction}; + use transaction::{Transaction, Condition, PendingTransaction}; use ethkey::{Brain, Generator}; // we want to test: round-trip of good transactions. diff --git a/miner/Cargo.toml b/miner/Cargo.toml new file mode 100644 index 000000000..ac5295799 --- /dev/null +++ b/miner/Cargo.toml @@ -0,0 +1,27 @@ +[package] +description = "Parity Miner interface." +name = "ethcore-miner" +homepage = "http://parity.io" +license = "GPL-3.0" +version = "1.9.0" +authors = ["Parity Technologies "] + +[dependencies] +# TODO [ToDr] Rewrite using reqwest +hyper = { git = "https://github.com/paritytech/hyper", default-features = false } + +common-types = { path = "../ethcore/types" } +ethash = { path = "../ethash" } +ethcore-transaction = { path = "../ethcore/transaction" } +ethereum-types = "0.1" +ethkey = { path = "../ethkey" } +futures = "0.1" +heapsize = "0.4" +keccak-hash = { path = "../util/hash" } +linked-hash-map = "0.5" +log = "0.3" +native-contracts = { path = "../ethcore/native_contracts" } +parking_lot = "0.4" +rustc-hex = "1.0" +table = { path = "../util/table" } +transient-hashmap = "0.4" diff --git a/ethcore/src/miner/banning_queue.rs b/miner/src/banning_queue.rs similarity index 86% rename from ethcore/src/miner/banning_queue.rs rename to miner/src/banning_queue.rs index 2f7a49b78..388ae5e00 100644 --- a/ethcore/src/miner/banning_queue.rs +++ b/miner/src/banning_queue.rs @@ -19,13 +19,12 @@ use std::time::Duration; use std::ops::{Deref, DerefMut}; -use transaction::{SignedTransaction, Action}; -use transient_hashmap::TransientHashMap; -use miner::{TransactionQueue, TransactionQueueDetailsProvider, TransactionImportResult, TransactionOrigin}; -use miner::transaction_queue::QueuingInstant; -use error::{Error, TransactionError}; use ethereum_types::{H256, U256, Address}; use hash::keccak; +use transaction::{self, SignedTransaction, Action}; +use transient_hashmap::TransientHashMap; + +use transaction_queue::{TransactionQueue, TransactionDetailsProvider, TransactionOrigin, QueuingInstant}; type Count = u16; @@ -80,8 +79,8 @@ impl BanningTransactionQueue { &mut self, transaction: SignedTransaction, time: QueuingInstant, - details_provider: &TransactionQueueDetailsProvider, - ) -> Result { + details_provider: &TransactionDetailsProvider, + ) -> Result { if let Threshold::BanAfter(threshold) = self.ban_threshold { // NOTE In all checks use direct query to avoid increasing ban timeout. @@ -90,7 +89,7 @@ impl BanningTransactionQueue { let count = self.senders_bans.direct().get(&sender).cloned().unwrap_or(0); if count > threshold { debug!(target: "txqueue", "Ignoring transaction {:?} because sender is banned.", transaction.hash()); - return Err(Error::Transaction(TransactionError::SenderBanned)); + return Err(transaction::Error::SenderBanned); } // Check recipient @@ -98,7 +97,7 @@ impl BanningTransactionQueue { let count = self.recipients_bans.direct().get(&recipient).cloned().unwrap_or(0); if count > threshold { debug!(target: "txqueue", "Ignoring transaction {:?} because recipient is banned.", transaction.hash()); - return Err(Error::Transaction(TransactionError::RecipientBanned)); + return Err(transaction::Error::RecipientBanned); } } @@ -108,7 +107,7 @@ impl BanningTransactionQueue { let count = self.codes_bans.direct().get(&code_hash).cloned().unwrap_or(0); if count > threshold { debug!(target: "txqueue", "Ignoring transaction {:?} because code is banned.", transaction.hash()); - return Err(Error::Transaction(TransactionError::CodeBanned)); + return Err(transaction::Error::CodeBanned); } } } @@ -209,17 +208,11 @@ impl DerefMut for BanningTransactionQueue { #[cfg(test)] mod tests { - use std::time::Duration; - use rustc_hex::FromHex; - use hash::keccak; - use super::{BanningTransactionQueue, Threshold}; + use super::*; use ethkey::{Random, Generator}; - use transaction::{Transaction, SignedTransaction, Action}; - use error::{Error, TransactionError}; - use client::TransactionImportResult; - use miner::{TransactionQueue, TransactionOrigin}; + use rustc_hex::FromHex; + use transaction_queue::test::DummyTransactionDetailsProvider; use ethereum_types::{U256, Address}; - use miner::transaction_queue::test::DummyTransactionDetailsProvider; fn queue() -> BanningTransactionQueue { BanningTransactionQueue::new(TransactionQueue::default(), Threshold::BanAfter(1), Duration::from_secs(180)) @@ -231,7 +224,7 @@ mod tests { fn transaction(action: Action) -> SignedTransaction { let keypair = Random.generate().unwrap(); - Transaction { + transaction::Transaction { action: action, value: U256::from(100), data: "3331600055".from_hex().unwrap(), @@ -241,12 +234,8 @@ mod tests { }.sign(keypair.secret(), None) } - fn unwrap_err(res: Result) -> TransactionError { - match res { - Err(Error::Transaction(e)) => e, - Ok(x) => panic!("Expected error, got: Ok({:?})", x), - Err(e) => panic!("Unexpected error type returned by queue: {:?}", e), - } + fn unwrap_err(res: Result) -> transaction::Error { + res.unwrap_err() } #[test] @@ -273,7 +262,7 @@ mod tests { assert!(!banlist1, "Threshold not reached yet."); // Insert once let import1 = txq.add_with_banlist(tx.clone(), 0, &default_tx_provider()).unwrap(); - assert_eq!(import1, TransactionImportResult::Current); + assert_eq!(import1, transaction::ImportResult::Current); // when let banlist2 = txq.ban_sender(tx.sender()); @@ -281,7 +270,7 @@ mod tests { // then assert!(banlist2, "Threshold should be reached - banned."); - assert_eq!(unwrap_err(import2), TransactionError::SenderBanned); + assert_eq!(unwrap_err(import2), transaction::Error::SenderBanned); // Should also remove transacion from the queue assert_eq!(txq.find(&tx.hash()), None); } @@ -297,7 +286,7 @@ mod tests { assert!(!banlist1, "Threshold not reached yet."); // Insert once let import1 = txq.add_with_banlist(tx.clone(), 0, &default_tx_provider()).unwrap(); - assert_eq!(import1, TransactionImportResult::Current); + assert_eq!(import1, transaction::ImportResult::Current); // when let banlist2 = txq.ban_recipient(recipient); @@ -305,7 +294,7 @@ mod tests { // then assert!(banlist2, "Threshold should be reached - banned."); - assert_eq!(unwrap_err(import2), TransactionError::RecipientBanned); + assert_eq!(unwrap_err(import2), transaction::Error::RecipientBanned); } #[test] @@ -319,7 +308,7 @@ mod tests { assert!(!banlist1, "Threshold not reached yet."); // Insert once let import1 = txq.add_with_banlist(tx.clone(), 0, &default_tx_provider()).unwrap(); - assert_eq!(import1, TransactionImportResult::Current); + assert_eq!(import1, transaction::ImportResult::Current); // when let banlist2 = txq.ban_codehash(codehash); @@ -327,6 +316,6 @@ mod tests { // then assert!(banlist2, "Threshold should be reached - banned."); - assert_eq!(unwrap_err(import2), TransactionError::CodeBanned); + assert_eq!(unwrap_err(import2), transaction::Error::CodeBanned); } } diff --git a/ethcore/src/miner/external.rs b/miner/src/external.rs similarity index 98% rename from ethcore/src/miner/external.rs rename to miner/src/external.rs index 601a49447..cbd830cd5 100644 --- a/ethcore/src/miner/external.rs +++ b/miner/src/external.rs @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . +//! External Miner hashrate tracker. + use std::collections::HashMap; use std::sync::Arc; use std::time::{Instant, Duration}; diff --git a/miner/src/lib.rs b/miner/src/lib.rs new file mode 100644 index 000000000..fe6e5fe21 --- /dev/null +++ b/miner/src/lib.rs @@ -0,0 +1,47 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity 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 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. If not, see . + +#![warn(missing_docs)] + +//! Miner module +//! Keeps track of transactions and mined block. + +extern crate common_types as types; +extern crate ethereum_types; +extern crate ethcore_transaction as transaction; +extern crate futures; +extern crate heapsize; +extern crate keccak_hash as hash; +extern crate linked_hash_map; +extern crate native_contracts; +extern crate parking_lot; +extern crate table; +extern crate transient_hashmap; + +#[macro_use] +extern crate log; + +#[cfg(test)] +extern crate rustc_hex; +#[cfg(test)] +extern crate ethkey; + +pub mod banning_queue; +pub mod external; +pub mod local_transactions; +pub mod service_transaction_checker; +pub mod transaction_queue; +pub mod work_notify; diff --git a/ethcore/src/miner/local_transactions.rs b/miner/src/local_transactions.rs similarity index 87% rename from ethcore/src/miner/local_transactions.rs rename to miner/src/local_transactions.rs index 8b9d6e13c..e8d1988a4 100644 --- a/ethcore/src/miner/local_transactions.rs +++ b/miner/src/local_transactions.rs @@ -16,10 +16,9 @@ //! Local Transactions List. -use linked_hash_map::LinkedHashMap; -use transaction::{SignedTransaction, PendingTransaction}; -use error::TransactionError; use ethereum_types::{H256, U256}; +use linked_hash_map::LinkedHashMap; +use transaction::{self, SignedTransaction, PendingTransaction}; /// Status of local transaction. /// Can indicate that the transaction is currently part of the queue (`Pending/Future`) @@ -37,7 +36,7 @@ pub enum Status { /// Replaced because of higher gas price of another transaction. Replaced(SignedTransaction, U256, H256), /// Transaction was never accepted to the queue. - Rejected(SignedTransaction, TransactionError), + Rejected(SignedTransaction, transaction::Error), /// Transaction is invalid. Invalid(SignedTransaction), /// Transaction was canceled. @@ -64,6 +63,7 @@ impl Default for LocalTransactionsList { } impl LocalTransactionsList { + /// Create a new list of local transactions. pub fn new(max_old: usize) -> Self { LocalTransactionsList { max_old: max_old, @@ -71,58 +71,68 @@ impl LocalTransactionsList { } } + /// Mark transaction with given hash as pending. pub fn mark_pending(&mut self, hash: H256) { debug!(target: "own_tx", "Imported to Current (hash {:?})", hash); self.clear_old(); self.transactions.insert(hash, Status::Pending); } + /// Mark transaction with given hash as future. pub fn mark_future(&mut self, hash: H256) { debug!(target: "own_tx", "Imported to Future (hash {:?})", hash); self.transactions.insert(hash, Status::Future); self.clear_old(); } - pub fn mark_rejected(&mut self, tx: SignedTransaction, err: TransactionError) { + /// Mark given transaction as rejected from the queue. + pub fn mark_rejected(&mut self, tx: SignedTransaction, err: transaction::Error) { debug!(target: "own_tx", "Transaction rejected (hash {:?}): {:?}", tx.hash(), err); self.transactions.insert(tx.hash(), Status::Rejected(tx, err)); self.clear_old(); } + /// Mark the transaction as replaced by transaction with given hash. pub fn mark_replaced(&mut self, tx: SignedTransaction, gas_price: U256, hash: H256) { debug!(target: "own_tx", "Transaction replaced (hash {:?}) by {:?} (new gas price: {:?})", tx.hash(), hash, gas_price); self.transactions.insert(tx.hash(), Status::Replaced(tx, gas_price, hash)); self.clear_old(); } + /// Mark transaction as invalid. pub fn mark_invalid(&mut self, tx: SignedTransaction) { warn!(target: "own_tx", "Transaction marked invalid (hash {:?})", tx.hash()); self.transactions.insert(tx.hash(), Status::Invalid(tx)); self.clear_old(); } + /// Mark transaction as canceled. pub fn mark_canceled(&mut self, tx: PendingTransaction) { warn!(target: "own_tx", "Transaction canceled (hash {:?})", tx.hash()); self.transactions.insert(tx.hash(), Status::Canceled(tx)); self.clear_old(); } + /// Mark transaction as dropped because of limit. pub fn mark_dropped(&mut self, tx: SignedTransaction) { warn!(target: "own_tx", "Transaction dropped (hash {:?})", tx.hash()); self.transactions.insert(tx.hash(), Status::Dropped(tx)); self.clear_old(); } + /// Mark transaction as mined. pub fn mark_mined(&mut self, tx: SignedTransaction) { info!(target: "own_tx", "Transaction mined (hash {:?})", tx.hash()); self.transactions.insert(tx.hash(), Status::Mined(tx)); self.clear_old(); } + /// Returns true if the transaction is already in local transactions. pub fn contains(&self, hash: &H256) -> bool { self.transactions.contains_key(hash) } + /// Return a map of all currently stored transactions. pub fn all_transactions(&self) -> &LinkedHashMap { &self.transactions } @@ -152,10 +162,9 @@ impl LocalTransactionsList { #[cfg(test)] mod tests { + use super::*; use ethereum_types::U256; use ethkey::{Random, Generator}; - use transaction::{Action, Transaction, SignedTransaction}; - use super::{LocalTransactionsList, Status}; #[test] fn should_add_transaction_as_pending() { @@ -199,8 +208,8 @@ mod tests { fn new_tx(nonce: U256) -> SignedTransaction { let keypair = Random.generate().unwrap(); - Transaction { - action: Action::Create, + transaction::Transaction { + action: transaction::Action::Create, value: U256::from(100), data: Default::default(), gas: U256::from(10), diff --git a/ethcore/src/miner/service_transaction_checker.rs b/miner/src/service_transaction_checker.rs similarity index 76% rename from ethcore/src/miner/service_transaction_checker.rs rename to miner/src/service_transaction_checker.rs index 2d20227df..338768d55 100644 --- a/ethcore/src/miner/service_transaction_checker.rs +++ b/miner/src/service_transaction_checker.rs @@ -14,17 +14,26 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use client::MiningBlockChainClient; -use transaction::SignedTransaction; -use types::ids::BlockId; +//! A service transactions contract checker. use futures::{future, Future}; use native_contracts::ServiceTransactionChecker as Contract; -use ethereum_types::U256; +use ethereum_types::{U256, Address}; use parking_lot::Mutex; +use transaction::SignedTransaction; +use types::ids::BlockId; const SERVICE_TRANSACTION_CONTRACT_REGISTRY_NAME: &'static str = "service_transaction_checker"; +/// A contract calling interface. +pub trait ContractCaller { + /// Returns address of contract from the registry, given it's name + fn registry_address(&self, name: &str) -> Option
; + + /// Executes a contract call at given block. + fn call_contract(&self, BlockId, Address, Vec) -> Result, String>; +} + /// Service transactions checker. #[derive(Default)] pub struct ServiceTransactionChecker { @@ -33,10 +42,10 @@ pub struct ServiceTransactionChecker { impl ServiceTransactionChecker { /// Try to create instance, reading contract address from given chain client. - pub fn update_from_chain_client(&self, client: &MiningBlockChainClient) { + pub fn update_from_chain_client(&self, client: &ContractCaller) { let mut contract = self.contract.lock(); if contract.is_none() { - *contract = client.registry_address(SERVICE_TRANSACTION_CONTRACT_REGISTRY_NAME.to_owned()) + *contract = client.registry_address(SERVICE_TRANSACTION_CONTRACT_REGISTRY_NAME) .and_then(|contract_addr| { trace!(target: "txqueue", "Configuring for service transaction checker contract from {}", contract_addr); @@ -46,7 +55,7 @@ impl ServiceTransactionChecker { } /// Checks if service transaction can be appended to the transaction queue. - pub fn check(&self, client: &MiningBlockChainClient, tx: &SignedTransaction) -> Result { + pub fn check(&self, client: &ContractCaller, tx: &SignedTransaction) -> Result { debug_assert_eq!(tx.gas_price, U256::zero()); if let Some(ref contract) = *self.contract.lock() { diff --git a/ethcore/src/miner/transaction_queue.rs b/miner/src/transaction_queue.rs similarity index 94% rename from ethcore/src/miner/transaction_queue.rs rename to miner/src/transaction_queue.rs index 0d7395716..2be7fc8a3 100644 --- a/ethcore/src/miner/transaction_queue.rs +++ b/miner/src/transaction_queue.rs @@ -25,20 +25,21 @@ //! //! ```rust //! extern crate ethereum_types; -//! extern crate ethcore; +//! extern crate ethcore_miner as miner; +//! extern crate ethcore_transaction as transaction; //! extern crate ethkey; //! extern crate rustc_hex; //! //! use ethereum_types::{U256, Address}; //! use ethkey::{Random, Generator}; -//! use ethcore::miner::{TransactionQueue, RemovalReason, TransactionQueueDetailsProvider, AccountDetails, TransactionOrigin}; -//! use ethcore::transaction::*; +//! use miner::transaction_queue::{TransactionQueue, TransactionDetailsProvider, AccountDetails, TransactionOrigin, RemovalReason}; +//! use transaction::*; //! use rustc_hex::FromHex; //! //! #[derive(Default)] //! struct DummyTransactionDetailsProvider; //! -//! impl TransactionQueueDetailsProvider for DummyTransactionDetailsProvider { +//! impl TransactionDetailsProvider for DummyTransactionDetailsProvider { //! fn fetch_account(&self, _address: &Address) -> AccountDetails { //! AccountDetails { //! nonce: U256::from(10), @@ -100,19 +101,19 @@ //! 4. `remove_old` is used as convenient method to update the state nonce for all senders in the queue. //! - Invokes `cull` with latest state nonce for all senders. -use std::ops::Deref; use std::cmp::Ordering; use std::cmp; use std::collections::{HashSet, HashMap, BTreeSet, BTreeMap}; -use linked_hash_map::LinkedHashMap; -use heapsize::HeapSizeOf; +use std::ops::Deref; + use ethereum_types::{H256, U256, Address}; +use heapsize::HeapSizeOf; +use linked_hash_map::LinkedHashMap; +use local_transactions::{LocalTransactionsList, Status as LocalTransactionStatus}; use table::Table; -use transaction::*; -use error::{Error, TransactionError}; -use client::TransactionImportResult; -use header::BlockNumber; -use miner::local_transactions::{LocalTransactionsList, Status as LocalTransactionStatus}; +use transaction::{self, SignedTransaction, PendingTransaction}; + +type BlockNumber = u64; /// Transaction origin #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -281,7 +282,7 @@ struct VerifiedTransaction { /// Transaction origin. origin: TransactionOrigin, /// Delay until specified condition is met. - condition: Option, + condition: Option, /// Insertion time insertion_time: QueuingInstant, /// ID assigned upon insertion, should be unique. @@ -292,7 +293,7 @@ impl VerifiedTransaction { fn new( transaction: SignedTransaction, origin: TransactionOrigin, - condition: Option, + condition: Option, insertion_time: QueuingInstant, insertion_id: u64, ) -> Self { @@ -705,31 +706,28 @@ impl TransactionQueue { tx: SignedTransaction, origin: TransactionOrigin, time: QueuingInstant, - condition: Option, + condition: Option, details_provider: &TransactionDetailsProvider, - ) -> Result { + ) -> Result { if origin == TransactionOrigin::Local { let hash = tx.hash(); let cloned_tx = tx.clone(); let result = self.add_internal(tx, origin, time, condition, details_provider); match result { - Ok(TransactionImportResult::Current) => { + Ok(transaction::ImportResult::Current) => { self.local_transactions.mark_pending(hash); }, - Ok(TransactionImportResult::Future) => { + Ok(transaction::ImportResult::Future) => { self.local_transactions.mark_future(hash); }, - Err(Error::Transaction(ref err)) => { + Err(ref err) => { // Sometimes transactions are re-imported, so // don't overwrite transactions if they are already on the list if !self.local_transactions.contains(&hash) { self.local_transactions.mark_rejected(cloned_tx, err.clone()); } }, - Err(_) => { - self.local_transactions.mark_invalid(cloned_tx); - }, } result } else { @@ -743,9 +741,9 @@ impl TransactionQueue { tx: SignedTransaction, origin: TransactionOrigin, time: QueuingInstant, - condition: Option, + condition: Option, details_provider: &TransactionDetailsProvider, - ) -> Result { + ) -> Result { if origin != TransactionOrigin::Local && tx.gas_price < self.minimal_gas_price { // if it is non-service-transaction => drop let is_service_transaction = tx.gas_price.is_zero(); @@ -757,10 +755,10 @@ impl TransactionQueue { self.minimal_gas_price ); - return Err(Error::Transaction(TransactionError::InsufficientGasPrice { + return Err(transaction::Error::InsufficientGasPrice { minimal: self.minimal_gas_price, got: tx.gas_price, - })); + }); } let is_service_transaction_accepted = match details_provider.is_service_transaction_acceptable(&tx) { @@ -786,10 +784,10 @@ impl TransactionQueue { }; if !is_service_transaction_accepted { - return Err(Error::Transaction(TransactionError::InsufficientGasPrice { - minimal: self.minimal_gas_price, - got: tx.gas_price, - })); + return Err(transaction::Error::InsufficientGasPrice { + minimal: self.minimal_gas_price, + got: tx.gas_price, + }); } } @@ -802,10 +800,10 @@ impl TransactionQueue { full_queues_lowest ); - return Err(Error::Transaction(TransactionError::InsufficientGasPrice { + return Err(transaction::Error::InsufficientGasPrice { minimal: full_queues_lowest, got: tx.gas_price, - })); + }); } let gas_limit = cmp::min(self.tx_gas_limit, self.block_gas_limit); @@ -817,10 +815,10 @@ impl TransactionQueue { self.block_gas_limit, self.tx_gas_limit ); - return Err(Error::Transaction(TransactionError::GasLimitExceeded { + return Err(transaction::Error::GasLimitExceeded { limit: gas_limit, got: tx.gas, - })); + }); } let minimal_gas = details_provider.estimate_gas_required(&tx); @@ -832,10 +830,10 @@ impl TransactionQueue { minimal_gas, ); - return Err(Error::Transaction(TransactionError::InsufficientGas { + return Err(transaction::Error::InsufficientGas { minimal: minimal_gas, got: tx.gas, - })); + }); } let client_account = details_provider.fetch_account(&tx.sender()); @@ -848,17 +846,17 @@ impl TransactionQueue { cost ); - return Err(Error::Transaction(TransactionError::InsufficientBalance { + return Err(transaction::Error::InsufficientBalance { cost: cost, balance: client_account.balance - })); + }); } tx.check_low_s()?; // No invalid transactions beyond this point. let id = self.next_transaction_id; self.next_transaction_id += 1; let vtx = VerifiedTransaction::new(tx, origin, condition, time, id); - let r = self.import_tx(vtx, client_account.nonce).map_err(Error::Transaction); + let r = self.import_tx(vtx, client_account.nonce); assert_eq!(self.future.by_priority.len() + self.current.by_priority.len(), self.by_hash.len()); r } @@ -1140,8 +1138,8 @@ impl TransactionQueue { } } let delay = match tx.condition { - Some(Condition::Number(n)) => n > best_block, - Some(Condition::Timestamp(t)) => t > best_timestamp, + Some(transaction::Condition::Number(n)) => n > best_block, + Some(transaction::Condition::Timestamp(t)) => t > best_timestamp, None => false, }; if delay { @@ -1254,12 +1252,13 @@ impl TransactionQueue { /// iff `(address, nonce)` is the same but `gas_price` is higher. /// /// Returns `true` when transaction was imported successfuly - fn import_tx(&mut self, tx: VerifiedTransaction, state_nonce: U256) -> Result { + fn import_tx(&mut self, tx: VerifiedTransaction, state_nonce: U256) -> Result { if self.by_hash.get(&tx.hash()).is_some() { // Transaction is already imported. trace!(target: "txqueue", "Dropping already imported transaction: {:?}", tx.hash()); - return Err(TransactionError::AlreadyImported); + return Err(transaction::Error::AlreadyImported); } let min_gas_price = (self.minimal_gas_price, self.strategy); @@ -1273,7 +1272,7 @@ impl TransactionQueue { if nonce < state_nonce { // Droping transaction trace!(target: "txqueue", "Dropping old transaction: {:?} (nonce: {} < {})", tx.hash(), nonce, state_nonce); - return Err(TransactionError::Old); + return Err(transaction::Error::Old); } // Update nonces of transactions in future (remove old transactions) @@ -1304,7 +1303,7 @@ impl TransactionQueue { debug!(target: "txqueue", "Importing transaction to future: {:?}", hash); debug!(target: "txqueue", "status: {:?}", self.status()); - return Ok(TransactionImportResult::Future); + return Ok(transaction::ImportResult::Future); } // We might have filled a gap - move some more transactions from future @@ -1328,7 +1327,7 @@ impl TransactionQueue { debug!(target: "txqueue", "Imported transaction to current: {:?}", hash); debug!(target: "txqueue", "status: {:?}", self.status()); - Ok(TransactionImportResult::Current) + Ok(transaction::ImportResult::Current) } /// Updates @@ -1415,19 +1414,20 @@ impl TransactionQueue { } } -fn check_too_cheap(is_in: bool) -> Result<(), TransactionError> { +fn check_too_cheap(is_in: bool) -> Result<(), transaction::Error> { if is_in { Ok(()) } else { - Err(TransactionError::TooCheapToReplace) + Err(transaction::Error::TooCheapToReplace) } } -fn check_if_removed(sender: &Address, nonce: &U256, dropped: Option>) -> Result<(), TransactionError> { +fn check_if_removed(sender: &Address, nonce: &U256, dropped: Option>) -> Result<(), + transaction::Error> { match dropped { Some(ref dropped) => match dropped.get(sender) { Some(min) if nonce >= min => { - Err(TransactionError::LimitReached) + Err(transaction::Error::LimitReached) }, _ => Ok(()), }, @@ -1438,16 +1438,11 @@ fn check_if_removed(sender: &Address, nonce: &U256, dropped: Option) -> TransactionError { - match err.unwrap_err() { - Error::Transaction(e) => e, - _ => panic!("Expected transaction error!"), - } + fn unwrap_tx_err(err: Result) -> transaction::Error { + err.unwrap_err() } fn default_nonce() -> U256 { 123.into() } @@ -1522,7 +1514,7 @@ pub mod test { fn new_unsigned_tx(nonce: U256, gas: U256, gas_price: U256) -> Transaction { Transaction { - action: Action::Create, + action: transaction::Action::Create, value: U256::from(100), data: "3331600055".from_hex().unwrap(), gas: gas, @@ -1632,11 +1624,11 @@ pub mod test { // We may want to reconsider this in the near future so leaving this code in as a // possible alternative. /* - assert_eq!(res.unwrap(), TransactionImportResult::Current); + assert_eq!(res.unwrap(), transaction::ImportResult::Current); assert_eq!(txq.status().pending, 2); assert_eq!(txq.last_nonce(&sender), Some(nonce)); */ - assert_eq!(unwrap_tx_err(res), TransactionError::InsufficientGasPrice { + assert_eq!(unwrap_tx_err(res), transaction::Error::InsufficientGasPrice { minimal: 2.into(), got: 1.into(), }); @@ -1785,14 +1777,14 @@ pub mod test { // First insert one transaction to future let res = txq.add(tx, TransactionOrigin::External, 0, None, &default_tx_provider().with_account_nonce(prev_nonce)); - assert_eq!(res.unwrap(), TransactionImportResult::Future); + assert_eq!(res.unwrap(), transaction::ImportResult::Future); assert_eq!(txq.status().future, 1); // now import second transaction to current let res = txq.add(tx2.clone(), TransactionOrigin::External, 0, None, &default_tx_provider()); // and then there should be only one transaction in current (the one with higher gas_price) - assert_eq!(res.unwrap(), TransactionImportResult::Current); + assert_eq!(res.unwrap(), transaction::ImportResult::Current); assert_eq!(txq.status().pending, 1); assert_eq!(txq.status().future, 0); assert_eq!(txq.current.by_priority.len(), 1); @@ -1810,14 +1802,14 @@ pub mod test { // First insert one transaction to future let res = txq.add(tx.clone(), TransactionOrigin::External, 0, None, &default_tx_provider().with_account_nonce(prev_nonce)); - assert_eq!(res.unwrap(), TransactionImportResult::Future); + assert_eq!(res.unwrap(), transaction::ImportResult::Future); assert_eq!(txq.status().future, 1); // now import second transaction to current let res = txq.add(tx2.clone(), TransactionOrigin::External, 0, None, &default_tx_provider()); // then - assert_eq!(res.unwrap(), TransactionImportResult::Current); + assert_eq!(res.unwrap(), transaction::ImportResult::Current); assert_eq!(txq.status().pending, 2); assert_eq!(txq.status().future, 0); assert_eq!(txq.current.by_priority.len(), 2); @@ -1837,7 +1829,7 @@ pub mod test { let res = txq.add(tx, TransactionOrigin::External, 0, None, &default_tx_provider()); // then - assert_eq!(res.unwrap(), TransactionImportResult::Current); + assert_eq!(res.unwrap(), transaction::ImportResult::Current); let stats = txq.status(); assert_eq!(stats.pending, 1); } @@ -1859,13 +1851,13 @@ pub mod test { let res4 = txq.add(tx4, TransactionOrigin::External, 0, None, &default_tx_provider()); // then - assert_eq!(res1.unwrap(), TransactionImportResult::Current); - assert_eq!(res2.unwrap(), TransactionImportResult::Current); - assert_eq!(unwrap_tx_err(res3), TransactionError::InsufficientGasPrice { + assert_eq!(res1.unwrap(), transaction::ImportResult::Current); + assert_eq!(res2.unwrap(), transaction::ImportResult::Current); + assert_eq!(unwrap_tx_err(res3), transaction::Error::InsufficientGasPrice { minimal: U256::from(15), got: U256::from(10), }); - assert_eq!(res4.unwrap(), TransactionImportResult::Current); + assert_eq!(res4.unwrap(), transaction::ImportResult::Current); let stats = txq.status(); assert_eq!(stats.pending, 3); assert_eq!(txq.top_transactions()[0].gas, 40000.into()); @@ -1893,10 +1885,10 @@ pub mod test { let res4 = txq.add(tx4, TransactionOrigin::External, 0, None, &default_tx_provider()); // then - assert_eq!(res1.unwrap(), TransactionImportResult::Current); - assert_eq!(res2.unwrap(), TransactionImportResult::Current); - assert_eq!(res3.unwrap(), TransactionImportResult::Current); - assert_eq!(res4.unwrap(), TransactionImportResult::Current); + assert_eq!(res1.unwrap(), transaction::ImportResult::Current); + assert_eq!(res2.unwrap(), transaction::ImportResult::Current); + assert_eq!(res3.unwrap(), transaction::ImportResult::Current); + assert_eq!(res4.unwrap(), transaction::ImportResult::Current); let stats = txq.status(); assert_eq!(stats.pending, 4); assert_eq!(txq.top_transactions()[0].gas, 30_000.into()); @@ -1936,7 +1928,7 @@ pub mod test { let res = txq.add(tx, TransactionOrigin::External, 0, None, &default_tx_provider()); // then - assert_eq!(unwrap_tx_err(res), TransactionError::GasLimitExceeded { + assert_eq!(unwrap_tx_err(res), transaction::Error::GasLimitExceeded { limit: U256::from(50_000), got: gas, }); @@ -1960,7 +1952,7 @@ pub mod test { let res = txq.add(tx, TransactionOrigin::External, 0, None, &default_tx_provider().with_account(account)); // then - assert_eq!(unwrap_tx_err(res), TransactionError::InsufficientBalance { + assert_eq!(unwrap_tx_err(res), transaction::Error::InsufficientBalance { balance: U256::from(1), cost: U256::from(100_100), }); @@ -1980,7 +1972,7 @@ pub mod test { let res = txq.add(tx, TransactionOrigin::External, 0, None, &default_tx_provider()); // then - assert_eq!(unwrap_tx_err(res), TransactionError::InsufficientGasPrice { + assert_eq!(unwrap_tx_err(res), transaction::Error::InsufficientGasPrice { minimal: U256::from(2), got: U256::from(1), }); @@ -2000,7 +1992,7 @@ pub mod test { let res = txq.add(tx, TransactionOrigin::Local, 0, None, &default_tx_provider()); // then - assert_eq!(res.unwrap(), TransactionImportResult::Current); + assert_eq!(res.unwrap(), transaction::ImportResult::Current); let stats = txq.status(); assert_eq!(stats.pending, 1); assert_eq!(stats.future, 0); @@ -2235,8 +2227,8 @@ pub mod test { let res2 = txq.add(tx2.clone(), TransactionOrigin::External, 0, None, &default_tx_provider()).unwrap(); // then - assert_eq!(res1, TransactionImportResult::Current); - assert_eq!(res2, TransactionImportResult::Future); + assert_eq!(res1, transaction::ImportResult::Current); + assert_eq!(res2, transaction::ImportResult::Future); let stats = txq.status(); assert_eq!(stats.pending, 1); assert_eq!(stats.future, 1); @@ -2253,12 +2245,12 @@ pub mod test { let (tx, tx2) = new_tx_pair_default(1.into(), 0.into()); // when - let res1 = txq.add(tx.clone(), TransactionOrigin::External, 0, Some(Condition::Number(1)), &default_tx_provider()).unwrap(); + let res1 = txq.add(tx.clone(), TransactionOrigin::External, 0, Some(transaction::Condition::Number(1)), &default_tx_provider()).unwrap(); let res2 = txq.add(tx2.clone(), TransactionOrigin::External, 0, None, &default_tx_provider()).unwrap(); // then - assert_eq!(res1, TransactionImportResult::Current); - assert_eq!(res2, TransactionImportResult::Current); + assert_eq!(res1, transaction::ImportResult::Current); + assert_eq!(res2, transaction::ImportResult::Current); let top = txq.top_transactions_at(0, 0, None); assert_eq!(top.len(), 0); let top = txq.top_transactions_at(1, 0, None); @@ -2396,7 +2388,7 @@ pub mod test { // then let t = txq.top_transactions(); - assert_eq!(unwrap_tx_err(res), TransactionError::InsufficientGasPrice { minimal: 2.into(), got: 1.into() }); + assert_eq!(unwrap_tx_err(res), transaction::Error::InsufficientGasPrice { minimal: 2.into(), got: 1.into() }); assert_eq!(txq.status().pending, 1); assert_eq!(t.len(), 1); assert_eq!(t[0], tx); @@ -2478,7 +2470,7 @@ pub mod test { let res = txq.add(tx, TransactionOrigin::External, 0, None, &default_tx_provider().with_account_nonce(last_nonce)); // then - assert_eq!(unwrap_tx_err(res), TransactionError::Old); + assert_eq!(unwrap_tx_err(res), transaction::Error::Old); let stats = txq.status(); assert_eq!(stats.pending, 0); assert_eq!(stats.future, 0); @@ -2498,7 +2490,7 @@ pub mod test { let res = txq.add(tx2.clone(), TransactionOrigin::External, 0, None, &default_tx_provider().with_account_nonce(nonce)); // then - assert_eq!(unwrap_tx_err(res), TransactionError::AlreadyImported); + assert_eq!(unwrap_tx_err(res), transaction::Error::AlreadyImported); let stats = txq.status(); assert_eq!(stats.future, 1); assert_eq!(stats.pending, 0); @@ -2548,8 +2540,6 @@ pub mod test { #[test] fn should_not_replace_same_transaction_if_the_fee_is_less_than_minimal_bump() { - use ethcore_logger::init_log; - init_log(); // given let mut txq = TransactionQueue::default(); let keypair = Random.generate().unwrap(); @@ -2565,7 +2555,7 @@ pub mod test { let res = txq.add(tx2, TransactionOrigin::External, 0, None, &default_tx_provider()); // then - assert_eq!(unwrap_tx_err(res), TransactionError::TooCheapToReplace); + assert_eq!(unwrap_tx_err(res), transaction::Error::TooCheapToReplace); let stats = txq.status(); assert_eq!(stats.pending, 1); assert_eq!(stats.future, 0); @@ -2574,8 +2564,6 @@ pub mod test { #[test] fn should_replace_same_transaction_when_has_higher_fee() { - use ethcore_logger::init_log; - init_log(); // given let mut txq = TransactionQueue::default(); let keypair = Random.generate().unwrap(); @@ -2697,9 +2685,9 @@ pub mod test { // when // Insert first transaction - assert_eq!(txq.add(tx1, TransactionOrigin::External, 0, None, &default_tx_provider().with_account_nonce(nonce1)).unwrap(), TransactionImportResult::Current); + assert_eq!(txq.add(tx1, TransactionOrigin::External, 0, None, &default_tx_provider().with_account_nonce(nonce1)).unwrap(), transaction::ImportResult::Current); // Second should go to future - assert_eq!(txq.add(tx2, TransactionOrigin::External, 0, None, &default_tx_provider().with_account_nonce(nonce1)).unwrap(), TransactionImportResult::Future); + assert_eq!(txq.add(tx2, TransactionOrigin::External, 0, None, &default_tx_provider().with_account_nonce(nonce1)).unwrap(), transaction::ImportResult::Future); // Now block is imported txq.cull(sender, nonce2 - U256::from(1)); // tx2 should be not be promoted to current @@ -2718,9 +2706,10 @@ pub mod test { assert_eq!(txq.has_local_pending_transactions(), false); // when - assert_eq!(txq.add(tx1, TransactionOrigin::External, 0, None, &default_tx_provider()).unwrap(), TransactionImportResult::Current); + assert_eq!(txq.add(tx1, TransactionOrigin::External, 0, None, &default_tx_provider()).unwrap(), transaction::ImportResult::Current); assert_eq!(txq.has_local_pending_transactions(), false); - assert_eq!(txq.add(tx2, TransactionOrigin::Local, 0, None, &default_tx_provider()).unwrap(), TransactionImportResult::Current); + assert_eq!(txq.add(tx2, TransactionOrigin::Local, 0, None, &default_tx_provider()).unwrap(), + transaction::ImportResult::Current); // then assert_eq!(txq.has_local_pending_transactions(), true); @@ -2740,8 +2729,8 @@ pub mod test { let prev_nonce = default_account_details().nonce - U256::one(); // when - assert_eq!(txq.add(tx2, TransactionOrigin::External, 0, None, &default_tx_provider().with_account_nonce(prev_nonce)).unwrap(), TransactionImportResult::Future); - assert_eq!(txq.add(tx1.clone(), TransactionOrigin::External, 0, None, &default_tx_provider().with_account_nonce(prev_nonce)).unwrap(), TransactionImportResult::Future); + assert_eq!(txq.add(tx2, TransactionOrigin::External, 0, None, &default_tx_provider().with_account_nonce(prev_nonce)).unwrap(), transaction::ImportResult::Future); + assert_eq!(txq.add(tx1.clone(), TransactionOrigin::External, 0, None, &default_tx_provider().with_account_nonce(prev_nonce)).unwrap(), transaction::ImportResult::Future); // then assert_eq!(txq.future.by_priority.len(), 1); @@ -2777,7 +2766,7 @@ pub mod test { // then assert_eq!(txq.last_nonce(&sender).unwrap(), 125.into()); - assert_eq!(res.unwrap(), TransactionImportResult::Current); + assert_eq!(res.unwrap(), transaction::ImportResult::Current); assert_eq!(txq.current.by_priority.len(), 3); } @@ -2793,8 +2782,8 @@ pub mod test { let res2 = txq.add(tx2, TransactionOrigin::Local, 0, None, &default_tx_provider().with_tx_gas_required(high_gas)); // then - assert_eq!(res1.unwrap(), TransactionImportResult::Current); - assert_eq!(unwrap_tx_err(res2), TransactionError::InsufficientGas { + assert_eq!(res1.unwrap(), transaction::ImportResult::Current); + assert_eq!(unwrap_tx_err(res2), transaction::Error::InsufficientGas { minimal: 100_001.into(), got: 100_000.into(), }); @@ -2872,12 +2861,12 @@ pub mod test { // when assert_eq!(unwrap_tx_err(txq.add(tx1, TransactionOrigin::External, 0, None, &default_tx_provider())), - TransactionError::InsufficientGasPrice { + transaction::Error::InsufficientGasPrice { minimal: 100.into(), got: 0.into(), }); assert_eq!(unwrap_tx_err(txq.add(tx2, TransactionOrigin::RetractedBlock, 0, None, &default_tx_provider())), - TransactionError::InsufficientGasPrice { + transaction::Error::InsufficientGasPrice { minimal: 100.into(), got: 0.into(), }); @@ -2896,7 +2885,7 @@ pub mod test { // when let details_provider = default_tx_provider().service_transaction_checker_returns_error("Contract error"); assert_eq!(unwrap_tx_err(txq.add(tx, TransactionOrigin::External, 0, None, &details_provider)), - TransactionError::InsufficientGasPrice { + transaction::Error::InsufficientGasPrice { minimal: 100.into(), got: 0.into(), }); diff --git a/ethcore/src/miner/work_notify.rs b/miner/src/work_notify.rs similarity index 82% rename from ethcore/src/miner/work_notify.rs rename to miner/src/work_notify.rs index 692257285..f02393c89 100644 --- a/ethcore/src/miner/work_notify.rs +++ b/miner/src/work_notify.rs @@ -14,19 +14,22 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . +//! Sends HTTP notifications to a list of URLs every time new work is available. + +extern crate ethash; extern crate hyper; +use self::hyper::header::ContentType; +use self::hyper::method::Method; +use self::hyper::client::{Request, Response, Client}; +use self::hyper::{Next, Url}; +use self::hyper::net::HttpStream; + +use self::ethash::SeedHashCompute; + use std::io::Write; -use hyper::header::ContentType; -use hyper::method::Method; -use hyper::client::{Request, Response, Client}; -use hyper::{Next}; -use hyper::net::HttpStream; -use ethash::SeedHashCompute; -use hyper::Url; use ethereum_types::{H256, U256}; use parking_lot::Mutex; -use ethereum::ethash::Ethash; /// Trait for notifying about new mining work pub trait NotifyWork : Send + Sync { @@ -34,6 +37,7 @@ pub trait NotifyWork : Send + Sync { fn notify(&self, pow_hash: H256, difficulty: U256, number: u64); } +/// POSTs info about new work to given urls. pub struct WorkPoster { urls: Vec, client: Mutex>, @@ -41,6 +45,7 @@ pub struct WorkPoster { } impl WorkPoster { + /// Create new `WorkPoster`. pub fn new(urls: &[String]) -> Self { let urls = urls.into_iter().filter_map(|u| { match Url::parse(u) { @@ -67,10 +72,19 @@ impl WorkPoster { } } +/// Convert an Ethash difficulty to the target boundary. Basically just `f(x) = 2^256 / x`. +fn difficulty_to_boundary(difficulty: &U256) -> H256 { + if *difficulty <= U256::one() { + U256::max_value().into() + } else { + (((U256::one() << 255) / *difficulty) << 1).into() + } +} + impl NotifyWork for WorkPoster { fn notify(&self, pow_hash: H256, difficulty: U256, number: u64) { // TODO: move this to engine - let target = Ethash::difficulty_to_boundary(&difficulty); + let target = difficulty_to_boundary(&difficulty); let seed_hash = &self.seed_compute.lock().hash_block_number(number); let seed_hash = H256::from_slice(&seed_hash[..]); let body = format!( diff --git a/parity/configuration.rs b/parity/configuration.rs index a525e8043..085bd6a5d 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -1137,7 +1137,8 @@ mod tests { use devtools::{RandomTempPath}; use ethcore::client::{VMType, BlockId}; - use ethcore::miner::{MinerOptions, PrioritizationStrategy}; + use ethcore::miner::MinerOptions; + use miner::transaction_queue::PrioritizationStrategy; use parity_rpc::NetworkSettings; use updater::{UpdatePolicy, UpdateFilter, ReleaseTrack}; diff --git a/parity/dapps.rs b/parity/dapps.rs index ac20fb304..8d200aa09 100644 --- a/parity/dapps.rs +++ b/parity/dapps.rs @@ -17,10 +17,10 @@ use std::path::PathBuf; use std::sync::Arc; +use bytes::Bytes; use dir::default_data_path; use dir::helpers::replace_home; use ethcore::client::{Client, BlockChainClient, BlockId}; -use ethcore::transaction::{Transaction, Action}; use ethsync::LightSync; use futures::{future, IntoFuture, Future}; use hash_fetch::fetch::Client as FetchClient; @@ -30,8 +30,8 @@ use light::on_demand::{self, OnDemand}; use node_health::{SyncStatus, NodeHealth}; use rpc; use rpc_apis::SignerService; +use transaction::{Transaction, Action}; use ethereum_types::Address; -use bytes::Bytes; #[derive(Debug, PartialEq, Clone)] pub struct Configuration { diff --git a/parity/helpers.rs b/parity/helpers.rs index 86bbf083d..4ac92c9fc 100644 --- a/parity/helpers.rs +++ b/parity/helpers.rs @@ -22,7 +22,8 @@ use ethereum_types::{U256, clean_0x, Address}; use kvdb_rocksdb::CompactionProfile; use journaldb::Algorithm; use ethcore::client::{Mode, BlockId, VMType, DatabaseCompactionProfile, ClientConfig, VerifierType}; -use ethcore::miner::{PendingSet, GasLimit, PrioritizationStrategy}; +use ethcore::miner::{PendingSet, GasLimit}; +use miner::transaction_queue::PrioritizationStrategy; use cache::CacheConfig; use dir::DatabaseDirectories; use dir::helpers::replace_home; diff --git a/parity/main.rs b/parity/main.rs index e539467ad..ad3f786b1 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -47,12 +47,14 @@ extern crate time; extern crate toml; extern crate ethcore; +extern crate ethcore_bytes as bytes; extern crate ethcore_devtools as devtools; extern crate ethcore_io as io; extern crate ethcore_light as light; extern crate ethcore_logger; -extern crate ethcore_bytes as bytes; +extern crate ethcore_miner as miner; extern crate ethcore_network as network; +extern crate ethcore_transaction as transaction; extern crate ethereum_types; extern crate migration as migr; extern crate kvdb; diff --git a/parity/rpc_apis.rs b/parity/rpc_apis.rs index e39b42352..e519daf77 100644 --- a/parity/rpc_apis.rs +++ b/parity/rpc_apis.rs @@ -24,21 +24,22 @@ pub use parity_rpc::dapps::{DappsService, LocalDapp}; use ethcore::account_provider::AccountProvider; use ethcore::client::Client; -use ethcore::miner::{Miner, ExternalMiner}; +use ethcore::miner::Miner; use ethcore::snapshot::SnapshotService; use ethcore_logger::RotatingLogger; use ethsync::{ManageNetwork, SyncProvider, LightSync}; use hash_fetch::fetch::Client as FetchClient; use jsonrpc_core::{self as core, MetaIoHandler}; -use light::{TransactionQueue as LightTransactionQueue, Cache as LightDataCache}; use light::client::LightChainClient; +use light::{TransactionQueue as LightTransactionQueue, Cache as LightDataCache}; +use miner::external::ExternalMiner; use node_health::NodeHealth; use parity_reactor; use parity_rpc::dispatch::{FullDispatcher, LightDispatcher}; use parity_rpc::informant::{ActivityNotifier, ClientNotifier}; use parity_rpc::{Metadata, NetworkSettings, Host}; -use updater::Updater; use parking_lot::{Mutex, RwLock}; +use updater::Updater; #[derive(Debug, PartialEq, Clone, Eq, Hash)] pub enum Api { diff --git a/parity/run.rs b/parity/run.rs index 2d620c1e2..ae5a299e6 100644 --- a/parity/run.rs +++ b/parity/run.rs @@ -18,31 +18,32 @@ use std::fmt; use std::sync::{Arc, Weak}; use std::net::{TcpListener}; +use ansi_term::Colour; use ctrlc::CtrlC; -use ethcore_logger::{Config as LogConfig, RotatingLogger}; use ethcore::account_provider::{AccountProvider, AccountProviderSettings}; use ethcore::client::{Client, Mode, DatabaseCompactionProfile, VMType, BlockChainClient}; use ethcore::ethstore::ethkey; -use ethcore::miner::{Miner, MinerService, ExternalMiner, MinerOptions}; +use ethcore::miner::{Miner, MinerService, MinerOptions}; use ethcore::miner::{StratumOptions, Stratum}; use ethcore::service::ClientService; use ethcore::snapshot; use ethcore::spec::{SpecParams, OptimizeFor}; use ethcore::verification::queue::VerifierSettings; +use ethcore_logger::{Config as LogConfig, RotatingLogger}; use ethsync::{self, SyncConfig}; use fdlimit::raise_fd_limit; use hash_fetch::fetch::{Fetch, Client as FetchClient}; use informant::{Informant, LightNodeInformantData, FullNodeInformantData}; +use journaldb::Algorithm; use light::Cache as LightDataCache; +use miner::external::ExternalMiner; +use node_filter::NodeFilter; use node_health; use parity_reactor::EventLoop; use parity_rpc::{NetworkSettings, informant, is_major_importing}; -use updater::{UpdatePolicy, Updater}; -use ansi_term::Colour; -use parity_version::version; use parking_lot::{Condvar, Mutex}; -use node_filter::NodeFilter; -use journaldb::Algorithm; +use updater::{UpdatePolicy, Updater}; +use parity_version::version; use params::{ SpecType, Pruning, AccountsConfig, GasPricerConfig, MinerExtras, Switch, @@ -156,7 +157,7 @@ struct FullNodeInfo { } impl ::local_store::NodeInfo for FullNodeInfo { - fn pending_transactions(&self) -> Vec<::ethcore::transaction::PendingTransaction> { + fn pending_transactions(&self) -> Vec<::transaction::PendingTransaction> { let miner = match self.miner.as_ref() { Some(m) => m, None => return Vec::new(), diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index 3fbe7610b..7701097eb 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -36,20 +36,25 @@ jsonrpc-ipc-server = { git = "https://github.com/paritytech/jsonrpc.git", branch jsonrpc-macros = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.9" } jsonrpc-pubsub = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.9" } -ethcore-io = { path = "../util/io" } -ethcore-bytes = { path = "../util/bytes" } -ethereum-types = "0.1" -ethcore = { path = "../ethcore" } -ethcrypto = { path = "../ethcrypto" } -ethkey = { path = "../ethkey" } -ethstore = { path = "../ethstore" } ethash = { path = "../ethash" } -ethsync = { path = "../sync" } -ethjson = { path = "../json" } +ethcore = { path = "../ethcore" } +ethcore-bytes = { path = "../util/bytes" } ethcore-devtools = { path = "../devtools" } +ethcore-io = { path = "../util/io" } ethcore-light = { path = "../ethcore/light" } ethcore-logger = { path = "../logger" } +ethcore-miner = { path = "../miner" } +ethcore-transaction = { path = "../ethcore/transaction" } +ethereum-types = "0.1" + +ethcrypto = { path = "../ethcrypto" } +ethjson = { path = "../json" } +ethkey = { path = "../ethkey" } +ethstore = { path = "../ethstore" } +ethsync = { path = "../sync" } fetch = { path = "../util/fetch" } +hardware-wallet = { path = "../hw" } +keccak-hash = { path = "../util/hash" } node-health = { path = "../dapps/node-health" } parity-reactor = { path = "../util/reactor" } parity-updater = { path = "../updater" } @@ -57,8 +62,6 @@ parity-version = { path = "../util/version" } rlp = { path = "../util/rlp" } stats = { path = "../util/stats" } vm = { path = "../ethcore/vm" } -keccak-hash = { path = "../util/hash" } -hardware-wallet = { path = "../hw" } [dev-dependencies] pretty_assertions = "0.1" diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index bc3964a9f..ece8d956e 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -50,6 +50,8 @@ extern crate ethcore_bytes as bytes; extern crate ethcore_devtools as devtools; extern crate ethcore_io as io; extern crate ethcore_light as light; +extern crate ethcore_miner as miner; +extern crate ethcore_transaction as transaction; extern crate ethcrypto as crypto; extern crate ethereum_types; extern crate ethkey; diff --git a/rpc/src/v1/helpers/dispatch.rs b/rpc/src/v1/helpers/dispatch.rs index f6df58a41..b082320d5 100644 --- a/rpc/src/v1/helpers/dispatch.rs +++ b/rpc/src/v1/helpers/dispatch.rs @@ -36,9 +36,9 @@ use ethsync::LightSync; use ethcore::ids::BlockId; use ethcore::miner::MinerService; use ethcore::client::MiningBlockChainClient; -use ethcore::transaction::{Action, SignedTransaction, PendingTransaction, Transaction}; use ethcore::account_provider::AccountProvider; use crypto::DEFAULT_MAC; +use transaction::{Action, SignedTransaction, PendingTransaction, Transaction}; use jsonrpc_core::{BoxFuture, Result, Error}; use jsonrpc_core::futures::{future, Future, Poll, Async}; @@ -411,7 +411,6 @@ impl Dispatcher for LightDispatcher { let hash = signed_transaction.transaction.hash(); self.transaction_queue.write().import(signed_transaction) - .map_err(Into::into) .map_err(errors::transaction) .map(|_| hash) } diff --git a/rpc/src/v1/helpers/errors.rs b/rpc/src/v1/helpers/errors.rs index 3960107e7..9393fc53a 100644 --- a/rpc/src/v1/helpers/errors.rs +++ b/rpc/src/v1/helpers/errors.rs @@ -17,10 +17,12 @@ //! RPC Error codes and error objects use std::fmt; -use rlp::DecoderError; -use ethcore::error::{Error as EthcoreError, CallError, TransactionError}; + use ethcore::account_provider::{SignError as AccountError}; +use ethcore::error::{Error as EthcoreError, CallError}; use jsonrpc_core::{futures, Error, ErrorCode, Value}; +use rlp::DecoderError; +use transaction::Error as TransactionError; mod codes { // NOTE [ToDr] Codes from [-32099, -32000] @@ -287,7 +289,7 @@ pub fn password(error: AccountError) -> Error { } pub fn transaction_message(error: TransactionError) -> String { - use ethcore::error::TransactionError::*; + use self::TransactionError::*; match error { AlreadyImported => "Transaction with the same hash was already imported.".into(), @@ -310,6 +312,7 @@ pub fn transaction_message(error: TransactionError) -> String { GasLimitExceeded { limit, got } => { format!("Transaction cost exceeds current gas limit. Limit: {}, got: {}. Try decreasing supplied gas.", limit, got) }, + InvalidSignature(sig) => format!("Invalid signature: {}", sig), InvalidChainId => "Invalid chain id.".into(), InvalidGasLimit(_) => "Supplied gas is beyond limit.".into(), SenderBanned => "Sender is banned in local queue.".into(), @@ -319,8 +322,8 @@ pub fn transaction_message(error: TransactionError) -> String { } } -pub fn transaction(error: EthcoreError) -> Error { - +pub fn transaction>(error: T) -> Error { + let error = error.into(); if let EthcoreError::Transaction(e) = error { Error { code: ErrorCode::ServerError(codes::TRANSACTION_ERROR), diff --git a/rpc/src/v1/helpers/fake_sign.rs b/rpc/src/v1/helpers/fake_sign.rs index c2010f4b0..84a225d81 100644 --- a/rpc/src/v1/helpers/fake_sign.rs +++ b/rpc/src/v1/helpers/fake_sign.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use ethcore::transaction::{Transaction, SignedTransaction, Action}; +use transaction::{Transaction, SignedTransaction, Action}; use ethereum_types::U256; use jsonrpc_core::Error; diff --git a/rpc/src/v1/helpers/light_fetch.rs b/rpc/src/v1/helpers/light_fetch.rs index c32414b79..1099102c3 100644 --- a/rpc/src/v1/helpers/light_fetch.rs +++ b/rpc/src/v1/helpers/light_fetch.rs @@ -23,7 +23,6 @@ use ethcore::encoded; use ethcore::executed::{Executed, ExecutionError}; use ethcore::ids::BlockId; use ethcore::filter::Filter as EthcoreFilter; -use ethcore::transaction::{Action, Transaction as EthTransaction, SignedTransaction, LocalizedTransaction}; use ethcore::receipt::Receipt; use jsonrpc_core::{BoxFuture, Result}; @@ -41,6 +40,7 @@ use ethsync::LightSync; use ethereum_types::{U256, Address}; use hash::H256; use parking_lot::Mutex; +use transaction::{Action, Transaction as EthTransaction, SignedTransaction, LocalizedTransaction}; use v1::helpers::{CallRequest as CallRequestHelper, errors, dispatch}; use v1::types::{BlockNumber, CallRequest, Log, Transaction}; diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 4281c482a..08ce7fbbc 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -33,10 +33,11 @@ use ethcore::ethereum::Ethash; use ethcore::filter::Filter as EthcoreFilter; use ethcore::header::{Header as BlockHeader, BlockNumber as EthBlockNumber}; use ethcore::log_entry::LogEntry; -use ethcore::miner::{MinerService, ExternalMinerService}; -use ethcore::transaction::SignedTransaction; +use ethcore::miner::MinerService; use ethcore::snapshot::SnapshotService; use ethsync::{SyncProvider}; +use miner::external::ExternalMinerService; +use transaction::SignedTransaction; use jsonrpc_core::{BoxFuture, Result}; use jsonrpc_core::futures::future; diff --git a/rpc/src/v1/impls/light/eth.rs b/rpc/src/v1/impls/light/eth.rs index 51229cb79..af93b2b49 100644 --- a/rpc/src/v1/impls/light/eth.rs +++ b/rpc/src/v1/impls/light/eth.rs @@ -30,14 +30,14 @@ use light::on_demand::{request, OnDemand}; use ethcore::account_provider::{AccountProvider, DappId}; use ethcore::encoded; -use ethcore::ids::BlockId; use ethcore::filter::Filter as EthcoreFilter; -use ethcore::transaction::SignedTransaction; +use ethcore::ids::BlockId; use ethsync::LightSync; -use rlp::UntrustedRlp; use hash::{KECCAK_NULL_RLP, KECCAK_EMPTY_LIST_RLP}; use ethereum_types::U256; use parking_lot::{RwLock, Mutex}; +use rlp::UntrustedRlp; +use transaction::SignedTransaction; use v1::impls::eth_filter::Filterable; use v1::helpers::{errors, limit_logs}; @@ -367,7 +367,6 @@ impl Eth for EthClient { self.transaction_queue.write().import(signed.into()) .map(|_| hash) - .map_err(Into::into) .map_err(errors::transaction) }) .map(Into::into) diff --git a/rpc/src/v1/impls/personal.rs b/rpc/src/v1/impls/personal.rs index b6b56d1ae..c3560fe9d 100644 --- a/rpc/src/v1/impls/personal.rs +++ b/rpc/src/v1/impls/personal.rs @@ -17,12 +17,12 @@ //! Account management (personal) rpc implementation use std::sync::Arc; -use ethcore::account_provider::AccountProvider; -use ethcore::transaction::PendingTransaction; - use bytes::{Bytes, ToPretty}; +use ethcore::account_provider::AccountProvider; +use transaction::PendingTransaction; use ethereum_types::{H520, U128, Address}; use ethkey::{public_to_address, recover, Signature}; + use jsonrpc_core::{BoxFuture, Result}; use jsonrpc_core::futures::{future, Future}; use v1::helpers::errors; diff --git a/rpc/src/v1/impls/signer.rs b/rpc/src/v1/impls/signer.rs index 04f510702..ce3f13b97 100644 --- a/rpc/src/v1/impls/signer.rs +++ b/rpc/src/v1/impls/signer.rs @@ -19,11 +19,11 @@ use std::sync::Arc; use ethcore::account_provider::AccountProvider; -use ethcore::transaction::{SignedTransaction, PendingTransaction}; use ethkey; use parity_reactor::Remote; -use rlp::UntrustedRlp; use parking_lot::Mutex; +use rlp::UntrustedRlp; +use transaction::{SignedTransaction, PendingTransaction}; use jsonrpc_core::{Result, BoxFuture, Error}; use jsonrpc_core::futures::{future, Future, IntoFuture}; diff --git a/rpc/src/v1/impls/traces.rs b/rpc/src/v1/impls/traces.rs index 258f6747f..6ee10e237 100644 --- a/rpc/src/v1/impls/traces.rs +++ b/rpc/src/v1/impls/traces.rs @@ -19,8 +19,8 @@ use std::sync::Arc; use ethcore::client::{MiningBlockChainClient, CallAnalytics, TransactionId, TraceId}; -use ethcore::transaction::SignedTransaction; use rlp::UntrustedRlp; +use transaction::SignedTransaction; use jsonrpc_core::Result; use jsonrpc_macros::Trailing; diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index 620035d8e..c8444d304 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -25,13 +25,15 @@ use ethcore::block::Block; use ethcore::client::{BlockChainClient, Client, ClientConfig}; use ethcore::ethereum; use ethcore::ids::BlockId; -use ethcore::miner::{MinerOptions, Banning, GasPricer, MinerService, ExternalMiner, Miner, PendingSet, PrioritizationStrategy, GasLimit}; +use ethcore::miner::{MinerOptions, Banning, GasPricer, MinerService, Miner, PendingSet, GasLimit}; use ethcore::spec::{Genesis, Spec}; use ethcore::views::BlockView; use ethjson::blockchain::BlockChain; use ethjson::state::test::ForkSpec; use io::IoChannel; use kvdb_memorydb; +use miner::external::ExternalMiner; +use miner::transaction_queue::PrioritizationStrategy; use parking_lot::Mutex; use jsonrpc_core::IoHandler; diff --git a/rpc/src/v1/tests/helpers/miner_service.rs b/rpc/src/v1/tests/helpers/miner_service.rs index ed68c3789..994cd544a 100644 --- a/rpc/src/v1/tests/helpers/miner_service.rs +++ b/rpc/src/v1/tests/helpers/miner_service.rs @@ -20,15 +20,16 @@ use std::collections::{BTreeMap, HashMap}; use std::collections::hash_map::Entry; use ethereum_types::{H256, U256, Address}; use bytes::Bytes; -use parking_lot::{RwLock, Mutex}; -use ethcore::error::Error; -use ethcore::client::MiningBlockChainClient; -use ethcore::block::ClosedBlock; -use ethcore::header::BlockNumber; -use ethcore::transaction::{UnverifiedTransaction, SignedTransaction, PendingTransaction}; -use ethcore::receipt::{Receipt, RichReceipt}; -use ethcore::miner::{MinerService, MinerStatus, TransactionImportResult, LocalTransactionStatus}; use ethcore::account_provider::SignError as AccountError; +use ethcore::block::ClosedBlock; +use ethcore::client::MiningBlockChainClient; +use ethcore::error::Error; +use ethcore::header::BlockNumber; +use ethcore::miner::{MinerService, MinerStatus}; +use miner::local_transactions::Status as LocalTransactionStatus; +use ethcore::receipt::{Receipt, RichReceipt}; +use parking_lot::{RwLock, Mutex}; +use transaction::{UnverifiedTransaction, SignedTransaction, PendingTransaction, ImportResult as TransactionImportResult}; /// Test miner service. pub struct TestMinerService { diff --git a/rpc/src/v1/tests/mocked/eth.rs b/rpc/src/v1/tests/mocked/eth.rs index dabfd99a5..9abb94aa7 100644 --- a/rpc/src/v1/tests/mocked/eth.rs +++ b/rpc/src/v1/tests/mocked/eth.rs @@ -18,20 +18,21 @@ use std::str::FromStr; use std::collections::HashMap; use std::sync::Arc; use std::time::{Instant, Duration}; -use rustc_hex::{FromHex, ToHex}; -use time::get_time; -use rlp; use ethereum_types::{H256, U256, Address}; use parking_lot::Mutex; -use ethkey::Secret; use ethcore::account_provider::AccountProvider; use ethcore::client::{TestBlockChainClient, EachBlockWith, Executed, TransactionId}; use ethcore::log_entry::{LocalizedLogEntry, LogEntry}; +use ethcore::miner::MinerService; use ethcore::receipt::{LocalizedReceipt, TransactionOutcome}; -use ethcore::transaction::{Transaction, Action}; -use ethcore::miner::{ExternalMiner, MinerService}; +use ethkey::Secret; use ethsync::SyncState; +use miner::external::ExternalMiner; +use rlp; +use rustc_hex::{FromHex, ToHex}; +use time::get_time; +use transaction::{Transaction, Action}; use jsonrpc_core::IoHandler; use v1::{Eth, EthClient, EthClientOptions, EthFilter, EthFilterClient, EthSigning, SigningUnsafeClient}; @@ -539,7 +540,7 @@ fn rpc_eth_transaction_count_by_number_pending() { fn rpc_eth_pending_transaction_by_hash() { use ethereum_types::H256; use rlp; - use ethcore::transaction::SignedTransaction; + use transaction::SignedTransaction; let tester = EthTester::default(); { diff --git a/rpc/src/v1/tests/mocked/parity_set.rs b/rpc/src/v1/tests/mocked/parity_set.rs index cb5c046d1..0666d4f42 100644 --- a/rpc/src/v1/tests/mocked/parity_set.rs +++ b/rpc/src/v1/tests/mocked/parity_set.rs @@ -212,7 +212,7 @@ fn rpc_parity_set_hash_content() { #[test] fn rpc_parity_remove_transaction() { - use ethcore::transaction::{Transaction, Action}; + use transaction::{Transaction, Action}; let miner = miner_service(); let client = client_service(); diff --git a/rpc/src/v1/tests/mocked/personal.rs b/rpc/src/v1/tests/mocked/personal.rs index f81b8188d..6dd1da567 100644 --- a/rpc/src/v1/tests/mocked/personal.rs +++ b/rpc/src/v1/tests/mocked/personal.rs @@ -21,9 +21,9 @@ use bytes::ToPretty; use ethereum_types::{U256, Address}; use ethcore::account_provider::AccountProvider; use ethcore::client::TestBlockChainClient; -use ethcore::transaction::{Action, Transaction}; use jsonrpc_core::IoHandler; use parking_lot::Mutex; +use transaction::{Action, Transaction}; use v1::{PersonalClient, Personal, Metadata}; use v1::helpers::nonce; diff --git a/rpc/src/v1/tests/mocked/signer.rs b/rpc/src/v1/tests/mocked/signer.rs index ee07622d7..e7aa49d5a 100644 --- a/rpc/src/v1/tests/mocked/signer.rs +++ b/rpc/src/v1/tests/mocked/signer.rs @@ -21,10 +21,10 @@ use bytes::ToPretty; use ethcore::account_provider::AccountProvider; use ethcore::client::TestBlockChainClient; -use ethcore::transaction::{Transaction, Action, SignedTransaction}; use parity_reactor::EventLoop; use parking_lot::Mutex; use rlp::encode; +use transaction::{Transaction, Action, SignedTransaction}; use serde_json; use jsonrpc_core::IoHandler; diff --git a/rpc/src/v1/tests/mocked/signing.rs b/rpc/src/v1/tests/mocked/signing.rs index ff8017806..10c2dd116 100644 --- a/rpc/src/v1/tests/mocked/signing.rs +++ b/rpc/src/v1/tests/mocked/signing.rs @@ -32,13 +32,13 @@ use v1::tests::mocked::parity; use ethereum_types::{U256, Address}; use bytes::ToPretty; -use ethkey::Secret; use ethcore::account_provider::AccountProvider; use ethcore::client::TestBlockChainClient; -use ethcore::transaction::{Transaction, Action, SignedTransaction}; +use ethkey::Secret; use ethstore::ethkey::{Generator, Random}; -use serde_json; use parking_lot::Mutex; +use serde_json; +use transaction::{Transaction, Action, SignedTransaction}; use parity_reactor::Remote; diff --git a/rpc/src/v1/types/transaction.rs b/rpc/src/v1/types/transaction.rs index dbd326488..c5dd63624 100644 --- a/rpc/src/v1/types/transaction.rs +++ b/rpc/src/v1/types/transaction.rs @@ -18,7 +18,7 @@ use serde::{Serialize, Serializer}; use serde::ser::SerializeStruct; use ethcore::miner; use ethcore::{contract_address, CreateContractAddress}; -use ethcore::transaction::{LocalizedTransaction, Action, PendingTransaction, SignedTransaction}; +use transaction::{LocalizedTransaction, Action, PendingTransaction, SignedTransaction}; use v1::helpers::errors; use v1::types::{Bytes, H160, H256, U256, H512, U64, TransactionCondition}; diff --git a/rpc/src/v1/types/transaction_condition.rs b/rpc/src/v1/types/transaction_condition.rs index 1682f2dd9..541bd364a 100644 --- a/rpc/src/v1/types/transaction_condition.rs +++ b/rpc/src/v1/types/transaction_condition.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use ethcore; +use transaction; /// Represents condition on minimum block number or block timestamp. #[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)] @@ -28,27 +28,26 @@ pub enum TransactionCondition { Timestamp(u64), } -impl Into for TransactionCondition { - fn into(self) -> ethcore::transaction::Condition { +impl Into for TransactionCondition { + fn into(self) -> transaction::Condition { match self { - TransactionCondition::Number(n) => ethcore::transaction::Condition::Number(n), - TransactionCondition::Timestamp(n) => ethcore::transaction::Condition::Timestamp(n), + TransactionCondition::Number(n) => transaction::Condition::Number(n), + TransactionCondition::Timestamp(n) => transaction::Condition::Timestamp(n), } } } -impl From for TransactionCondition { - fn from(condition: ethcore::transaction::Condition) -> Self { +impl From for TransactionCondition { + fn from(condition: transaction::Condition) -> Self { match condition { - ethcore::transaction::Condition::Number(n) => TransactionCondition::Number(n), - ethcore::transaction::Condition::Timestamp(n) => TransactionCondition::Timestamp(n), + transaction::Condition::Number(n) => TransactionCondition::Number(n), + transaction::Condition::Timestamp(n) => TransactionCondition::Timestamp(n), } } } #[cfg(test)] mod tests { - use ethcore; use super::*; use serde_json; @@ -61,8 +60,8 @@ mod tests { #[test] fn condition_into() { - assert_eq!(ethcore::transaction::Condition::Number(100), TransactionCondition::Number(100).into()); - assert_eq!(ethcore::transaction::Condition::Timestamp(100), TransactionCondition::Timestamp(100).into()); + assert_eq!(transaction::Condition::Number(100), TransactionCondition::Number(100).into()); + assert_eq!(transaction::Condition::Timestamp(100), TransactionCondition::Timestamp(100).into()); } } diff --git a/sync/Cargo.toml b/sync/Cargo.toml index eb90a11d7..d1f3b9c50 100644 --- a/sync/Cargo.toml +++ b/sync/Cargo.toml @@ -11,7 +11,8 @@ authors = ["Parity Technologies "] ethcore-bytes = { path = "../util/bytes" } ethcore-network = { path = "../util/network" } ethcore-io = { path = "../util/io" } -ethcore-light = { path = "../ethcore/light"} +ethcore-light = { path = "../ethcore/light" } +ethcore-transaction = { path = "../ethcore/transaction" } ethcore = { path = "../ethcore" } ethereum-types = "0.1" plain_hasher = { path = "../util/plain_hasher" } diff --git a/sync/src/api.rs b/sync/src/api.rs index 79d69a552..391eef56f 100644 --- a/sync/src/api.rs +++ b/sync/src/api.rs @@ -440,7 +440,7 @@ impl ChainNotify for EthSync { struct TxRelay(Arc); impl LightHandler for TxRelay { - fn on_transactions(&self, ctx: &EventContext, relay: &[::ethcore::transaction::UnverifiedTransaction]) { + fn on_transactions(&self, ctx: &EventContext, relay: &[::transaction::UnverifiedTransaction]) { trace!(target: "pip", "Relaying {} transactions from peer {}", relay.len(), ctx.peer()); self.0.queue_transactions(relay.iter().map(|tx| ::rlp::encode(tx).into_vec()).collect(), ctx.peer()) } diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 249161f56..c5c291bd0 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -102,7 +102,7 @@ use ethcore::header::{BlockNumber, Header as BlockHeader}; use ethcore::client::{BlockChainClient, BlockStatus, BlockId, BlockChainInfo, BlockImportError, BlockQueueInfo}; use ethcore::error::*; use ethcore::snapshot::{ManifestData, RestorationStatus}; -use ethcore::transaction::PendingTransaction; +use transaction::PendingTransaction; use sync_io::SyncIo; use time; use super::SyncConfig; @@ -2233,8 +2233,8 @@ mod tests { use super::{PeerInfo, PeerAsking}; use ethcore::header::*; use ethcore::client::{BlockChainClient, EachBlockWith, TestBlockChainClient}; - use ethcore::transaction::UnverifiedTransaction; use ethcore::miner::MinerService; + use transaction::UnverifiedTransaction; fn get_dummy_block(order: u32, parent_hash: H256) -> Bytes { let mut header = Header::new(); diff --git a/sync/src/lib.rs b/sync/src/lib.rs index 64cd78cca..baceb0c7f 100644 --- a/sync/src/lib.rs +++ b/sync/src/lib.rs @@ -24,6 +24,7 @@ extern crate ethcore_network as network; extern crate ethcore_bytes as bytes; extern crate ethcore_io as io; +extern crate ethcore_transaction as transaction; extern crate ethcore; extern crate ethereum_types; extern crate env_logger; diff --git a/sync/src/tests/consensus.rs b/sync/src/tests/consensus.rs index cab515fd0..b6d915bda 100644 --- a/sync/src/tests/consensus.rs +++ b/sync/src/tests/consensus.rs @@ -22,9 +22,9 @@ use ethcore::client::{BlockChainClient, Client}; use ethcore::service::ClientIoMessage; use ethcore::spec::Spec; use ethcore::miner::MinerService; -use ethcore::transaction::*; use ethcore::account_provider::AccountProvider; use ethkey::{KeyPair, Secret}; +use transaction::{Action, PendingTransaction, Transaction}; use super::helpers::*; use SyncConfig;