TX queue gas limit config and allow local transactions over the gas limit (#2553)
* Gas limit config; Allow local transactions over the limit * Fix typo [ci:skip]
This commit is contained in:
parent
64f6f836ab
commit
26d7712d30
@ -48,6 +48,17 @@ pub enum PendingSet {
|
||||
SealingOrElseQueue,
|
||||
}
|
||||
|
||||
/// Type of the gas limit to apply to the transaction queue.
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum GasLimit {
|
||||
/// Depends on the block gas limit and is updated with every block.
|
||||
Auto,
|
||||
/// No limit.
|
||||
None,
|
||||
/// Set to a fixed gas value.
|
||||
Fixed(U256),
|
||||
}
|
||||
|
||||
/// Configures the behaviour of the miner.
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct MinerOptions {
|
||||
@ -71,6 +82,8 @@ pub struct MinerOptions {
|
||||
pub work_queue_size: usize,
|
||||
/// Can we submit two different solutions for the same block and expect both to result in an import?
|
||||
pub enable_resubmission: bool,
|
||||
/// Global gas limit for all transaction in the queue except for local and retracted.
|
||||
pub tx_queue_gas_limit: GasLimit,
|
||||
}
|
||||
|
||||
impl Default for MinerOptions {
|
||||
@ -86,6 +99,7 @@ impl Default for MinerOptions {
|
||||
reseal_min_period: Duration::from_secs(2),
|
||||
work_queue_size: 20,
|
||||
enable_resubmission: true,
|
||||
tx_queue_gas_limit: GasLimit::Auto,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -194,7 +208,11 @@ impl Miner {
|
||||
true => None,
|
||||
false => Some(WorkPoster::new(&options.new_work_notify))
|
||||
};
|
||||
let txq = Arc::new(Mutex::new(TransactionQueue::with_limits(options.tx_queue_size, !U256::zero(), options.tx_gas_limit)));
|
||||
let gas_limit = match options.tx_queue_gas_limit {
|
||||
GasLimit::Fixed(ref limit) => *limit,
|
||||
_ => !U256::zero(),
|
||||
};
|
||||
let txq = Arc::new(Mutex::new(TransactionQueue::with_limits(options.tx_queue_size, gas_limit, options.tx_gas_limit)));
|
||||
Miner {
|
||||
transaction_queue: txq,
|
||||
next_allowed_reseal: Mutex::new(Instant::now()),
|
||||
@ -443,9 +461,11 @@ impl Miner {
|
||||
let gas_limit = HeaderView::new(&chain.best_block_header()).gas_limit();
|
||||
let mut queue = self.transaction_queue.lock();
|
||||
queue.set_gas_limit(gas_limit);
|
||||
// Set total qx queue gas limit to be 2x the block gas limit.
|
||||
if let GasLimit::Auto = self.options.tx_queue_gas_limit {
|
||||
// Set total tx queue gas limit to be 2x the block gas limit.
|
||||
queue.set_total_gas_limit(gas_limit << 1);
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if we had to prepare new pending block.
|
||||
fn prepare_work_sealing(&self, chain: &MiningBlockChainClient) -> bool {
|
||||
@ -1062,6 +1082,7 @@ mod tests {
|
||||
reseal_min_period: Duration::from_secs(5),
|
||||
tx_gas_limit: !U256::zero(),
|
||||
tx_queue_size: 1024,
|
||||
tx_queue_gas_limit: GasLimit::None,
|
||||
pending_set: PendingSet::AlwaysSealing,
|
||||
work_queue_size: 5,
|
||||
enable_resubmission: true,
|
||||
|
@ -48,7 +48,7 @@ mod work_notify;
|
||||
mod price_info;
|
||||
|
||||
pub use self::transaction_queue::{TransactionQueue, AccountDetails, TransactionOrigin};
|
||||
pub use self::miner::{Miner, MinerOptions, PendingSet, GasPricer, GasPriceCalibratorOptions};
|
||||
pub use self::miner::{Miner, MinerOptions, PendingSet, GasPricer, GasPriceCalibratorOptions, GasLimit};
|
||||
pub use self::external::{ExternalMiner, ExternalMinerService};
|
||||
pub use client::TransactionImportResult;
|
||||
|
||||
|
@ -331,7 +331,9 @@ impl TransactionSet {
|
||||
let r = gas.overflowing_add(order.gas);
|
||||
if r.1 { return false }
|
||||
gas = r.0;
|
||||
count <= self.limit && gas <= self.gas_limit
|
||||
// Own and retracted transactions are allowed to go above the gas limit, bot not above the count limit.
|
||||
(gas <= self.gas_limit || order.origin == TransactionOrigin::Local || order.origin == TransactionOrigin::RetractedBlock) &&
|
||||
count <= self.limit
|
||||
})
|
||||
.map(|order| by_hash.get(&order.hash)
|
||||
.expect("All transactions in `self.by_priority` and `self.by_address` are kept in sync with `by_hash`."))
|
||||
@ -1762,13 +1764,27 @@ mod test {
|
||||
#[test]
|
||||
fn should_limit_by_gas() {
|
||||
let mut txq = TransactionQueue::with_limits(100, default_gas_val() * U256::from(2), !U256::zero());
|
||||
let (tx1, _) = new_tx_pair_default(U256::from(4), U256::from(1));
|
||||
let (tx3, _) = new_tx_pair_default(U256::from(4), U256::from(2));
|
||||
txq.add(tx1.clone(), &default_account_details, TransactionOrigin::External).unwrap();
|
||||
txq.add(tx3.clone(), &default_account_details, TransactionOrigin::External).unwrap();
|
||||
let (tx1, tx2) = new_tx_pair_default(U256::from(1), U256::from(1));
|
||||
let (tx3, tx4) = new_tx_pair_default(U256::from(1), U256::from(2));
|
||||
txq.add(tx1.clone(), &default_account_details, TransactionOrigin::External).ok();
|
||||
txq.add(tx2.clone(), &default_account_details, TransactionOrigin::External).ok();
|
||||
txq.add(tx3.clone(), &default_account_details, TransactionOrigin::External).ok();
|
||||
txq.add(tx4.clone(), &default_account_details, TransactionOrigin::External).ok();
|
||||
assert_eq!(txq.status().pending, 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_keep_own_transactions_above_gas_limit() {
|
||||
let mut txq = TransactionQueue::with_limits(100, default_gas_val() * U256::from(2), !U256::zero());
|
||||
let (tx1, tx2) = new_tx_pair_default(U256::from(1), U256::from(1));
|
||||
let (tx3, tx4) = new_tx_pair_default(U256::from(1), U256::from(2));
|
||||
txq.add(tx1.clone(), &default_account_details, TransactionOrigin::Local).unwrap();
|
||||
txq.add(tx2.clone(), &default_account_details, TransactionOrigin::Local).unwrap();
|
||||
txq.add(tx3.clone(), &default_account_details, TransactionOrigin::Local).unwrap();
|
||||
txq.add(tx4.clone(), &default_account_details, TransactionOrigin::Local).unwrap();
|
||||
assert_eq!(txq.status().pending, 4);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_drop_transactions_with_old_nonces() {
|
||||
let mut txq = TransactionQueue::new();
|
||||
|
@ -68,6 +68,7 @@ price_update_period = "hourly"
|
||||
gas_floor_target = "4700000"
|
||||
gas_cap = "6283184"
|
||||
tx_queue_size = 2048
|
||||
tx_queue_gas = "auto"
|
||||
tx_gas_limit = "6283184"
|
||||
extra_data = "Parity"
|
||||
remove_solved = false
|
||||
|
@ -41,6 +41,7 @@ reseal_on_txs = "all"
|
||||
reseal_min_period = 4000
|
||||
price_update_period = "hourly"
|
||||
tx_queue_size = 2048
|
||||
tx_queue_gas = "auto"
|
||||
|
||||
[footprint]
|
||||
tracing = "on"
|
||||
|
@ -195,6 +195,8 @@ usage! {
|
||||
or |c: &Config| otry!(c.mining).extra_data.clone().map(Some),
|
||||
flag_tx_queue_size: usize = 2048usize,
|
||||
or |c: &Config| otry!(c.mining).tx_queue_size.clone(),
|
||||
flag_tx_queue_gas: String = "auto",
|
||||
or |c: &Config| otry!(c.mining).tx_queue_gas.clone(),
|
||||
flag_remove_solved: bool = false,
|
||||
or |c: &Config| otry!(c.mining).remove_solved.clone(),
|
||||
flag_notify_work: Option<String> = None,
|
||||
@ -348,6 +350,7 @@ struct Mining {
|
||||
gas_cap: Option<String>,
|
||||
extra_data: Option<String>,
|
||||
tx_queue_size: Option<usize>,
|
||||
tx_queue_gas: Option<String>,
|
||||
remove_solved: Option<bool>,
|
||||
notify_work: Option<Vec<String>>,
|
||||
}
|
||||
@ -523,6 +526,7 @@ mod tests {
|
||||
flag_gas_cap: "6283184".into(),
|
||||
flag_extra_data: Some("Parity".into()),
|
||||
flag_tx_queue_size: 2048usize,
|
||||
flag_tx_queue_gas: "auto".into(),
|
||||
flag_remove_solved: false,
|
||||
flag_notify_work: Some("http://localhost:3001".into()),
|
||||
|
||||
@ -673,6 +677,7 @@ mod tests {
|
||||
gas_floor_target: None,
|
||||
gas_cap: None,
|
||||
tx_queue_size: Some(2048),
|
||||
tx_queue_gas: Some("auto".into()),
|
||||
tx_gas_limit: None,
|
||||
extra_data: None,
|
||||
remove_solved: None,
|
||||
|
@ -184,6 +184,10 @@ Sealing/Mining Options:
|
||||
more than 32 characters. (default: {flag_extra_data:?})
|
||||
--tx-queue-size LIMIT Maximum amount of transactions in the queue (waiting
|
||||
to be included in next block) (default: {flag_tx_queue_size}).
|
||||
--tx-queue-gas LIMIT Maximum amount of total gas for external transactions in
|
||||
the queue. LIMIT can be either an amount of gas or
|
||||
'auto' or 'off'. 'auto' sets the limit to be 2x
|
||||
the current block gas limit. (default: {flag_tx_queue_gas}).
|
||||
--remove-solved Move solved blocks from the work package queue
|
||||
instead of cloning them. This gives a slightly
|
||||
faster import speed, but means that extra solutions
|
||||
|
@ -30,7 +30,7 @@ use rpc::{IpcConfiguration, HttpConfiguration};
|
||||
use ethcore_rpc::NetworkSettings;
|
||||
use cache::CacheConfig;
|
||||
use helpers::{to_duration, to_mode, to_block_id, to_u256, to_pending_set, to_price, replace_home,
|
||||
geth_ipc_path, parity_ipc_path, to_bootnodes, to_addresses, to_address};
|
||||
geth_ipc_path, parity_ipc_path, to_bootnodes, to_addresses, to_address, to_gas_limit};
|
||||
use params::{ResealPolicy, AccountsConfig, GasPricerConfig, MinerExtras, SpecType};
|
||||
use ethcore_logger::Config as LogConfig;
|
||||
use dir::Directories;
|
||||
@ -348,6 +348,7 @@ impl Configuration {
|
||||
None => U256::max_value(),
|
||||
},
|
||||
tx_queue_size: self.args.flag_tx_queue_size,
|
||||
tx_queue_gas_limit: try!(to_gas_limit(&self.args.flag_tx_queue_gas)),
|
||||
pending_set: try!(to_pending_set(&self.args.flag_relay_set)),
|
||||
reseal_min_period: Duration::from_millis(self.args.flag_reseal_min_period),
|
||||
work_queue_size: self.args.flag_work_queue_size,
|
||||
|
@ -22,7 +22,7 @@ use std::fs::File;
|
||||
use util::{clean_0x, U256, Uint, Address, path, CompactionProfile};
|
||||
use util::journaldb::Algorithm;
|
||||
use ethcore::client::{Mode, BlockID, VMType, DatabaseCompactionProfile, ClientConfig};
|
||||
use ethcore::miner::PendingSet;
|
||||
use ethcore::miner::{PendingSet, GasLimit};
|
||||
use cache::CacheConfig;
|
||||
use dir::DatabaseDirectories;
|
||||
use upgrade::upgrade;
|
||||
@ -93,6 +93,14 @@ pub fn to_pending_set(s: &str) -> Result<PendingSet, String> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_gas_limit(s: &str) -> Result<GasLimit, String> {
|
||||
match s {
|
||||
"auto" => Ok(GasLimit::Auto),
|
||||
"off" => Ok(GasLimit::None),
|
||||
other => Ok(GasLimit::Fixed(try!(to_u256(other)))),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_address(s: Option<String>) -> Result<Address, String> {
|
||||
match s {
|
||||
Some(ref a) => clean_0x(a).parse().map_err(|_| format!("Invalid address: {:?}", a)),
|
||||
|
@ -24,7 +24,7 @@ use ethcore::spec::{Genesis, Spec};
|
||||
use ethcore::block::Block;
|
||||
use ethcore::views::BlockView;
|
||||
use ethcore::ethereum;
|
||||
use ethcore::miner::{MinerOptions, GasPricer, MinerService, ExternalMiner, Miner, PendingSet};
|
||||
use ethcore::miner::{MinerOptions, GasPricer, MinerService, ExternalMiner, Miner, PendingSet, GasLimit};
|
||||
use ethcore::account_provider::AccountProvider;
|
||||
use devtools::RandomTempPath;
|
||||
use util::Hashable;
|
||||
@ -58,6 +58,7 @@ fn miner_service(spec: &Spec, accounts: Arc<AccountProvider>) -> Arc<Miner> {
|
||||
reseal_on_own_tx: true,
|
||||
tx_queue_size: 1024,
|
||||
tx_gas_limit: !U256::zero(),
|
||||
tx_queue_gas_limit: GasLimit::None,
|
||||
pending_set: PendingSet::SealingOrElseQueue,
|
||||
reseal_min_period: Duration::from_secs(0),
|
||||
work_queue_size: 50,
|
||||
|
Loading…
Reference in New Issue
Block a user