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
This commit is contained in:
Tomasz Drwięga 2018-01-11 17:49:10 +01:00 committed by Marek Kotewicz
parent 9a12945304
commit f044b61f42
74 changed files with 778 additions and 522 deletions

51
Cargo.lock generated
View File

@ -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",

View File

@ -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",
]

View File

@ -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 = []

View File

@ -10,6 +10,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
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" }

View File

@ -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;

View File

@ -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};

View File

@ -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};

View File

@ -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};

View File

@ -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<T: ProvingBlockChainClient + ?Sized> Provider for T {
}
fn transaction_proof(&self, req: request::CompleteExecutionRequest) -> Option<request::ExecutionResponse> {
use ethcore::transaction::Transaction;
use transaction::Transaction;
let id = BlockId::Hash(req.block_hash);
let nonce = match self.nonce(&req.from, id.clone()) {

View File

@ -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<TransactionImportResult, TransactionError> {
pub fn import(&mut self, tx: PendingTransaction) -> Result<transaction::ImportResult, transaction::Error> {
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() {

View File

@ -1094,7 +1094,7 @@ pub mod block_body {
impl Decodable for Response {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
use ethcore::header::Header as FullHeader;
use ethcore::transaction::UnverifiedTransaction;
use transaction::UnverifiedTransaction;
// check body validity.
let _: Vec<UnverifiedTransaction> = 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(),

View File

@ -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<LockedBlock, Error> {
let block = BlockView::new(block_bytes);
let header = block.header();
let transactions: Result<Vec<_>, Error> = block.transactions().into_iter().map(SignedTransaction::new).collect();
let transactions: Result<Vec<_>, Error> = block
.transactions()
.into_iter()
.map(SignedTransaction::new)
.map(|r| r.map_err(Into::into))
.collect();
let transactions = transactions?;
{

View File

@ -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<TransactionImportResult, EthcoreError> {
fn transact_contract(&self, address: Address, data: Bytes) -> Result<transaction::ImportResult, EthcoreError> {
let transaction = Transaction {
nonce: self.latest_nonce(&self.miner.author()),
action: Action::Call(address),

View File

@ -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(),
};
}

View File

@ -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;

View File

@ -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<Bytes, String> { Ok(vec![]) }
fn transact_contract(&self, address: Address, data: Bytes) -> Result<TransactionImportResult, EthcoreError> {
fn transact_contract(&self, address: Address, data: Bytes) -> Result<transaction::ImportResult, EthcoreError> {
let transaction = Transaction {
nonce: self.latest_nonce(&self.miner.author()),
action: Action::Call(address),

View File

@ -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};

View File

@ -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<U256>),
/// 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<Error> 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 {

View File

@ -42,8 +42,10 @@ fn do_json_test(json_data: &[u8]) -> Vec<String> {
let rlp: Vec<u8> = 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) {

View File

@ -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;

View File

@ -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, Error> {
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())
}
}

View File

@ -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<bool, String> {
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<Address> {
MiningBlockChainClient::registry_address(*self, name.into())
}
fn call_contract(&self, block: BlockId, address: Address, data: Vec<u8>) -> Result<Vec<u8>, 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]

View File

@ -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 {

View File

@ -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<AddrParseError> 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<Miner>, client: Weak<Client>) -> Result<(), Error> {
let stratum = miner::Stratum::start(cfg, Arc::downgrade(&miner.clone()), client)?;
miner.push_notifier(Box::new(stratum) as Box<miner::NotifyWork>);
miner.push_notifier(Box::new(stratum) as Box<NotifyWork>);
Ok(())
}
}

View File

@ -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));

View File

@ -0,0 +1,21 @@
[package]
name = "ethcore-transaction"
description = "Transaction type"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
[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 = []

View File

@ -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 <http://www.gnu.org/licenses/>.
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<U256>),
/// 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<ethkey::Error> 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))
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
//! 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
}

View File

@ -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<u8>;
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<Self, DecoderError> {
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<Self, DecoderError> {
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<Public, Error> {
pub fn recover_public(&self) -> Result<Public, ethkey::Error> {
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<UnverifiedTransaction, Error> {
pub fn validate(self, schedule: &Schedule, require_low: bool, allow_chain_id_of_one: bool, allow_empty_signature: bool)
-> Result<UnverifiedTransaction, error::Error>
{
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<u64>, allow_empty_signature: bool) -> Result<(), Error> {
pub fn verify_basic(&self, check_low_s: bool, chain_id: Option<u64>, 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<SignedTransaction> for UnverifiedTransaction {
impl SignedTransaction {
/// Try to verify transaction and recover sender.
pub fn new(transaction: UnverifiedTransaction) -> Result<Self, Error> {
pub fn new(transaction: UnverifiedTransaction) -> Result<Self, ethkey::Error> {
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");

View File

@ -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;

View File

@ -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"

View File

@ -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

View File

@ -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;

View File

@ -5,14 +5,15 @@ version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
[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" }

View File

@ -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.

27
miner/Cargo.toml Normal file
View File

@ -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 <admin@parity.io>"]
[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"

View File

@ -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<TransactionImportResult, Error> {
details_provider: &TransactionDetailsProvider,
) -> Result<transaction::ImportResult, transaction::Error> {
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<TransactionImportResult, Error>) -> 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::ImportResult, transaction::Error>) -> 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);
}
}

View File

@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! External Miner hashrate tracker.
use std::collections::HashMap;
use std::sync::Arc;
use std::time::{Instant, Duration};

47
miner/src/lib.rs Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
#![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;

View File

@ -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<H256, Status> {
&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),

View File

@ -14,17 +14,26 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
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<Address>;
/// Executes a contract call at given block.
fn call_contract(&self, BlockId, Address, Vec<u8>) -> Result<Vec<u8>, 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<bool, String> {
pub fn check(&self, client: &ContractCaller, tx: &SignedTransaction) -> Result<bool, String> {
debug_assert_eq!(tx.gas_price, U256::zero());
if let Some(ref contract) = *self.contract.lock() {

View File

@ -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>,
condition: Option<transaction::Condition>,
/// 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>,
condition: Option<transaction::Condition>,
insertion_time: QueuingInstant,
insertion_id: u64,
) -> Self {
@ -705,31 +706,28 @@ impl TransactionQueue {
tx: SignedTransaction,
origin: TransactionOrigin,
time: QueuingInstant,
condition: Option<Condition>,
condition: Option<transaction::Condition>,
details_provider: &TransactionDetailsProvider,
) -> Result<TransactionImportResult, Error> {
) -> Result<transaction::ImportResult, transaction::Error> {
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>,
condition: Option<transaction::Condition>,
details_provider: &TransactionDetailsProvider,
) -> Result<TransactionImportResult, Error> {
) -> Result<transaction::ImportResult, transaction::Error> {
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 {
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<TransactionImportResult, TransactionError> {
fn import_tx(&mut self, tx: VerifiedTransaction, state_nonce: U256) -> Result<transaction::ImportResult,
transaction::Error> {
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<HashMap<Address, U256>>) -> Result<(), TransactionError> {
fn check_if_removed(sender: &Address, nonce: &U256, dropped: Option<HashMap<Address, U256>>) -> 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<HashMap<Addr
#[cfg(test)]
pub mod test {
use rustc_hex::FromHex;
use table::Table;
use ethereum_types::{U256, Address};
use ethkey::{Random, Generator};
use error::{Error, TransactionError};
use super::*;
use super::{TransactionSet, TransactionOrder, VerifiedTransaction};
use miner::local_transactions::LocalTransactionsList;
use client::TransactionImportResult;
use transaction::{SignedTransaction, Transaction, Action, Condition};
use ethkey::{Random, Generator};
use rustc_hex::FromHex;
use transaction::Transaction;
pub struct DummyTransactionDetailsProvider {
account_details: AccountDetails,
@ -1509,11 +1504,8 @@ pub mod test {
}
}
fn unwrap_tx_err(err: Result<TransactionImportResult, Error>) -> TransactionError {
match err.unwrap_err() {
Error::Transaction(e) => e,
_ => panic!("Expected transaction error!"),
}
fn unwrap_tx_err(err: Result<transaction::ImportResult, transaction::Error>) -> 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(),
});

View File

@ -14,19 +14,22 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! 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<Url>,
client: Mutex<Client<PostHandler>>,
@ -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!(

View File

@ -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};

View File

@ -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 {

View File

@ -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;

View File

@ -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;

View File

@ -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 {

View File

@ -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(),

View File

@ -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"

View File

@ -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;

View File

@ -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)
}

View File

@ -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<T: Into<EthcoreError>>(error: T) -> Error {
let error = error.into();
if let EthcoreError::Transaction(e) = error {
Error {
code: ErrorCode::ServerError(codes::TRANSACTION_ERROR),

View File

@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use ethcore::transaction::{Transaction, SignedTransaction, Action};
use transaction::{Transaction, SignedTransaction, Action};
use ethereum_types::U256;
use jsonrpc_core::Error;

View File

@ -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};

View File

@ -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;

View File

@ -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<T: LightChainClient + 'static> Eth for EthClient<T> {
self.transaction_queue.write().import(signed.into())
.map(|_| hash)
.map_err(Into::into)
.map_err(errors::transaction)
})
.map(Into::into)

View File

@ -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;

View File

@ -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};

View File

@ -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;

View File

@ -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;

View File

@ -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 {

View File

@ -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();
{

View File

@ -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();

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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};

View File

@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
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<ethcore::transaction::Condition> for TransactionCondition {
fn into(self) -> ethcore::transaction::Condition {
impl Into<transaction::Condition> 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<ethcore::transaction::Condition> for TransactionCondition {
fn from(condition: ethcore::transaction::Condition) -> Self {
impl From<transaction::Condition> 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());
}
}

View File

@ -11,7 +11,8 @@ authors = ["Parity Technologies <admin@parity.io>"]
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" }

View File

@ -440,7 +440,7 @@ impl ChainNotify for EthSync {
struct TxRelay(Arc<BlockChainClient>);
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())
}

View File

@ -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();

View File

@ -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;

View File

@ -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;