New jsonrpc-core with futures and metadata support (#3859)

* Bumping serde & serde_json

* Super-initial usage of new jsonrpc

* Single event loop for jsonrpc

* Metadata

* Supporting metadata extraction for eth_accounts

* Fixing Cargo.lock

* Removing uneccessary clones

* Fixing unused import

* Unused import

* Fixing test
This commit is contained in:
Tomasz Drwięga
2017-01-11 20:02:27 +01:00
committed by Gav Wood
parent c4d96a64a2
commit 41da1a0a79
45 changed files with 706 additions and 642 deletions

View File

@@ -22,9 +22,9 @@ use ethcore::client::Client;
use ethsync::SyncProvider;
use helpers::replace_home;
use dir::default_data_path;
use jsonrpc_core::reactor::Remote;
use rpc_apis::SignerService;
use hash_fetch::fetch::Client as FetchClient;
use parity_reactor::Remote;
#[derive(Debug, PartialEq, Clone)]
pub struct Configuration {
@@ -130,6 +130,8 @@ mod server {
use rpc_apis;
use ethcore_rpc::is_major_importing;
use hash_fetch::urlhint::ContractClient;
use jsonrpc_core::reactor::RpcHandler;
use parity_reactor;
pub use ethcore_dapps::Server as WebappServer;
@@ -146,8 +148,9 @@ mod server {
let server = dapps::ServerBuilder::new(
&dapps_path,
Arc::new(Registrar { client: deps.client.clone() }),
deps.remote.clone(),
parity_reactor::Remote::new(deps.remote.clone()),
);
let sync = deps.sync.clone();
let client = deps.client.clone();
let signer = deps.signer.clone();
@@ -156,15 +159,17 @@ mod server {
.sync_status(Arc::new(move || is_major_importing(Some(sync.status().state), client.queue_info())))
.web_proxy_tokens(Arc::new(move |token| signer.is_valid_web_proxy_access_token(&token)))
.extra_dapps(&extra_dapps)
.signer_address(deps.signer.address());
.signer_address(deps.signer.address())
.allowed_hosts(allowed_hosts);
let server = rpc_apis::setup_rpc(server, deps.apis.clone(), rpc_apis::ApiSet::UnsafeContext);
let apis = rpc_apis::setup_rpc(Default::default(), deps.apis.clone(), rpc_apis::ApiSet::UnsafeContext);
let handler = RpcHandler::new(Arc::new(apis), deps.remote);
let start_result = match auth {
None => {
server.start_unsecured_http(url, allowed_hosts)
server.start_unsecured_http(url, handler)
},
Some((username, password)) => {
server.start_basic_auth_http(url, allowed_hosts, &username, &password)
server.start_basic_auth_http(url, &username, &password, handler)
},
};
@@ -175,8 +180,9 @@ mod server {
},
Err(e) => Err(format!("WebApps error: {:?}", e)),
Ok(server) => {
let ph = deps.panic_handler;
server.set_panic_handler(move || {
deps.panic_handler.notify_all("Panic in WebApp thread.".to_owned());
ph.notify_all("Panic in WebApp thread.".to_owned());
});
Ok(server)
},

View File

@@ -41,6 +41,7 @@ extern crate ethcore_ipc as ipc;
extern crate ethcore_ipc_nano as nanoipc;
extern crate serde;
extern crate serde_json;
extern crate jsonrpc_core;
extern crate rlp;
extern crate ethcore_light as light;
extern crate parity_hash_fetch as hash_fetch;

View File

@@ -19,11 +19,14 @@ use std::sync::Arc;
use std::net::SocketAddr;
use std::io;
use io::PanicHandler;
use ethcore_rpc::{RpcServerError, RpcServer as Server, IpcServerError};
use dir::default_data_path;
use ethcore_rpc::{self as rpc, RpcServerError, IpcServerError, Metadata};
use helpers::parity_ipc_path;
use jsonrpc_core::MetaIoHandler;
use jsonrpc_core::reactor::{RpcHandler, Remote};
use rpc_apis;
use rpc_apis::ApiSet;
use helpers::parity_ipc_path;
use dir::default_data_path;
pub use ethcore_rpc::{IpcServer, Server as HttpServer};
@@ -81,6 +84,7 @@ impl fmt::Display for IpcConfiguration {
pub struct Dependencies {
pub panic_handler: Arc<PanicHandler>,
pub apis: Arc<rpc_apis::Dependencies>,
pub remote: Remote,
}
pub fn new_http(conf: HttpConfiguration, deps: &Dependencies) -> Result<Option<HttpServer>, String> {
@@ -93,9 +97,8 @@ pub fn new_http(conf: HttpConfiguration, deps: &Dependencies) -> Result<Option<H
Ok(Some(setup_http_rpc_server(deps, &addr, conf.cors, conf.hosts, conf.apis)?))
}
fn setup_rpc_server(apis: ApiSet, deps: &Dependencies) -> Result<Server, String> {
let server = Server::new();
Ok(rpc_apis::setup_rpc(server, deps.apis.clone(), apis))
fn setup_apis(apis: ApiSet, deps: &Dependencies) -> MetaIoHandler<Metadata> {
rpc_apis::setup_rpc(MetaIoHandler::default(), deps.apis.clone(), apis)
}
pub fn setup_http_rpc_server(
@@ -105,9 +108,10 @@ pub fn setup_http_rpc_server(
allowed_hosts: Option<Vec<String>>,
apis: ApiSet
) -> Result<HttpServer, String> {
let server = setup_rpc_server(apis, dependencies)?;
let apis = setup_apis(apis, dependencies);
let handler = RpcHandler::new(Arc::new(apis), dependencies.remote.clone());
let ph = dependencies.panic_handler.clone();
let start_result = server.start_http(url, cors_domains, allowed_hosts, ph);
let start_result = rpc::start_http(url, cors_domains, allowed_hosts, ph, handler);
match start_result {
Err(RpcServerError::IoError(err)) => match err.kind() {
io::ErrorKind::AddrInUse => Err(format!("RPC address {} is already in use, make sure that another instance of an Ethereum client is not running or change the address using the --jsonrpc-port and --jsonrpc-interface options.", url)),
@@ -118,14 +122,15 @@ pub fn setup_http_rpc_server(
}
}
pub fn new_ipc(conf: IpcConfiguration, deps: &Dependencies) -> Result<Option<IpcServer>, String> {
pub fn new_ipc(conf: IpcConfiguration, deps: &Dependencies) -> Result<Option<IpcServer<Metadata>>, String> {
if !conf.enabled { return Ok(None); }
Ok(Some(setup_ipc_rpc_server(deps, &conf.socket_addr, conf.apis)?))
}
pub fn setup_ipc_rpc_server(dependencies: &Dependencies, addr: &str, apis: ApiSet) -> Result<IpcServer, String> {
let server = setup_rpc_server(apis, dependencies)?;
match server.start_ipc(addr) {
pub fn setup_ipc_rpc_server(dependencies: &Dependencies, addr: &str, apis: ApiSet) -> Result<IpcServer<Metadata>, String> {
let apis = setup_apis(apis, dependencies);
let handler = RpcHandler::new(Arc::new(apis), dependencies.remote.clone());
match rpc::start_ipc(addr, handler) {
Err(IpcServerError::Io(io_error)) => Err(format!("RPC io error: {}", io_error)),
Err(any_error) => Err(format!("Rpc error: {:?}", any_error)),
Ok(server) => Ok(server)

View File

@@ -20,16 +20,16 @@ use std::cmp::PartialEq;
use std::str::FromStr;
use std::sync::Arc;
use util::RotatingLogger;
use jsonrpc_core::{MetaIoHandler};
use ethcore::miner::{Miner, ExternalMiner};
use ethcore::client::Client;
use ethcore::account_provider::AccountProvider;
use ethcore::snapshot::SnapshotService;
use ethsync::{ManageNetwork, SyncProvider};
use ethcore_rpc::{Extendable, NetworkSettings};
use ethcore_rpc::{Metadata, NetworkSettings};
pub use ethcore_rpc::SignerService;
use updater::Updater;
use hash_fetch::fetch::Client as FetchClient;
use parity_reactor::Remote;
#[derive(Debug, PartialEq, Clone, Eq, Hash)]
pub enum Api {
@@ -125,7 +125,6 @@ pub struct Dependencies {
pub dapps_interface: Option<String>,
pub dapps_port: Option<u16>,
pub fetch: FetchClient,
pub remote: Remote,
}
fn to_modules(apis: &[Api]) -> BTreeMap<String, String> {
@@ -170,18 +169,20 @@ impl ApiSet {
}
macro_rules! add_signing_methods {
($namespace:ident, $server:expr, $deps:expr) => {
let server = &$server;
let deps = &$deps;
if deps.signer_service.is_enabled() {
server.add_delegate($namespace::to_delegate(SigningQueueClient::new(&deps.signer_service, &deps.client, &deps.miner, &deps.secret_store)))
} else {
server.add_delegate($namespace::to_delegate(SigningUnsafeClient::new(&deps.client, &deps.secret_store, &deps.miner)))
($namespace:ident, $handler:expr, $deps:expr) => {
{
let handler = &mut $handler;
let deps = &$deps;
if deps.signer_service.is_enabled() {
handler.extend_with($namespace::to_delegate(SigningQueueClient::new(&deps.signer_service, &deps.client, &deps.miner, &deps.secret_store)))
} else {
handler.extend_with($namespace::to_delegate(SigningUnsafeClient::new(&deps.client, &deps.secret_store, &deps.miner)))
}
}
}
}
pub fn setup_rpc<T: Extendable>(server: T, deps: Arc<Dependencies>, apis: ApiSet) -> T {
pub fn setup_rpc(mut handler: MetaIoHandler<Metadata>, deps: Arc<Dependencies>, apis: ApiSet) -> MetaIoHandler<Metadata> {
use ethcore_rpc::v1::*;
// it's turned into vector, cause ont of the cases requires &[]
@@ -189,10 +190,10 @@ pub fn setup_rpc<T: Extendable>(server: T, deps: Arc<Dependencies>, apis: ApiSet
for api in &apis {
match *api {
Api::Web3 => {
server.add_delegate(Web3Client::new().to_delegate());
handler.extend_with(Web3Client::new().to_delegate());
},
Api::Net => {
server.add_delegate(NetClient::new(&deps.sync).to_delegate());
handler.extend_with(NetClient::new(&deps.sync).to_delegate());
},
Api::Eth => {
let client = EthClient::new(
@@ -207,25 +208,25 @@ pub fn setup_rpc<T: Extendable>(server: T, deps: Arc<Dependencies>, apis: ApiSet
send_block_number_in_get_work: !deps.geth_compatibility,
}
);
server.add_delegate(client.to_delegate());
handler.extend_with(client.to_delegate());
let filter_client = EthFilterClient::new(&deps.client, &deps.miner);
server.add_delegate(filter_client.to_delegate());
handler.extend_with(filter_client.to_delegate());
add_signing_methods!(EthSigning, server, deps);
add_signing_methods!(EthSigning, handler, deps);
},
Api::Personal => {
server.add_delegate(PersonalClient::new(&deps.secret_store, &deps.client, &deps.miner, deps.geth_compatibility).to_delegate());
handler.extend_with(PersonalClient::new(&deps.secret_store, &deps.client, &deps.miner, deps.geth_compatibility).to_delegate());
},
Api::Signer => {
server.add_delegate(SignerClient::new(&deps.secret_store, &deps.client, &deps.miner, &deps.signer_service).to_delegate());
handler.extend_with(SignerClient::new(&deps.secret_store, &deps.client, &deps.miner, &deps.signer_service).to_delegate());
},
Api::Parity => {
let signer = match deps.signer_service.is_enabled() {
true => Some(deps.signer_service.clone()),
false => None,
};
server.add_delegate(ParityClient::new(
handler.extend_with(ParityClient::new(
&deps.client,
&deps.miner,
&deps.sync,
@@ -239,32 +240,31 @@ pub fn setup_rpc<T: Extendable>(server: T, deps: Arc<Dependencies>, apis: ApiSet
deps.dapps_port,
).to_delegate());
add_signing_methods!(EthSigning, server, deps);
add_signing_methods!(ParitySigning, server, deps);
add_signing_methods!(EthSigning, handler, deps);
add_signing_methods!(ParitySigning, handler, deps);
},
Api::ParityAccounts => {
server.add_delegate(ParityAccountsClient::new(&deps.secret_store, &deps.client).to_delegate());
handler.extend_with(ParityAccountsClient::new(&deps.secret_store, &deps.client).to_delegate());
},
Api::ParitySet => {
server.add_delegate(ParitySetClient::new(
handler.extend_with(ParitySetClient::new(
&deps.client,
&deps.miner,
&deps.updater,
&deps.net_service,
deps.fetch.clone(),
deps.remote.clone(),
).to_delegate())
},
Api::Traces => {
server.add_delegate(TracesClient::new(&deps.client, &deps.miner).to_delegate())
handler.extend_with(TracesClient::new(&deps.client, &deps.miner).to_delegate())
},
Api::Rpc => {
let modules = to_modules(&apis);
server.add_delegate(RpcClient::new(modules).to_delegate());
handler.extend_with(RpcClient::new(modules).to_delegate());
}
}
}
server
handler
}
#[cfg(test)]

View File

@@ -347,7 +347,6 @@ pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) -> R
);
service.add_notify(updater.clone());
// set up dependencies for rpc servers
let signer_path = cmd.signer_conf.signer_path.clone();
let deps_for_rpc_apis = Arc::new(rpc_apis::Dependencies {
@@ -375,12 +374,12 @@ pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) -> R
false => None,
},
fetch: fetch.clone(),
remote: event_loop.remote(),
});
let dependencies = rpc::Dependencies {
panic_handler: panic_handler.clone(),
apis: deps_for_rpc_apis.clone(),
remote: event_loop.raw_remote(),
};
// start rpc servers
@@ -393,7 +392,7 @@ pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) -> R
apis: deps_for_rpc_apis.clone(),
client: client.clone(),
sync: sync_provider.clone(),
remote: event_loop.remote(),
remote: event_loop.raw_remote(),
fetch: fetch.clone(),
signer: deps_for_rpc_apis.signer_service.clone(),
};
@@ -403,6 +402,7 @@ pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) -> R
let signer_deps = signer::Dependencies {
panic_handler: panic_handler.clone(),
apis: deps_for_rpc_apis.clone(),
remote: event_loop.raw_remote(),
};
let signer_server = signer::start(cmd.signer_conf.clone(), signer_deps)?;

View File

@@ -22,8 +22,9 @@ use io::{ForwardPanic, PanicHandler};
use util::path::restrict_permissions_owner;
use rpc_apis;
use ethcore_signer as signer;
use helpers::replace_home;
use dir::default_data_path;
use helpers::replace_home;
use jsonrpc_core::reactor::{RpcHandler, Remote};
pub use ethcore_signer::Server as SignerServer;
const CODES_FILENAME: &'static str = "authcodes";
@@ -53,6 +54,7 @@ impl Default for Configuration {
pub struct Dependencies {
pub panic_handler: Arc<PanicHandler>,
pub apis: Arc<rpc_apis::Dependencies>,
pub remote: Remote,
}
pub struct NewToken {
@@ -124,8 +126,9 @@ fn do_start(conf: Configuration, deps: Dependencies) -> Result<SignerServer, Str
info!("If you do not intend this, exit now.");
}
let server = server.skip_origin_validation(conf.skip_origin_validation);
let server = rpc_apis::setup_rpc(server, deps.apis, rpc_apis::ApiSet::SafeContext);
server.start(addr)
let apis = rpc_apis::setup_rpc(Default::default(), deps.apis, rpc_apis::ApiSet::SafeContext);
let handler = RpcHandler::new(Arc::new(apis), deps.remote);
server.start(addr, handler)
};
match start_result {