Limit for logs filter. (#2180)

* Limit for logs filter.

* Moving limit inside the filter object

* Fixing tests
This commit is contained in:
Tomasz Drwięga
2016-09-21 12:51:10 +02:00
committed by Gav Wood
parent 2e6684dae8
commit 8c111da70b
11 changed files with 147 additions and 47 deletions

View File

@@ -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)
@@ -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>> {

View File

@@ -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
@@ -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,
@@ -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();
@@ -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 {

View File

@@ -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>;

View File

@@ -142,7 +142,8 @@ fn returns_logs() {
to_block: BlockID::Latest,
address: None,
topics: vec![],
}, None);
limit: None,
});
assert_eq!(logs.len(), 0);
}
@@ -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);
}

View File

@@ -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 {
@@ -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(),
limit: self.limit,
}
}
}
@@ -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();
@@ -136,7 +144,8 @@ mod tests {
None,
None,
None,
]
],
limit: None,
};
let possibilities = filter.bloom_possibilities();
@@ -154,7 +163,8 @@ mod tests {
Some(vec!["ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9".into()]),
None,
None,
]
],
limit: None,
};
let possibilities = filter.bloom_possibilities();
@@ -181,7 +191,8 @@ mod tests {
]),
Some(vec!["ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9".into()]),
None
]
],
limit: None,
};
// number of possibilites should be equal 2 * 2 * 2 * 1 = 8
@@ -201,7 +212,8 @@ mod tests {
Some(vec!["ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23fa".into()]),
None,
None,
]
],
limit: None,
};
let entry0 = LogEntry {