Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Limit for logs filter. #2180

Merged
merged 3 commits into from
Sep 21, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions ethcore/src/client/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -957,7 +957,7 @@ impl BlockChainClient for Client {
}
}

fn logs(&self, filter: Filter, limit: Option<usize>) -> Vec<LocalizedLogEntry> {
fn logs(&self, filter: Filter) -> Vec<LocalizedLogEntry> {
let blocks = filter.bloom_possibilities().iter()
.filter_map(|bloom| self.blocks_with_bloom(bloom, filter.from_block.clone(), filter.to_block.clone()))
.flat_map(|m| m)
Expand All @@ -966,7 +966,7 @@ impl BlockChainClient for Client {
.into_iter()
.collect::<Vec<u64>>();

self.chain.read().logs(blocks, |entry| filter.matches(entry), limit)
self.chain.read().logs(blocks, |entry| filter.matches(entry), filter.limit)
}

fn filter_traces(&self, filter: TraceFilter) -> Option<Vec<LocalizedTrace>> {
Expand Down
17 changes: 15 additions & 2 deletions ethcore/src/client/test_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ pub struct TestBlockChainClient {
pub execution_result: RwLock<Option<Result<Executed, CallError>>>,
/// Transaction receipts.
pub receipts: RwLock<HashMap<TransactionID, LocalizedReceipt>>,
/// Logs
pub logs: RwLock<Vec<LocalizedLogEntry>>,
/// Block queue size.
pub queue_size: AtomicUsize,
/// Miner
Expand Down Expand Up @@ -114,6 +116,7 @@ impl TestBlockChainClient {
code: RwLock::new(HashMap::new()),
execution_result: RwLock::new(None),
receipts: RwLock::new(HashMap::new()),
logs: RwLock::new(Vec::new()),
queue_size: AtomicUsize::new(0),
miner: Arc::new(Miner::with_spec(&spec)),
spec: spec,
Expand Down Expand Up @@ -165,6 +168,11 @@ impl TestBlockChainClient {
*self.latest_block_timestamp.write() = ts;
}

/// Set logs to return for each logs call.
pub fn set_logs(&self, logs: Vec<LocalizedLogEntry>) {
*self.logs.write() = logs;
}

/// Add blocks to test client.
pub fn add_blocks(&self, count: usize, with: EachBlockWith) {
let len = self.numbers.read().len();
Expand Down Expand Up @@ -390,8 +398,13 @@ impl BlockChainClient for TestBlockChainClient {
unimplemented!();
}

fn logs(&self, _filter: Filter, _limit: Option<usize>) -> Vec<LocalizedLogEntry> {
Vec::new()
fn logs(&self, filter: Filter) -> Vec<LocalizedLogEntry> {
let mut logs = self.logs.read().clone();
let len = logs.len();
match filter.limit {
Some(limit) if limit <= len => logs.split_off(len - limit),
_ => logs,
}
}

fn last_hashes(&self) -> LastHashes {
Expand Down
2 changes: 1 addition & 1 deletion ethcore/src/client/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ pub trait BlockChainClient : Sync + Send {
fn blocks_with_bloom(&self, bloom: &H2048, from_block: BlockID, to_block: BlockID) -> Option<Vec<BlockNumber>>;

/// Returns logs matching given filter.
fn logs(&self, filter: Filter, limit: Option<usize>) -> Vec<LocalizedLogEntry>;
fn logs(&self, filter: Filter) -> Vec<LocalizedLogEntry>;

/// Makes a non-persistent transaction call.
fn call(&self, t: &SignedTransaction, block: BlockID, analytics: CallAnalytics) -> Result<Executed, CallError>;
Expand Down
6 changes: 4 additions & 2 deletions ethcore/src/tests/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,8 @@ fn returns_logs() {
to_block: BlockID::Latest,
address: None,
topics: vec![],
}, None);
limit: None,
});
assert_eq!(logs.len(), 0);
}

Expand All @@ -156,7 +157,8 @@ fn returns_logs_with_limit() {
to_block: BlockID::Latest,
address: None,
topics: vec![],
}, Some(2));
limit: Some(2),
});
assert_eq!(logs.len(), 0);
}

Expand Down
22 changes: 17 additions & 5 deletions ethcore/src/types/filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ pub struct Filter {
/// If None, match all.
/// If specified, log must contain one of these topics.
pub topics: Vec<Option<Vec<H256>>>,

/// Logs limit
///
/// If None, return all logs
/// If specified, should only return *last* `n` logs.
pub limit: Option<usize>,
}

impl Clone for Filter {
Expand All @@ -59,7 +65,8 @@ impl Clone for Filter {
from_block: self.from_block.clone(),
to_block: self.to_block.clone(),
address: self.address.clone(),
topics: topics[..].to_vec()
topics: topics[..].to_vec(),
Copy link
Contributor

@rphmeier rphmeier Sep 21, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

side note: seems that topics only has four members -- why bother allocating a Vec at all?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, it can contain up to 4 entries - but that's true, we could substitute this with array of 4 Option. I will prepare a separate PR.

limit: self.limit,
}
}
}
Expand Down Expand Up @@ -117,6 +124,7 @@ mod tests {
to_block: BlockID::Latest,
address: None,
topics: vec![None, None, None, None],
limit: None,
};

let possibilities = none_filter.bloom_possibilities();
Expand All @@ -136,7 +144,8 @@ mod tests {
None,
None,
None,
]
],
limit: None,
};

let possibilities = filter.bloom_possibilities();
Expand All @@ -154,7 +163,8 @@ mod tests {
Some(vec!["ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9".into()]),
None,
None,
]
],
limit: None,
};

let possibilities = filter.bloom_possibilities();
Expand All @@ -181,7 +191,8 @@ mod tests {
]),
Some(vec!["ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9".into()]),
None
]
],
limit: None,
};

// number of possibilites should be equal 2 * 2 * 2 * 1 = 8
Expand All @@ -201,7 +212,8 @@ mod tests {
Some(vec!["ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23fa".into()]),
None,
None,
]
],
limit: None,
};

let entry0 = LogEntry {
Expand Down
2 changes: 1 addition & 1 deletion rpc/src/v1/helpers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ mod signing_queue;
mod network_settings;

pub use self::poll_manager::PollManager;
pub use self::poll_filter::PollFilter;
pub use self::poll_filter::{PollFilter, limit_logs};
pub use self::requests::{TransactionRequest, FilledTransactionRequest, ConfirmationRequest, ConfirmationPayload, CallRequest};
pub use self::signing_queue::{ConfirmationsQueue, ConfirmationPromise, ConfirmationResult, SigningQueue, QueueEvent};
pub use self::network_settings::NetworkSettings;
11 changes: 10 additions & 1 deletion rpc/src/v1/helpers/poll_filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@ pub enum PollFilter {
Block(BlockNumber),
/// Hashes of all transactions which client was notified about.
PendingTransaction(Vec<H256>),
/// Number of From block number, pending logs and log filter iself.
/// Number of From block number, pending logs and log filter itself.
Logs(BlockNumber, HashSet<Log>, Filter)
}

/// Returns only last `n` logs
pub fn limit_logs(mut logs: Vec<Log>, limit: Option<usize>) -> Vec<Log> {
let len = logs.len();
match limit {
Some(limit) if len >= limit => logs.split_off(len - limit),
_ => logs,
}
}
19 changes: 4 additions & 15 deletions rpc/src/v1/impls/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ use ethcore::filter::Filter as EthcoreFilter;
use self::ethash::SeedHashCompute;
use v1::traits::Eth;
use v1::types::{Block, BlockTransactions, BlockNumber, Bytes, SyncStatus, SyncInfo, Transaction, CallRequest, Index, Filter, Log, Receipt, H64 as RpcH64, H256 as RpcH256, H160 as RpcH160, U256 as RpcU256};
use v1::helpers::{CallRequest as CRequest, errors};
use v1::helpers::{CallRequest as CRequest, errors, limit_logs};
use v1::helpers::dispatch::{default_gas_price, dispatch_transaction};
use v1::helpers::params::{expect_no_params, params_len, from_params_default_second, from_params_default_third};

Expand Down Expand Up @@ -498,14 +498,10 @@ impl<C, S: ?Sized, M, EM> Eth for EthClient<C, S, M, EM> where

fn logs(&self, params: Params) -> Result<Value, Error> {
try!(self.active());
let params = match params_len(&params) {
1 => from_params::<(Filter, )>(params).map(|(filter, )| (filter, None)),
_ => from_params::<(Filter, usize)>(params).map(|(filter, val)| (filter, Some(val))),
};
params.and_then(|(filter, limit)| {
from_params::<(Filter, )>(params).and_then(|(filter,)| {
let include_pending = filter.to_block == Some(BlockNumber::Pending);
let filter: EthcoreFilter = filter.into();
let mut logs = take_weak!(self.client).logs(filter.clone(), limit)
let mut logs = take_weak!(self.client).logs(filter.clone())
.into_iter()
.map(From::from)
.collect::<Vec<Log>>();
Expand All @@ -515,14 +511,7 @@ impl<C, S: ?Sized, M, EM> Eth for EthClient<C, S, M, EM> where
logs.extend(pending);
}

let len = logs.len();
match limit {
Some(limit) if len >= limit => {
logs = logs.split_off(len - limit);
},
_ => {},
}

let logs = limit_logs(logs, filter.limit);
Ok(to_value(&logs))
})
}
Expand Down
16 changes: 10 additions & 6 deletions rpc/src/v1/impls/eth_filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ use ethcore::client::{BlockChainClient, BlockID};
use util::Mutex;
use v1::traits::EthFilter;
use v1::types::{BlockNumber, Index, Filter, Log, H256 as RpcH256, U256 as RpcU256};
use v1::helpers::{PollFilter, PollManager};
use v1::helpers::params::expect_no_params;
use v1::helpers::{PollFilter, PollManager, limit_logs};
use v1::helpers::params::{expect_no_params, params_len};
use v1::impls::eth::pending_logs;

/// Eth filter rpc implementation.
Expand Down Expand Up @@ -65,8 +65,8 @@ impl<C, M> EthFilter for EthFilterClient<C, M> where

fn new_filter(&self, params: Params) -> Result<Value, Error> {
try!(self.active());
from_params::<(Filter,)>(params)
.and_then(|(filter,)| {
from_params::<(Filter, )>(params)
.and_then(|(filter, )| {
let mut polls = self.polls.lock();
let block_number = take_weak!(self.client).chain_info().best_block_number;
let id = polls.create_poll(PollFilter::Logs(block_number, Default::default(), filter));
Expand Down Expand Up @@ -152,7 +152,7 @@ impl<C, M> EthFilter for EthFilterClient<C, M> where
filter.to_block = BlockID::Latest;

// retrieve logs in range from_block..min(BlockID::Latest..to_block)
let mut logs = client.logs(filter.clone(), None)
let mut logs = client.logs(filter.clone())
.into_iter()
.map(From::from)
.collect::<Vec<Log>>();
Expand All @@ -174,6 +174,8 @@ impl<C, M> EthFilter for EthFilterClient<C, M> where
logs.extend(new_pending_logs);
}

let logs = limit_logs(logs, filter.limit);

// save the number of the next block as a first block from which
// we want to get logs
*block_number = current_number + 1;
Expand All @@ -194,7 +196,7 @@ impl<C, M> EthFilter for EthFilterClient<C, M> where
Some(&PollFilter::Logs(ref _block_number, ref _previous_log, ref filter)) => {
let include_pending = filter.to_block == Some(BlockNumber::Pending);
let filter: EthcoreFilter = filter.clone().into();
let mut logs = take_weak!(self.client).logs(filter.clone(), None)
let mut logs = take_weak!(self.client).logs(filter.clone())
.into_iter()
.map(From::from)
.collect::<Vec<Log>>();
Expand All @@ -203,6 +205,8 @@ impl<C, M> EthFilter for EthFilterClient<C, M> where
logs.extend(pending_logs(&*take_weak!(self.miner), &filter));
}

let logs = limit_logs(logs, filter.limit);

Ok(to_value(&logs))
},
// just empty array
Expand Down
Loading