diff --git a/rpc/src/v1/helpers/auto_args.rs b/rpc/src/v1/helpers/auto_args.rs
new file mode 100644
index 000000000..c7deb0436
--- /dev/null
+++ b/rpc/src/v1/helpers/auto_args.rs
@@ -0,0 +1,171 @@
+// 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 .
+
+//! Automatically serialize and deserialize parameters around a strongly-typed function.
+
+// because we reuse the type names as idents in the macros as a dirty hack to
+// work around `concat_idents!` being unstable.
+#![allow(non_snake_case)]
+
+use super::errors;
+
+use jsonrpc_core::{Error, Params, Value, from_params, to_value};
+use serde::{Serialize, Deserialize};
+
+/// Auto-generates an RPC trait from trait definition.
+///
+/// This just copies out all the methods, docs, and adds another
+/// function `to_delegate` which will automatically wrap each strongly-typed
+/// function in a wrapper which handles parameter and output type serialization.
+///
+/// Every function must have a `#[name("rpc_nameHere")]` attribute after
+/// its documentation, and no other attributes. All function names are
+/// allowed except for `to_delegate`, which is auto-generated.
+macro_rules! build_rpc_trait {
+ (
+ $(#[$t_attr: meta])*
+ pub trait $name: ident {
+ $(
+ $(#[doc=$m_doc: expr])* #[name($rpc_name: expr)]
+ fn $method: ident (&self $(, $param: ty)*) -> $out: ty;
+ )*
+ }
+ ) => {
+ $(#[$t_attr])*
+ pub trait $name: Sized + Send + Sync + 'static {
+ $(
+ $(#[doc=$m_doc])*
+ fn $method(&self $(, $param)*) -> $out;
+ )*
+
+ /// Transform this into an `IoDelegate`, automatically wrapping
+ /// the parameters.
+ fn to_delegate(self) -> ::jsonrpc_core::IoDelegate {
+ let mut del = ::jsonrpc_core::IoDelegate::new(self.into());
+ $(
+ del.add_method($rpc_name, move |base, params| {
+ ($name::$method as fn(&_ $(, $param)*) -> $out).wrap_rpc(base, params)
+ });
+ )*
+ del
+ }
+ }
+ }
+}
+
+/// A wrapper type without an implementation of `Deserialize`
+/// which allows a special implementation of `Wrap` for functions
+/// that take a trailing default parameter.
+pub struct Trailing(pub T);
+
+/// Wrapper trait for synchronous RPC functions.
+pub trait Wrap {
+ fn wrap_rpc(&self, base: &B, params: Params) -> Result;
+}
+
+// special impl for no parameters.
+impl Wrap for fn(&B) -> Result
+ where B: Send + Sync + 'static, OUT: Serialize
+{
+ fn wrap_rpc(&self, base: &B, params: Params) -> Result {
+ ::v1::helpers::params::expect_no_params(params)
+ .and_then(|()| (self)(base))
+ .map(to_value)
+ }
+}
+
+// creates a wrapper implementation which deserializes the parameters,
+// calls the function with concrete type, and serializes the output.
+macro_rules! wrap {
+ ($($x: ident),+) => {
+ impl <
+ BASE: Send + Sync + 'static,
+ OUT: Serialize,
+ $($x: Deserialize,)+
+ > Wrap for fn(&BASE, $($x,)+) -> Result {
+ fn wrap_rpc(&self, base: &BASE, params: Params) -> Result {
+ from_params::<($($x,)+)>(params).and_then(|($($x,)+)| {
+ (self)(base, $($x,)+)
+ }).map(to_value)
+ }
+ }
+ }
+}
+
+// special impl for no parameters other than block parameter.
+impl Wrap for fn(&B, Trailing) -> Result
+ where B: Send + Sync + 'static, OUT: Serialize, T: Default + Deserialize
+{
+ fn wrap_rpc(&self, base: &B, params: Params) -> Result {
+ let len = match params {
+ Params::Array(ref v) => v.len(),
+ Params::None => 0,
+ _ => return Err(errors::invalid_params("not an array", "")),
+ };
+
+ let (id,) = match len {
+ 0 => (T::default(),),
+ 1 => try!(from_params::<(T,)>(params)),
+ _ => return Err(Error::invalid_params()),
+ };
+
+ (self)(base, Trailing(id)).map(to_value)
+ }
+}
+
+// similar to `wrap!`, but handles a single default trailing parameter
+// accepts an additional argument indicating the number of non-trailing parameters.
+macro_rules! wrap_with_trailing {
+ ($num: expr, $($x: ident),+) => {
+ impl <
+ BASE: Send + Sync + 'static,
+ OUT: Serialize,
+ $($x: Deserialize,)+
+ TRAILING: Default + Deserialize,
+ > Wrap for fn(&BASE, $($x,)+ Trailing) -> Result {
+ fn wrap_rpc(&self, base: &BASE, params: Params) -> Result {
+ let len = match params {
+ Params::Array(ref v) => v.len(),
+ Params::None => 0,
+ _ => return Err(errors::invalid_params("not an array", "")),
+ };
+
+ let params = match len - $num {
+ 0 => from_params::<($($x,)+)>(params)
+ .map(|($($x,)+)| ($($x,)+ TRAILING::default())),
+ 1 => from_params::<($($x,)+ TRAILING)>(params)
+ .map(|($($x,)+ id)| ($($x,)+ id)),
+ _ => Err(Error::invalid_params()),
+ };
+
+ let ($($x,)+ id) = try!(params);
+ (self)(base, $($x,)+ Trailing(id)).map(to_value)
+ }
+ }
+ }
+}
+
+wrap!(A, B, C, D, E);
+wrap!(A, B, C, D);
+wrap!(A, B, C);
+wrap!(A, B);
+wrap!(A);
+
+wrap_with_trailing!(5, A, B, C, D, E);
+wrap_with_trailing!(4, A, B, C, D);
+wrap_with_trailing!(3, A, B, C);
+wrap_with_trailing!(2, A, B);
+wrap_with_trailing!(1, A);
\ No newline at end of file
diff --git a/rpc/src/v1/helpers/dispatch.rs b/rpc/src/v1/helpers/dispatch.rs
index 5587673d8..df2d8cbd3 100644
--- a/rpc/src/v1/helpers/dispatch.rs
+++ b/rpc/src/v1/helpers/dispatch.rs
@@ -41,7 +41,7 @@ fn prepare_transaction(client: &C, miner: &M, request: TransactionRequest)
}
}
-pub fn dispatch_transaction(client: &C, miner: &M, signed_transaction: SignedTransaction) -> Result
+pub fn dispatch_transaction(client: &C, miner: &M, signed_transaction: SignedTransaction) -> Result
where C: MiningBlockChainClient, M: MinerService {
let hash = RpcH256::from(signed_transaction.hash());
@@ -49,7 +49,7 @@ pub fn dispatch_transaction(client: &C, miner: &M, signed_transaction: Sig
import
.map_err(errors::from_transaction_error)
- .map(|_| to_value(&hash))
+ .map(|_| hash)
}
pub fn signature_with_password(accounts: &AccountProvider, address: Address, hash: H256, pass: String) -> Result {
@@ -70,7 +70,7 @@ pub fn unlock_sign_and_dispatch(client: &C, miner: &M, request: Transactio
};
trace!(target: "miner", "send_transaction: dispatching tx: {}", ::rlp::encode(&signed_transaction).to_vec().pretty());
- dispatch_transaction(&*client, &*miner, signed_transaction)
+ dispatch_transaction(&*client, &*miner, signed_transaction).map(to_value)
}
pub fn sign_and_dispatch(client: &C, miner: &M, request: TransactionRequest, account_provider: &AccountProvider, address: Address) -> Result
@@ -84,7 +84,7 @@ pub fn sign_and_dispatch(client: &C, miner: &M, request: TransactionReques
};
trace!(target: "miner", "send_transaction: dispatching tx: {}", ::rlp::encode(&signed_transaction).to_vec().pretty());
- dispatch_transaction(&*client, &*miner, signed_transaction)
+ dispatch_transaction(&*client, &*miner, signed_transaction).map(to_value)
}
pub fn default_gas_price(client: &C, miner: &M) -> U256 where C: MiningBlockChainClient, M: MinerService {
diff --git a/rpc/src/v1/helpers/mod.rs b/rpc/src/v1/helpers/mod.rs
index 7d4e19749..e6ada3379 100644
--- a/rpc/src/v1/helpers/mod.rs
+++ b/rpc/src/v1/helpers/mod.rs
@@ -14,10 +14,15 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see .
+#[macro_use]
+pub mod auto_args;
+
#[macro_use]
pub mod errors;
+
pub mod dispatch;
pub mod params;
+
mod poll_manager;
mod poll_filter;
mod requests;
diff --git a/rpc/src/v1/helpers/params.rs b/rpc/src/v1/helpers/params.rs
index 4a6abf542..f56c500fc 100644
--- a/rpc/src/v1/helpers/params.rs
+++ b/rpc/src/v1/helpers/params.rs
@@ -36,14 +36,6 @@ pub fn params_len(params: &Params) -> usize {
}
}
-/// Deserialize request parameters with optional second parameter `BlockNumber` defaulting to `BlockNumber::Latest`.
-pub fn from_params_default_second(params: Params) -> Result<(F, BlockNumber, ), Error> where F: serde::de::Deserialize {
- match params_len(¶ms) {
- 1 => from_params::<(F, )>(params).map(|(f,)| (f, BlockNumber::Latest)),
- _ => from_params::<(F, BlockNumber)>(params),
- }
-}
-
/// Deserialize request parameters with optional third parameter `BlockNumber` defaulting to `BlockNumber::Latest`.
pub fn from_params_default_third(params: Params) -> Result<(F1, F2, BlockNumber, ), Error> where F1: serde::de::Deserialize, F2: serde::de::Deserialize {
match params_len(¶ms) {
diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs
index cffbe87e5..755539ebd 100644
--- a/rpc/src/v1/impls/eth.rs
+++ b/rpc/src/v1/impls/eth.rs
@@ -42,10 +42,14 @@ use ethcore::log_entry::LogEntry;
use ethcore::filter::Filter as EthcoreFilter;
use self::ethash::SeedHashCompute;
use v1::traits::Eth;
-use v1::types::{Block, BlockTransactions, BlockNumber, Bytes, SyncStatus, SyncInfo, Transaction, CallRequest, Index, Filter, Log, Receipt, H64 as RpcH64, H256 as RpcH256, H160 as RpcH160, U256 as RpcU256};
+use v1::types::{
+ Block, BlockTransactions, BlockNumber, Bytes, SyncStatus, SyncInfo,
+ Transaction, CallRequest, Index, Filter, Log, Receipt, Work,
+ H64 as RpcH64, H256 as RpcH256, H160 as RpcH160, U256 as RpcU256,
+};
use v1::helpers::{CallRequest as CRequest, errors, limit_logs};
use v1::helpers::dispatch::{default_gas_price, dispatch_transaction};
-use v1::helpers::params::{expect_no_params, from_params_default_second, from_params_default_third};
+use v1::helpers::auto_args::Trailing;
/// Eth RPC options
pub struct EthClientOptions {
@@ -100,7 +104,7 @@ impl EthClient where
}
}
- fn block(&self, id: BlockID, include_txs: bool) -> Result {
+ fn block(&self, id: BlockID, include_txs: bool) -> Result, Error> {
let client = take_weak!(self.client);
match (client.block(id.clone()), client.block_total_difficulty(id)) {
(Some(bytes), Some(total_difficulty)) => {
@@ -131,28 +135,28 @@ impl EthClient where
},
extra_data: Bytes::new(view.extra_data())
};
- Ok(to_value(&block))
+ Ok(Some(block))
},
- _ => Ok(Value::Null)
+ _ => Ok(None)
}
}
- fn transaction(&self, id: TransactionID) -> Result {
+ fn transaction(&self, id: TransactionID) -> Result, Error> {
match take_weak!(self.client).transaction(id) {
- Some(t) => Ok(to_value(&Transaction::from(t))),
- None => Ok(Value::Null)
+ Some(t) => Ok(Some(Transaction::from(t))),
+ None => Ok(None),
}
}
- fn uncle(&self, id: UncleID) -> Result {
+ fn uncle(&self, id: UncleID) -> Result, Error> {
let client = take_weak!(self.client);
let uncle: BlockHeader = match client.uncle(id) {
Some(rlp) => rlp::decode(&rlp),
- None => { return Ok(Value::Null); }
+ None => { return Ok(None); }
};
let parent_difficulty = match client.block_total_difficulty(BlockID::Hash(uncle.parent_hash().clone())) {
Some(difficulty) => difficulty,
- None => { return Ok(Value::Null); }
+ None => { return Ok(None); }
};
let block = Block {
@@ -177,7 +181,7 @@ impl EthClient where
uncles: vec![],
transactions: BlockTransactions::Hashes(vec![]),
};
- Ok(to_value(&block))
+ Ok(Some(block))
}
fn sign_call(&self, request: CRequest) -> Result {
@@ -240,20 +244,19 @@ impl Eth for EthClient where
M: MinerService + 'static,
EM: ExternalMinerService + 'static {
- fn protocol_version(&self, params: Params) -> Result {
+ fn protocol_version(&self) -> Result {
try!(self.active());
- try!(expect_no_params(params));
- Ok(Value::String(format!("{}", take_weak!(self.sync).status().protocol_version).to_owned()))
+ let version = take_weak!(self.sync).status().protocol_version.to_owned();
+ Ok(format!("{}", version))
}
- fn syncing(&self, params: Params) -> Result {
+ fn syncing(&self) -> Result {
try!(self.active());
- try!(expect_no_params(params));
let status = take_weak!(self.sync).status();
- let res = match status.state {
- SyncState::Idle => SyncStatus::None,
+ match status.state {
+ SyncState::Idle => Ok(SyncStatus::None),
SyncState::Waiting | SyncState::Blocks | SyncState::NewBlocks | SyncState::ChainHead
| SyncState::SnapshotManifest | SyncState::SnapshotData | SyncState::SnapshotWaiting => {
let current_block = U256::from(take_weak!(self.client).chain_info().best_block_number);
@@ -265,260 +268,242 @@ impl Eth for EthClient where
current_block: current_block.into(),
highest_block: highest_block.into(),
};
- SyncStatus::Info(info)
+ Ok(SyncStatus::Info(info))
} else {
- SyncStatus::None
+ Ok(SyncStatus::None)
}
}
- };
- Ok(to_value(&res))
+ }
}
- fn author(&self, params: Params) -> Result {
+ fn author(&self) -> Result {
try!(self.active());
- try!(expect_no_params(params));
- Ok(to_value(&RpcH160::from(take_weak!(self.miner).author())))
+ Ok(RpcH160::from(take_weak!(self.miner).author()))
}
- fn is_mining(&self, params: Params) -> Result {
+ fn is_mining(&self) -> Result {
try!(self.active());
- try!(expect_no_params(params));
- Ok(to_value(&(take_weak!(self.miner).is_sealing())))
+ Ok(take_weak!(self.miner).is_sealing())
}
- fn hashrate(&self, params: Params) -> Result {
+ fn hashrate(&self) -> Result {
try!(self.active());
- try!(expect_no_params(params));
- Ok(to_value(&RpcU256::from(self.external_miner.hashrate())))
+ Ok(RpcU256::from(self.external_miner.hashrate()))
}
- fn gas_price(&self, params: Params) -> Result {
+ fn gas_price(&self) -> Result {
try!(self.active());
- try!(expect_no_params(params));
let (client, miner) = (take_weak!(self.client), take_weak!(self.miner));
- Ok(to_value(&RpcU256::from(default_gas_price(&*client, &*miner))))
+ Ok(RpcU256::from(default_gas_price(&*client, &*miner)))
}
- fn accounts(&self, params: Params) -> Result {
+ fn accounts(&self) -> Result, Error> {
try!(self.active());
- try!(expect_no_params(params));
let store = take_weak!(self.accounts);
let accounts = try!(store.accounts().map_err(|e| errors::internal("Could not fetch accounts.", e)));
- Ok(to_value(&accounts.into_iter().map(Into::into).collect::>()))
+ Ok(accounts.into_iter().map(Into::into).collect())
}
- fn block_number(&self, params: Params) -> Result {
+ fn block_number(&self) -> Result {
try!(self.active());
- try!(expect_no_params(params));
- Ok(to_value(&RpcU256::from(take_weak!(self.client).chain_info().best_block_number)))
+ Ok(RpcU256::from(take_weak!(self.client).chain_info().best_block_number))
}
- fn balance(&self, params: Params) -> Result {
+ fn balance(&self, address: RpcH160, num: Trailing) -> Result {
try!(self.active());
- from_params_default_second(params)
- .and_then(|(address, block_number,)| {
- let address: Address = RpcH160::into(address);
- match block_number {
- BlockNumber::Pending => Ok(to_value(&RpcU256::from(take_weak!(self.miner).balance(&*take_weak!(self.client), &address)))),
- id => match take_weak!(self.client).balance(&address, id.into()) {
- Some(balance) => Ok(to_value(&RpcU256::from(balance))),
- None => Err(errors::state_pruned()),
- }
- }
- })
+
+ let address = address.into();
+ match num.0 {
+ BlockNumber::Pending => Ok(take_weak!(self.miner).balance(&*take_weak!(self.client), &address).into()),
+ id => match take_weak!(self.client).balance(&address, id.into()) {
+ Some(balance) => Ok(balance.into()),
+ None => Err(errors::state_pruned()),
+ }
+ }
}
- fn storage_at(&self, params: Params) -> Result {
+ fn storage_at(&self, address: RpcH160, pos: RpcU256, num: Trailing) -> Result {
try!(self.active());
- from_params_default_third::(params)
- .and_then(|(address, position, block_number,)| {
- let address: Address = RpcH160::into(address);
- let position: U256 = RpcU256::into(position);
- match block_number {
- BlockNumber::Pending => Ok(to_value(&RpcU256::from(take_weak!(self.miner).storage_at(&*take_weak!(self.client), &address, &H256::from(position))))),
- id => match take_weak!(self.client).storage_at(&address, &H256::from(position), id.into()) {
- Some(s) => Ok(to_value(&RpcH256::from(s))),
- None => Err(errors::state_pruned()),
- }
- }
- })
-
+ let address: Address = RpcH160::into(address);
+ let position: U256 = RpcU256::into(pos);
+ match num.0 {
+ BlockNumber::Pending => Ok(take_weak!(self.miner).storage_at(&*take_weak!(self.client), &address, &H256::from(position)).into()),
+ id => match take_weak!(self.client).storage_at(&address, &H256::from(position), id.into()) {
+ Some(s) => Ok(s.into()),
+ None => Err(errors::state_pruned()),
+ }
+ }
}
- fn transaction_count(&self, params: Params) -> Result {
+ fn transaction_count(&self, address: RpcH160, num: Trailing) -> Result {
try!(self.active());
- from_params_default_second(params)
- .and_then(|(address, block_number,)| {
- let address: Address = RpcH160::into(address);
- match block_number {
- BlockNumber::Pending => Ok(to_value(&RpcU256::from(take_weak!(self.miner).nonce(&*take_weak!(self.client), &address)))),
- id => match take_weak!(self.client).nonce(&address, id.into()) {
- Some(nonce) => Ok(to_value(&RpcU256::from(nonce))),
- None => Err(errors::state_pruned()),
- }
- }
- })
+
+ let address: Address = RpcH160::into(address);
+ match num.0 {
+ BlockNumber::Pending => Ok(take_weak!(self.miner).nonce(&*take_weak!(self.client), &address).into()),
+ id => match take_weak!(self.client).nonce(&address, id.into()) {
+ Some(nonce) => Ok(nonce.into()),
+ None => Err(errors::state_pruned()),
+ }
+ }
}
- fn block_transaction_count_by_hash(&self, params: Params) -> Result {
+ fn block_transaction_count_by_hash(&self, hash: RpcH256) -> Result, Error> {
try!(self.active());
- from_params::<(RpcH256,)>(params)
- .and_then(|(hash,)| // match
- take_weak!(self.client).block(BlockID::Hash(hash.into()))
- .map_or(Ok(Value::Null), |bytes| Ok(to_value(&RpcU256::from(BlockView::new(&bytes).transactions_count())))))
+ Ok(
+ take_weak!(self.client).block(BlockID::Hash(hash.into()))
+ .map(|bytes| BlockView::new(&bytes).transactions_count().into())
+ )
}
- fn block_transaction_count_by_number(&self, params: Params) -> Result {
+ fn block_transaction_count_by_number(&self, num: BlockNumber) -> Result, Error> {
try!(self.active());
- from_params::<(BlockNumber,)>(params)
- .and_then(|(block_number,)| match block_number {
- BlockNumber::Pending => Ok(to_value(
- &RpcU256::from(take_weak!(self.miner).status().transactions_in_pending_block)
- )),
- _ => take_weak!(self.client).block(block_number.into())
- .map_or(Ok(Value::Null), |bytes| Ok(to_value(&RpcU256::from(BlockView::new(&bytes).transactions_count()))))
- })
+
+ match num {
+ BlockNumber::Pending => Ok(Some(
+ take_weak!(self.miner).status().transactions_in_pending_block.into()
+ )),
+ _ => Ok(
+ take_weak!(self.client).block(num.into())
+ .map(|bytes| BlockView::new(&bytes).transactions_count().into())
+ )
+ }
}
- fn block_uncles_count_by_hash(&self, params: Params) -> Result {
+ fn block_uncles_count_by_hash(&self, hash: RpcH256) -> Result, Error> {
try!(self.active());
- from_params::<(RpcH256,)>(params)
- .and_then(|(hash,)|
- take_weak!(self.client).block(BlockID::Hash(hash.into()))
- .map_or(Ok(Value::Null), |bytes| Ok(to_value(&RpcU256::from(BlockView::new(&bytes).uncles_count())))))
+
+ Ok(
+ take_weak!(self.client).block(BlockID::Hash(hash.into()))
+ .map(|bytes| BlockView::new(&bytes).uncles_count().into())
+ )
}
- fn block_uncles_count_by_number(&self, params: Params) -> Result {
+ fn block_uncles_count_by_number(&self, num: BlockNumber) -> Result, Error> {
try!(self.active());
- from_params::<(BlockNumber,)>(params)
- .and_then(|(block_number,)| match block_number {
- BlockNumber::Pending => Ok(to_value(&RpcU256::from(0))),
- _ => take_weak!(self.client).block(block_number.into())
- .map_or(Ok(Value::Null), |bytes| Ok(to_value(&RpcU256::from(BlockView::new(&bytes).uncles_count()))))
- })
+
+ match num {
+ BlockNumber::Pending => Ok(Some(0.into())),
+ _ => Ok(
+ take_weak!(self.client).block(num.into())
+ .map(|bytes| BlockView::new(&bytes).uncles_count().into())
+ ),
+ }
}
- fn code_at(&self, params: Params) -> Result {
+ fn code_at(&self, address: RpcH160, num: Trailing) -> Result {
try!(self.active());
- from_params_default_second(params)
- .and_then(|(address, block_number,)| {
- let address: Address = RpcH160::into(address);
- match block_number {
- BlockNumber::Pending => Ok(to_value(&take_weak!(self.miner).code(&*take_weak!(self.client), &address).map_or_else(Bytes::default, Bytes::new))),
- _ => match take_weak!(self.client).code(&address, block_number.into()) {
- Some(code) => Ok(to_value(&code.map_or_else(Bytes::default, Bytes::new))),
- None => Err(errors::state_pruned()),
- },
- }
- })
+
+ let address: Address = RpcH160::into(address);
+ match num.0 {
+ BlockNumber::Pending => Ok(take_weak!(self.miner).code(&*take_weak!(self.client), &address).map_or_else(Bytes::default, Bytes::new)),
+ _ => match take_weak!(self.client).code(&address, num.0.into()) {
+ Some(code) => Ok(code.map_or_else(Bytes::default, Bytes::new)),
+ None => Err(errors::state_pruned()),
+ },
+ }
}
- fn block_by_hash(&self, params: Params) -> Result {
+ fn block_by_hash(&self, hash: RpcH256, include_txs: bool) -> Result, Error> {
try!(self.active());
- from_params::<(RpcH256, bool)>(params)
- .and_then(|(hash, include_txs)| self.block(BlockID::Hash(hash.into()), include_txs))
+
+ self.block(BlockID::Hash(hash.into()), include_txs)
}
- fn block_by_number(&self, params: Params) -> Result {
+ fn block_by_number(&self, num: BlockNumber, include_txs: bool) -> Result, Error> {
try!(self.active());
- from_params::<(BlockNumber, bool)>(params)
- .and_then(|(number, include_txs)| self.block(number.into(), include_txs))
+
+ self.block(num.into(), include_txs)
}
- fn transaction_by_hash(&self, params: Params) -> Result {
+ fn transaction_by_hash(&self, hash: RpcH256) -> Result, Error> {
try!(self.active());
- from_params::<(RpcH256,)>(params)
- .and_then(|(hash,)| {
- let miner = take_weak!(self.miner);
- let hash: H256 = hash.into();
- match miner.transaction(&hash) {
- Some(pending_tx) => Ok(to_value(&Transaction::from(pending_tx))),
- None => self.transaction(TransactionID::Hash(hash))
- }
- })
+
+ let miner = take_weak!(self.miner);
+ let hash: H256 = hash.into();
+ match miner.transaction(&hash) {
+ Some(pending_tx) => Ok(Some(pending_tx.into())),
+ None => self.transaction(TransactionID::Hash(hash))
+ }
}
- fn transaction_by_block_hash_and_index(&self, params: Params) -> Result {
+ fn transaction_by_block_hash_and_index(&self, hash: RpcH256, index: Index) -> Result, Error> {
try!(self.active());
- from_params::<(RpcH256, Index)>(params)
- .and_then(|(hash, index)| self.transaction(TransactionID::Location(BlockID::Hash(hash.into()), index.value())))
+
+ self.transaction(TransactionID::Location(BlockID::Hash(hash.into()), index.value()))
}
- fn transaction_by_block_number_and_index(&self, params: Params) -> Result {
+ fn transaction_by_block_number_and_index(&self, num: BlockNumber, index: Index) -> Result, Error> {
try!(self.active());
- from_params::<(BlockNumber, Index)>(params)
- .and_then(|(number, index)| self.transaction(TransactionID::Location(number.into(), index.value())))
+
+ self.transaction(TransactionID::Location(num.into(), index.value()))
}
- fn transaction_receipt(&self, params: Params) -> Result {
+ fn transaction_receipt(&self, hash: RpcH256) -> Result, Error> {
try!(self.active());
- from_params::<(RpcH256,)>(params)
- .and_then(|(hash,)| {
- let miner = take_weak!(self.miner);
- let hash: H256 = hash.into();
- match (miner.pending_receipt(&hash), self.options.allow_pending_receipt_query) {
- (Some(receipt), true) => Ok(to_value(&Receipt::from(receipt))),
- _ => {
- let client = take_weak!(self.client);
- let receipt = client.transaction_receipt(TransactionID::Hash(hash));
- Ok(to_value(&receipt.map(Receipt::from)))
- }
- }
- })
+
+ let miner = take_weak!(self.miner);
+ let hash: H256 = hash.into();
+ match (miner.pending_receipt(&hash), self.options.allow_pending_receipt_query) {
+ (Some(receipt), true) => Ok(Some(receipt.into())),
+ _ => {
+ let client = take_weak!(self.client);
+ let receipt = client.transaction_receipt(TransactionID::Hash(hash));
+ Ok(receipt.map(Into::into))
+ }
+ }
}
- fn uncle_by_block_hash_and_index(&self, params: Params) -> Result {
+ fn uncle_by_block_hash_and_index(&self, hash: RpcH256, index: Index) -> Result, Error> {
try!(self.active());
- from_params::<(RpcH256, Index)>(params)
- .and_then(|(hash, index)| self.uncle(UncleID { block: BlockID::Hash(hash.into()), position: index.value() }))
+
+ self.uncle(UncleID { block: BlockID::Hash(hash.into()), position: index.value() })
}
- fn uncle_by_block_number_and_index(&self, params: Params) -> Result {
+ fn uncle_by_block_number_and_index(&self, num: BlockNumber, index: Index) -> Result, Error> {
try!(self.active());
- from_params::<(BlockNumber, Index)>(params)
- .and_then(|(number, index)| self.uncle(UncleID { block: number.into(), position: index.value() }))
+
+ self.uncle(UncleID { block: num.into(), position: index.value() })
}
- fn compilers(&self, params: Params) -> Result {
+ fn compilers(&self) -> Result, Error> {
try!(self.active());
- try!(expect_no_params(params));
let mut compilers = vec![];
if Command::new(SOLC).output().is_ok() {
compilers.push("solidity".to_owned())
}
- Ok(to_value(&compilers))
+
+ Ok(compilers)
}
- fn logs(&self, params: Params) -> Result {
- try!(self.active());
- from_params::<(Filter, )>(params).and_then(|(filter,)| {
- let include_pending = filter.to_block == Some(BlockNumber::Pending);
- let filter: EthcoreFilter = filter.into();
- let mut logs = take_weak!(self.client).logs(filter.clone())
- .into_iter()
- .map(From::from)
- .collect::>();
+ fn logs(&self, filter: Filter) -> Result, Error> {
+ let include_pending = filter.to_block == Some(BlockNumber::Pending);
+ let filter: EthcoreFilter = filter.into();
+ let mut logs = take_weak!(self.client).logs(filter.clone())
+ .into_iter()
+ .map(From::from)
+ .collect::>();
- if include_pending {
- let pending = pending_logs(&*take_weak!(self.miner), &filter);
- logs.extend(pending);
- }
+ if include_pending {
+ let pending = pending_logs(&*take_weak!(self.miner), &filter);
+ logs.extend(pending);
+ }
- let logs = limit_logs(logs, filter.limit);
- Ok(to_value(&logs))
- })
+ let logs = limit_logs(logs, filter.limit);
+
+ Ok(logs)
}
- fn work(&self, params: Params) -> Result {
+ fn work(&self, no_new_work_timeout: Trailing) -> Result {
try!(self.active());
- let (no_new_work_timeout,) = from_params::<(u64,)>(params).unwrap_or((0,));
+ let no_new_work_timeout = no_new_work_timeout.0;
let client = take_weak!(self.client);
// check if we're still syncing and return empty strings in that case
@@ -550,115 +535,118 @@ impl Eth for EthClient where
if no_new_work_timeout > 0 && b.block().header().timestamp() + no_new_work_timeout < get_time().sec as u64 {
Err(errors::no_new_work())
} else if self.options.send_block_number_in_get_work {
- let block_number = RpcU256::from(b.block().header().number());
- Ok(to_value(&(RpcH256::from(pow_hash), RpcH256::from(seed_hash), RpcH256::from(target), block_number)))
+ let block_number = b.block().header().number();
+ Ok(Work {
+ pow_hash: pow_hash.into(),
+ seed_hash: seed_hash.into(),
+ target: target.into(),
+ number: Some(block_number),
+ })
} else {
- Ok(to_value(&(RpcH256::from(pow_hash), RpcH256::from(seed_hash), RpcH256::from(target))))
+ Ok(Work {
+ pow_hash: pow_hash.into(),
+ seed_hash: seed_hash.into(),
+ target: target.into(),
+ number: None
+ })
}
}).unwrap_or(Err(Error::internal_error())) // no work found.
}
- fn submit_work(&self, params: Params) -> Result {
+ fn submit_work(&self, nonce: RpcH64, pow_hash: RpcH256, mix_hash: RpcH256) -> Result {
try!(self.active());
- from_params::<(RpcH64, RpcH256, RpcH256)>(params).and_then(|(nonce, pow_hash, mix_hash)| {
- let nonce: H64 = nonce.into();
- let pow_hash: H256 = pow_hash.into();
- let mix_hash: H256 = mix_hash.into();
- trace!(target: "miner", "submit_work: Decoded: nonce={}, pow_hash={}, mix_hash={}", nonce, pow_hash, mix_hash);
- let miner = take_weak!(self.miner);
- let client = take_weak!(self.client);
- let seal = vec![rlp::encode(&mix_hash).to_vec(), rlp::encode(&nonce).to_vec()];
- let r = miner.submit_seal(&*client, pow_hash, seal);
- Ok(to_value(&r.is_ok()))
- })
+
+ let nonce: H64 = nonce.into();
+ let pow_hash: H256 = pow_hash.into();
+ let mix_hash: H256 = mix_hash.into();
+ trace!(target: "miner", "submit_work: Decoded: nonce={}, pow_hash={}, mix_hash={}", nonce, pow_hash, mix_hash);
+
+ let miner = take_weak!(self.miner);
+ let client = take_weak!(self.client);
+ let seal = vec![rlp::encode(&mix_hash).to_vec(), rlp::encode(&nonce).to_vec()];
+ Ok(miner.submit_seal(&*client, pow_hash, seal).is_ok())
}
- fn submit_hashrate(&self, params: Params) -> Result {
+ fn submit_hashrate(&self, rate: RpcU256, id: RpcH256) -> Result {
try!(self.active());
- from_params::<(RpcU256, RpcH256)>(params).and_then(|(rate, id)| {
- self.external_miner.submit_hashrate(rate.into(), id.into());
- Ok(to_value(&true))
- })
+ self.external_miner.submit_hashrate(rate.into(), id.into());
+ Ok(true)
}
- fn send_raw_transaction(&self, params: Params) -> Result {
+ fn send_raw_transaction(&self, raw: Bytes) -> Result {
try!(self.active());
- from_params::<(Bytes, )>(params)
- .and_then(|(raw_transaction, )| {
- let raw_transaction = raw_transaction.to_vec();
- match UntrustedRlp::new(&raw_transaction).as_val() {
- Ok(signed_transaction) => dispatch_transaction(&*take_weak!(self.client), &*take_weak!(self.miner), signed_transaction),
- Err(_) => Ok(to_value(&RpcH256::from(H256::from(0)))),
+
+ let raw_transaction = raw.to_vec();
+ match UntrustedRlp::new(&raw_transaction).as_val() {
+ Ok(signed_transaction) => dispatch_transaction(&*take_weak!(self.client), &*take_weak!(self.miner), signed_transaction),
+ Err(_) => Ok(RpcH256::from(H256::from(0))),
+ }
+ }
+
+ fn call(&self, request: CallRequest, num: Trailing) -> Result {
+ try!(self.active());
+
+ let request = CallRequest::into(request);
+ let signed = try!(self.sign_call(request));
+
+ let r = match num.0 {
+ BlockNumber::Pending => take_weak!(self.miner).call(&*take_weak!(self.client), &signed, Default::default()),
+ num => take_weak!(self.client).call(&signed, num.into(), Default::default()),
+ };
+
+ Ok(r.map(|e| Bytes(e.output)).unwrap_or(Bytes::new(vec![])))
+ }
+
+ fn estimate_gas(&self, request: CallRequest, num: Trailing) -> Result {
+ try!(self.active());
+
+ let request = CallRequest::into(request);
+ let signed = try!(self.sign_call(request));
+ let r = match num.0 {
+ BlockNumber::Pending => take_weak!(self.miner).call(&*take_weak!(self.client), &signed, Default::default()),
+ num => take_weak!(self.client).call(&signed, num.into(), Default::default()),
+ };
+
+ Ok(RpcU256::from(r.map(|res| res.gas_used + res.refunded).unwrap_or(From::from(0))))
+ }
+
+ fn compile_lll(&self, _: String) -> Result {
+ try!(self.active());
+
+ rpc_unimplemented!()
+ }
+
+ fn compile_serpent(&self, _: String) -> Result {
+ try!(self.active());
+
+ rpc_unimplemented!()
+ }
+
+ fn compile_solidity(&self, code: String) -> Result {
+ try!(self.active());
+ let maybe_child = Command::new(SOLC)
+ .arg("--bin")
+ .arg("--optimize")
+ .stdin(Stdio::piped())
+ .stdout(Stdio::piped())
+ .stderr(Stdio::null())
+ .spawn();
+
+ maybe_child
+ .map_err(errors::compilation)
+ .and_then(|mut child| {
+ try!(child.stdin.as_mut()
+ .expect("we called child.stdin(Stdio::piped()) before spawn; qed")
+ .write_all(code.as_bytes())
+ .map_err(errors::compilation));
+ let output = try!(child.wait_with_output().map_err(errors::compilation));
+
+ let s = String::from_utf8_lossy(&output.stdout);
+ if let Some(hex) = s.lines().skip_while(|ref l| !l.contains("Binary")).skip(1).next() {
+ Ok(Bytes::new(hex.from_hex().unwrap_or(vec![])))
+ } else {
+ Err(errors::compilation("Unexpected output."))
}
- })
- }
-
- fn call(&self, params: Params) -> Result {
- try!(self.active());
- from_params_default_second(params)
- .and_then(|(request, block_number,)| {
- let request = CallRequest::into(request);
- let signed = try!(self.sign_call(request));
- let r = match block_number {
- BlockNumber::Pending => take_weak!(self.miner).call(&*take_weak!(self.client), &signed, Default::default()),
- block_number => take_weak!(self.client).call(&signed, block_number.into(), Default::default()),
- };
- Ok(to_value(&r.map(|e| Bytes(e.output)).unwrap_or(Bytes::new(vec![]))))
- })
- }
-
- fn estimate_gas(&self, params: Params) -> Result {
- try!(self.active());
- from_params_default_second(params)
- .and_then(|(request, block_number,)| {
- let request = CallRequest::into(request);
- let signed = try!(self.sign_call(request));
- let r = match block_number {
- BlockNumber::Pending => take_weak!(self.miner).call(&*take_weak!(self.client), &signed, Default::default()),
- block => take_weak!(self.client).call(&signed, block.into(), Default::default()),
- };
- Ok(to_value(&RpcU256::from(r.map(|res| res.gas_used + res.refunded).unwrap_or(From::from(0)))))
- })
- }
-
- fn compile_lll(&self, _: Params) -> Result {
- try!(self.active());
- rpc_unimplemented!()
- }
-
- fn compile_serpent(&self, _: Params) -> Result {
- try!(self.active());
- rpc_unimplemented!()
- }
-
- fn compile_solidity(&self, params: Params) -> Result {
- try!(self.active());
- from_params::<(String, )>(params)
- .and_then(|(code, )| {
- let maybe_child = Command::new(SOLC)
- .arg("--bin")
- .arg("--optimize")
- .stdin(Stdio::piped())
- .stdout(Stdio::piped())
- .stderr(Stdio::null())
- .spawn();
-
- maybe_child
- .map_err(errors::compilation)
- .and_then(|mut child| {
- try!(child.stdin.as_mut()
- .expect("we called child.stdin(Stdio::piped()) before spawn; qed")
- .write_all(code.as_bytes())
- .map_err(errors::compilation));
- let output = try!(child.wait_with_output().map_err(errors::compilation));
-
- let s = String::from_utf8_lossy(&output.stdout);
- if let Some(hex) = s.lines().skip_while(|ref l| !l.contains("Binary")).skip(1).next() {
- Ok(to_value(&Bytes::new(hex.from_hex().unwrap_or(vec![]))))
- } else {
- Err(errors::compilation("Unexpected output."))
- }
- })
})
}
}
diff --git a/rpc/src/v1/impls/eth_filter.rs b/rpc/src/v1/impls/eth_filter.rs
index b6e932d28..03d9d7215 100644
--- a/rpc/src/v1/impls/eth_filter.rs
+++ b/rpc/src/v1/impls/eth_filter.rs
@@ -24,9 +24,8 @@ use ethcore::filter::Filter as EthcoreFilter;
use ethcore::client::{BlockChainClient, BlockID};
use util::Mutex;
use v1::traits::EthFilter;
-use v1::types::{BlockNumber, Index, Filter, Log, H256 as RpcH256, U256 as RpcU256};
+use v1::types::{BlockNumber, Index, Filter, FilterChanges, Log, H256 as RpcH256, U256 as RpcU256};
use v1::helpers::{PollFilter, PollManager, limit_logs};
-use v1::helpers::params::expect_no_params;
use v1::impls::eth::pending_logs;
/// Eth filter rpc implementation.
@@ -59,168 +58,154 @@ impl EthFilterClient where
}
}
-impl EthFilter for EthFilterClient where
- C: BlockChainClient + 'static,
- M: MinerService + 'static {
-
- fn new_filter(&self, params: Params) -> Result {
+impl EthFilter for EthFilterClient
+ where C: BlockChainClient + 'static, M: MinerService + 'static
+{
+ fn new_filter(&self, filter: Filter) -> Result {
try!(self.active());
- from_params::<(Filter, )>(params)
- .and_then(|(filter, )| {
- let mut polls = self.polls.lock();
- let block_number = take_weak!(self.client).chain_info().best_block_number;
- let id = polls.create_poll(PollFilter::Logs(block_number, Default::default(), filter));
- Ok(to_value(&RpcU256::from(id)))
- })
+ let mut polls = self.polls.lock();
+ let block_number = take_weak!(self.client).chain_info().best_block_number;
+ let id = polls.create_poll(PollFilter::Logs(block_number, Default::default(), filter));
+ Ok(id.into())
}
- fn new_block_filter(&self, params: Params) -> Result {
+ fn new_block_filter(&self) -> Result {
try!(self.active());
- try!(expect_no_params(params));
let mut polls = self.polls.lock();
let id = polls.create_poll(PollFilter::Block(take_weak!(self.client).chain_info().best_block_number));
- Ok(to_value(&RpcU256::from(id)))
+ Ok(id.into())
}
- fn new_pending_transaction_filter(&self, params: Params) -> Result {
+ fn new_pending_transaction_filter(&self) -> Result {
try!(self.active());
- try!(expect_no_params(params));
let mut polls = self.polls.lock();
let pending_transactions = take_weak!(self.miner).pending_transactions_hashes();
let id = polls.create_poll(PollFilter::PendingTransaction(pending_transactions));
-
- Ok(to_value(&RpcU256::from(id)))
+ Ok(id.into())
}
- fn filter_changes(&self, params: Params) -> Result {
+ fn filter_changes(&self, index: Index) -> Result {
try!(self.active());
let client = take_weak!(self.client);
- from_params::<(Index,)>(params)
- .and_then(|(index,)| {
- let mut polls = self.polls.lock();
- match polls.poll_mut(&index.value()) {
- None => Ok(Value::Array(vec![] as Vec)),
- Some(filter) => match *filter {
- PollFilter::Block(ref mut block_number) => {
- // + 1, cause we want to return hashes including current block hash.
- let current_number = client.chain_info().best_block_number + 1;
- let hashes = (*block_number..current_number).into_iter()
- .map(BlockID::Number)
- .filter_map(|id| client.block_hash(id))
- .map(Into::into)
- .collect::>();
+ let mut polls = self.polls.lock();
+ match polls.poll_mut(&index.value()) {
+ None => Ok(FilterChanges::Empty),
+ Some(filter) => match *filter {
+ PollFilter::Block(ref mut block_number) => {
+ // + 1, cause we want to return hashes including current block hash.
+ let current_number = client.chain_info().best_block_number + 1;
+ let hashes = (*block_number..current_number).into_iter()
+ .map(BlockID::Number)
+ .filter_map(|id| client.block_hash(id))
+ .map(Into::into)
+ .collect::>();
- *block_number = current_number;
+ *block_number = current_number;
- Ok(to_value(&hashes))
- },
- PollFilter::PendingTransaction(ref mut previous_hashes) => {
- // get hashes of pending transactions
- let current_hashes = take_weak!(self.miner).pending_transactions_hashes();
+ Ok(FilterChanges::Hashes(hashes))
+ },
+ PollFilter::PendingTransaction(ref mut previous_hashes) => {
+ // get hashes of pending transactions
+ let current_hashes = take_weak!(self.miner).pending_transactions_hashes();
- let new_hashes =
- {
- let previous_hashes_set = previous_hashes.iter().collect::>();
+ let new_hashes =
+ {
+ let previous_hashes_set = previous_hashes.iter().collect::>();
- // find all new hashes
- current_hashes
- .iter()
- .filter(|hash| !previous_hashes_set.contains(hash))
- .cloned()
- .map(Into::into)
- .collect::>()
- };
+ // find all new hashes
+ current_hashes
+ .iter()
+ .filter(|hash| !previous_hashes_set.contains(hash))
+ .cloned()
+ .map(Into::into)
+ .collect::>()
+ };
- // save all hashes of pending transactions
- *previous_hashes = current_hashes;
+ // save all hashes of pending transactions
+ *previous_hashes = current_hashes;
- // return new hashes
- Ok(to_value(&new_hashes))
- },
- PollFilter::Logs(ref mut block_number, ref mut previous_logs, ref filter) => {
- // retrive the current block number
- let current_number = client.chain_info().best_block_number;
+ // return new hashes
+ Ok(FilterChanges::Hashes(new_hashes))
+ },
+ PollFilter::Logs(ref mut block_number, ref mut previous_logs, ref filter) => {
+ // retrive the current block number
+ let current_number = client.chain_info().best_block_number;
- // check if we need to check pending hashes
- let include_pending = filter.to_block == Some(BlockNumber::Pending);
+ // check if we need to check pending hashes
+ let include_pending = filter.to_block == Some(BlockNumber::Pending);
- // build appropriate filter
- let mut filter: EthcoreFilter = filter.clone().into();
- filter.from_block = BlockID::Number(*block_number);
- filter.to_block = BlockID::Latest;
+ // build appropriate filter
+ let mut filter: EthcoreFilter = filter.clone().into();
+ filter.from_block = BlockID::Number(*block_number);
+ filter.to_block = BlockID::Latest;
- // retrieve logs in range from_block..min(BlockID::Latest..to_block)
- let mut logs = client.logs(filter.clone())
- .into_iter()
- .map(From::from)
- .collect::>();
+ // retrieve logs in range from_block..min(BlockID::Latest..to_block)
+ let mut logs = client.logs(filter.clone())
+ .into_iter()
+ .map(From::from)
+ .collect::>();
- // additionally retrieve pending logs
- if include_pending {
- let pending_logs = pending_logs(&*take_weak!(self.miner), &filter);
+ // additionally retrieve pending logs
+ if include_pending {
+ let pending_logs = pending_logs(&*take_weak!(self.miner), &filter);
- // remove logs about which client was already notified about
- let new_pending_logs: Vec<_> = pending_logs.iter()
- .filter(|p| !previous_logs.contains(p))
- .cloned()
- .collect();
+ // remove logs about which client was already notified about
+ let new_pending_logs: Vec<_> = pending_logs.iter()
+ .filter(|p| !previous_logs.contains(p))
+ .cloned()
+ .collect();
- // save all logs retrieved by client
- *previous_logs = pending_logs.into_iter().collect();
+ // save all logs retrieved by client
+ *previous_logs = pending_logs.into_iter().collect();
- // append logs array with new pending logs
- logs.extend(new_pending_logs);
- }
-
- let logs = limit_logs(logs, filter.limit);
-
- // save the number of the next block as a first block from which
- // we want to get logs
- *block_number = current_number + 1;
-
- Ok(to_value(&logs))
- }
+ // append logs array with new pending logs
+ logs.extend(new_pending_logs);
}
+
+ let logs = limit_logs(logs, filter.limit);
+
+ // save the number of the next block as a first block from which
+ // we want to get logs
+ *block_number = current_number + 1;
+
+ Ok(FilterChanges::Logs(logs))
}
- })
+ }
+ }
}
- fn filter_logs(&self, params: Params) -> Result {
+ fn filter_logs(&self, index: Index) -> Result, Error> {
try!(self.active());
- from_params::<(Index,)>(params)
- .and_then(|(index,)| {
- let mut polls = self.polls.lock();
- match polls.poll(&index.value()) {
- Some(&PollFilter::Logs(ref _block_number, ref _previous_log, ref filter)) => {
- let include_pending = filter.to_block == Some(BlockNumber::Pending);
- let filter: EthcoreFilter = filter.clone().into();
- let mut logs = take_weak!(self.client).logs(filter.clone())
- .into_iter()
- .map(From::from)
- .collect::>();
- if include_pending {
- logs.extend(pending_logs(&*take_weak!(self.miner), &filter));
- }
+ let mut polls = self.polls.lock();
+ match polls.poll(&index.value()) {
+ Some(&PollFilter::Logs(ref _block_number, ref _previous_log, ref filter)) => {
+ let include_pending = filter.to_block == Some(BlockNumber::Pending);
+ let filter: EthcoreFilter = filter.clone().into();
+ let mut logs = take_weak!(self.client).logs(filter.clone())
+ .into_iter()
+ .map(From::from)
+ .collect::>();
- let logs = limit_logs(logs, filter.limit);
-
- Ok(to_value(&logs))
- },
- // just empty array
- _ => Ok(Value::Array(vec![] as Vec)),
+ if include_pending {
+ logs.extend(pending_logs(&*take_weak!(self.miner), &filter));
}
- })
+
+ let logs = limit_logs(logs, filter.limit);
+
+ Ok(logs)
+ },
+ // just empty array
+ _ => Ok(Vec::new()),
+ }
}
- fn uninstall_filter(&self, params: Params) -> Result {
+ fn uninstall_filter(&self, index: Index) -> Result {
try!(self.active());
- from_params::<(Index,)>(params)
- .map(|(index,)| {
- self.polls.lock().remove_poll(&index.value());
- to_value(&true)
- })
+
+ self.polls.lock().remove_poll(&index.value());
+ Ok(true)
}
}
diff --git a/rpc/src/v1/traits/eth.rs b/rpc/src/v1/traits/eth.rs
index 744d3b83a..80789fd0e 100644
--- a/rpc/src/v1/traits/eth.rs
+++ b/rpc/src/v1/traits/eth.rs
@@ -18,186 +18,185 @@
use std::sync::Arc;
use jsonrpc_core::*;
-/// Eth rpc interface.
-pub trait Eth: Sized + Send + Sync + 'static {
- /// Returns protocol version.
- fn protocol_version(&self, _: Params) -> Result;
+use v1::types::{Block, BlockNumber, Bytes, CallRequest, Filter, FilterChanges, Index};
+use v1::types::{Log, Receipt, SyncStatus, Transaction, Work};
+use v1::types::{H64, H160, H256, U256};
- /// Returns an object with data about the sync status or false. (wtf?)
- fn syncing(&self, _: Params) -> Result;
+use v1::helpers::auto_args::{Trailing, Wrap};
- /// Returns the number of hashes per second that the node is mining with.
- fn hashrate(&self, _: Params) -> Result;
+build_rpc_trait! {
+ /// Eth rpc interface.
+ pub trait Eth {
+ /// Returns protocol version encoded as a string (quotes are necessary).
+ #[name("eth_protocolVersion")]
+ fn protocol_version(&self) -> Result;
- /// Returns block author.
- fn author(&self, _: Params) -> Result;
+ /// Returns an object with data about the sync status or false. (wtf?)
+ #[name("eth_syncing")]
+ fn syncing(&self) -> Result;
- /// Returns true if client is actively mining new blocks.
- fn is_mining(&self, _: Params) -> Result;
+ /// Returns the number of hashes per second that the node is mining with.
+ #[name("eth_hashrate")]
+ fn hashrate(&self) -> Result;
- /// Returns current gas_price.
- fn gas_price(&self, _: Params) -> Result;
+ /// Returns block author.
+ #[name("eth_coinbase")]
+ fn author(&self) -> Result;
- /// Returns accounts list.
- fn accounts(&self, _: Params) -> Result;
+ /// Returns true if client is actively mining new blocks.
+ #[name("eth_mining")]
+ fn is_mining(&self) -> Result;
- /// Returns highest block number.
- fn block_number(&self, _: Params) -> Result;
+ /// Returns current gas_price.
+ #[name("eth_gasPrice")]
+ fn gas_price(&self) -> Result;
- /// Returns balance of the given account.
- fn balance(&self, _: Params) -> Result;
+ /// Returns accounts list.
+ #[name("eth_accounts")]
+ fn accounts(&self) -> Result, Error>;
- /// Returns content of the storage at given address.
- fn storage_at(&self, _: Params) -> Result;
+ /// Returns highest block number.
+ #[name("eth_blockNumber")]
+ fn block_number(&self) -> Result;
- /// Returns block with given hash.
- fn block_by_hash(&self, _: Params) -> Result;
+ /// Returns balance of the given account.
+ #[name("eth_getBalance")]
+ fn balance(&self, H160, Trailing) -> Result;
- /// Returns block with given number.
- fn block_by_number(&self, _: Params) -> Result;
+ /// Returns content of the storage at given address.
+ #[name("eth_getStorageAt")]
+ fn storage_at(&self, H160, U256, Trailing) -> Result;
- /// Returns the number of transactions sent from given address at given time (block number).
- fn transaction_count(&self, _: Params) -> Result;
+ /// Returns block with given hash.
+ #[name("eth_getBlockByHash")]
+ fn block_by_hash(&self, H256, bool) -> Result, Error>;
- /// Returns the number of transactions in a block with given hash.
- fn block_transaction_count_by_hash(&self, _: Params) -> Result;
+ /// Returns block with given number.
+ #[name("eth_getBlockByNumber")]
+ fn block_by_number(&self, BlockNumber, bool) -> Result, Error>;
- /// Returns the number of transactions in a block with given block number.
- fn block_transaction_count_by_number(&self, _: Params) -> Result;
+ /// Returns the number of transactions sent from given address at given time (block number).
+ #[name("eth_getTransactionCount")]
+ fn transaction_count(&self, H160, Trailing) -> Result;
- /// Returns the number of uncles in a block with given hash.
- fn block_uncles_count_by_hash(&self, _: Params) -> Result;
+ /// Returns the number of transactions in a block with given hash.
+ #[name("eth_getBlockTransactionCountByHash")]
+ fn block_transaction_count_by_hash(&self, H256) -> Result, Error>;
- /// Returns the number of uncles in a block with given block number.
- fn block_uncles_count_by_number(&self, _: Params) -> Result;
+ /// Returns the number of transactions in a block with given block number.
+ #[name("eth_getBlockTransactionCountByNumber")]
+ fn block_transaction_count_by_number(&self, BlockNumber) -> Result, Error>;
- /// Returns the code at given address at given time (block number).
- fn code_at(&self, _: Params) -> Result;
+ /// Returns the number of uncles in a block with given hash.
+ #[name("eth_getUncleCountByBlockHash")]
+ fn block_uncles_count_by_hash(&self, H256) -> Result, Error>;
- /// Sends signed transaction.
- fn send_raw_transaction(&self, _: Params) -> Result;
+ /// Returns the number of uncles in a block with given block number.
+ #[name("eth_getUncleCountByBlockNumber")]
+ fn block_uncles_count_by_number(&self, BlockNumber) -> Result, Error>;
- /// Call contract.
- fn call(&self, _: Params) -> Result;
+ /// Returns the code at given address at given time (block number).
+ #[name("eth_getCode")]
+ fn code_at(&self, H160, Trailing) -> Result;
- /// Estimate gas needed for execution of given contract.
- fn estimate_gas(&self, _: Params) -> Result;
+ /// Sends signed transaction, returning its hash.
+ #[name("eth_sendRawTransaction")]
+ fn send_raw_transaction(&self, Bytes) -> Result;
- /// Get transaction by its hash.
- fn transaction_by_hash(&self, _: Params) -> Result;
+ /// Call contract, returning the output data.
+ #[name("eth_call")]
+ fn call(&self, CallRequest, Trailing) -> Result;
- /// Returns transaction at given block hash and index.
- fn transaction_by_block_hash_and_index(&self, _: Params) -> Result;
+ /// Estimate gas needed for execution of given contract.
+ #[name("eth_estimateGas")]
+ fn estimate_gas(&self, CallRequest, Trailing) -> Result;
- /// Returns transaction by given block number and index.
- fn transaction_by_block_number_and_index(&self, _: Params) -> Result;
+ /// Get transaction by its hash.
+ #[name("eth_getTransactionByHash")]
+ fn transaction_by_hash(&self, H256) -> Result, Error>;
- /// Returns transaction receipt.
- fn transaction_receipt(&self, _: Params) -> Result;
+ /// Returns transaction at given block hash and index.
+ #[name("eth_getTransactionByBlockHashAndIndex")]
+ fn transaction_by_block_hash_and_index(&self, H256, Index) -> Result, Error>;
- /// Returns an uncles at given block and index.
- fn uncle_by_block_hash_and_index(&self, _: Params) -> Result;
+ /// Returns transaction by given block number and index.
+ #[name("eth_getTransactionByBlockNumberAndIndex")]
+ fn transaction_by_block_number_and_index(&self, BlockNumber, Index) -> Result, Error>;
- /// Returns an uncles at given block and index.
- fn uncle_by_block_number_and_index(&self, _: Params) -> Result;
+ /// Returns transaction receipt.
+ #[name("eth_getTransactionReceipt")]
+ fn transaction_receipt(&self, H256) -> Result, Error>;
- /// Returns available compilers.
- fn compilers(&self, _: Params) -> Result;
+ /// Returns an uncles at given block and index.
+ #[name("eth_getUncleByBlockHashAndIndex")]
+ fn uncle_by_block_hash_and_index(&self, H256, Index) -> Result, Error>;
- /// Compiles lll code.
- fn compile_lll(&self, _: Params) -> Result;
+ /// Returns an uncles at given block and index.
+ #[name("eth_getUncleByBlockNumberAndIndex")]
+ fn uncle_by_block_number_and_index(&self, BlockNumber, Index) -> Result, Error>;
- /// Compiles solidity.
- fn compile_solidity(&self, _: Params) -> Result;
+ /// Returns available compilers.
+ #[name("eth_getCompilers")]
+ fn compilers(&self) -> Result, Error>;
- /// Compiles serpent.
- fn compile_serpent(&self, _: Params) -> Result;
+ /// Compiles lll code.
+ #[name("eth_compileLLL")]
+ fn compile_lll(&self, String) -> Result;
- /// Returns logs matching given filter object.
- fn logs(&self, _: Params) -> Result;
+ /// Compiles solidity.
+ #[name("eth_compileSolidity")]
+ fn compile_solidity(&self, String) -> Result;
- /// Returns the hash of the current block, the seedHash, and the boundary condition to be met.
- fn work(&self, _: Params) -> Result;
+ /// Compiles serpent.
+ #[name("eth_compileSerpent")]
+ fn compile_serpent(&self, String) -> Result;
- /// Used for submitting a proof-of-work solution.
- fn submit_work(&self, _: Params) -> Result;
+ /// Returns logs matching given filter object.
+ #[name("eth_getLogs")]
+ fn logs(&self, Filter) -> Result, Error>;
- /// Used for submitting mining hashrate.
- fn submit_hashrate(&self, _: Params) -> Result;
+ /// Returns the hash of the current block, the seedHash, and the boundary condition to be met.
+ #[name("eth_getWork")]
+ fn work(&self, Trailing) -> Result;
- /// Should be used to convert object to io delegate.
- fn to_delegate(self) -> IoDelegate {
- let mut delegate = IoDelegate::new(Arc::new(self));
- delegate.add_method("eth_protocolVersion", Eth::protocol_version);
- delegate.add_method("eth_syncing", Eth::syncing);
- delegate.add_method("eth_hashrate", Eth::hashrate);
- delegate.add_method("eth_coinbase", Eth::author);
- delegate.add_method("eth_mining", Eth::is_mining);
- delegate.add_method("eth_gasPrice", Eth::gas_price);
- delegate.add_method("eth_accounts", Eth::accounts);
- delegate.add_method("eth_blockNumber", Eth::block_number);
- delegate.add_method("eth_getBalance", Eth::balance);
- delegate.add_method("eth_getStorageAt", Eth::storage_at);
- delegate.add_method("eth_getTransactionCount", Eth::transaction_count);
- delegate.add_method("eth_getBlockTransactionCountByHash", Eth::block_transaction_count_by_hash);
- delegate.add_method("eth_getBlockTransactionCountByNumber", Eth::block_transaction_count_by_number);
- delegate.add_method("eth_getUncleCountByBlockHash", Eth::block_uncles_count_by_hash);
- delegate.add_method("eth_getUncleCountByBlockNumber", Eth::block_uncles_count_by_number);
- delegate.add_method("eth_getCode", Eth::code_at);
- delegate.add_method("eth_sendRawTransaction", Eth::send_raw_transaction);
- delegate.add_method("eth_call", Eth::call);
- delegate.add_method("eth_estimateGas", Eth::estimate_gas);
- delegate.add_method("eth_getBlockByHash", Eth::block_by_hash);
- delegate.add_method("eth_getBlockByNumber", Eth::block_by_number);
- delegate.add_method("eth_getTransactionByHash", Eth::transaction_by_hash);
- delegate.add_method("eth_getTransactionByBlockHashAndIndex", Eth::transaction_by_block_hash_and_index);
- delegate.add_method("eth_getTransactionByBlockNumberAndIndex", Eth::transaction_by_block_number_and_index);
- delegate.add_method("eth_getTransactionReceipt", Eth::transaction_receipt);
- delegate.add_method("eth_getUncleByBlockHashAndIndex", Eth::uncle_by_block_hash_and_index);
- delegate.add_method("eth_getUncleByBlockNumberAndIndex", Eth::uncle_by_block_number_and_index);
- delegate.add_method("eth_getCompilers", Eth::compilers);
- delegate.add_method("eth_compileLLL", Eth::compile_lll);
- delegate.add_method("eth_compileSolidity", Eth::compile_solidity);
- delegate.add_method("eth_compileSerpent", Eth::compile_serpent);
- delegate.add_method("eth_getLogs", Eth::logs);
- delegate.add_method("eth_getWork", Eth::work);
- delegate.add_method("eth_submitWork", Eth::submit_work);
- delegate.add_method("eth_submitHashrate", Eth::submit_hashrate);
- delegate
+ /// Used for submitting a proof-of-work solution.
+ #[name("eth_submitWork")]
+ fn submit_work(&self, H64, H256, H256) -> Result;
+
+ /// Used for submitting mining hashrate.
+ #[name("eth_submitHashrate")]
+ fn submit_hashrate(&self, U256, H256) -> Result;
}
}
-/// Eth filters rpc api (polling).
-// TODO: do filters api properly
-pub trait EthFilter: Sized + Send + Sync + 'static {
- /// Returns id of new filter.
- fn new_filter(&self, _: Params) -> Result;
+build_rpc_trait! {
- /// Returns id of new block filter.
- fn new_block_filter(&self, _: Params) -> Result;
+ /// Eth filters rpc api (polling).
+ // TODO: do filters api properly
+ pub trait EthFilter {
+ /// Returns id of new filter.
+ #[name("eth_newFilter")]
+ fn new_filter(&self, Filter) -> Result;
- /// Returns id of new block filter.
- fn new_pending_transaction_filter(&self, _: Params) -> Result;
+ /// Returns id of new block filter.
+ #[name("eth_newBlockFilter")]
+ fn new_block_filter(&self) -> Result;
- /// Returns filter changes since last poll.
- fn filter_changes(&self, _: Params) -> Result;
+ /// Returns id of new block filter.
+ #[name("eth_newPendingTransactionFilter")]
+ fn new_pending_transaction_filter(&self) -> Result;
- /// Returns all logs matching given filter (in a range 'from' - 'to').
- fn filter_logs(&self, _: Params) -> Result;
+ /// Returns filter changes since last poll.
+ #[name("eth_getFilterChanges")]
+ fn filter_changes(&self, Index) -> Result;
- /// Uninstalls filter.
- fn uninstall_filter(&self, _: Params) -> Result;
+ /// Returns all logs matching given filter (in a range 'from' - 'to').
+ #[name("eth_getFilterLogs")]
+ fn filter_logs(&self, Index) -> Result, Error>;
- /// Should be used to convert object to io delegate.
- fn to_delegate(self) -> IoDelegate {
- let mut delegate = IoDelegate::new(Arc::new(self));
- delegate.add_method("eth_newFilter", EthFilter::new_filter);
- delegate.add_method("eth_newBlockFilter", EthFilter::new_block_filter);
- delegate.add_method("eth_newPendingTransactionFilter", EthFilter::new_pending_transaction_filter);
- delegate.add_method("eth_getFilterChanges", EthFilter::filter_changes);
- delegate.add_method("eth_getFilterLogs", EthFilter::filter_logs);
- delegate.add_method("eth_uninstallFilter", EthFilter::uninstall_filter);
- delegate
+ /// Uninstalls filter.
+ #[name("eth_uninstallFilter")]
+ fn uninstall_filter(&self, Index) -> Result;
}
}
diff --git a/rpc/src/v1/types/block_number.rs b/rpc/src/v1/types/block_number.rs
index 302d099d5..01625f8ed 100644
--- a/rpc/src/v1/types/block_number.rs
+++ b/rpc/src/v1/types/block_number.rs
@@ -31,6 +31,12 @@ pub enum BlockNumber {
Pending,
}
+impl Default for BlockNumber {
+ fn default() -> Self {
+ BlockNumber::Latest
+ }
+}
+
impl Deserialize for BlockNumber {
fn deserialize(deserializer: &mut D) -> Result