Port a couple more RPC APIs to the new auto args (#2325)

* add auto-args deserialization for RPC

* make block param member public

* change BlockParam to a more generic Trailing<T> mechanism

* define work type

* build_rpc_trait macro, implement eth protocol

* fix up tests

* move eth_filter API to new macro

* port ethcore module to new rpc macro

* port ethcore_set to auto_args

* port net RPC to auto_args

* port rpc meta api to new

* skeleton for async RPC auto_args

* macro implementations for strongly-typed async RPC wrapper

* clarify docs

* reflect new required Rust version in README

[ci skip]
This commit is contained in:
Robert Habermeier 2016-10-04 19:05:46 +02:00 committed by Arkadiy Paronyan
parent 6e477951ba
commit b7814fa65c
14 changed files with 534 additions and 405 deletions

View File

@ -5,6 +5,7 @@
[Internal Documentation][doc-url] [Internal Documentation][doc-url]
Be sure to check out [our wiki][wiki-url] for more information. Be sure to check out [our wiki][wiki-url] for more information.
[travis-image]: https://travis-ci.org/ethcore/parity.svg?branch=master [travis-image]: https://travis-ci.org/ethcore/parity.svg?branch=master
@ -18,8 +19,11 @@ Be sure to check out [our wiki][wiki-url] for more information.
[doc-url]: https://ethcore.github.io/parity/ethcore/index.html [doc-url]: https://ethcore.github.io/parity/ethcore/index.html
[wiki-url]: https://github.com/ethcore/parity/wiki [wiki-url]: https://github.com/ethcore/parity/wiki
**Requires Rust version 1.12.0 to build**
---- ----
## About Parity ## About Parity
Parity's goal is to be the fastest, lightest, and most secure Ethereum client. We are developing Parity using the sophisticated and Parity's goal is to be the fastest, lightest, and most secure Ethereum client. We are developing Parity using the sophisticated and
@ -96,9 +100,9 @@ and Parity will begin syncing the Ethereum blockchain.
### Using systemd service file ### Using systemd service file
To start Parity as a regular user using systemd init: To start Parity as a regular user using systemd init:
1. Copy ```parity/scripts/parity.service``` to your 1. Copy `parity/scripts/parity.service` to your
systemd user directory (usually ```~/.config/systemd/user```). systemd user directory (usually `~/.config/systemd/user`).
2. To pass any argument to Parity, write a ```~/.parity/parity.conf``` file this way: 2. To pass any argument to Parity, write a `~/.parity/parity.conf` file this way:
```ARGS="ARG1 ARG2 ARG3"```. `ARGS="ARG1 ARG2 ARG3"`.
Example: ```ARGS="ui --geth --identity MyMachine"```. Example: `ARGS="ui --geth --identity MyMachine"`.

View File

@ -31,16 +31,32 @@ use serde::{Serialize, Deserialize};
/// function `to_delegate` which will automatically wrap each strongly-typed /// function `to_delegate` which will automatically wrap each strongly-typed
/// function in a wrapper which handles parameter and output type serialization. /// function in a wrapper which handles parameter and output type serialization.
/// ///
/// Every function must have a `#[name("rpc_nameHere")]` attribute after /// RPC functions may come in a couple forms: async and synchronous.
/// its documentation, and no other attributes. All function names are /// These are parsed with the custom `#[rpc]` attribute, which must follow
/// allowed except for `to_delegate`, which is auto-generated. /// documentation.
///
/// ## The #[rpc] attribute
///
/// Valid forms:
/// - `#[rpc(name = "name_here")]` (a synchronous rpc function which should be bound to the given name)
/// - `#[rpc(async, name = "name_here")]` (an async rpc function which should be bound to the given name)
///
/// Synchronous function format:
/// `fn foo(&self, Param1, Param2, Param3) -> Out`.
///
/// Asynchronous RPC functions must come in this form:
/// `fn foo(&self, Param1, Param2, Param3, Ready<Out>);
///
/// Anything else will be rejected by the code generator.
macro_rules! build_rpc_trait { macro_rules! build_rpc_trait {
// entry-point. todo: make another for traits w/ bounds.
( (
$(#[$t_attr: meta])* $(#[$t_attr: meta])*
pub trait $name: ident { pub trait $name: ident {
$( $(
$(#[doc=$m_doc: expr])* #[name($rpc_name: expr)] $( #[doc=$m_doc:expr] )*
fn $method: ident (&self $(, $param: ty)*) -> $out: ty; #[ rpc( $($t:tt)* ) ]
fn $m_name: ident ( $($p: tt)* ) $( -> Result<$out: ty, Error> )* ;
)* )*
} }
) => { ) => {
@ -48,7 +64,7 @@ macro_rules! build_rpc_trait {
pub trait $name: Sized + Send + Sync + 'static { pub trait $name: Sized + Send + Sync + 'static {
$( $(
$(#[doc=$m_doc])* $(#[doc=$m_doc])*
fn $method(&self $(, $param)*) -> $out; fn $m_name ( $($p)* ) $( -> Result<$out, Error> )* ;
)* )*
/// Transform this into an `IoDelegate`, automatically wrapping /// Transform this into an `IoDelegate`, automatically wrapping
@ -56,14 +72,33 @@ macro_rules! build_rpc_trait {
fn to_delegate(self) -> ::jsonrpc_core::IoDelegate<Self> { fn to_delegate(self) -> ::jsonrpc_core::IoDelegate<Self> {
let mut del = ::jsonrpc_core::IoDelegate::new(self.into()); let mut del = ::jsonrpc_core::IoDelegate::new(self.into());
$( $(
del.add_method($rpc_name, move |base, params| { build_rpc_trait!(WRAP del =>
($name::$method as fn(&_ $(, $param)*) -> $out).wrap_rpc(base, params) ( $($t)* )
}); fn $m_name ( $($p)* ) $( -> Result<$out, Error> )*
);
)* )*
del del
} }
} }
} };
( WRAP $del: expr =>
(name = $name: expr)
fn $method: ident (&self $(, $param: ty)*) -> Result<$out: ty, Error>
) => {
$del.add_method($name, move |base, params| {
(Self::$method as fn(&_ $(, $param)*) -> Result<$out, Error>).wrap_rpc(base, params)
})
};
( WRAP $del: expr =>
(async, name = $name: expr)
fn $method: ident (&self, Ready<$out: ty> $(, $param: ty)*)
) => {
$del.add_async_method($name, move |base, params, ready| {
(Self::$method as fn(&_, Ready<$out> $(, $param)*)).wrap_rpc(base, params, ready)
})
};
} }
/// A wrapper type without an implementation of `Deserialize` /// A wrapper type without an implementation of `Deserialize`
@ -71,11 +106,35 @@ macro_rules! build_rpc_trait {
/// that take a trailing default parameter. /// that take a trailing default parameter.
pub struct Trailing<T: Default + Deserialize>(pub T); pub struct Trailing<T: Default + Deserialize>(pub T);
/// A wrapper type for `jsonrpc_core`'s weakly-typed `Ready` struct.
pub struct Ready<T: Serialize> {
inner: ::jsonrpc_core::Ready,
_marker: ::std::marker::PhantomData<T>,
}
impl<T: Serialize> From<::jsonrpc_core::Ready> for Ready<T> {
fn from(ready: ::jsonrpc_core::Ready) -> Self {
Ready { inner: ready, _marker: ::std::marker::PhantomData }
}
}
impl<T: Serialize> Ready<T> {
/// Respond withthe asynchronous result.
pub fn ready(self, result: Result<T, Error>) {
self.inner.ready(result.map(to_value))
}
}
/// Wrapper trait for synchronous RPC functions. /// Wrapper trait for synchronous RPC functions.
pub trait Wrap<B: Send + Sync + 'static> { pub trait Wrap<B: Send + Sync + 'static> {
fn wrap_rpc(&self, base: &B, params: Params) -> Result<Value, Error>; fn wrap_rpc(&self, base: &B, params: Params) -> Result<Value, Error>;
} }
/// Wrapper trait for asynchronous RPC functions.
pub trait WrapAsync<B: Send + Sync + 'static> {
fn wrap_rpc(&self, base: &B, params: Params, ready: ::jsonrpc_core::Ready);
}
// special impl for no parameters. // special impl for no parameters.
impl<B, OUT> Wrap<B> for fn(&B) -> Result<OUT, Error> impl<B, OUT> Wrap<B> for fn(&B) -> Result<OUT, Error>
where B: Send + Sync + 'static, OUT: Serialize where B: Send + Sync + 'static, OUT: Serialize
@ -87,10 +146,23 @@ impl<B, OUT> Wrap<B> for fn(&B) -> Result<OUT, Error>
} }
} }
impl<B, OUT> WrapAsync<B> for fn(&B, Ready<OUT>)
where B: Send + Sync + 'static, OUT: Serialize
{
fn wrap_rpc(&self, base: &B, params: Params, ready: ::jsonrpc_core::Ready) {
match ::v1::helpers::params::expect_no_params(params) {
Ok(()) => (self)(base, ready.into()),
Err(e) => ready.ready(Err(e)),
}
}
}
// creates a wrapper implementation which deserializes the parameters, // creates a wrapper implementation which deserializes the parameters,
// calls the function with concrete type, and serializes the output. // calls the function with concrete type, and serializes the output.
macro_rules! wrap { macro_rules! wrap {
($($x: ident),+) => { ($($x: ident),+) => {
// synchronous implementation
impl < impl <
BASE: Send + Sync + 'static, BASE: Send + Sync + 'static,
OUT: Serialize, OUT: Serialize,
@ -102,6 +174,20 @@ macro_rules! wrap {
}).map(to_value) }).map(to_value)
} }
} }
// asynchronous implementation
impl <
BASE: Send + Sync + 'static,
OUT: Serialize,
$($x: Deserialize,)+
> WrapAsync<BASE> for fn(&BASE, Ready<OUT>, $($x,)+ ) {
fn wrap_rpc(&self, base: &BASE, params: Params, ready: ::jsonrpc_core::Ready) {
match from_params::<($($x,)+)>(params) {
Ok(($($x,)+)) => (self)(base, ready.into(), $($x,)+),
Err(e) => ready.ready(Err(e)),
}
}
}
} }
} }
@ -126,10 +212,34 @@ impl<B, OUT, T> Wrap<B> for fn(&B, Trailing<T>) -> Result<OUT, Error>
} }
} }
impl<B, OUT, T> WrapAsync<B> for fn(&B, Ready<OUT>, Trailing<T>)
where B: Send + Sync + 'static, OUT: Serialize, T: Default + Deserialize
{
fn wrap_rpc(&self, base: &B, params: Params, ready: ::jsonrpc_core::Ready) {
let len = match params {
Params::Array(ref v) => v.len(),
Params::None => 0,
_ => return ready.ready(Err(errors::invalid_params("not an array", ""))),
};
let id = match len {
0 => Ok((T::default(),)),
1 => from_params::<(T,)>(params),
_ => Err(Error::invalid_params()),
};
match id {
Ok((id,)) => (self)(base, ready.into(), Trailing(id)),
Err(e) => ready.ready(Err(e)),
}
}
}
// similar to `wrap!`, but handles a single default trailing parameter // similar to `wrap!`, but handles a single default trailing parameter
// accepts an additional argument indicating the number of non-trailing parameters. // accepts an additional argument indicating the number of non-trailing parameters.
macro_rules! wrap_with_trailing { macro_rules! wrap_with_trailing {
($num: expr, $($x: ident),+) => { ($num: expr, $($x: ident),+) => {
// synchronous implementation
impl < impl <
BASE: Send + Sync + 'static, BASE: Send + Sync + 'static,
OUT: Serialize, OUT: Serialize,
@ -155,6 +265,35 @@ macro_rules! wrap_with_trailing {
(self)(base, $($x,)+ Trailing(id)).map(to_value) (self)(base, $($x,)+ Trailing(id)).map(to_value)
} }
} }
// asynchronous implementation
impl <
BASE: Send + Sync + 'static,
OUT: Serialize,
$($x: Deserialize,)+
TRAILING: Default + Deserialize,
> WrapAsync<BASE> for fn(&BASE, Ready<OUT>, $($x,)+ Trailing<TRAILING>) {
fn wrap_rpc(&self, base: &BASE, params: Params, ready: ::jsonrpc_core::Ready) {
let len = match params {
Params::Array(ref v) => v.len(),
Params::None => 0,
_ => return ready.ready(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()),
};
match params {
Ok(($($x,)+ id)) => (self)(base, ready.into(), $($x,)+ Trailing(id)),
Err(e) => ready.ready(Err(e))
}
}
}
} }
} }

View File

@ -18,7 +18,7 @@
use std::{fs, io}; use std::{fs, io};
use std::sync::{mpsc, Arc, Weak}; use std::sync::{mpsc, Arc, Weak};
use std::str::FromStr; use std::str::FromStr;
use std::collections::{BTreeMap};
use util::{RotatingLogger, Address, Mutex, sha3}; use util::{RotatingLogger, Address, Mutex, sha3};
use util::misc::version_data; use util::misc::version_data;
@ -31,11 +31,11 @@ use ethcore::miner::MinerService;
use ethcore::client::{MiningBlockChainClient}; use ethcore::client::{MiningBlockChainClient};
use ethcore::ids::BlockID; use ethcore::ids::BlockID;
use jsonrpc_core::{from_params, to_value, Value, Error, Params, Ready}; use jsonrpc_core::Error;
use v1::traits::Ethcore; use v1::traits::Ethcore;
use v1::types::{Bytes, U256, H160, H256, H512, Peers, Transaction}; use v1::types::{Bytes, U256, H160, H256, H512, Peers, Transaction, RpcSettings};
use v1::helpers::{errors, SigningQueue, SignerService, NetworkSettings}; use v1::helpers::{errors, SigningQueue, SignerService, NetworkSettings};
use v1::helpers::params::expect_no_params; use v1::helpers::auto_args::Ready;
/// Ethcore implementation. /// Ethcore implementation.
pub struct EthcoreClient<C, M, S: ?Sized, F=FetchClient> where pub struct EthcoreClient<C, M, S: ?Sized, F=FetchClient> where
@ -113,180 +113,168 @@ impl<C, M, S: ?Sized, F> Ethcore for EthcoreClient<C, M, S, F> where
S: SyncProvider + 'static, S: SyncProvider + 'static,
F: Fetch + 'static { F: Fetch + 'static {
fn transactions_limit(&self, params: Params) -> Result<Value, Error> { fn transactions_limit(&self) -> Result<usize, Error> {
try!(self.active()); try!(self.active());
try!(expect_no_params(params));
Ok(to_value(&take_weak!(self.miner).transactions_limit())) Ok(take_weak!(self.miner).transactions_limit())
} }
fn min_gas_price(&self, params: Params) -> Result<Value, Error> { fn min_gas_price(&self) -> Result<U256, Error> {
try!(self.active()); try!(self.active());
try!(expect_no_params(params));
Ok(to_value(&U256::from(take_weak!(self.miner).minimal_gas_price()))) Ok(U256::from(take_weak!(self.miner).minimal_gas_price()))
} }
fn extra_data(&self, params: Params) -> Result<Value, Error> { fn extra_data(&self) -> Result<Bytes, Error> {
try!(self.active()); try!(self.active());
try!(expect_no_params(params));
Ok(to_value(&Bytes::new(take_weak!(self.miner).extra_data()))) Ok(Bytes::new(take_weak!(self.miner).extra_data()))
} }
fn gas_floor_target(&self, params: Params) -> Result<Value, Error> { fn gas_floor_target(&self) -> Result<U256, Error> {
try!(self.active()); try!(self.active());
try!(expect_no_params(params));
Ok(to_value(&U256::from(take_weak!(self.miner).gas_floor_target()))) Ok(U256::from(take_weak!(self.miner).gas_floor_target()))
} }
fn gas_ceil_target(&self, params: Params) -> Result<Value, Error> { fn gas_ceil_target(&self) -> Result<U256, Error> {
try!(self.active()); try!(self.active());
try!(expect_no_params(params));
Ok(to_value(&U256::from(take_weak!(self.miner).gas_ceil_target()))) Ok(U256::from(take_weak!(self.miner).gas_ceil_target()))
} }
fn dev_logs(&self, params: Params) -> Result<Value, Error> { fn dev_logs(&self) -> Result<Vec<String>, Error> {
try!(self.active()); try!(self.active());
try!(expect_no_params(params));
let logs = self.logger.logs(); let logs = self.logger.logs();
Ok(to_value(&logs.as_slice())) Ok(logs.as_slice().to_owned())
} }
fn dev_logs_levels(&self, params: Params) -> Result<Value, Error> { fn dev_logs_levels(&self) -> Result<String, Error> {
try!(self.active()); try!(self.active());
try!(expect_no_params(params));
Ok(to_value(&self.logger.levels())) Ok(self.logger.levels().to_owned())
} }
fn net_chain(&self, params: Params) -> Result<Value, Error> { fn net_chain(&self) -> Result<String, Error> {
try!(self.active()); try!(self.active());
try!(expect_no_params(params));
Ok(to_value(&self.settings.chain)) Ok(self.settings.chain.clone())
} }
fn net_peers(&self, params: Params) -> Result<Value, Error> { fn net_peers(&self) -> Result<Peers, Error> {
try!(self.active()); try!(self.active());
try!(expect_no_params(params));
let sync_status = take_weak!(self.sync).status(); let sync_status = take_weak!(self.sync).status();
let net_config = take_weak!(self.net).network_config(); let net_config = take_weak!(self.net).network_config();
Ok(to_value(&Peers { Ok(Peers {
active: sync_status.num_active_peers, active: sync_status.num_active_peers,
connected: sync_status.num_peers, connected: sync_status.num_peers,
max: sync_status.current_max_peers(net_config.min_peers, net_config.max_peers), max: sync_status.current_max_peers(net_config.min_peers, net_config.max_peers),
})) })
} }
fn net_port(&self, params: Params) -> Result<Value, Error> { fn net_port(&self) -> Result<u16, Error> {
try!(self.active()); try!(self.active());
try!(expect_no_params(params));
Ok(to_value(&self.settings.network_port)) Ok(self.settings.network_port)
} }
fn node_name(&self, params: Params) -> Result<Value, Error> { fn node_name(&self) -> Result<String, Error> {
try!(self.active()); try!(self.active());
try!(expect_no_params(params));
Ok(to_value(&self.settings.name)) Ok(self.settings.name.clone())
} }
fn registry_address(&self, params: Params) -> Result<Value, Error> { fn registry_address(&self) -> Result<Option<H160>, Error> {
try!(self.active()); try!(self.active());
try!(expect_no_params(params));
let r = take_weak!(self.client) Ok(
take_weak!(self.client)
.additional_params() .additional_params()
.get("registrar") .get("registrar")
.and_then(|s| Address::from_str(s).ok()) .and_then(|s| Address::from_str(s).ok())
.map(|s| H160::from(s)); .map(|s| H160::from(s))
Ok(to_value(&r)) )
} }
fn rpc_settings(&self, params: Params) -> Result<Value, Error> { fn rpc_settings(&self) -> Result<RpcSettings, Error> {
try!(self.active()); try!(self.active());
try!(expect_no_params(params)); Ok(RpcSettings {
let mut map = BTreeMap::new(); enabled: self.settings.rpc_enabled,
map.insert("enabled".to_owned(), Value::Bool(self.settings.rpc_enabled)); interface: self.settings.rpc_interface.clone(),
map.insert("interface".to_owned(), Value::String(self.settings.rpc_interface.clone())); port: self.settings.rpc_port as u64,
map.insert("port".to_owned(), Value::U64(self.settings.rpc_port as u64)); })
Ok(Value::Object(map))
} }
fn default_extra_data(&self, params: Params) -> Result<Value, Error> { fn default_extra_data(&self) -> Result<Bytes, Error> {
try!(self.active()); try!(self.active());
try!(expect_no_params(params));
Ok(to_value(&Bytes::new(version_data()))) Ok(Bytes::new(version_data()))
} }
fn gas_price_statistics(&self, params: Params) -> Result<Value, Error> { fn gas_price_statistics(&self) -> Result<Vec<U256>, Error> {
try!(self.active()); try!(self.active());
try!(expect_no_params(params));
match take_weak!(self.client).gas_price_statistics(100, 8) { match take_weak!(self.client).gas_price_statistics(100, 8) {
Ok(stats) => Ok(to_value(&stats Ok(stats) => Ok(stats.into_iter().map(Into::into).collect()),
.into_iter()
.map(|x| to_value(&U256::from(x)))
.collect::<Vec<_>>())),
_ => Err(Error::internal_error()), _ => Err(Error::internal_error()),
} }
} }
fn unsigned_transactions_count(&self, params: Params) -> Result<Value, Error> { fn unsigned_transactions_count(&self) -> Result<usize, Error> {
try!(self.active()); try!(self.active());
try!(expect_no_params(params));
match self.signer { match self.signer {
None => Err(errors::signer_disabled()), None => Err(errors::signer_disabled()),
Some(ref signer) => Ok(to_value(&signer.len())), Some(ref signer) => Ok(signer.len()),
} }
} }
fn generate_secret_phrase(&self, params: Params) -> Result<Value, Error> { fn generate_secret_phrase(&self) -> Result<String, Error> {
try!(self.active()); try!(self.active());
try!(expect_no_params(params));
Ok(to_value(&random_phrase(12))) Ok(random_phrase(12))
} }
fn phrase_to_address(&self, params: Params) -> Result<Value, Error> { fn phrase_to_address(&self, phrase: String) -> Result<H160, Error> {
try!(self.active()); try!(self.active());
from_params::<(String,)>(params).map(|(phrase,)|
to_value(&H160::from(Brain::new(phrase).generate().unwrap().address())) Ok(Brain::new(phrase).generate().unwrap().address().into())
)
} }
fn list_accounts(&self, params: Params) -> Result<Value, Error> { fn list_accounts(&self) -> Result<Option<Vec<H160>>, Error> {
try!(self.active()); try!(self.active());
try!(expect_no_params(params));
take_weak!(self.client) Ok(take_weak!(self.client)
.list_accounts(BlockID::Latest) .list_accounts(BlockID::Latest)
.map(|a| Ok(to_value(&a.into_iter().map(Into::into).collect::<Vec<H160>>()))) .map(|a| a.into_iter().map(Into::into).collect()))
.unwrap_or(Ok(Value::Null))
} }
fn list_storage_keys(&self, params: Params) -> Result<Value, Error> { fn list_storage_keys(&self, _address: H160) -> Result<Option<Vec<H256>>, Error> {
try!(self.active()); try!(self.active());
from_params::<(H160,)>(params).and_then(|(_addr,)| // TODO: implement this
Ok(Value::Null) Ok(None)
)
} }
fn encrypt_message(&self, params: Params) -> Result<Value, Error> { fn encrypt_message(&self, key: H512, phrase: Bytes) -> Result<Bytes, Error> {
try!(self.active()); try!(self.active());
from_params::<(H512, Bytes)>(params).and_then(|(key, phrase)| {
let s = try!(ecies::encrypt(&key.into(), &[0; 0], &phrase.0).map_err(|_| Error::internal_error())); ecies::encrypt(&key.into(), &[0; 0], &phrase.0)
Ok(to_value(&Bytes::from(s))) .map_err(|_| Error::internal_error())
}) .map(Into::into)
} }
fn pending_transactions(&self, params: Params) -> Result<Value, Error> { fn pending_transactions(&self) -> Result<Vec<Transaction>, Error> {
try!(self.active()); try!(self.active());
try!(expect_no_params(params));
Ok(to_value(&take_weak!(self.miner).all_transactions().into_iter().map(Into::into).collect::<Vec<Transaction>>())) Ok(take_weak!(self.miner).all_transactions().into_iter().map(Into::into).collect::<Vec<_>>())
} }
fn hash_content(&self, params: Params, ready: Ready) { fn hash_content(&self, ready: Ready<H256>, url: String) {
let res = self.active().and_then(|_| from_params::<(String,)>(params)); let res = self.active();
let hash_content = |result| { let hash_content = |result| {
let path = try!(result); let path = try!(result);
@ -301,15 +289,15 @@ impl<C, M, S: ?Sized, F> Ethcore for EthcoreClient<C, M, S, F> where
match res { match res {
Err(e) => ready.ready(Err(e)), Err(e) => ready.ready(Err(e)),
Ok((url, )) => { Ok(()) => {
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
let res = self.fetch.lock().request_async(&url, Default::default(), Box::new(move |result| { let res = self.fetch.lock().request_async(&url, Default::default(), Box::new(move |result| {
let result = hash_content(result) let result = hash_content(result)
.map_err(errors::from_fetch_error) .map_err(errors::from_fetch_error)
.map(|hash| to_value(H256::from(hash))); .map(Into::into);
// Receive ready and invoke with result. // Receive ready and invoke with result.
let ready: Ready = rx.try_recv().expect("When on_done is invoked ready object is always sent."); let ready: Ready<H256> = rx.try_recv().expect("When on_done is invoked ready object is always sent.");
ready.ready(result); ready.ready(result);
})); }));

View File

@ -21,7 +21,6 @@ use ethcore::miner::MinerService;
use ethcore::client::MiningBlockChainClient; use ethcore::client::MiningBlockChainClient;
use ethsync::ManageNetwork; use ethsync::ManageNetwork;
use v1::helpers::errors; use v1::helpers::errors;
use v1::helpers::params::expect_no_params;
use v1::traits::EthcoreSet; use v1::traits::EthcoreSet;
use v1::types::{Bytes, H160, U256}; use v1::types::{Bytes, H160, U256};
@ -58,105 +57,94 @@ impl<C, M> EthcoreSet for EthcoreSetClient<C, M> where
C: MiningBlockChainClient + 'static, C: MiningBlockChainClient + 'static,
M: MinerService + 'static { M: MinerService + 'static {
fn set_min_gas_price(&self, params: Params) -> Result<Value, Error> { fn set_min_gas_price(&self, gas_price: U256) -> Result<bool, Error> {
try!(self.active()); try!(self.active());
from_params::<(U256,)>(params).and_then(|(gas_price,)| {
take_weak!(self.miner).set_minimal_gas_price(gas_price.into()); take_weak!(self.miner).set_minimal_gas_price(gas_price.into());
Ok(to_value(&true)) Ok(true)
})
} }
fn set_gas_floor_target(&self, params: Params) -> Result<Value, Error> { fn set_gas_floor_target(&self, target: U256) -> Result<bool, Error> {
try!(self.active()); try!(self.active());
from_params::<(U256,)>(params).and_then(|(target,)| {
take_weak!(self.miner).set_gas_floor_target(target.into()); take_weak!(self.miner).set_gas_floor_target(target.into());
Ok(to_value(&true)) Ok(true)
})
} }
fn set_gas_ceil_target(&self, params: Params) -> Result<Value, Error> { fn set_gas_ceil_target(&self, target: U256) -> Result<bool, Error> {
try!(self.active()); try!(self.active());
from_params::<(U256,)>(params).and_then(|(target,)| {
take_weak!(self.miner).set_gas_ceil_target(target.into()); take_weak!(self.miner).set_gas_ceil_target(target.into());
Ok(to_value(&true)) Ok(true)
})
} }
fn set_extra_data(&self, params: Params) -> Result<Value, Error> { fn set_extra_data(&self, extra_data: Bytes) -> Result<bool, Error> {
try!(self.active()); try!(self.active());
from_params::<(Bytes,)>(params).and_then(|(extra_data,)| {
take_weak!(self.miner).set_extra_data(extra_data.to_vec()); take_weak!(self.miner).set_extra_data(extra_data.to_vec());
Ok(to_value(&true)) Ok(true)
})
} }
fn set_author(&self, params: Params) -> Result<Value, Error> { fn set_author(&self, author: H160) -> Result<bool, Error> {
try!(self.active()); try!(self.active());
from_params::<(H160,)>(params).and_then(|(author,)| {
take_weak!(self.miner).set_author(author.into()); take_weak!(self.miner).set_author(author.into());
Ok(to_value(&true)) Ok(true)
})
} }
fn set_transactions_limit(&self, params: Params) -> Result<Value, Error> { fn set_transactions_limit(&self, limit: usize) -> Result<bool, Error> {
try!(self.active()); try!(self.active());
from_params::<(usize,)>(params).and_then(|(limit,)| {
take_weak!(self.miner).set_transactions_limit(limit); take_weak!(self.miner).set_transactions_limit(limit);
Ok(to_value(&true)) Ok(true)
})
} }
fn set_tx_gas_limit(&self, params: Params) -> Result<Value, Error> { fn set_tx_gas_limit(&self, limit: U256) -> Result<bool, Error> {
try!(self.active()); try!(self.active());
from_params::<(U256,)>(params).and_then(|(limit,)| {
take_weak!(self.miner).set_tx_gas_limit(limit.into()); take_weak!(self.miner).set_tx_gas_limit(limit.into());
Ok(to_value(&true)) Ok(true)
})
} }
fn add_reserved_peer(&self, params: Params) -> Result<Value, Error> { fn add_reserved_peer(&self, peer: String) -> Result<bool, Error> {
try!(self.active()); try!(self.active());
from_params::<(String,)>(params).and_then(|(peer,)| {
match take_weak!(self.net).add_reserved_peer(peer) { match take_weak!(self.net).add_reserved_peer(peer) {
Ok(()) => Ok(to_value(&true)), Ok(()) => Ok(true),
Err(e) => Err(errors::invalid_params("Peer address", e)), Err(e) => Err(errors::invalid_params("Peer address", e)),
} }
})
} }
fn remove_reserved_peer(&self, params: Params) -> Result<Value, Error> { fn remove_reserved_peer(&self, peer: String) -> Result<bool, Error> {
try!(self.active()); try!(self.active());
from_params::<(String,)>(params).and_then(|(peer,)| {
match take_weak!(self.net).remove_reserved_peer(peer) { match take_weak!(self.net).remove_reserved_peer(peer) {
Ok(()) => Ok(to_value(&true)), Ok(()) => Ok(true),
Err(e) => Err(errors::invalid_params("Peer address", e)), Err(e) => Err(errors::invalid_params("Peer address", e)),
} }
})
} }
fn drop_non_reserved_peers(&self, params: Params) -> Result<Value, Error> { fn drop_non_reserved_peers(&self) -> Result<bool, Error> {
try!(self.active()); try!(self.active());
try!(expect_no_params(params));
take_weak!(self.net).deny_unreserved_peers(); take_weak!(self.net).deny_unreserved_peers();
Ok(to_value(&true)) Ok(true)
} }
fn accept_non_reserved_peers(&self, params: Params) -> Result<Value, Error> { fn accept_non_reserved_peers(&self) -> Result<bool, Error> {
try!(self.active()); try!(self.active());
try!(expect_no_params(params));
take_weak!(self.net).accept_unreserved_peers(); take_weak!(self.net).accept_unreserved_peers();
Ok(to_value(&true)) Ok(true)
} }
fn start_network(&self, params: Params) -> Result<Value, Error> { fn start_network(&self) -> Result<bool, Error> {
try!(expect_no_params(params));
take_weak!(self.net).start_network(); take_weak!(self.net).start_network();
Ok(Value::Bool(true)) Ok(true)
} }
fn stop_network(&self, params: Params) -> Result<Value, Error> { fn stop_network(&self) -> Result<bool, Error> {
try!(expect_no_params(params));
take_weak!(self.net).stop_network(); take_weak!(self.net).stop_network();
Ok(Value::Bool(true)) Ok(true)
} }
} }

View File

@ -16,10 +16,9 @@
//! Net rpc implementation. //! Net rpc implementation.
use std::sync::{Arc, Weak}; use std::sync::{Arc, Weak};
use jsonrpc_core::*; use jsonrpc_core::Error;
use ethsync::SyncProvider; use ethsync::SyncProvider;
use v1::traits::Net; use v1::traits::Net;
use v1::helpers::params::expect_no_params;
/// Net rpc implementation. /// Net rpc implementation.
pub struct NetClient<S: ?Sized> where S: SyncProvider { pub struct NetClient<S: ?Sized> where S: SyncProvider {
@ -36,20 +35,19 @@ impl<S: ?Sized> NetClient<S> where S: SyncProvider {
} }
impl<S: ?Sized> Net for NetClient<S> where S: SyncProvider + 'static { impl<S: ?Sized> Net for NetClient<S> where S: SyncProvider + 'static {
fn version(&self, params: Params) -> Result<Value, Error> { fn version(&self) -> Result<String, Error> {
try!(expect_no_params(params)); Ok(format!("{}", take_weak!(self.sync).status().network_id).to_owned())
Ok(Value::String(format!("{}", take_weak!(self.sync).status().network_id).to_owned()))
} }
fn peer_count(&self, params: Params) -> Result<Value, Error> { fn peer_count(&self) -> Result<String, Error> {
try!(expect_no_params(params)); Ok(format!("0x{:x}", take_weak!(self.sync).status().num_peers as u64).to_owned())
Ok(Value::String(format!("0x{:x}", take_weak!(self.sync).status().num_peers as u64).to_owned()))
} }
fn is_listening(&self, params: Params) -> Result<Value, Error> { fn is_listening(&self) -> Result<bool, Error> {
try!(expect_no_params(params));
// right now (11 march 2016), we are always listening for incoming connections // right now (11 march 2016), we are always listening for incoming connections
Ok(Value::Bool(true)) //
// (this may not be true now -- 26 september 2016)
Ok(true)
} }
} }

View File

@ -16,9 +16,8 @@
//! RPC generic methods implementation. //! RPC generic methods implementation.
use std::collections::BTreeMap; use std::collections::BTreeMap;
use jsonrpc_core::*; use jsonrpc_core::Error;
use v1::traits::Rpc; use v1::traits::Rpc;
use v1::helpers::params::expect_no_params;
/// RPC generic methods implementation. /// RPC generic methods implementation.
pub struct RpcClient { pub struct RpcClient {
@ -40,26 +39,26 @@ impl RpcClient {
} }
impl Rpc for RpcClient { impl Rpc for RpcClient {
fn rpc_modules(&self, params: Params) -> Result<Value, Error> { fn rpc_modules(&self) -> Result<BTreeMap<String, String>, Error> {
try!(expect_no_params(params));
let modules = self.modules.iter() let modules = self.modules.iter()
.fold(BTreeMap::new(), |mut map, (k, v)| { .fold(BTreeMap::new(), |mut map, (k, v)| {
map.insert(k.to_owned(), Value::String(v.to_owned())); map.insert(k.to_owned(), v.to_owned());
map map
}); });
Ok(Value::Object(modules))
Ok(modules)
} }
fn modules(&self, params: Params) -> Result<Value, Error> { fn modules(&self) -> Result<BTreeMap<String, String>, Error> {
try!(expect_no_params(params));
let modules = self.modules.iter() let modules = self.modules.iter()
.filter(|&(k, _v)| { .filter(|&(k, _v)| {
self.valid_apis.contains(k) self.valid_apis.contains(k)
}) })
.fold(BTreeMap::new(), |mut map, (k, v)| { .fold(BTreeMap::new(), |mut map, (k, v)| {
map.insert(k.to_owned(), Value::String(v.to_owned())); map.insert(k.to_owned(), v.to_owned());
map map
}); });
Ok(Value::Object(modules))
Ok(modules)
} }
} }

View File

@ -28,174 +28,173 @@ build_rpc_trait! {
/// Eth rpc interface. /// Eth rpc interface.
pub trait Eth { pub trait Eth {
/// Returns protocol version encoded as a string (quotes are necessary). /// Returns protocol version encoded as a string (quotes are necessary).
#[name("eth_protocolVersion")] #[rpc(name = "eth_protocolVersion")]
fn protocol_version(&self) -> Result<String, Error>; fn protocol_version(&self) -> Result<String, Error>;
/// Returns an object with data about the sync status or false. (wtf?) /// Returns an object with data about the sync status or false. (wtf?)
#[name("eth_syncing")] #[rpc(name = "eth_syncing")]
fn syncing(&self) -> Result<SyncStatus, Error>; fn syncing(&self) -> Result<SyncStatus, Error>;
/// Returns the number of hashes per second that the node is mining with. /// Returns the number of hashes per second that the node is mining with.
#[name("eth_hashrate")] #[rpc(name = "eth_hashrate")]
fn hashrate(&self) -> Result<U256, Error>; fn hashrate(&self) -> Result<U256, Error>;
/// Returns block author. /// Returns block author.
#[name("eth_coinbase")] #[rpc(name = "eth_coinbase")]
fn author(&self) -> Result<H160, Error>; fn author(&self) -> Result<H160, Error>;
/// Returns true if client is actively mining new blocks. /// Returns true if client is actively mining new blocks.
#[name("eth_mining")] #[rpc(name = "eth_mining")]
fn is_mining(&self) -> Result<bool, Error>; fn is_mining(&self) -> Result<bool, Error>;
/// Returns current gas_price. /// Returns current gas_price.
#[name("eth_gasPrice")] #[rpc(name = "eth_gasPrice")]
fn gas_price(&self) -> Result<U256, Error>; fn gas_price(&self) -> Result<U256, Error>;
/// Returns accounts list. /// Returns accounts list.
#[name("eth_accounts")] #[rpc(name = "eth_accounts")]
fn accounts(&self) -> Result<Vec<H160>, Error>; fn accounts(&self) -> Result<Vec<H160>, Error>;
/// Returns highest block number. /// Returns highest block number.
#[name("eth_blockNumber")] #[rpc(name = "eth_blockNumber")]
fn block_number(&self) -> Result<U256, Error>; fn block_number(&self) -> Result<U256, Error>;
/// Returns balance of the given account. /// Returns balance of the given account.
#[name("eth_getBalance")] #[rpc(name = "eth_getBalance")]
fn balance(&self, H160, Trailing<BlockNumber>) -> Result<U256, Error>; fn balance(&self, H160, Trailing<BlockNumber>) -> Result<U256, Error>;
/// Returns content of the storage at given address. /// Returns content of the storage at given address.
#[name("eth_getStorageAt")] #[rpc(name = "eth_getStorageAt")]
fn storage_at(&self, H160, U256, Trailing<BlockNumber>) -> Result<H256, Error>; fn storage_at(&self, H160, U256, Trailing<BlockNumber>) -> Result<H256, Error>;
/// Returns block with given hash. /// Returns block with given hash.
#[name("eth_getBlockByHash")] #[rpc(name = "eth_getBlockByHash")]
fn block_by_hash(&self, H256, bool) -> Result<Option<Block>, Error>; fn block_by_hash(&self, H256, bool) -> Result<Option<Block>, Error>;
/// Returns block with given number. /// Returns block with given number.
#[name("eth_getBlockByNumber")] #[rpc(name = "eth_getBlockByNumber")]
fn block_by_number(&self, BlockNumber, bool) -> Result<Option<Block>, Error>; fn block_by_number(&self, BlockNumber, bool) -> Result<Option<Block>, Error>;
/// Returns the number of transactions sent from given address at given time (block number). /// Returns the number of transactions sent from given address at given time (block number).
#[name("eth_getTransactionCount")] #[rpc(name = "eth_getTransactionCount")]
fn transaction_count(&self, H160, Trailing<BlockNumber>) -> Result<U256, Error>; fn transaction_count(&self, H160, Trailing<BlockNumber>) -> Result<U256, Error>;
/// Returns the number of transactions in a block with given hash. /// Returns the number of transactions in a block with given hash.
#[name("eth_getBlockTransactionCountByHash")] #[rpc(name = "eth_getBlockTransactionCountByHash")]
fn block_transaction_count_by_hash(&self, H256) -> Result<Option<U256>, Error>; fn block_transaction_count_by_hash(&self, H256) -> Result<Option<U256>, Error>;
/// Returns the number of transactions in a block with given block number. /// Returns the number of transactions in a block with given block number.
#[name("eth_getBlockTransactionCountByNumber")] #[rpc(name = "eth_getBlockTransactionCountByNumber")]
fn block_transaction_count_by_number(&self, BlockNumber) -> Result<Option<U256>, Error>; fn block_transaction_count_by_number(&self, BlockNumber) -> Result<Option<U256>, Error>;
/// Returns the number of uncles in a block with given hash. /// Returns the number of uncles in a block with given hash.
#[name("eth_getUncleCountByBlockHash")] #[rpc(name = "eth_getUncleCountByBlockHash")]
fn block_uncles_count_by_hash(&self, H256) -> Result<Option<U256>, Error>; fn block_uncles_count_by_hash(&self, H256) -> Result<Option<U256>, Error>;
/// Returns the number of uncles in a block with given block number. /// Returns the number of uncles in a block with given block number.
#[name("eth_getUncleCountByBlockNumber")] #[rpc(name = "eth_getUncleCountByBlockNumber")]
fn block_uncles_count_by_number(&self, BlockNumber) -> Result<Option<U256>, Error>; fn block_uncles_count_by_number(&self, BlockNumber) -> Result<Option<U256>, Error>;
/// Returns the code at given address at given time (block number). /// Returns the code at given address at given time (block number).
#[name("eth_getCode")] #[rpc(name = "eth_getCode")]
fn code_at(&self, H160, Trailing<BlockNumber>) -> Result<Bytes, Error>; fn code_at(&self, H160, Trailing<BlockNumber>) -> Result<Bytes, Error>;
/// Sends signed transaction, returning its hash. /// Sends signed transaction, returning its hash.
#[name("eth_sendRawTransaction")] #[rpc(name = "eth_sendRawTransaction")]
fn send_raw_transaction(&self, Bytes) -> Result<H256, Error>; fn send_raw_transaction(&self, Bytes) -> Result<H256, Error>;
/// Call contract, returning the output data. /// Call contract, returning the output data.
#[name("eth_call")] #[rpc(name = "eth_call")]
fn call(&self, CallRequest, Trailing<BlockNumber>) -> Result<Bytes, Error>; fn call(&self, CallRequest, Trailing<BlockNumber>) -> Result<Bytes, Error>;
/// Estimate gas needed for execution of given contract. /// Estimate gas needed for execution of given contract.
#[name("eth_estimateGas")] #[rpc(name = "eth_estimateGas")]
fn estimate_gas(&self, CallRequest, Trailing<BlockNumber>) -> Result<U256, Error>; fn estimate_gas(&self, CallRequest, Trailing<BlockNumber>) -> Result<U256, Error>;
/// Get transaction by its hash. /// Get transaction by its hash.
#[name("eth_getTransactionByHash")] #[rpc(name = "eth_getTransactionByHash")]
fn transaction_by_hash(&self, H256) -> Result<Option<Transaction>, Error>; fn transaction_by_hash(&self, H256) -> Result<Option<Transaction>, Error>;
/// Returns transaction at given block hash and index. /// Returns transaction at given block hash and index.
#[name("eth_getTransactionByBlockHashAndIndex")] #[rpc(name = "eth_getTransactionByBlockHashAndIndex")]
fn transaction_by_block_hash_and_index(&self, H256, Index) -> Result<Option<Transaction>, Error>; fn transaction_by_block_hash_and_index(&self, H256, Index) -> Result<Option<Transaction>, Error>;
/// Returns transaction by given block number and index. /// Returns transaction by given block number and index.
#[name("eth_getTransactionByBlockNumberAndIndex")] #[rpc(name = "eth_getTransactionByBlockNumberAndIndex")]
fn transaction_by_block_number_and_index(&self, BlockNumber, Index) -> Result<Option<Transaction>, Error>; fn transaction_by_block_number_and_index(&self, BlockNumber, Index) -> Result<Option<Transaction>, Error>;
/// Returns transaction receipt. /// Returns transaction receipt.
#[name("eth_getTransactionReceipt")] #[rpc(name = "eth_getTransactionReceipt")]
fn transaction_receipt(&self, H256) -> Result<Option<Receipt>, Error>; fn transaction_receipt(&self, H256) -> Result<Option<Receipt>, Error>;
/// Returns an uncles at given block and index. /// Returns an uncles at given block and index.
#[name("eth_getUncleByBlockHashAndIndex")] #[rpc(name = "eth_getUncleByBlockHashAndIndex")]
fn uncle_by_block_hash_and_index(&self, H256, Index) -> Result<Option<Block>, Error>; fn uncle_by_block_hash_and_index(&self, H256, Index) -> Result<Option<Block>, Error>;
/// Returns an uncles at given block and index. /// Returns an uncles at given block and index.
#[name("eth_getUncleByBlockNumberAndIndex")] #[rpc(name = "eth_getUncleByBlockNumberAndIndex")]
fn uncle_by_block_number_and_index(&self, BlockNumber, Index) -> Result<Option<Block>, Error>; fn uncle_by_block_number_and_index(&self, BlockNumber, Index) -> Result<Option<Block>, Error>;
/// Returns available compilers. /// Returns available compilers.
#[name("eth_getCompilers")] #[rpc(name = "eth_getCompilers")]
fn compilers(&self) -> Result<Vec<String>, Error>; fn compilers(&self) -> Result<Vec<String>, Error>;
/// Compiles lll code. /// Compiles lll code.
#[name("eth_compileLLL")] #[rpc(name = "eth_compileLLL")]
fn compile_lll(&self, String) -> Result<Bytes, Error>; fn compile_lll(&self, String) -> Result<Bytes, Error>;
/// Compiles solidity. /// Compiles solidity.
#[name("eth_compileSolidity")] #[rpc(name = "eth_compileSolidity")]
fn compile_solidity(&self, String) -> Result<Bytes, Error>; fn compile_solidity(&self, String) -> Result<Bytes, Error>;
/// Compiles serpent. /// Compiles serpent.
#[name("eth_compileSerpent")] #[rpc(name = "eth_compileSerpent")]
fn compile_serpent(&self, String) -> Result<Bytes, Error>; fn compile_serpent(&self, String) -> Result<Bytes, Error>;
/// Returns logs matching given filter object. /// Returns logs matching given filter object.
#[name("eth_getLogs")] #[rpc(name = "eth_getLogs")]
fn logs(&self, Filter) -> Result<Vec<Log>, Error>; fn logs(&self, Filter) -> Result<Vec<Log>, Error>;
/// Returns the hash of the current block, the seedHash, and the boundary condition to be met. /// Returns the hash of the current block, the seedHash, and the boundary condition to be met.
#[name("eth_getWork")] #[rpc(name = "eth_getWork")]
fn work(&self, Trailing<u64>) -> Result<Work, Error>; fn work(&self, Trailing<u64>) -> Result<Work, Error>;
/// Used for submitting a proof-of-work solution. /// Used for submitting a proof-of-work solution.
#[name("eth_submitWork")] #[rpc(name = "eth_submitWork")]
fn submit_work(&self, H64, H256, H256) -> Result<bool, Error>; fn submit_work(&self, H64, H256, H256) -> Result<bool, Error>;
/// Used for submitting mining hashrate. /// Used for submitting mining hashrate.
#[name("eth_submitHashrate")] #[rpc(name = "eth_submitHashrate")]
fn submit_hashrate(&self, U256, H256) -> Result<bool, Error>; fn submit_hashrate(&self, U256, H256) -> Result<bool, Error>;
} }
} }
build_rpc_trait! { build_rpc_trait! {
/// Eth filters rpc api (polling). /// Eth filters rpc api (polling).
// TODO: do filters api properly // TODO: do filters api properly
pub trait EthFilter { pub trait EthFilter {
/// Returns id of new filter. /// Returns id of new filter.
#[name("eth_newFilter")] #[rpc(name = "eth_newFilter")]
fn new_filter(&self, Filter) -> Result<U256, Error>; fn new_filter(&self, Filter) -> Result<U256, Error>;
/// Returns id of new block filter. /// Returns id of new block filter.
#[name("eth_newBlockFilter")] #[rpc(name = "eth_newBlockFilter")]
fn new_block_filter(&self) -> Result<U256, Error>; fn new_block_filter(&self) -> Result<U256, Error>;
/// Returns id of new block filter. /// Returns id of new block filter.
#[name("eth_newPendingTransactionFilter")] #[rpc(name = "eth_newPendingTransactionFilter")]
fn new_pending_transaction_filter(&self) -> Result<U256, Error>; fn new_pending_transaction_filter(&self) -> Result<U256, Error>;
/// Returns filter changes since last poll. /// Returns filter changes since last poll.
#[name("eth_getFilterChanges")] #[rpc(name = "eth_getFilterChanges")]
fn filter_changes(&self, Index) -> Result<FilterChanges, Error>; fn filter_changes(&self, Index) -> Result<FilterChanges, Error>;
/// Returns all logs matching given filter (in a range 'from' - 'to'). /// Returns all logs matching given filter (in a range 'from' - 'to').
#[name("eth_getFilterLogs")] #[rpc(name = "eth_getFilterLogs")]
fn filter_logs(&self, Index) -> Result<Vec<Log>, Error>; fn filter_logs(&self, Index) -> Result<Vec<Log>, Error>;
/// Uninstalls filter. /// Uninstalls filter.
#[name("eth_uninstallFilter")] #[rpc(name = "eth_uninstallFilter")]
fn uninstall_filter(&self, Index) -> Result<bool, Error>; fn uninstall_filter(&self, Index) -> Result<bool, Error>;
} }
} }

View File

@ -15,113 +15,107 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! Ethcore-specific rpc interface. //! Ethcore-specific rpc interface.
use std::sync::Arc; use jsonrpc_core::Error;
use jsonrpc_core::*;
use v1::helpers::auto_args::{Wrap, WrapAsync, Ready};
use v1::types::{H160, H256, H512, U256, Bytes, Peers, Transaction, RpcSettings};
build_rpc_trait! {
/// Ethcore-specific rpc interface. /// Ethcore-specific rpc interface.
pub trait Ethcore: Sized + Send + Sync + 'static { pub trait Ethcore {
/// Returns current transactions limit. /// Returns current transactions limit.
fn transactions_limit(&self, _: Params) -> Result<Value, Error>; #[rpc(name = "ethcore_transactionsLimit")]
fn transactions_limit(&self) -> Result<usize, Error>;
/// Returns mining extra data. /// Returns mining extra data.
fn extra_data(&self, _: Params) -> Result<Value, Error>; #[rpc(name = "ethcore_extraData")]
fn extra_data(&self) -> Result<Bytes, Error>;
/// Returns mining gas floor target. /// Returns mining gas floor target.
fn gas_floor_target(&self, _: Params) -> Result<Value, Error>; #[rpc(name = "ethcore_gasFloorTarget")]
fn gas_floor_target(&self) -> Result<U256, Error>;
/// Returns mining gas floor cap. /// Returns mining gas floor cap.
fn gas_ceil_target(&self, _: Params) -> Result<Value, Error>; #[rpc(name = "ethcore_gasCeilTarget")]
fn gas_ceil_target(&self) -> Result<U256, Error>;
/// Returns minimal gas price for transaction to be included in queue. /// Returns minimal gas price for transaction to be included in queue.
fn min_gas_price(&self, _: Params) -> Result<Value, Error>; #[rpc(name = "ethcore_minGasPrice")]
fn min_gas_price(&self) -> Result<U256, Error>;
/// Returns latest logs /// Returns latest logs
fn dev_logs(&self, _: Params) -> Result<Value, Error>; #[rpc(name = "ethcore_devLogs")]
fn dev_logs(&self) -> Result<Vec<String>, Error>;
/// Returns logs levels /// Returns logs levels
fn dev_logs_levels(&self, _: Params) -> Result<Value, Error>; #[rpc(name = "ethcore_devLogsLevels")]
fn dev_logs_levels(&self) -> Result<String, Error>;
/// Returns chain name /// Returns chain name
fn net_chain(&self, _: Params) -> Result<Value, Error>; #[rpc(name = "ethcore_netChain")]
fn net_chain(&self) -> Result<String, Error>;
/// Returns peers details /// Returns peers details
fn net_peers(&self, _: Params) -> Result<Value, Error>; #[rpc(name = "ethcore_netPeers")]
fn net_peers(&self) -> Result<Peers, Error>;
/// Returns network port /// Returns network port
fn net_port(&self, _: Params) -> Result<Value, Error>; #[rpc(name = "ethcore_netPort")]
fn net_port(&self) -> Result<u16, Error>;
/// Returns rpc settings /// Returns rpc settings
fn rpc_settings(&self, _: Params) -> Result<Value, Error>; #[rpc(name = "ethcore_rpcSettings")]
fn rpc_settings(&self) -> Result<RpcSettings, Error>;
/// Returns node name /// Returns node name
fn node_name(&self, _: Params) -> Result<Value, Error>; #[rpc(name = "ethcore_nodeName")]
fn node_name(&self) -> Result<String, Error>;
/// Returns default extra data /// Returns default extra data
fn default_extra_data(&self, _: Params) -> Result<Value, Error>; #[rpc(name = "ethcore_defaultExtraData")]
fn default_extra_data(&self) -> Result<Bytes, Error>;
/// Returns distribution of gas price in latest blocks. /// Returns distribution of gas price in latest blocks.
fn gas_price_statistics(&self, _: Params) -> Result<Value, Error>; #[rpc(name = "ethcore_gasPriceStatistics")]
fn gas_price_statistics(&self) -> Result<Vec<U256>, Error>;
/// Returns number of unsigned transactions waiting in the signer queue (if signer enabled) /// Returns number of unsigned transactions waiting in the signer queue (if signer enabled)
/// Returns error when signer is disabled /// Returns error when signer is disabled
fn unsigned_transactions_count(&self, _: Params) -> Result<Value, Error>; #[rpc(name = "ethcore_unsignedTransactionsCount")]
fn unsigned_transactions_count(&self) -> Result<usize, Error>;
/// Returns a cryptographically random phrase sufficient for securely seeding a secret key. /// Returns a cryptographically random phrase sufficient for securely seeding a secret key.
fn generate_secret_phrase(&self, _: Params) -> Result<Value, Error>; #[rpc(name = "ethcore_generateSecretPhrase")]
fn generate_secret_phrase(&self) -> Result<String, Error>;
/// Returns whatever address would be derived from the given phrase if it were to seed a brainwallet. /// Returns whatever address would be derived from the given phrase if it were to seed a brainwallet.
fn phrase_to_address(&self, _: Params) -> Result<Value, Error>; #[rpc(name = "ethcore_phraseToAddress")]
fn phrase_to_address(&self, String) -> Result<H160, Error>;
/// Returns the value of the registrar for this network. /// Returns the value of the registrar for this network.
fn registry_address(&self, _: Params) -> Result<Value, Error>; #[rpc(name = "ethcore_registryAddress")]
fn registry_address(&self) -> Result<Option<H160>, Error>;
/// Returns all addresses if Fat DB is enabled (`--fat-db`), or null if not. /// Returns all addresses if Fat DB is enabled (`--fat-db`), or null if not.
/// Takes no parameters. #[rpc(name = "ethcore_listAccounts")]
fn list_accounts(&self, _: Params) -> Result<Value, Error>; fn list_accounts(&self) -> Result<Option<Vec<H160>>, Error>;
/// Returns all storage keys of the given address (first parameter) if Fat DB is enabled (`--fat-db`), /// Returns all storage keys of the given address (first parameter) if Fat DB is enabled (`--fat-db`),
/// or null if not. /// or null if not.
fn list_storage_keys(&self, _: Params) -> Result<Value, Error>; #[rpc(name = "ethcore_listStorageKeys")]
fn list_storage_keys(&self, H160) -> Result<Option<Vec<H256>>, Error>;
/// Encrypt some data with a public key under ECIES. /// Encrypt some data with a public key under ECIES.
/// First parameter is the 512-byte destination public key, second is the message. /// First parameter is the 512-byte destination public key, second is the message.
fn encrypt_message(&self, _: Params) -> Result<Value, Error>; #[rpc(name = "ethcore_encryptMessage")]
fn encrypt_message(&self, H512, Bytes) -> Result<Bytes, Error>;
/// Returns all pending (current) transactions from transaction queue. /// Returns all pending transactions from transaction queue.
fn pending_transactions(&self, _: Params) -> Result<Value, Error>; #[rpc(name = "ethcore_pendingTransactions")]
fn pending_transactions(&self) -> Result<Vec<Transaction>, Error>;
/// Hash a file content under given URL. /// Hash a file content under given URL.
fn hash_content(&self, _: Params, _: Ready); #[rpc(async, name = "ethcore_hashContent")]
fn hash_content(&self, Ready<H256>, String);
/// Should be used to convert object to io delegate.
fn to_delegate(self) -> IoDelegate<Self> {
let mut delegate = IoDelegate::new(Arc::new(self));
delegate.add_method("ethcore_extraData", Ethcore::extra_data);
delegate.add_method("ethcore_gasFloorTarget", Ethcore::gas_floor_target);
delegate.add_method("ethcore_gasCeilTarget", Ethcore::gas_ceil_target);
delegate.add_method("ethcore_minGasPrice", Ethcore::min_gas_price);
delegate.add_method("ethcore_transactionsLimit", Ethcore::transactions_limit);
delegate.add_method("ethcore_devLogs", Ethcore::dev_logs);
delegate.add_method("ethcore_devLogsLevels", Ethcore::dev_logs_levels);
delegate.add_method("ethcore_netChain", Ethcore::net_chain);
delegate.add_method("ethcore_netPeers", Ethcore::net_peers);
delegate.add_method("ethcore_netPort", Ethcore::net_port);
delegate.add_method("ethcore_rpcSettings", Ethcore::rpc_settings);
delegate.add_method("ethcore_nodeName", Ethcore::node_name);
delegate.add_method("ethcore_defaultExtraData", Ethcore::default_extra_data);
delegate.add_method("ethcore_gasPriceStatistics", Ethcore::gas_price_statistics);
delegate.add_method("ethcore_unsignedTransactionsCount", Ethcore::unsigned_transactions_count);
delegate.add_method("ethcore_generateSecretPhrase", Ethcore::generate_secret_phrase);
delegate.add_method("ethcore_phraseToAddress", Ethcore::phrase_to_address);
delegate.add_method("ethcore_registryAddress", Ethcore::registry_address);
delegate.add_method("ethcore_listAccounts", Ethcore::list_accounts);
delegate.add_method("ethcore_listStorageKeys", Ethcore::list_storage_keys);
delegate.add_method("ethcore_encryptMessage", Ethcore::encrypt_message);
delegate.add_method("ethcore_pendingTransactions", Ethcore::pending_transactions);
delegate.add_async_method("ethcore_hashContent", Ethcore::hash_content);
delegate
} }
} }

View File

@ -16,66 +16,64 @@
//! Ethcore-specific rpc interface for operations altering the settings. //! Ethcore-specific rpc interface for operations altering the settings.
use std::sync::Arc; use jsonrpc_core::Error;
use jsonrpc_core::*;
use v1::helpers::auto_args::Wrap;
use v1::types::{Bytes, H160, U256};
build_rpc_trait! {
/// Ethcore-specific rpc interface for operations altering the settings. /// Ethcore-specific rpc interface for operations altering the settings.
pub trait EthcoreSet: Sized + Send + Sync + 'static { pub trait EthcoreSet {
/// Sets new minimal gas price for mined blocks. /// Sets new minimal gas price for mined blocks.
fn set_min_gas_price(&self, _: Params) -> Result<Value, Error>; #[rpc(name = "ethcore_setMinGasPrice")]
fn set_min_gas_price(&self, U256) -> Result<bool, Error>;
/// Sets new gas floor target for mined blocks. /// Sets new gas floor target for mined blocks.
fn set_gas_floor_target(&self, _: Params) -> Result<Value, Error>; #[rpc(name = "ethcore_setGasFloorTarget")]
fn set_gas_floor_target(&self, U256) -> Result<bool, Error>;
/// Sets new gas ceiling target for mined blocks. /// Sets new gas ceiling target for mined blocks.
fn set_gas_ceil_target(&self, _: Params) -> Result<Value, Error>; #[rpc(name = "ethcore_setGasCeilTarget")]
fn set_gas_ceil_target(&self, U256) -> Result<bool, Error>;
/// Sets new extra data for mined blocks. /// Sets new extra data for mined blocks.
fn set_extra_data(&self, _: Params) -> Result<Value, Error>; #[rpc(name = "ethcore_setExtraData")]
fn set_extra_data(&self, Bytes) -> Result<bool, Error>;
/// Sets new author for mined block. /// Sets new author for mined block.
fn set_author(&self, _: Params) -> Result<Value, Error>; #[rpc(name = "ethcore_setAuthor")]
fn set_author(&self, H160) -> Result<bool, Error>;
/// Sets the limits for transaction queue. /// Sets the limits for transaction queue.
fn set_transactions_limit(&self, _: Params) -> Result<Value, Error>; #[rpc(name = "ethcore_setTransactionsLimit")]
fn set_transactions_limit(&self, usize) -> Result<bool, Error>;
/// Sets the maximum amount of gas a single transaction may consume. /// Sets the maximum amount of gas a single transaction may consume.
fn set_tx_gas_limit(&self, _: Params) -> Result<Value, Error>; #[rpc(name = "ethcore_setMaxTransactionGas")]
fn set_tx_gas_limit(&self, U256) -> Result<bool, Error>;
/// Add a reserved peer. /// Add a reserved peer.
fn add_reserved_peer(&self, _: Params) -> Result<Value, Error>; #[rpc(name = "ethcore_addReservedPeer")]
fn add_reserved_peer(&self, String) -> Result<bool, Error>;
/// Remove a reserved peer. /// Remove a reserved peer.
fn remove_reserved_peer(&self, _: Params) -> Result<Value, Error>; #[rpc(name = "ethcore_removeReservedPeer")]
fn remove_reserved_peer(&self, String) -> Result<bool, Error>;
/// Drop all non-reserved peers. /// Drop all non-reserved peers.
fn drop_non_reserved_peers(&self, _: Params) -> Result<Value, Error>; #[rpc(name = "ethcore_dropNonReservedPeers")]
fn drop_non_reserved_peers(&self) -> Result<bool, Error>;
/// Accept non-reserved peers (default behavior) /// Accept non-reserved peers (default behavior)
fn accept_non_reserved_peers(&self, _: Params) -> Result<Value, Error>; #[rpc(name = "ethcore_acceptNonReservedPeers")]
fn accept_non_reserved_peers(&self) -> Result<bool, Error>;
/// Start the network. /// Start the network.
fn start_network(&self, _: Params) -> Result<Value, Error>; #[rpc(name = "ethcore_startNetwork")]
fn start_network(&self) -> Result<bool, Error>;
/// Stop the network. /// Stop the network.
fn stop_network(&self, _: Params) -> Result<Value, Error>; #[rpc(name = "ethcore_stopNetwork")]
fn stop_network(&self) -> Result<bool, Error>;
/// Should be used to convert object to io delegate.
fn to_delegate(self) -> IoDelegate<Self> {
let mut delegate = IoDelegate::new(Arc::new(self));
delegate.add_method("ethcore_setMinGasPrice", EthcoreSet::set_min_gas_price);
delegate.add_method("ethcore_setGasFloorTarget", EthcoreSet::set_gas_floor_target);
delegate.add_method("ethcore_setGasCeilTarget", EthcoreSet::set_gas_ceil_target);
delegate.add_method("ethcore_setExtraData", EthcoreSet::set_extra_data);
delegate.add_method("ethcore_setAuthor", EthcoreSet::set_author);
delegate.add_method("ethcore_setMaxTransactionGas", EthcoreSet::set_tx_gas_limit);
delegate.add_method("ethcore_setTransactionsLimit", EthcoreSet::set_transactions_limit);
delegate.add_method("ethcore_addReservedPeer", EthcoreSet::add_reserved_peer);
delegate.add_method("ethcore_removeReservedPeer", EthcoreSet::remove_reserved_peer);
delegate.add_method("ethcore_dropNonReservedPeers", EthcoreSet::drop_non_reserved_peers);
delegate.add_method("ethcore_acceptNonReservedPeers", EthcoreSet::accept_non_reserved_peers);
delegate
} }
} }

View File

@ -15,27 +15,24 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! Net rpc interface. //! Net rpc interface.
use std::sync::Arc; use jsonrpc_core::Error;
use jsonrpc_core::*;
use v1::helpers::auto_args::Wrap;
build_rpc_trait! {
/// Net rpc interface. /// Net rpc interface.
pub trait Net: Sized + Send + Sync + 'static { pub trait Net {
/// Returns protocol version. /// Returns protocol version.
fn version(&self, _: Params) -> Result<Value, Error>; #[rpc(name = "net_version")]
fn version(&self) -> Result<String, Error>;
/// Returns number of peers connected to node. /// Returns number of peers connected to node.
fn peer_count(&self, _: Params) -> Result<Value, Error>; #[rpc(name = "net_peerCount")]
fn peer_count(&self) -> Result<String, Error>;
/// Returns true if client is actively listening for network connections. /// Returns true if client is actively listening for network connections.
/// Otherwise false. /// Otherwise false.
fn is_listening(&self, _: Params) -> Result<Value, Error>; #[rpc(name = "net_listening")]
fn is_listening(&self) -> Result<bool, Error>;
/// Should be used to convert object to io delegate.
fn to_delegate(self) -> IoDelegate<Self> {
let mut delegate = IoDelegate::new(Arc::new(self));
delegate.add_method("net_version", Net::version);
delegate.add_method("net_peerCount", Net::peer_count);
delegate.add_method("net_listening", Net::is_listening);
delegate
} }
} }

View File

@ -16,26 +16,21 @@
//! RPC interface. //! RPC interface.
use std::sync::Arc; use jsonrpc_core::Error;
use jsonrpc_core::*;
use v1::helpers::auto_args::Wrap;
use std::collections::BTreeMap;
build_rpc_trait! {
/// RPC Interface. /// RPC Interface.
pub trait Rpc: Sized + Send + Sync + 'static { pub trait Rpc {
/// Returns supported modules for Geth 1.3.6 /// Returns supported modules for Geth 1.3.6
fn modules(&self, _: Params) -> Result<Value, Error>; #[rpc(name = "modules")]
fn modules(&self) -> Result<BTreeMap<String, String>, Error>;
/// Returns supported modules for Geth 1.4.0 /// Returns supported modules for Geth 1.4.0
fn rpc_modules(&self, _: Params) -> Result<Value, Error>; #[rpc(name = "rpc_modules")]
fn rpc_modules(&self) -> Result<BTreeMap<String, String>, Error>;
/// Should be used to convert object to io delegate.
fn to_delegate(self) -> IoDelegate<Self> {
let mut delegate = IoDelegate::new(Arc::new(self));
// Geth 1.3.6 compatibility
delegate.add_method("modules", Rpc::modules);
// Geth 1.4.0 compatibility
delegate.add_method("rpc_modules", Rpc::rpc_modules);
delegate
} }
} }

View File

@ -27,6 +27,7 @@ mod sync;
mod transaction; mod transaction;
mod transaction_request; mod transaction_request;
mod receipt; mod receipt;
mod rpc_settings;
mod trace; mod trace;
mod trace_filter; mod trace_filter;
mod uint; mod uint;
@ -45,6 +46,7 @@ pub use self::sync::{SyncStatus, SyncInfo, Peers};
pub use self::transaction::Transaction; pub use self::transaction::Transaction;
pub use self::transaction_request::TransactionRequest; pub use self::transaction_request::TransactionRequest;
pub use self::receipt::Receipt; pub use self::receipt::Receipt;
pub use self::rpc_settings::RpcSettings;
pub use self::trace::{LocalizedTrace, TraceResults}; pub use self::trace::{LocalizedTrace, TraceResults};
pub use self::trace_filter::TraceFilter; pub use self::trace_filter::TraceFilter;
pub use self::uint::U256; pub use self::uint::U256;

View File

@ -0,0 +1,28 @@
// 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/>.
//! RPC Settings data.
/// Values of RPC settings.
#[derive(Serialize, Deserialize)]
pub struct RpcSettings {
/// Whether RPC is enabled.
pub enabled: bool,
/// The interface being listened on.
pub interface: String,
/// The port being listened on.
pub port: u64,
}