[ethcore]: apply filter when PendingSet::AlwaysQueue
in ready_transactions_filtered
(#11227)
* [ethcore]: apply filter when `from_queue` In `ready_transactions_filtered` the filter were never applied when the options PendingSet::AlwaysQueue` was configured which this fixes It also adds a two tests for it * [ethcore test-helpers]: stray printlns * docs(ethcore filter options): more generic desc * tests(ethcore miner): simply filter tests * [ethcore filter_options]: fix nits * doc: nit Co-Authored-By: David <dvdplm@gmail.com> * doc: nit Co-Authored-By: David <dvdplm@gmail.com> * doc: nit Co-Authored-By: David <dvdplm@gmail.com> * doc: nit Co-Authored-By: David <dvdplm@gmail.com> * doc: nit Co-Authored-By: David <dvdplm@gmail.com> * doc(miner filter): simplify documentation * [rpc]: make tests compile
This commit is contained in:
parent
1b0948d9d1
commit
dcb69ba353
File diff suppressed because it is too large
Load Diff
@ -31,7 +31,7 @@ use ethcore_miner::work_notify::NotifyWork;
|
|||||||
use ethereum_types::{H256, U256, Address};
|
use ethereum_types::{H256, U256, Address};
|
||||||
use futures::sync::mpsc;
|
use futures::sync::mpsc;
|
||||||
use io::IoChannel;
|
use io::IoChannel;
|
||||||
use miner::filter_options::{FilterOptions, FilterOperator};
|
use miner::filter_options::FilterOptions;
|
||||||
use miner::pool_client::{PoolClient, CachedNonceClient, NonceCache};
|
use miner::pool_client::{PoolClient, CachedNonceClient, NonceCache};
|
||||||
use miner::{self, MinerService};
|
use miner::{self, MinerService};
|
||||||
use parking_lot::{Mutex, RwLock};
|
use parking_lot::{Mutex, RwLock};
|
||||||
@ -1095,7 +1095,8 @@ impl miner::MinerService for Miner {
|
|||||||
max_len: usize,
|
max_len: usize,
|
||||||
filter: Option<FilterOptions>,
|
filter: Option<FilterOptions>,
|
||||||
ordering: miner::PendingOrdering,
|
ordering: miner::PendingOrdering,
|
||||||
) -> Vec<Arc<VerifiedTransaction>> where
|
) -> Vec<Arc<VerifiedTransaction>>
|
||||||
|
where
|
||||||
C: ChainInfo + Nonce + Sync,
|
C: ChainInfo + Nonce + Sync,
|
||||||
{
|
{
|
||||||
let chain_info = chain.chain_info();
|
let chain_info = chain.chain_info();
|
||||||
@ -1106,7 +1107,7 @@ impl miner::MinerService for Miner {
|
|||||||
// those transactions are valid and will just be ready to be included in next block.
|
// those transactions are valid and will just be ready to be included in next block.
|
||||||
let nonce_cap = None;
|
let nonce_cap = None;
|
||||||
|
|
||||||
self.transaction_queue.pending(
|
let mut pending = self.transaction_queue.pending(
|
||||||
CachedNonceClient::new(chain, &self.nonce_cache),
|
CachedNonceClient::new(chain, &self.nonce_cache),
|
||||||
pool::PendingSettings {
|
pool::PendingSettings {
|
||||||
block_number: chain_info.best_block_number,
|
block_number: chain_info.best_block_number,
|
||||||
@ -1115,77 +1116,26 @@ impl miner::MinerService for Miner {
|
|||||||
max_len,
|
max_len,
|
||||||
ordering,
|
ordering,
|
||||||
},
|
},
|
||||||
)
|
);
|
||||||
|
|
||||||
|
pending.retain(|tx| {
|
||||||
|
filter.as_ref().map_or(true, |filter| {
|
||||||
|
filter.matches(tx.signed())
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
pending
|
||||||
};
|
};
|
||||||
|
|
||||||
use miner::filter_options::FilterOperator::*;
|
|
||||||
let from_pending = || {
|
let from_pending = || {
|
||||||
self.map_existing_pending_block(|sealing| {
|
self.map_existing_pending_block(|sealing| {
|
||||||
// This filter is used for gas, gas price, value and nonce.
|
|
||||||
// Sender and receiver have their custom matches, since those
|
|
||||||
// allow/disallow different operators.
|
|
||||||
fn match_common_filter(operator: &FilterOperator<U256>, tx_value: &U256) -> bool {
|
|
||||||
match operator {
|
|
||||||
Eq(value) => tx_value == value,
|
|
||||||
GreaterThan(value) => tx_value > value,
|
|
||||||
LessThan(value) => tx_value < value,
|
|
||||||
// Will always occur on `Any`, other operators
|
|
||||||
// get handled during deserialization
|
|
||||||
_ => true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sealing.transactions
|
sealing.transactions
|
||||||
.iter()
|
.iter()
|
||||||
.map(|signed| pool::VerifiedTransaction::from_pending_block_transaction(signed.clone()))
|
.map(|signed| pool::VerifiedTransaction::from_pending_block_transaction(signed.clone()))
|
||||||
.map(Arc::new)
|
.map(Arc::new)
|
||||||
// Filter by sender
|
|
||||||
.filter(|tx| {
|
.filter(|tx| {
|
||||||
filter.as_ref().map_or(true, |filter| {
|
filter.as_ref().map_or(true, |filter| {
|
||||||
let sender = tx.signed().sender();
|
filter.matches(tx.signed())
|
||||||
match filter.from {
|
|
||||||
Eq(value) => sender == value,
|
|
||||||
// Will always occur on `Any`, other operators
|
|
||||||
// get handled during deserialization
|
|
||||||
_ => true,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
// Filter by receiver
|
|
||||||
.filter(|tx| {
|
|
||||||
filter.as_ref().map_or(true, |filter| {
|
|
||||||
let receiver = (*tx.signed()).receiver();
|
|
||||||
match filter.to {
|
|
||||||
// Could apply to `Some(Address)` or `None` (for contract creation)
|
|
||||||
Eq(value) => receiver == value,
|
|
||||||
// Will always occur on `Any`, other operators
|
|
||||||
// get handled during deserialization
|
|
||||||
_ => true,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
// Filter by gas
|
|
||||||
.filter(|tx| {
|
|
||||||
filter.as_ref().map_or(true, |filter| {
|
|
||||||
match_common_filter(&filter.gas, &(*tx.signed()).gas)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
// Filter by gas price
|
|
||||||
.filter(|tx| {
|
|
||||||
filter.as_ref().map_or(true, |filter| {
|
|
||||||
match_common_filter(&filter.gas_price, &(*tx.signed()).gas_price)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
// Filter by tx value
|
|
||||||
.filter(|tx| {
|
|
||||||
filter.as_ref().map_or(true, |filter| {
|
|
||||||
match_common_filter(&filter.value, &(*tx.signed()).value)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
// Filter by nonce
|
|
||||||
.filter(|tx| {
|
|
||||||
filter.as_ref().map_or(true, |filter| {
|
|
||||||
match_common_filter(&filter.nonce, &(*tx.signed()).nonce)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.take(max_len)
|
.take(max_len)
|
||||||
@ -1520,7 +1470,7 @@ mod tests {
|
|||||||
|
|
||||||
use client_traits::ChainInfo;
|
use client_traits::ChainInfo;
|
||||||
use client::ImportSealedBlock;
|
use client::ImportSealedBlock;
|
||||||
use miner::{MinerService, PendingOrdering};
|
use miner::{MinerService, PendingOrdering, filter_options::FilterOperator};
|
||||||
use test_helpers::{
|
use test_helpers::{
|
||||||
generate_dummy_client, generate_dummy_client_with_spec, TestBlockChainClient, EachBlockWith
|
generate_dummy_client, generate_dummy_client_with_spec, TestBlockChainClient, EachBlockWith
|
||||||
};
|
};
|
||||||
@ -1937,4 +1887,93 @@ mod tests {
|
|||||||
|
|
||||||
assert!(received_error_msg == expected_error_msg);
|
assert!(received_error_msg == expected_error_msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn filter_tester(option: PendingSet) {
|
||||||
|
let client = TestBlockChainClient::default();
|
||||||
|
let mut miner = miner();
|
||||||
|
miner.options.pending_set = option;
|
||||||
|
let transaction = transaction();
|
||||||
|
let best_block = 10;
|
||||||
|
let mut sender = transaction.sender();
|
||||||
|
|
||||||
|
miner.import_own_transaction(&client, PendingTransaction::new(transaction, None)).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(miner.pending_transactions(best_block), None);
|
||||||
|
assert_eq!(miner.pending_receipts(best_block), None);
|
||||||
|
assert_eq!(
|
||||||
|
miner.ready_transactions_filtered(&client, 10, Some(FilterOptions::default()), PendingOrdering::Priority).len(),
|
||||||
|
1
|
||||||
|
);
|
||||||
|
|
||||||
|
// sender filter
|
||||||
|
{
|
||||||
|
// reverse address for false match
|
||||||
|
for byte in sender.as_bytes_mut() {
|
||||||
|
*byte = !*byte;
|
||||||
|
}
|
||||||
|
let mut filter = FilterOptions::default();
|
||||||
|
filter.from = FilterOperator::Eq(sender);
|
||||||
|
assert_eq!(
|
||||||
|
miner.ready_transactions_filtered(&client, 10, Some(filter), PendingOrdering::Priority).len(),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// receiver filter
|
||||||
|
{
|
||||||
|
let mut filter = FilterOptions::default();
|
||||||
|
filter.to = FilterOperator::Eq(Some(sender));
|
||||||
|
assert_eq!(
|
||||||
|
miner.ready_transactions_filtered(&client, 10, Some(filter), PendingOrdering::Priority).len(),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// gas filter
|
||||||
|
{
|
||||||
|
let mut filter = FilterOptions::default();
|
||||||
|
filter.gas = FilterOperator::LessThan(U256::from(100_000));
|
||||||
|
assert_eq!(
|
||||||
|
miner.ready_transactions_filtered(&client, 10, Some(filter), PendingOrdering::Priority).len(),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// gas_price filter
|
||||||
|
{
|
||||||
|
let mut filter = FilterOptions::default();
|
||||||
|
filter.gas_price = FilterOperator::GreaterThan(U256::from(10));
|
||||||
|
assert_eq!(
|
||||||
|
miner.ready_transactions_filtered(&client, 10, Some(filter), PendingOrdering::Priority).len(),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// value filter
|
||||||
|
{
|
||||||
|
let mut filter = FilterOptions::default();
|
||||||
|
filter.value = FilterOperator::Eq(U256::from(19));
|
||||||
|
assert_eq!(
|
||||||
|
miner.ready_transactions_filtered(&client, 10, Some(filter), PendingOrdering::Priority).len(),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// nonce filter
|
||||||
|
{
|
||||||
|
let mut filter = FilterOptions::default();
|
||||||
|
filter.nonce = FilterOperator::GreaterThan(U256::from(10));
|
||||||
|
assert_eq!(
|
||||||
|
miner.ready_transactions_filtered(&client, 10, Some(filter), PendingOrdering::Priority).len(),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn transaction_filtering() {
|
||||||
|
filter_tester(PendingSet::AlwaysQueue);
|
||||||
|
filter_tester(PendingSet::AlwaysSealing);
|
||||||
|
filter_tester(PendingSet::SealingOrElseQueue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -229,8 +229,23 @@ impl MinerService for TestMinerService {
|
|||||||
self.queued_transactions()
|
self.queued_transactions()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ready_transactions_filtered<C>(&self, _chain: &C, _max_len: usize, _filter: Option<FilterOptions>, _ordering: miner::PendingOrdering) -> Vec<Arc<VerifiedTransaction>> {
|
fn ready_transactions_filtered<C>(
|
||||||
|
&self,
|
||||||
|
_chain: &C,
|
||||||
|
max_len: usize,
|
||||||
|
filter: Option<FilterOptions>,
|
||||||
|
_ordering: miner::PendingOrdering
|
||||||
|
) -> Vec<Arc<VerifiedTransaction>> {
|
||||||
self.queued_transactions()
|
self.queued_transactions()
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.filter(|tx| {
|
||||||
|
filter.as_ref().map_or(true, |filter| {
|
||||||
|
filter.matches(tx.signed())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.take(max_len)
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pending_transaction_hashes<C>(&self, _chain: &C) -> BTreeSet<H256> {
|
fn pending_transaction_hashes<C>(&self, _chain: &C) -> BTreeSet<H256> {
|
||||||
|
Loading…
Reference in New Issue
Block a user