diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 2c4499e57..0082aa4c5 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -792,8 +792,8 @@ impl BlockChainClient for Client where V: Verifier { } } - fn all_transactions(&self) -> Vec { - self.miner.all_transactions() + fn pending_transactions(&self) -> Vec { + self.miner.pending_transactions() } } diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index 80625ad85..c05874e64 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -197,7 +197,7 @@ pub trait BlockChainClient : Sync + Send { fn queue_transactions(&self, transactions: Vec); /// list all transactions - fn all_transactions(&self) -> Vec; + fn pending_transactions(&self) -> Vec; /// Get the gas price distribution. fn gas_price_statistics(&self, sample_size: usize, distribution_size: usize) -> Result, ()> { diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index 812c15655..a7f508a51 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -500,7 +500,7 @@ impl BlockChainClient for TestBlockChainClient { self.import_transactions(tx); } - fn all_transactions(&self) -> Vec { - self.miner.all_transactions() + fn pending_transactions(&self) -> Vec { + self.miner.pending_transactions() } } diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index e5ecff8c4..72228a959 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -29,6 +29,18 @@ use spec::Spec; use engine::Engine; use miner::{MinerService, MinerStatus, TransactionQueue, AccountDetails, TransactionImportResult, TransactionOrigin}; +/// Different possible definitions for pending transaction set. +#[derive(Debug)] +pub enum PendingSet { + /// Always just the transactions in the queue. These have had only cheap checks. + AlwaysQueue, + /// Always just the transactions in the sealing block. These have had full checks but + /// may be empty if the node is not actively mining or has force_sealing enabled. + AlwaysSealing, + /// Try the sealing block, but if it is not currently sealing, fallback to the queue. + SealingOrElseQueue, +} + /// Configures the behaviour of the miner. #[derive(Debug)] pub struct MinerOptions { @@ -42,7 +54,7 @@ pub struct MinerOptions { /// If `None`, then no limit. pub max_tx_gas: Option, /// Whether we should fallback to providing all the queue's transactions or just pending. - pub strict_valid_pending: bool, + pub pending_set: PendingSet, } impl Default for MinerOptions { @@ -52,7 +64,7 @@ impl Default for MinerOptions { reseal_on_external_tx: true, reseal_on_own_tx: true, max_tx_gas: None, - strict_valid_pending: false, + pending_set: PendingSet::AlwaysQueue, } } } @@ -462,24 +474,6 @@ impl MinerService for Miner { imported } - fn pending_transactions_hashes(&self) -> Vec { - let queue = self.transaction_queue.lock().unwrap(); - match (self.sealing_enabled.load(atomic::Ordering::Relaxed), self.sealing_work.lock().unwrap().peek_last_ref()) { - (true, Some(pending)) => pending.transactions().iter().map(|t| t.hash()).collect(), - _ if self.options.strict_valid_pending => Vec::new(), - _ => queue.pending_hashes(), - } - } - - fn transaction(&self, hash: &H256) -> Option { - let queue = self.transaction_queue.lock().unwrap(); - match (self.sealing_enabled.load(atomic::Ordering::Relaxed), self.sealing_work.lock().unwrap().peek_last_ref()) { - (true, Some(pending)) => pending.transactions().iter().find(|t| &t.hash() == hash).cloned(), - _ if self.options.strict_valid_pending => None, - _ => queue.find(hash), - } - } - fn all_transactions(&self) -> Vec { let queue = self.transaction_queue.lock().unwrap(); queue.top_transactions() @@ -487,11 +481,41 @@ impl MinerService for Miner { fn pending_transactions(&self) -> Vec { let queue = self.transaction_queue.lock().unwrap(); + let sw = self.sealing_work.lock().unwrap(); // TODO: should only use the sealing_work when it's current (it could be an old block) - match (self.sealing_enabled.load(atomic::Ordering::Relaxed), self.sealing_work.lock().unwrap().peek_last_ref()) { - (true, Some(pending)) => pending.transactions().clone(), - _ if self.options.strict_valid_pending => Vec::new(), - _ => queue.top_transactions(), + let sealing_set = match self.sealing_enabled.load(atomic::Ordering::Relaxed) { + true => sw.peek_last_ref(), + false => None, + }; + match (&self.options.pending_set, sealing_set) { + (&PendingSet::AlwaysQueue, _) | (&PendingSet::SealingOrElseQueue, None) => queue.top_transactions(), + (_, sealing) => sealing.map(|s| s.transactions().clone()).unwrap_or(Vec::new()), + } + } + + fn pending_transactions_hashes(&self) -> Vec { + let queue = self.transaction_queue.lock().unwrap(); + let sw = self.sealing_work.lock().unwrap(); + let sealing_set = match self.sealing_enabled.load(atomic::Ordering::Relaxed) { + true => sw.peek_last_ref(), + false => None, + }; + match (&self.options.pending_set, sealing_set) { + (&PendingSet::AlwaysQueue, _) | (&PendingSet::SealingOrElseQueue, None) => queue.pending_hashes(), + (_, sealing) => sealing.map(|s| s.transactions().iter().map(|t| t.hash()).collect()).unwrap_or(Vec::new()), + } + } + + fn transaction(&self, hash: &H256) -> Option { + let queue = self.transaction_queue.lock().unwrap(); + let sw = self.sealing_work.lock().unwrap(); + let sealing_set = match self.sealing_enabled.load(atomic::Ordering::Relaxed) { + true => sw.peek_last_ref(), + false => None, + }; + match (&self.options.pending_set, sealing_set) { + (&PendingSet::AlwaysQueue, _) | (&PendingSet::SealingOrElseQueue, None) => queue.find(hash), + (_, sealing) => sealing.and_then(|s| s.transactions().iter().find(|t| &t.hash() == hash).cloned()), } } diff --git a/ethcore/src/miner/mod.rs b/ethcore/src/miner/mod.rs index 8a282490c..f02925438 100644 --- a/ethcore/src/miner/mod.rs +++ b/ethcore/src/miner/mod.rs @@ -47,7 +47,7 @@ mod external; mod transaction_queue; pub use self::transaction_queue::{TransactionQueue, AccountDetails, TransactionImportResult, TransactionOrigin}; -pub use self::miner::{Miner, MinerOptions}; +pub use self::miner::{Miner, MinerOptions, PendingSet}; pub use self::external::{ExternalMiner, ExternalMinerService}; use std::collections::BTreeMap; diff --git a/parity/cli.rs b/parity/cli.rs index 3090e83c5..2fe9186f5 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -141,9 +141,14 @@ Sealing/Mining Options: all - reseal on all new transactions [default: all]. --max-tx-gas GAS Apply a limit of GAS as the maximum amount of gas a single transaction may have for it to be mined. - --relay-validity REQ Requirements for relaying. REQ may be: - cheap - Relay only after cheap checks; - strict - Relay only once executed [default: cheap]. + --relay-set SET Set of transactions to relay. SET may be: + cheap - Relay any transaction in the queue (this + may include invalid transactions); + strict - Relay only executed transactions (this + guarantees we don't relay invalid transactions, but + means we relay nothing if not mining); + lenient - Same as struct when mining, and cheap + when not [default: cheap]. --usd-per-tx USD Amount of USD to be paid for a basic transaction [default: 0.005]. The minimum gas price is set accordingly. @@ -296,7 +301,7 @@ pub struct Args { pub flag_force_sealing: bool, pub flag_reseal_on_txs: String, pub flag_max_tx_gas: Option, - pub flag_relay_validity: String, + pub flag_relay_set: String, pub flag_author: Option, pub flag_usd_per_tx: String, pub flag_usd_per_eth: String, diff --git a/parity/configuration.rs b/parity/configuration.rs index 57c62f839..501cc68cb 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -27,7 +27,7 @@ use util::*; use ethcore::account_provider::AccountProvider; use util::network_settings::NetworkSettings; use ethcore::client::{append_path, get_db_path, ClientConfig, Switch, VMType}; -use ethcore::miner::MinerOptions; +use ethcore::miner::{MinerOptions, PendingSet}; use ethcore::ethereum; use ethcore::spec::Spec; use ethsync::SyncConfig; @@ -89,10 +89,11 @@ impl Configuration { reseal_on_external_tx: ext, reseal_on_own_tx: own, max_tx_gas: self.args.flag_max_tx_gas.as_ref().map(|d| Self::decode_u256(d, "--max-tx-gas")), - strict_valid_pending: match self.args.flag_relay_validity.as_str() { - "cheap" => false, - "strict" => true, - x => die!("{}: Invalid value for --relay-validity option. Use --help for more information.", x) + pending_set: match self.args.flag_relay_set.as_str() { + "cheap" => PendingSet::AlwaysQueue, + "strict" => PendingSet::AlwaysSealing, + "lenient" => PendingSet::SealingOrElseQueue, + x => die!("{}: Invalid value for --relay-set option. Use --help for more information.", x) }, } } diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 5d0976aac..aa3657419 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -1314,7 +1314,7 @@ impl ChainSync { return 0; } - let mut transactions = io.chain().all_transactions(); + let mut transactions = io.chain().pending_transactions(); if transactions.is_empty() { return 0; }