Disable parallel verification and skip verifiying already imported txs. (#8834)
* Reject transactions that are already in pool without verifying them. * Avoid verifying already imported transactions.
This commit is contained in:
parent
13bc922e54
commit
af1088ef61
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -691,7 +691,6 @@ dependencies = [
|
|||||||
"parity-reactor 0.1.0",
|
"parity-reactor 0.1.0",
|
||||||
"parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"price-info 1.12.0",
|
"price-info 1.12.0",
|
||||||
"rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"rlp 0.2.1",
|
"rlp 0.2.1",
|
||||||
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"trace-time 0.1.0",
|
"trace-time 0.1.0",
|
||||||
|
@ -27,7 +27,6 @@ linked-hash-map = "0.5"
|
|||||||
log = "0.3"
|
log = "0.3"
|
||||||
parking_lot = "0.5"
|
parking_lot = "0.5"
|
||||||
price-info = { path = "../price-info" }
|
price-info = { path = "../price-info" }
|
||||||
rayon = "1.0"
|
|
||||||
rlp = { path = "../util/rlp" }
|
rlp = { path = "../util/rlp" }
|
||||||
trace-time = { path = "../util/trace-time" }
|
trace-time = { path = "../util/trace-time" }
|
||||||
transaction-pool = { path = "../transaction-pool" }
|
transaction-pool = { path = "../transaction-pool" }
|
||||||
|
@ -29,7 +29,6 @@ extern crate keccak_hash as hash;
|
|||||||
extern crate linked_hash_map;
|
extern crate linked_hash_map;
|
||||||
extern crate parking_lot;
|
extern crate parking_lot;
|
||||||
extern crate price_info;
|
extern crate price_info;
|
||||||
extern crate rayon;
|
|
||||||
extern crate rlp;
|
extern crate rlp;
|
||||||
extern crate trace_time;
|
extern crate trace_time;
|
||||||
extern crate transaction_pool as txpool;
|
extern crate transaction_pool as txpool;
|
||||||
|
@ -23,7 +23,6 @@ use std::collections::BTreeMap;
|
|||||||
|
|
||||||
use ethereum_types::{H256, U256, Address};
|
use ethereum_types::{H256, U256, Address};
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use rayon::prelude::*;
|
|
||||||
use transaction;
|
use transaction;
|
||||||
use txpool::{self, Verifier};
|
use txpool::{self, Verifier};
|
||||||
|
|
||||||
@ -179,8 +178,14 @@ impl TransactionQueue {
|
|||||||
|
|
||||||
let verifier = verifier::Verifier::new(client, options, self.insertion_id.clone());
|
let verifier = verifier::Verifier::new(client, options, self.insertion_id.clone());
|
||||||
let results = transactions
|
let results = transactions
|
||||||
.into_par_iter()
|
.into_iter()
|
||||||
.map(|transaction| verifier.verify_transaction(transaction))
|
.map(|transaction| {
|
||||||
|
if self.pool.read().find(&transaction.hash()).is_some() {
|
||||||
|
bail!(transaction::Error::AlreadyImported)
|
||||||
|
}
|
||||||
|
|
||||||
|
verifier.verify_transaction(transaction)
|
||||||
|
})
|
||||||
.map(|result| result.and_then(|verified| {
|
.map(|result| result.and_then(|verified| {
|
||||||
self.pool.write().import(verified)
|
self.pool.write().import(verified)
|
||||||
.map(|_imported| ())
|
.map(|_imported| ())
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
use std::sync::{atomic, Arc};
|
||||||
|
|
||||||
use ethereum_types::{U256, H256, Address};
|
use ethereum_types::{U256, H256, Address};
|
||||||
use rlp::Rlp;
|
use rlp::Rlp;
|
||||||
use transaction::{self, Transaction, SignedTransaction, UnverifiedTransaction};
|
use transaction::{self, Transaction, SignedTransaction, UnverifiedTransaction};
|
||||||
@ -25,6 +27,7 @@ const MAX_TRANSACTION_SIZE: usize = 15 * 1024;
|
|||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct TestClient {
|
pub struct TestClient {
|
||||||
|
verification_invoked: Arc<atomic::AtomicBool>,
|
||||||
account_details: AccountDetails,
|
account_details: AccountDetails,
|
||||||
gas_required: U256,
|
gas_required: U256,
|
||||||
is_service_transaction: bool,
|
is_service_transaction: bool,
|
||||||
@ -35,6 +38,7 @@ pub struct TestClient {
|
|||||||
impl Default for TestClient {
|
impl Default for TestClient {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
TestClient {
|
TestClient {
|
||||||
|
verification_invoked: Default::default(),
|
||||||
account_details: AccountDetails {
|
account_details: AccountDetails {
|
||||||
nonce: 123.into(),
|
nonce: 123.into(),
|
||||||
balance: 63_100.into(),
|
balance: 63_100.into(),
|
||||||
@ -88,6 +92,10 @@ impl TestClient {
|
|||||||
insertion_id: 1,
|
insertion_id: 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn was_verification_triggered(&self) -> bool {
|
||||||
|
self.verification_invoked.load(atomic::Ordering::SeqCst)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl pool::client::Client for TestClient {
|
impl pool::client::Client for TestClient {
|
||||||
@ -98,6 +106,7 @@ impl pool::client::Client for TestClient {
|
|||||||
fn verify_transaction(&self, tx: UnverifiedTransaction)
|
fn verify_transaction(&self, tx: UnverifiedTransaction)
|
||||||
-> Result<SignedTransaction, transaction::Error>
|
-> Result<SignedTransaction, transaction::Error>
|
||||||
{
|
{
|
||||||
|
self.verification_invoked.store(true, atomic::Ordering::SeqCst);
|
||||||
Ok(SignedTransaction::new(tx)?)
|
Ok(SignedTransaction::new(tx)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -796,3 +796,37 @@ fn should_include_local_transaction_to_a_full_pool() {
|
|||||||
// then
|
// then
|
||||||
assert_eq!(txq.status().status.transaction_count, 1);
|
assert_eq!(txq.status().status.transaction_count, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_avoid_verifying_transaction_already_in_pool() {
|
||||||
|
// 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(),
|
||||||
|
},
|
||||||
|
PrioritizationStrategy::GasPriceOnly,
|
||||||
|
);
|
||||||
|
let client = TestClient::new();
|
||||||
|
let tx1 = Tx::default().signed().unverified();
|
||||||
|
|
||||||
|
let res = txq.import(client.clone(), vec![tx1.clone()]);
|
||||||
|
assert_eq!(res, vec![Ok(())]);
|
||||||
|
assert_eq!(txq.status().status.transaction_count, 1);
|
||||||
|
assert!(client.was_verification_triggered());
|
||||||
|
|
||||||
|
// when
|
||||||
|
let client = TestClient::new();
|
||||||
|
let res = txq.import(client.clone(), vec![tx1]);
|
||||||
|
assert_eq!(res, vec![Err(transaction::Error::AlreadyImported)]);
|
||||||
|
assert!(!client.was_verification_triggered());
|
||||||
|
|
||||||
|
// then
|
||||||
|
assert_eq!(txq.status().status.transaction_count, 1);
|
||||||
|
}
|
||||||
|
@ -57,6 +57,7 @@ impl Default for Options {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Transaction to verify.
|
/// Transaction to verify.
|
||||||
|
#[cfg_attr(test, derive(Clone))]
|
||||||
pub enum Transaction {
|
pub enum Transaction {
|
||||||
/// Fresh, never verified transaction.
|
/// Fresh, never verified transaction.
|
||||||
///
|
///
|
||||||
@ -75,7 +76,8 @@ pub enum Transaction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Transaction {
|
impl Transaction {
|
||||||
fn hash(&self) -> H256 {
|
/// Return transaction hash
|
||||||
|
pub fn hash(&self) -> H256 {
|
||||||
match *self {
|
match *self {
|
||||||
Transaction::Unverified(ref tx) => tx.hash(),
|
Transaction::Unverified(ref tx) => tx.hash(),
|
||||||
Transaction::Retracted(ref tx) => tx.hash(),
|
Transaction::Retracted(ref tx) => tx.hash(),
|
||||||
|
Loading…
Reference in New Issue
Block a user