From 0a5c9b046570a875a88d11f4aa007001e811888f Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Tue, 3 Oct 2017 10:03:46 +0200 Subject: [PATCH] Add pagination for trace_filter rpc method (#6312) * Optional offset and count added on client level * Rpc interface extended * Tests corrected * Filtering code refactored a little bit * Offset type was changed to usize * Handling of block hash in offset added * Offset reworked to number * Trailing comma removed * Import for Quantity type added * Offset and count moved into filter object * Lost comma removed * Return empty vec instead of None in case of incorrect range --- ethcore/src/client/client.rs | 14 +++++++++++--- ethcore/types/src/trace_filter.rs | 4 ++++ js/src/jsonrpc/interfaces/trace.js | 16 ++++++++++++++-- rpc/src/v1/types/trace_filter.rs | 16 ++++++++++++++-- 4 files changed, 43 insertions(+), 7 deletions(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index afe36a6f3..d79ac5580 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -1692,14 +1692,22 @@ impl BlockChainClient for Client { match (start, end) { (Some(s), Some(e)) => { - let filter = trace::Filter { + let db_filter = trace::Filter { range: s as usize..e as usize, from_address: From::from(filter.from_address), to_address: From::from(filter.to_address), }; - let traces = self.tracedb.read().filter(&filter); - Some(traces) + let traces = self.tracedb.read().filter(&db_filter); + if traces.is_empty() { + return Some(vec![]); + } + + let traces_iter = traces.into_iter().skip(filter.after.unwrap_or(0)); + Some(match filter.count { + Some(count) => traces_iter.take(count).collect(), + None => traces_iter.collect(), + }) }, _ => None, } diff --git a/ethcore/types/src/trace_filter.rs b/ethcore/types/src/trace_filter.rs index 4eed19b4c..5ec6fab10 100644 --- a/ethcore/types/src/trace_filter.rs +++ b/ethcore/types/src/trace_filter.rs @@ -28,4 +28,8 @@ pub struct Filter { pub from_address: Vec
, /// To address. pub to_address: Vec
, + /// Output offset + pub after: Option, + /// Output amount + pub count: Option, } diff --git a/js/src/jsonrpc/interfaces/trace.js b/js/src/jsonrpc/interfaces/trace.js index 9e35da629..ce814fdcb 100644 --- a/js/src/jsonrpc/interfaces/trace.js +++ b/js/src/jsonrpc/interfaces/trace.js @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import { Address, BlockNumber, Data, Hash, CallRequest } from '../types'; +import { Address, BlockNumber, Data, Hash, CallRequest, Quantity } from '../types'; import { withPreamble, Dummy, fromDecimal } from '../helpers'; const SECTION_FILTERING = 'Transaction-Trace Filtering'; @@ -134,12 +134,24 @@ then it should look something like: type: Address, desc: 'Sent to these addresses.', optional: true + }, + after: { + type: Quantity, + desc: 'The offset trace number', + optional: true + }, + count: { + type: Quantity, + desc: 'Integer number of traces to display in a batch.', + optional: true } }, example: { fromBlock: fromDecimal(3068100), toBlock: fromDecimal(3068200), - toAddress: ['0x8bbB73BCB5d553B5A556358d27625323Fd781D37'] + toAddress: ['0x8bbB73BCB5d553B5A556358d27625323Fd781D37'], + after: 1000, + count: 100 } } ], diff --git a/rpc/src/v1/types/trace_filter.rs b/rpc/src/v1/types/trace_filter.rs index 4390efa2a..5aa1eda1e 100644 --- a/rpc/src/v1/types/trace_filter.rs +++ b/rpc/src/v1/types/trace_filter.rs @@ -36,6 +36,10 @@ pub struct TraceFilter { /// To address #[serde(rename="toAddress")] pub to_address: Option>, + /// Output offset + pub after: Option, + /// Output amount + pub count: Option, } impl Into for TraceFilter { @@ -46,6 +50,8 @@ impl Into for TraceFilter { range: start..end, from_address: self.from_address.map_or_else(Vec::new, |x| x.into_iter().map(Into::into).collect()), to_address: self.to_address.map_or_else(Vec::new, |x| x.into_iter().map(Into::into).collect()), + after: self.after, + count: self.count, } } } @@ -64,7 +70,9 @@ mod tests { from_block: None, to_block: None, from_address: None, - to_address: None + to_address: None, + after: None, + count: None, }); } @@ -74,7 +82,9 @@ mod tests { "fromBlock": "latest", "toBlock": "latest", "fromAddress": ["0x0000000000000000000000000000000000000003"], - "toAddress": ["0x0000000000000000000000000000000000000005"] + "toAddress": ["0x0000000000000000000000000000000000000005"], + "after": 50, + "count": 100 }"#; let deserialized: TraceFilter = serde_json::from_str(s).unwrap(); assert_eq!(deserialized, TraceFilter { @@ -82,6 +92,8 @@ mod tests { to_block: Some(BlockNumber::Latest), from_address: Some(vec![Address::from(3).into()]), to_address: Some(vec![Address::from(5).into()]), + after: 50.into(), + count: 100.into(), }); } }