diff --git a/ethcore/src/client.rs b/ethcore/src/client.rs index d9e461024..c7a5ec268 100644 --- a/ethcore/src/client.rs +++ b/ethcore/src/client.rs @@ -144,6 +144,9 @@ pub trait BlockChainClient : Sync + Send { fn best_block_header(&self) -> Bytes { self.block_header(BlockId::Hash(self.chain_info().best_block_hash)).unwrap() } + + /// Returns numbers of blocks containing given bloom. + fn blocks_with_bloom(&self, bloom: &H2048, from_block: BlockId, to_block: BlockId) -> Option>; } #[derive(Default, Clone, Debug, Eq, PartialEq)] @@ -358,6 +361,15 @@ impl Client { BlockId::Latest => Some(self.chain.read().unwrap().best_block_hash()) } } + + fn block_number(&self, id: BlockId) -> Option { + match id { + BlockId::Number(number) => Some(number), + BlockId::Hash(ref hash) => self.chain.read().unwrap().block_number(hash), + BlockId::Earliest => Some(0), + BlockId::Latest => Some(self.chain.read().unwrap().best_block_number()) + } + } } impl BlockChainClient for Client { @@ -450,6 +462,13 @@ impl BlockChainClient for Client { best_block_number: From::from(chain.best_block_number()) } } + + fn blocks_with_bloom(&self, bloom: &H2048, from_block: BlockId, to_block: BlockId) -> Option> { + match (self.block_number(from_block), self.block_number(to_block)) { + (Some(from), Some(to)) => Some(self.chain.read().unwrap().blocks_with_bloom(bloom, from, to)), + _ => None + } + } } impl MayPanic for Client { diff --git a/rpc/src/v1/types/filter.rs b/rpc/src/v1/types/filter.rs index 9b21cf8e7..cac1f7ef9 100644 --- a/rpc/src/v1/types/filter.rs +++ b/rpc/src/v1/types/filter.rs @@ -18,40 +18,95 @@ use serde::{Deserialize, Deserializer, Error}; use serde_json::value; use jsonrpc_core::Value; use util::hash::*; +use util::sha3::*; use v1::types::BlockNumber; #[derive(Debug, PartialEq)] -pub enum Topic { - Single(H256), - Multiple(Vec), +pub enum VariadicValue where T: Deserialize { + Single(T), + Multiple(Vec), Null } -impl Deserialize for Topic { - fn deserialize(deserializer: &mut D) -> Result +impl Deserialize for VariadicValue where T: Deserialize { + fn deserialize(deserializer: &mut D) -> Result, D::Error> where D: Deserializer { let v = try!(Value::deserialize(deserializer)); if v.is_null() { - return Ok(Topic::Null); + return Ok(VariadicValue::Null); } - Deserialize::deserialize(&mut value::Deserializer::new(v.clone())).map(Topic::Single) - .or_else(|_| Deserialize::deserialize(&mut value::Deserializer::new(v.clone())).map(Topic::Multiple)) + Deserialize::deserialize(&mut value::Deserializer::new(v.clone())).map(VariadicValue::Single) + .or_else(|_| Deserialize::deserialize(&mut value::Deserializer::new(v.clone())).map(VariadicValue::Multiple)) .map_err(|_| Error::syntax("")) // unreachable, but types must match } } +pub type FilterAddress = VariadicValue
; +pub type Topic = VariadicValue; + #[derive(Debug, PartialEq, Deserialize)] pub struct Filter { #[serde(rename="fromBlock")] pub from_block: Option, #[serde(rename="toBlock")] pub to_block: Option, - pub address: Option
, + pub address: Option, pub topics: Option> } +impl Filter { + /// Returns combinations of each of address topic. + pub fn bloom_possibilities(&self) -> Vec { + let blooms = match self.address { + Some(VariadicValue::Single(ref address)) => { + let mut bloom = H2048::new(); + bloom.shift_bloomed(&address.sha3()); + vec![bloom] + }, + Some(VariadicValue::Multiple(ref addresses)) => { + addresses.iter().map(|ref address| { + let mut bloom = H2048::new(); + bloom.shift_bloomed(&address.sha3()); + bloom + }).collect() + }, + _ => vec![H2048::new()] + }; + + match self.topics { + None => blooms, + Some(ref topics) => blooms.into_iter().map(|bloom| { + //for topic in topics { + //match topic { + //VariadicValue::Single => { + //bloom.shift_bloomed(&topic.sha3()); + //bloom + //} + //} + //} + }).collect() + } + //self.address.as_ref().map(|a| match *a { + //VariadicValue::Single(ref address) => { + //let mut bloom = H2048::new(); + //bloom.shift_bloomed(&address.sha3()); + //vec![bloom] + //}, + //VariadicValue::Multiple(ref addresses) => { + //addresses.iter().map(|ref address| { + //let mut bloom = H2048::new(); + //bloom.shift_bloomed(&address.sha3()); + //bloom + //}).collect() + //}, + //VariadicValue::Null => vec![H2048::new()] + //}.into_iter().map(|bloom| match self. { + //}).unwrap_or_else(Vec::new) + } +} + #[cfg(test)] mod tests { use serde_json; @@ -65,9 +120,9 @@ mod tests { let s = r#"["0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b", null, ["0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b", "0x0000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebccc"]]"#; let deserialized: Vec = serde_json::from_str(s).unwrap(); assert_eq!(deserialized, vec![ - Topic::Single(H256::from_str("000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b").unwrap()), - Topic::Null, - Topic::Multiple(vec![ + VariadicValue::Single(H256::from_str("000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b").unwrap()), + VariadicValue::Null, + VariadicValue::Multiple(vec![ H256::from_str("000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b").unwrap(), H256::from_str("0000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebccc").unwrap() ])