Merge pull request #418 from ethcore/jsonrpc2

bloomfilter
This commit is contained in:
Gav Wood
2016-02-26 13:08:41 +01:00
26 changed files with 3338 additions and 553 deletions

View File

@@ -25,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};
use v1::types::{Block, BlockTransactions, BlockNumber, Bytes, SyncStatus, SyncInfo, Transaction, OptionalValue, Index, Filter, Log};
/// Eth rpc implementation.
pub struct EthClient {
@@ -197,8 +197,18 @@ impl Eth for EthClient {
from_params::<(BlockNumber, Index)>(params)
.and_then(|(number, index)| self.transaction(TransactionId::Location(number.into(), index.value())))
}
}
fn logs(&self, params: Params) -> Result<Value, Error> {
from_params::<(Filter,)>(params)
.and_then(|(filter,)| {
let logs = self.client.logs(filter.into())
.into_iter()
.map(From::from)
.collect::<Vec<Log>>();
to_value(&logs)
})
}
}
/// Eth filter rpc implementation.
pub struct EthFilterClient {

View File

@@ -19,37 +19,64 @@ use serde_json::value;
use jsonrpc_core::Value;
use util::hash::*;
use v1::types::BlockNumber;
use ethcore::filter::Filter as EthFilter;
use ethcore::client::BlockId;
#[derive(Debug, PartialEq)]
pub enum Topic {
Single(H256),
Multiple(Vec<H256>),
Null
pub enum VariadicValue<T> where T: Deserialize {
Single(T),
Multiple(Vec<T>),
Null,
}
impl Deserialize for Topic {
fn deserialize<D>(deserializer: &mut D) -> Result<Topic, D::Error>
impl<T> Deserialize for VariadicValue<T> where T: Deserialize {
fn deserialize<D>(deserializer: &mut D) -> Result<VariadicValue<T>, 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<Address>;
pub type Topic = VariadicValue<H256>;
#[derive(Debug, PartialEq, Deserialize)]
pub struct Filter {
#[serde(rename="fromBlock")]
pub from_block: Option<BlockNumber>,
#[serde(rename="toBlock")]
pub to_block: Option<BlockNumber>,
pub address: Option<Address>,
pub topics: Option<Vec<Topic>>
pub address: Option<FilterAddress>,
pub topics: Option<Vec<Topic>>,
}
impl Into<EthFilter> 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()]
}
}
}
}
#[cfg(test)]
@@ -65,9 +92,9 @@ mod tests {
let s = r#"["0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b", null, ["0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b", "0x0000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebccc"]]"#;
let deserialized: Vec<Topic> = 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()
])

83
rpc/src/v1/types/log.rs Normal file
View File

@@ -0,0 +1,83 @@
// 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)
}
}
}
#[cfg(test)]
mod tests {
use serde_json;
use std::str::FromStr;
use util::hash::*;
use util::uint::*;
use v1::types::{Bytes, Log};
#[test]
fn log_serialization() {
let s = r#"{"address":"0x33990122638b9132ca29c723bdf037f1a891a70c","topics":["0xa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc","0x4861736852656700000000000000000000000000000000000000000000000000"],"data":"0x","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x04510c","transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x00","logIndex":"0x01"}"#;
let log = Log {
address: Address::from_str("33990122638b9132ca29c723bdf037f1a891a70c").unwrap(),
topics: vec![
H256::from_str("a6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc").unwrap(),
H256::from_str("4861736852656700000000000000000000000000000000000000000000000000").unwrap()
],
data: Bytes::new(vec![]),
block_hash: H256::from_str("ed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5").unwrap(),
block_number: U256::from(0x4510c),
transaction_hash: H256::new(),
transaction_index: U256::zero(),
log_index: U256::one()
};
let serialized = serde_json::to_string(&log).unwrap();
assert_eq!(serialized, s);
}
}

View File

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