diff --git a/ethcore/private-tx/src/private_transactions.rs b/ethcore/private-tx/src/private_transactions.rs index fcc6da514..e16d6ab91 100644 --- a/ethcore/private-tx/src/private_transactions.rs +++ b/ethcore/private-tx/src/private_transactions.rs @@ -67,6 +67,7 @@ impl Default for VerificationStore { minimal_gas_price: 0.into(), block_gas_limit: 8_000_000.into(), tx_gas_limit: U256::max_value(), + no_early_reject: false }, pool::PrioritizationStrategy::GasPriceOnly, ) diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index 90d28f44e..1939d02b1 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -176,6 +176,7 @@ impl Default for MinerOptions { minimal_gas_price: DEFAULT_MINIMAL_GAS_PRICE.into(), block_gas_limit: U256::max_value(), tx_gas_limit: U256::max_value(), + no_early_reject: false, }, } } @@ -283,6 +284,7 @@ impl Miner { minimal_gas_price, block_gas_limit: U256::max_value(), tx_gas_limit: U256::max_value(), + no_early_reject: false, }, reseal_min_period: Duration::from_secs(0), ..Default::default() @@ -1338,6 +1340,7 @@ mod tests { minimal_gas_price: 0.into(), block_gas_limit: U256::max_value(), tx_gas_limit: U256::max_value(), + no_early_reject: false, }, }, GasPricer::new_fixed(0u64.into()), diff --git a/miner/src/pool/queue.rs b/miner/src/pool/queue.rs index 24a56c226..d11052108 100644 --- a/miner/src/pool/queue.rs +++ b/miner/src/pool/queue.rs @@ -243,11 +243,15 @@ impl TransactionQueue { let options = self.options.read().clone(); let transaction_to_replace = { - let pool = self.pool.read(); - if pool.is_full() { - pool.worst_transaction().map(|worst| (pool.scoring().clone(), worst)) - } else { + if options.no_early_reject { None + } else { + let pool = self.pool.read(); + if pool.is_full() { + pool.worst_transaction().map(|worst| (pool.scoring().clone(), worst)) + } else { + None + } } }; diff --git a/miner/src/pool/tests/mod.rs b/miner/src/pool/tests/mod.rs index 1f6935589..7fd486b0f 100644 --- a/miner/src/pool/tests/mod.rs +++ b/miner/src/pool/tests/mod.rs @@ -37,6 +37,7 @@ fn new_queue() -> TransactionQueue { minimal_gas_price: 1.into(), block_gas_limit: 1_000_000.into(), tx_gas_limit: 1_000_000.into(), + no_early_reject: false, }, PrioritizationStrategy::GasPriceOnly, ) @@ -54,6 +55,7 @@ fn should_return_correct_nonces_when_dropped_because_of_limit() { minimal_gas_price: 1.into(), block_gas_limit: 1_000_000.into(), tx_gas_limit: 1_000_000.into(), + no_early_reject: false, }, PrioritizationStrategy::GasPriceOnly, ); @@ -105,6 +107,7 @@ fn should_never_drop_local_transactions_from_different_senders() { minimal_gas_price: 1.into(), block_gas_limit: 1_000_000.into(), tx_gas_limit: 1_000_000.into(), + no_early_reject: false, }, PrioritizationStrategy::GasPriceOnly, ); @@ -478,6 +481,7 @@ fn should_prefer_current_transactions_when_hitting_the_limit() { minimal_gas_price: 1.into(), block_gas_limit: 1_000_000.into(), tx_gas_limit: 1_000_000.into(), + no_early_reject: false, }, PrioritizationStrategy::GasPriceOnly, ); @@ -890,6 +894,7 @@ fn should_include_local_transaction_to_a_full_pool() { minimal_gas_price: 1.into(), block_gas_limit: 1_000_000.into(), tx_gas_limit: 1_000_000.into(), + no_early_reject: false, }, PrioritizationStrategy::GasPriceOnly, ); @@ -921,6 +926,7 @@ fn should_avoid_verifying_transaction_already_in_pool() { minimal_gas_price: 1.into(), block_gas_limit: 1_000_000.into(), tx_gas_limit: 1_000_000.into(), + no_early_reject: false, }, PrioritizationStrategy::GasPriceOnly, ); @@ -955,6 +961,7 @@ fn should_avoid_reverifying_recently_rejected_transactions() { minimal_gas_price: 1.into(), block_gas_limit: 1_000_000.into(), tx_gas_limit: 1_000_000.into(), + no_early_reject: false, }, PrioritizationStrategy::GasPriceOnly, ); @@ -996,6 +1003,7 @@ fn should_reject_early_in_case_gas_price_is_less_than_min_effective() { minimal_gas_price: 1.into(), block_gas_limit: 1_000_000.into(), tx_gas_limit: 1_000_000.into(), + no_early_reject: false, }, PrioritizationStrategy::GasPriceOnly, ); @@ -1020,3 +1028,42 @@ fn should_reject_early_in_case_gas_price_is_less_than_min_effective() { // then assert_eq!(txq.status().status.transaction_count, 1); } + + +#[test] +fn should_not_reject_early_in_case_gas_price_is_less_than_min_effective() { + // given + let txq = TransactionQueue::new( + txpool::Options { + max_count: 1, + max_per_sender: 2, + max_mem_usage: 50 + }, + verifier::Options { + minimal_gas_price: 1.into(), + block_gas_limit: 1_000_000.into(), + tx_gas_limit: 1_000_000.into(), + no_early_reject: true, + }, + PrioritizationStrategy::GasPriceOnly, + ); + // when + let tx1 = Tx::gas_price(2).signed(); + let client = TestClient::new().with_local(&tx1.sender()); + let res = txq.import(client.clone(), vec![tx1.unverified()]); + + // then + assert_eq!(res, vec![Ok(())]); + assert_eq!(txq.status().status.transaction_count, 1); + assert!(client.was_verification_triggered()); + + // when + let tx1 = Tx::gas_price(1).signed(); + let client = TestClient::new().with_local(&tx1.sender()); + let res = txq.import(client.clone(), vec![tx1.unverified()]); + + // then + assert_eq!(res, vec![Ok(())]); + assert_eq!(txq.status().status.transaction_count, 2); + assert!(client.was_verification_triggered()); +} diff --git a/miner/src/pool/verifier.rs b/miner/src/pool/verifier.rs index 4703088ff..eaa13b3da 100644 --- a/miner/src/pool/verifier.rs +++ b/miner/src/pool/verifier.rs @@ -43,6 +43,8 @@ pub struct Options { pub block_gas_limit: U256, /// Maximal gas limit for a single transaction. pub tx_gas_limit: U256, + /// Skip checks for early rejection, to make sure that local transactions are always imported. + pub no_early_reject: bool, } #[cfg(test)] @@ -52,6 +54,7 @@ impl Default for Options { minimal_gas_price: 0.into(), block_gas_limit: U256::max_value(), tx_gas_limit: U256::max_value(), + no_early_reject: false, } } } @@ -204,7 +207,7 @@ impl txpool::Verifier for Verifier, tx_queue_ban_time: Option, tx_queue_no_unfamiliar_locals: Option, + tx_queue_no_early_reject: Option, remove_solved: Option, notify_work: Option>, refuse_service_transactions: Option, @@ -1720,6 +1725,7 @@ mod tests { arg_gas_cap: "6283184".into(), arg_extra_data: Some("Parity".into()), flag_tx_queue_no_unfamiliar_locals: false, + flag_tx_queue_no_early_reject: false, arg_tx_queue_size: 8192usize, arg_tx_queue_per_sender: None, arg_tx_queue_mem_limit: 4u32, @@ -1988,6 +1994,7 @@ mod tests { tx_queue_ban_count: None, tx_queue_ban_time: None, tx_queue_no_unfamiliar_locals: None, + tx_queue_no_early_reject: None, tx_gas_limit: None, tx_time_limit: None, extra_data: None, diff --git a/parity/cli/tests/config.full.toml b/parity/cli/tests/config.full.toml index 2dcba6f19..d615996cf 100644 --- a/parity/cli/tests/config.full.toml +++ b/parity/cli/tests/config.full.toml @@ -134,6 +134,7 @@ tx_queue_ban_time = 180 #s tx_gas_limit = "6283184" tx_time_limit = 100 #ms tx_queue_no_unfamiliar_locals = false +tx_queue_no_early_reject = false extra_data = "Parity" remove_solved = false notify_work = ["http://localhost:3001"] diff --git a/parity/configuration.rs b/parity/configuration.rs index 52bcc40b2..6a40aff3d 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -570,6 +570,7 @@ impl Configuration { Some(ref d) => to_u256(d)?, None => U256::max_value(), }, + no_early_reject: self.args.flag_tx_queue_no_early_reject, }) } diff --git a/rpc/src/v1/tests/helpers/miner_service.rs b/rpc/src/v1/tests/helpers/miner_service.rs index 7ecd2a474..a57e5d5f2 100644 --- a/rpc/src/v1/tests/helpers/miner_service.rs +++ b/rpc/src/v1/tests/helpers/miner_service.rs @@ -264,6 +264,7 @@ impl MinerService for TestMinerService { minimal_gas_price: 0x1312d00.into(), block_gas_limit: 5_000_000.into(), tx_gas_limit: 5_000_000.into(), + no_early_reject: false, }, status: txpool::LightStatus { mem_usage: 1_000,