diff --git a/ethcore/src/client.rs b/ethcore/src/client.rs index 7fe3fe836..ba3c97422 100644 --- a/ethcore/src/client.rs +++ b/ethcore/src/client.rs @@ -33,7 +33,7 @@ use env_info::LastHashes; use verification::*; use block::*; use transaction::LocalizedTransaction; -use extras::{TransactionAddress, BlockReceipts}; +use extras::TransactionAddress; use filter::Filter; use log_entry::LocalizedLogEntry; pub use blockchain::TreeRoute; @@ -512,7 +512,7 @@ impl BlockChainClient for Client { block_number: number as usize, transaction_hash: H256::new(), transaction_index: index, - log_index: log_index + log_index: log_index + i }) .collect::>() }) diff --git a/ethcore/src/filter.rs b/ethcore/src/filter.rs index 89295b9c2..5daecebd3 100644 --- a/ethcore/src/filter.rs +++ b/ethcore/src/filter.rs @@ -14,12 +14,14 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . +//! Blockchain filter + use util::hash::*; use util::sha3::*; use client::BlockId; use log_entry::LogEntry; -/// Blockchain log filter data. +/// Blockchain Filter. pub struct Filter { /// Blockchain will be searched from this block. pub from_block: BlockId, diff --git a/ethcore/src/lib.rs b/ethcore/src/lib.rs index 38f961d10..ab3378d7f 100644 --- a/ethcore/src/lib.rs +++ b/ethcore/src/lib.rs @@ -102,8 +102,10 @@ pub mod block_queue; pub mod client; pub mod error; pub mod ethereum; +pub mod filter; pub mod header; pub mod service; +pub mod log_entry; pub mod spec; pub mod transaction; pub mod views; @@ -112,7 +114,6 @@ pub mod receipt; mod common; mod basic_types; #[macro_use] mod evm; -mod log_entry; mod env_info; mod pod_account; mod pod_state; @@ -131,7 +132,6 @@ mod substate; mod executive; mod externalities; mod verification; -mod filter; #[cfg(test)] mod tests; diff --git a/ethcore/src/log_entry.rs b/ethcore/src/log_entry.rs index 24f449dce..a7d409833 100644 --- a/ethcore/src/log_entry.rs +++ b/ethcore/src/log_entry.rs @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . +//! Block log. + use util::*; use basic_types::LogBloom; diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index bbeb475dc..42e58493a 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -15,7 +15,6 @@ // along with Parity. If not, see . //! Eth rpc implementation. -use std::collections::HashSet; use std::sync::Arc; use ethsync::{EthSync, SyncState}; use jsonrpc_core::*; @@ -26,7 +25,7 @@ use ethcore::client::*; use ethcore::views::*; use ethcore::ethereum::denominations::shannon; use v1::traits::{Eth, EthFilter}; -use v1::types::{Block, BlockTransactions, BlockNumber, Bytes, SyncStatus, SyncInfo, Transaction, OptionalValue, Index, Filter}; +use v1::types::{Block, BlockTransactions, BlockNumber, Bytes, SyncStatus, SyncInfo, Transaction, OptionalValue, Index, Filter, Log}; /// Eth rpc implementation. pub struct EthClient { @@ -202,18 +201,11 @@ impl Eth for EthClient { fn logs(&self, params: Params) -> Result { from_params::<(Filter,)>(params) .and_then(|(filter,)| { - let possibilities = filter.bloom_possibilities(); - let from = filter.from_block.map_or_else(|| BlockId::Earliest, Into::into); - let to = filter.to_block.map_or_else(|| BlockId::Latest, Into::into); - let mut blocks: Vec = possibilities.iter() - .map(|bloom| self.client.blocks_with_bloom(bloom, from.clone(), to.clone())) - .filter_map(|m| m) - .flat_map(|m| m) - .collect::>() + let logs = self.client.logs(filter.into()) .into_iter() - .collect(); - blocks.sort(); - to_value(&blocks) + .map(From::from) + .collect::>(); + to_value(&logs) }) } } diff --git a/rpc/src/v1/types/filter.rs b/rpc/src/v1/types/filter.rs index 62b865bee..bb932f349 100644 --- a/rpc/src/v1/types/filter.rs +++ b/rpc/src/v1/types/filter.rs @@ -18,8 +18,9 @@ use serde::{Deserialize, Deserializer, Error}; use serde_json::value; use jsonrpc_core::Value; use util::hash::*; -use util::sha3::*; use v1::types::BlockNumber; +use ethcore::filter::Filter as EthFilter; +use ethcore::client::BlockId; #[derive(Debug, PartialEq)] pub enum VariadicValue where T: Deserialize { @@ -56,41 +57,24 @@ pub struct Filter { pub topics: Option> } -impl Filter { - /// Returns combinations of each address and 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) => topics.iter().fold(blooms, | bs, topic | match *topic { - VariadicValue::Null => bs, - VariadicValue::Single(ref topic) => bs.into_iter().map(|mut bloom| { - bloom.shift_bloomed(&topic.sha3()); - bloom - }).collect(), - VariadicValue::Multiple(ref topics) => bs.into_iter().map(|bloom| { - topics.into_iter().map(|topic| { - let mut b = bloom.clone(); - b.shift_bloomed(&topic.sha3()); - b - }).collect::>() - }).flat_map(|m| m).collect::>() - }) +impl Into for Filter { + fn into(self) -> EthFilter { + EthFilter { + from_block: self.from_block.map_or_else(|| BlockId::Earliest, Into::into), + to_block: self.to_block.map_or_else(|| BlockId::Latest, Into::into), + address: self.address.and_then(|address| match address { + VariadicValue::Null => None, + VariadicValue::Single(a) => Some(vec![a]), + VariadicValue::Multiple(a) => Some(a) + }), + topics: { + let mut iter = self.topics.map_or_else(Vec::new, |topics| topics.into_iter().take(4).map(|topic| match topic { + VariadicValue::Null => None, + VariadicValue::Single(t) => Some(vec![t]), + VariadicValue::Multiple(t) => Some(t) + }).filter_map(|m| m).collect()).into_iter(); + [iter.next(), iter.next(), iter.next(), iter.next()] + } } } } @@ -128,75 +112,4 @@ mod tests { topics: None }); } - - #[test] - fn test_bloom_possibilities_none() { - let none_filter = Filter { - from_block: None, - to_block: None, - address: None, - topics: None - }; - - let possibilities = none_filter.bloom_possibilities(); - assert_eq!(possibilities, vec![H2048::new()]); - } - - // block 399849 - #[test] - fn test_bloom_possibilities_single_address_and_topic() { - let filter = Filter { - from_block: None, - to_block: None, - address: Some(VariadicValue::Single(Address::from_str("b372018f3be9e171df0581136b59d2faf73a7d5d").unwrap())), - topics: Some(vec![VariadicValue::Single(H256::from_str("ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9").unwrap())]) - }; - - let possibilities = filter.bloom_possibilities(); - assert_eq!(possibilities, vec![H2048::from_str("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000004000000004000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000").unwrap()]); - } - - #[test] - fn test_bloom_possibilities_single_address_and_many_topics() { - let filter = Filter { - from_block: None, - to_block: None, - address: Some(VariadicValue::Single(Address::from_str("b372018f3be9e171df0581136b59d2faf73a7d5d").unwrap())), - topics: Some(vec![ - VariadicValue::Single(H256::from_str("ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9").unwrap()), - VariadicValue::Single(H256::from_str("ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9").unwrap()) - ]) - }; - - let possibilities = filter.bloom_possibilities(); - assert_eq!(possibilities, vec![H2048::from_str("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000004000000004000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000").unwrap()]); - } - - #[test] - fn test_bloom_possibilites_multiple_addresses_and_topics() { - let filter = Filter { - from_block: None, - to_block: None, - address: Some(VariadicValue::Multiple(vec![ - Address::from_str("b372018f3be9e171df0581136b59d2faf73a7d5d").unwrap(), - Address::from_str("b372018f3be9e171df0581136b59d2faf73a7d5d").unwrap() - ])), - topics: Some(vec![ - VariadicValue::Multiple(vec![ - H256::from_str("ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9").unwrap(), - H256::from_str("ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9").unwrap() - ]), - VariadicValue::Multiple(vec![ - H256::from_str("ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9").unwrap(), - H256::from_str("ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9").unwrap() - ]), - VariadicValue::Single(H256::from_str("ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9").unwrap()) - ]) - }; - - // number of possibilites should be equal 2 * 2 * 2 * 1 = 8 - let possibilities = filter.bloom_possibilities(); - assert_eq!(possibilities.len(), 8); - assert_eq!(possibilities[0], H2048::from_str("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000004000000004000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000").unwrap()); - } } diff --git a/rpc/src/v1/types/log.rs b/rpc/src/v1/types/log.rs new file mode 100644 index 000000000..4b8661075 --- /dev/null +++ b/rpc/src/v1/types/log.rs @@ -0,0 +1,52 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +use util::hash::*; +use util::uint::*; +use ethcore::log_entry::LocalizedLogEntry; +use v1::types::Bytes; + +#[derive(Debug, Serialize)] +pub struct Log { + address: Address, + topics: Vec, + data: Bytes, + #[serde(rename="blockHash")] + block_hash: H256, + #[serde(rename="blockNumber")] + block_number: U256, + #[serde(rename="transactionHash")] + transaction_hash: H256, + #[serde(rename="transactionIndex")] + transaction_index: U256, + #[serde(rename="logIndex")] + log_index: U256 +} + +impl From for Log { + fn from(e: LocalizedLogEntry) -> Log { + Log { + address: e.entry.address, + topics: e.entry.topics, + data: Bytes::new(e.entry.data), + block_hash: e.block_hash, + block_number: From::from(e.block_number), + transaction_hash: e.transaction_hash, + transaction_index: From::from(e.transaction_index), + log_index: From::from(e.log_index) + } + } +} diff --git a/rpc/src/v1/types/mod.rs b/rpc/src/v1/types/mod.rs index c4c6e8295..34c1f1cff 100644 --- a/rpc/src/v1/types/mod.rs +++ b/rpc/src/v1/types/mod.rs @@ -19,6 +19,7 @@ mod block_number; mod bytes; mod filter; mod index; +mod log; mod optionals; mod sync; mod transaction; @@ -28,6 +29,7 @@ pub use self::block_number::BlockNumber; pub use self::bytes::Bytes; pub use self::filter::Filter; pub use self::index::Index; +pub use self::log::Log; pub use self::optionals::OptionalValue; pub use self::sync::{SyncStatus, SyncInfo}; pub use self::transaction::Transaction;