Latest headers Pub-Sub (#5655)

* Signer subscription.

* Fixing RPC tests.

* Block Headers eth-pubsub.

* PubSub for light client.

* Fixing tests.

* Updating to proper jsonrpc version.

* Update to correct tests.

* Fixing tests.
This commit is contained in:
Tomasz Drwięga
2017-05-23 12:26:39 +02:00
committed by Arkadiy Paronyan
parent 92f5aa7e10
commit f38cc8e182
20 changed files with 551 additions and 96 deletions

View File

@@ -172,7 +172,7 @@ usage! {
or |c: &Config| otry!(c.rpc).interface.clone(),
flag_jsonrpc_cors: Option<String> = None,
or |c: &Config| otry!(c.rpc).cors.clone().map(Some),
flag_jsonrpc_apis: String = "web3,eth,net,parity,traces,rpc,secretstore",
flag_jsonrpc_apis: String = "web3,eth,pubsub,net,parity,traces,rpc,secretstore",
or |c: &Config| otry!(c.rpc).apis.as_ref().map(|vec| vec.join(",")),
flag_jsonrpc_hosts: String = "none",
or |c: &Config| otry!(c.rpc).hosts.as_ref().map(|vec| vec.join(",")),
@@ -186,7 +186,7 @@ usage! {
or |c: &Config| otry!(c.websockets).port.clone(),
flag_ws_interface: String = "local",
or |c: &Config| otry!(c.websockets).interface.clone(),
flag_ws_apis: String = "web3,eth,net,parity,traces,rpc,secretstore",
flag_ws_apis: String = "web3,eth,pubsub,net,parity,traces,rpc,secretstore",
or |c: &Config| otry!(c.websockets).apis.as_ref().map(|vec| vec.join(",")),
flag_ws_origins: String = "none",
or |c: &Config| otry!(c.websockets).origins.as_ref().map(|vec| vec.join(",")),
@@ -198,7 +198,7 @@ usage! {
or |c: &Config| otry!(c.ipc).disable.clone(),
flag_ipc_path: String = if cfg!(windows) { r"\\.\pipe\jsonrpc.ipc" } else { "$BASE/jsonrpc.ipc" },
or |c: &Config| otry!(c.ipc).path.clone(),
flag_ipc_apis: String = "web3,eth,net,parity,parity_accounts,traces,rpc,secretstore",
flag_ipc_apis: String = "web3,eth,pubsub,net,parity,parity_accounts,traces,rpc,secretstore",
or |c: &Config| otry!(c.ipc).apis.as_ref().map(|vec| vec.join(",")),
// DAPPS

View File

@@ -180,7 +180,7 @@ API and Console Options:
all (all interfaces) or local (default: {flag_ws_interface}).
--ws-apis APIS Specify the APIs available through the WebSockets
interface. APIS is a comma-delimited list of API
name. Possible name are web3, eth, net, personal,
name. Possible name are web3, eth, pubsub, net, personal,
parity, parity_set, traces, rpc, parity_accounts.
(default: {flag_ws_apis}).
--ws-origins URL Specify Origin header values allowed to connect.

View File

@@ -21,7 +21,7 @@ use dapps;
use parity_rpc::informant::{RpcStats, Middleware};
use parity_rpc::{self as rpc, HttpServerError, Metadata, Origin, DomainsValidation};
use helpers::parity_ipc_path;
use jsonrpc_core::{futures, MetaIoHandler};
use jsonrpc_core::MetaIoHandler;
use parity_reactor::TokioRemote;
use rpc_apis::{self, ApiSet};
@@ -129,53 +129,13 @@ impl rpc::IpcMetaExtractor<Metadata> for RpcExtractor {
}
}
struct Sender(rpc::ws::ws::Sender, futures::sync::mpsc::Receiver<String>);
impl futures::Future for Sender {
type Item = ();
type Error = ();
fn poll(&mut self) -> futures::Poll<Self::Item, Self::Error> {
use self::futures::Stream;
let item = self.1.poll()?;
match item {
futures::Async::NotReady => {
Ok(futures::Async::NotReady)
},
futures::Async::Ready(None) => {
Ok(futures::Async::Ready(()))
},
futures::Async::Ready(Some(val)) => {
if let Err(e) = self.0.send(val) {
warn!("Error sending a subscription update: {:?}", e);
}
self.poll()
},
}
}
}
struct WsRpcExtractor {
remote: TokioRemote,
}
impl WsRpcExtractor {
fn wrap_out(&self, out: rpc::ws::ws::Sender) -> futures::sync::mpsc::Sender<String> {
let (sender, receiver) = futures::sync::mpsc::channel(8);
self.remote.spawn(move |_| Sender(out, receiver));
sender
}
}
struct WsRpcExtractor;
impl rpc::ws::MetaExtractor<Metadata> for WsRpcExtractor {
fn extract(&self, req: &rpc::ws::RequestContext) -> Metadata {
let mut metadata = Metadata::default();
let id = req.session_id as u64;
metadata.origin = Origin::Ws(id.into());
metadata.session = Some(Arc::new(rpc::PubSubSession::new(
self.wrap_out(req.out.clone())
)));
metadata.session = Some(Arc::new(rpc::PubSubSession::new(req.sender())));
metadata
}
}
@@ -221,9 +181,7 @@ pub fn new_ws<D: rpc_apis::Dependencies>(
remote.clone(),
allowed_origins,
allowed_hosts,
WsRpcExtractor {
remote: remote,
},
WsRpcExtractor,
WsStats {
stats: deps.stats.clone(),
},

View File

@@ -18,7 +18,7 @@ use std::cmp::PartialEq;
use std::collections::BTreeMap;
use std::collections::HashSet;
use std::str::FromStr;
use std::sync::Arc;
use std::sync::{Arc, Weak};
pub use parity_rpc::SignerService;
@@ -46,6 +46,8 @@ pub enum Api {
Net,
/// Eth (Safe)
Eth,
/// Eth Pub-Sub (Safe)
EthPubSub,
/// Geth-compatible "personal" API (DEPRECATED; only used in `--geth` mode.)
Personal,
/// Signer - Confirm transactions in Signer (UNSAFE: Passwords, List of transactions)
@@ -74,6 +76,7 @@ impl FromStr for Api {
"web3" => Ok(Web3),
"net" => Ok(Net),
"eth" => Ok(Eth),
"pubsub" => Ok(EthPubSub),
"personal" => Ok(Personal),
"signer" => Ok(Signer),
"parity" => Ok(Parity),
@@ -153,6 +156,7 @@ fn to_modules(apis: &[Api]) -> BTreeMap<String, String> {
Api::Web3 => ("web3", "1.0"),
Api::Net => ("net", "1.0"),
Api::Eth => ("eth", "1.0"),
Api::EthPubSub => ("pubsub", "1.0"),
Api::Personal => ("personal", "1.0"),
Api::Signer => ("signer", "1.0"),
Api::Parity => ("parity", "1.0"),
@@ -254,6 +258,11 @@ impl FullDependencies {
add_signing_methods!(EthSigning, handler, self);
}
},
Api::EthPubSub => {
let client = EthPubSubClient::new(self.client.clone(), self.remote.clone());
self.client.add_notify(client.handler());
handler.extend_with(client.to_delegate());
},
Api::Personal => {
handler.extend_with(PersonalClient::new(&self.secret_store, dispatcher.clone(), self.geth_compatibility).to_delegate());
},
@@ -410,6 +419,13 @@ impl Dependencies for LightDependencies {
handler.extend_with(EthFilter::to_delegate(client));
add_signing_methods!(EthSigning, handler, self);
},
Api::EthPubSub => {
let client = EthPubSubClient::new(self.client.clone(), self.remote.clone());
self.client.add_listener(
Arc::downgrade(&client.handler()) as Weak<::light::client::LightChainNotify>
);
handler.extend_with(EthPubSub::to_delegate(client));
},
Api::Personal => {
let secret_store = Some(self.secret_store.clone());
handler.extend_with(PersonalClient::new(&secret_store, dispatcher.clone(), self.geth_compatibility).to_delegate());
@@ -471,7 +487,7 @@ impl ApiSet {
pub fn list_apis(&self) -> HashSet<Api> {
let mut public_list = vec![
Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Rpc, Api::SecretStore,
Api::Web3, Api::Net, Api::Eth, Api::EthPubSub, Api::Parity, Api::Rpc, Api::SecretStore,
].into_iter().collect();
match *self {
ApiSet::List(ref apis) => apis.clone(),
@@ -522,6 +538,7 @@ mod test {
assert_eq!(Api::Web3, "web3".parse().unwrap());
assert_eq!(Api::Net, "net".parse().unwrap());
assert_eq!(Api::Eth, "eth".parse().unwrap());
assert_eq!(Api::EthPubSub, "pubsub".parse().unwrap());
assert_eq!(Api::Personal, "personal".parse().unwrap());
assert_eq!(Api::Signer, "signer".parse().unwrap());
assert_eq!(Api::Parity, "parity".parse().unwrap());
@@ -547,7 +564,7 @@ mod test {
fn test_api_set_unsafe_context() {
let expected = vec![
// make sure this list contains only SAFE methods
Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc, Api::SecretStore
Api::Web3, Api::Net, Api::Eth, Api::EthPubSub, Api::Parity, Api::Traces, Api::Rpc, Api::SecretStore
].into_iter().collect();
assert_eq!(ApiSet::UnsafeContext.list_apis(), expected);
}
@@ -556,7 +573,7 @@ mod test {
fn test_api_set_ipc_context() {
let expected = vec![
// safe
Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc, Api::SecretStore,
Api::Web3, Api::Net, Api::Eth, Api::EthPubSub, Api::Parity, Api::Traces, Api::Rpc, Api::SecretStore,
// semi-safe
Api::ParityAccounts
].into_iter().collect();
@@ -567,7 +584,7 @@ mod test {
fn test_api_set_safe_context() {
let expected = vec![
// safe
Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc, Api::SecretStore,
Api::Web3, Api::Net, Api::Eth, Api::EthPubSub, Api::Parity, Api::Traces, Api::Rpc, Api::SecretStore,
// semi-safe
Api::ParityAccounts,
// Unsafe
@@ -579,7 +596,7 @@ mod test {
#[test]
fn test_all_apis() {
assert_eq!("all".parse::<ApiSet>().unwrap(), ApiSet::List(vec![
Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc, Api::SecretStore,
Api::Web3, Api::Net, Api::Eth, Api::EthPubSub, Api::Parity, Api::Traces, Api::Rpc, Api::SecretStore,
Api::ParityAccounts,
Api::ParitySet, Api::Signer,
Api::Personal
@@ -589,7 +606,7 @@ mod test {
#[test]
fn test_all_without_personal_apis() {
assert_eq!("personal,all,-personal".parse::<ApiSet>().unwrap(), ApiSet::List(vec![
Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc, Api::SecretStore,
Api::Web3, Api::Net, Api::Eth, Api::EthPubSub, Api::Parity, Api::Traces, Api::Rpc, Api::SecretStore,
Api::ParityAccounts,
Api::ParitySet, Api::Signer,
].into_iter().collect()));
@@ -598,7 +615,7 @@ mod test {
#[test]
fn test_safe_parsing() {
assert_eq!("safe".parse::<ApiSet>().unwrap(), ApiSet::List(vec![
Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc, Api::SecretStore,
Api::Web3, Api::Net, Api::Eth, Api::EthPubSub, Api::EthPubSub, Api::Parity, Api::Traces, Api::Rpc, Api::SecretStore,
].into_iter().collect()));
}
}

View File

@@ -101,7 +101,7 @@ pub fn execute(cmd: Configuration) -> Result<String, String> {
}
pub fn generate_token_and_url(conf: &Configuration) -> Result<NewToken, String> {
let code = generate_new_token(conf.signer_path.clone()).map_err(|err| format!("Error generating token: {:?}", err))?;
let code = generate_new_token(conf.signer_path.clone()).map_err(|err| format!("Error generating token: {}", err))?;
let auth_url = format!("http://{}:{}/#/auth?token={}", conf.interface, conf.port, code);
// And print in to the console
Ok(NewToken {