diff --git a/src/bin/client/ethrpc.rs b/src/bin/client/ethrpc.rs index 735250d87..09c93041f 100644 --- a/src/bin/client/ethrpc.rs +++ b/src/bin/client/ethrpc.rs @@ -2,46 +2,101 @@ extern crate jsonrpc_core; extern crate jsonrpc_http_server; use std::sync::{Arc, RwLock}; +use rustc_serialize::hex::ToHex; use self::jsonrpc_core::{IoHandler, IoDelegate, Params, Value, Error, ErrorCode}; use ethcore::client::*; +use util::hash::*; macro_rules! rpcerr { - () => (Err(Error::new(ErrorCode::InternalError))) + () => (Err(Error::internal_error())) } -/// This could be a part of `jsonrpc_core`. Unfortunately, -/// "only traits defined in the current crate can be implemented for a type parameter". -pub trait IntoDelegate where T: Send + Sync + 'static { - /// This function should be called to translate custom type into IoDelegate - fn into_delegate(self) -> IoDelegate; +/// Web3 rpc interface. +pub trait Web3: Sized + Send + Sync + 'static { + /// Returns current client version. + fn client_version(&self, _: Params) -> Result { rpcerr!() } + + /// 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("web3_clientVersion", Web3::client_version); + delegate + } } -/// eth rpc interface -pub trait Eth { - /// returns protocol version + +/// Eth rpc interface. +pub trait Eth: Sized + Send + Sync + 'static { + /// Returns protocol version. fn protocol_version(&self, _: Params) -> Result { rpcerr!() } - /// returns block author + /// Returns block author. fn author(&self, _: Params) -> Result { rpcerr!() } - /// returns current gas_price + /// Returns current gas_price. fn gas_price(&self, _: Params) -> Result { rpcerr!() } - /// returns highest block number + /// Returns highest block number. fn block_number(&self, _: Params) -> Result { rpcerr!() } + + /// Returns block with given index / hash. + fn block(&self, _: Params) -> Result { rpcerr!() } + + /// Returns true if client is actively mining new blocks. + fn is_mining(&self, _: Params) -> Result { rpcerr!() } + + /// Returns the number of hashes per second that the node is mining with. + fn hashrate(&self, _: Params) -> Result { rpcerr!() } + + /// Returns the number of transactions in a block. + fn block_transaction_count(&self, _: Params) -> Result { rpcerr!() } + + /// 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_coinbase", Eth::author); + delegate.add_method("eth_gasPrice", Eth::gas_price); + delegate.add_method("eth_blockNumber", Eth::block_number); + delegate.add_method("eth_getBlockByNumber", Eth::block); + delegate.add_method("eth_mining", Eth::is_mining); + delegate.add_method("eth_hashrate", Eth::hashrate); + delegate.add_method("eth_getBlockTransactionCountByNumber", Eth::block_transaction_count); + delegate + } } -impl IntoDelegate for D where D: Eth + Send + Sync + 'static { - fn into_delegate(self) -> IoDelegate { +/// Net rpc interface. +pub trait Net: Sized + Send + Sync + 'static { + /// Returns protocol version. + fn version(&self, _: Params) -> Result { rpcerr!() } + + /// Returns number of peers connected to node. + fn peer_count(&self, _: Params) -> Result { rpcerr!() } + + fn to_delegate(self) -> IoDelegate { let mut delegate = IoDelegate::new(Arc::new(self)); - delegate.add_method("eth_protocolVersion", D::protocol_version); - delegate.add_method("eth_coinbase", D::author); - delegate.add_method("eth_gasPrice", D::gas_price); - delegate.add_method("eth_blockNumber", D::block_number); + delegate.add_method("peer_count", Net::version); + delegate.add_method("net_version", Net::version); delegate } } +pub struct Web3Client; + +impl Web3Client { + pub fn new() -> Self { Web3Client } +} + +impl Web3 for Web3Client { + fn client_version(&self, params: Params) -> Result { + match params { + Params::None => Ok(Value::String("parity/0.1.0/-/rust1.7-nightly".to_string())), + _ => Err(Error::invalid_params()) + } + } +} + pub struct EthClient { client: Arc>, } @@ -55,15 +110,35 @@ impl EthClient { } impl Eth for EthClient { + fn protocol_version(&self, params: Params) -> Result { + match params { + Params::None => Ok(Value::U64(63)), + _ => Err(Error::invalid_params()) + } + } + + fn author(&self, params: Params) -> Result { + match params { + Params::None => Ok(Value::String(Address::new().to_hex())), + _ => Err(Error::invalid_params()) + } + } + fn block_number(&self, params: Params) -> Result { match params { Params::None => Ok(Value::U64(self.client.read().unwrap().chain_info().best_block_number)), - _ => Err(Error::new(ErrorCode::InvalidParams)), + _ => Err(Error::invalid_params()) + } + } + + fn is_mining(&self, params: Params) -> Result { + match params { + Params::None => Ok(Value::Bool(false)), + _ => Err(Error::invalid_params()) } } } - pub struct HttpServer { handler: IoHandler, threads: usize @@ -77,8 +152,8 @@ impl HttpServer { } } - pub fn add_delegate(&mut self, delegate: I) where D: Send + Sync + 'static, I: IntoDelegate { - self.handler.add_delegate(delegate.into_delegate()); + pub fn add_delegate(&mut self, delegate: IoDelegate) where D: Send + Sync + 'static { + self.handler.add_delegate(delegate); } pub fn start_async(self, addr: &str) { diff --git a/src/bin/client/main.rs b/src/bin/client/main.rs index 3dd9b9c5c..f9f073718 100644 --- a/src/bin/client/main.rs +++ b/src/bin/client/main.rs @@ -32,8 +32,11 @@ fn setup_log() { #[cfg(feature = "rpc")] fn setup_rpc_server(client: Arc>) { - let mut server = ethrpc::HttpServer::new(1); - server.add_delegate(ethrpc::EthClient::new(client)); + use self::ethrpc::*; + + let mut server = HttpServer::new(1); + server.add_delegate(Web3Client::new().to_delegate()); + server.add_delegate(EthClient::new(client).to_delegate()); server.start_async("127.0.0.1:3030"); }