moved filter logic from rpc module to ethcore
This commit is contained in:
parent
5826a34ebb
commit
c74c016ce2
@ -33,7 +33,7 @@ use env_info::LastHashes;
|
|||||||
use verification::*;
|
use verification::*;
|
||||||
use block::*;
|
use block::*;
|
||||||
use transaction::LocalizedTransaction;
|
use transaction::LocalizedTransaction;
|
||||||
use extras::{TransactionAddress, BlockReceipts};
|
use extras::TransactionAddress;
|
||||||
use filter::Filter;
|
use filter::Filter;
|
||||||
use log_entry::LocalizedLogEntry;
|
use log_entry::LocalizedLogEntry;
|
||||||
pub use blockchain::TreeRoute;
|
pub use blockchain::TreeRoute;
|
||||||
@ -512,7 +512,7 @@ impl BlockChainClient for Client {
|
|||||||
block_number: number as usize,
|
block_number: number as usize,
|
||||||
transaction_hash: H256::new(),
|
transaction_hash: H256::new(),
|
||||||
transaction_index: index,
|
transaction_index: index,
|
||||||
log_index: log_index
|
log_index: log_index + i
|
||||||
})
|
})
|
||||||
.collect::<Vec<LocalizedLogEntry>>()
|
.collect::<Vec<LocalizedLogEntry>>()
|
||||||
})
|
})
|
||||||
|
@ -14,12 +14,14 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
//! Blockchain filter
|
||||||
|
|
||||||
use util::hash::*;
|
use util::hash::*;
|
||||||
use util::sha3::*;
|
use util::sha3::*;
|
||||||
use client::BlockId;
|
use client::BlockId;
|
||||||
use log_entry::LogEntry;
|
use log_entry::LogEntry;
|
||||||
|
|
||||||
/// Blockchain log filter data.
|
/// Blockchain Filter.
|
||||||
pub struct Filter {
|
pub struct Filter {
|
||||||
/// Blockchain will be searched from this block.
|
/// Blockchain will be searched from this block.
|
||||||
pub from_block: BlockId,
|
pub from_block: BlockId,
|
||||||
|
@ -102,8 +102,10 @@ pub mod block_queue;
|
|||||||
pub mod client;
|
pub mod client;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod ethereum;
|
pub mod ethereum;
|
||||||
|
pub mod filter;
|
||||||
pub mod header;
|
pub mod header;
|
||||||
pub mod service;
|
pub mod service;
|
||||||
|
pub mod log_entry;
|
||||||
pub mod spec;
|
pub mod spec;
|
||||||
pub mod transaction;
|
pub mod transaction;
|
||||||
pub mod views;
|
pub mod views;
|
||||||
@ -112,7 +114,6 @@ pub mod receipt;
|
|||||||
mod common;
|
mod common;
|
||||||
mod basic_types;
|
mod basic_types;
|
||||||
#[macro_use] mod evm;
|
#[macro_use] mod evm;
|
||||||
mod log_entry;
|
|
||||||
mod env_info;
|
mod env_info;
|
||||||
mod pod_account;
|
mod pod_account;
|
||||||
mod pod_state;
|
mod pod_state;
|
||||||
@ -131,7 +132,6 @@ mod substate;
|
|||||||
mod executive;
|
mod executive;
|
||||||
mod externalities;
|
mod externalities;
|
||||||
mod verification;
|
mod verification;
|
||||||
mod filter;
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
//! Block log.
|
||||||
|
|
||||||
use util::*;
|
use util::*;
|
||||||
use basic_types::LogBloom;
|
use basic_types::LogBloom;
|
||||||
|
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
//! Eth rpc implementation.
|
//! Eth rpc implementation.
|
||||||
use std::collections::HashSet;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use ethsync::{EthSync, SyncState};
|
use ethsync::{EthSync, SyncState};
|
||||||
use jsonrpc_core::*;
|
use jsonrpc_core::*;
|
||||||
@ -26,7 +25,7 @@ use ethcore::client::*;
|
|||||||
use ethcore::views::*;
|
use ethcore::views::*;
|
||||||
use ethcore::ethereum::denominations::shannon;
|
use ethcore::ethereum::denominations::shannon;
|
||||||
use v1::traits::{Eth, EthFilter};
|
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.
|
/// Eth rpc implementation.
|
||||||
pub struct EthClient {
|
pub struct EthClient {
|
||||||
@ -202,18 +201,11 @@ impl Eth for EthClient {
|
|||||||
fn logs(&self, params: Params) -> Result<Value, Error> {
|
fn logs(&self, params: Params) -> Result<Value, Error> {
|
||||||
from_params::<(Filter,)>(params)
|
from_params::<(Filter,)>(params)
|
||||||
.and_then(|(filter,)| {
|
.and_then(|(filter,)| {
|
||||||
let possibilities = filter.bloom_possibilities();
|
let logs = self.client.logs(filter.into())
|
||||||
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<u64> = possibilities.iter()
|
|
||||||
.map(|bloom| self.client.blocks_with_bloom(bloom, from.clone(), to.clone()))
|
|
||||||
.filter_map(|m| m)
|
|
||||||
.flat_map(|m| m)
|
|
||||||
.collect::<HashSet<u64>>()
|
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect();
|
.map(From::from)
|
||||||
blocks.sort();
|
.collect::<Vec<Log>>();
|
||||||
to_value(&blocks)
|
to_value(&logs)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,8 +18,9 @@ use serde::{Deserialize, Deserializer, Error};
|
|||||||
use serde_json::value;
|
use serde_json::value;
|
||||||
use jsonrpc_core::Value;
|
use jsonrpc_core::Value;
|
||||||
use util::hash::*;
|
use util::hash::*;
|
||||||
use util::sha3::*;
|
|
||||||
use v1::types::BlockNumber;
|
use v1::types::BlockNumber;
|
||||||
|
use ethcore::filter::Filter as EthFilter;
|
||||||
|
use ethcore::client::BlockId;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum VariadicValue<T> where T: Deserialize {
|
pub enum VariadicValue<T> where T: Deserialize {
|
||||||
@ -56,41 +57,24 @@ pub struct Filter {
|
|||||||
pub topics: Option<Vec<Topic>>
|
pub topics: Option<Vec<Topic>>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Filter {
|
impl Into<EthFilter> for Filter {
|
||||||
/// Returns combinations of each address and topic.
|
fn into(self) -> EthFilter {
|
||||||
pub fn bloom_possibilities(&self) -> Vec<H2048> {
|
EthFilter {
|
||||||
let blooms = match self.address {
|
from_block: self.from_block.map_or_else(|| BlockId::Earliest, Into::into),
|
||||||
Some(VariadicValue::Single(ref address)) => {
|
to_block: self.to_block.map_or_else(|| BlockId::Latest, Into::into),
|
||||||
let mut bloom = H2048::new();
|
address: self.address.and_then(|address| match address {
|
||||||
bloom.shift_bloomed(&address.sha3());
|
VariadicValue::Null => None,
|
||||||
vec![bloom]
|
VariadicValue::Single(a) => Some(vec![a]),
|
||||||
},
|
VariadicValue::Multiple(a) => Some(a)
|
||||||
Some(VariadicValue::Multiple(ref addresses)) => {
|
}),
|
||||||
addresses.iter().map(|ref address| {
|
topics: {
|
||||||
let mut bloom = H2048::new();
|
let mut iter = self.topics.map_or_else(Vec::new, |topics| topics.into_iter().take(4).map(|topic| match topic {
|
||||||
bloom.shift_bloomed(&address.sha3());
|
VariadicValue::Null => None,
|
||||||
bloom
|
VariadicValue::Single(t) => Some(vec![t]),
|
||||||
}).collect()
|
VariadicValue::Multiple(t) => Some(t)
|
||||||
},
|
}).filter_map(|m| m).collect()).into_iter();
|
||||||
_ => vec![H2048::new()]
|
[iter.next(), iter.next(), iter.next(), iter.next()]
|
||||||
};
|
}
|
||||||
|
|
||||||
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::<Vec<H2048>>()
|
|
||||||
}).flat_map(|m| m).collect::<Vec<H2048>>()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -128,75 +112,4 @@ mod tests {
|
|||||||
topics: None
|
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());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
52
rpc/src/v1/types/log.rs
Normal file
52
rpc/src/v1/types/log.rs
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
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<H256>,
|
||||||
|
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<LocalizedLogEntry> 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -19,6 +19,7 @@ mod block_number;
|
|||||||
mod bytes;
|
mod bytes;
|
||||||
mod filter;
|
mod filter;
|
||||||
mod index;
|
mod index;
|
||||||
|
mod log;
|
||||||
mod optionals;
|
mod optionals;
|
||||||
mod sync;
|
mod sync;
|
||||||
mod transaction;
|
mod transaction;
|
||||||
@ -28,6 +29,7 @@ pub use self::block_number::BlockNumber;
|
|||||||
pub use self::bytes::Bytes;
|
pub use self::bytes::Bytes;
|
||||||
pub use self::filter::Filter;
|
pub use self::filter::Filter;
|
||||||
pub use self::index::Index;
|
pub use self::index::Index;
|
||||||
|
pub use self::log::Log;
|
||||||
pub use self::optionals::OptionalValue;
|
pub use self::optionals::OptionalValue;
|
||||||
pub use self::sync::{SyncStatus, SyncInfo};
|
pub use self::sync::{SyncStatus, SyncInfo};
|
||||||
pub use self::transaction::Transaction;
|
pub use self::transaction::Transaction;
|
||||||
|
Loading…
Reference in New Issue
Block a user