Merge branch 'master' into on-demand-priority

This commit is contained in:
Robert Habermeier
2017-05-10 12:18:30 +02:00
416 changed files with 24801 additions and 4853 deletions

View File

@@ -461,7 +461,7 @@ fn execute_export_state(cmd: ExportState) -> Result<(), String> {
let at = cmd.at;
let mut i = 0usize;
out.write_fmt(format_args!("{{ \"state\": [", )).expect("Couldn't write to stream.");
out.write_fmt(format_args!("{{ \"state\": {{", )).expect("Couldn't write to stream.");
loop {
let accounts = client.list_accounts(at, last.as_ref(), 1000).ok_or("Specified block not found")?;
if accounts.is_empty() {
@@ -498,13 +498,11 @@ fn execute_export_state(cmd: ExportState) -> Result<(), String> {
break;
}
let mut si = 0;
for key in keys.into_iter() {
if si != 0 {
if last_storage.is_some() {
out.write(b",").expect("Write error");
}
out.write_fmt(format_args!("\n\t\"0x{}\": \"0x{}\"", key.hex(), client.storage_at(&account, &key, at).unwrap_or_else(Default::default).hex())).expect("Write error");
si += 1;
last_storage = Some(key);
}
}
@@ -519,7 +517,7 @@ fn execute_export_state(cmd: ExportState) -> Result<(), String> {
last = Some(account);
}
}
out.write_fmt(format_args!("\n]}}")).expect("Write error");
out.write_fmt(format_args!("\n}}}}")).expect("Write error");
info!("Export completed.");
Ok(())
}

View File

@@ -19,7 +19,7 @@ use std::cmp::max;
const MIN_BC_CACHE_MB: u32 = 4;
const MIN_DB_CACHE_MB: u32 = 2;
const MIN_BLOCK_QUEUE_SIZE_LIMIT_MB: u32 = 16;
const DEFAULT_BLOCK_QUEUE_SIZE_LIMIT_MB: u32 = 50;
const DEFAULT_BLOCK_QUEUE_SIZE_LIMIT_MB: u32 = 40;
const DEFAULT_TRACE_CACHE_SIZE: u32 = 20;
const DEFAULT_STATE_CACHE_SIZE: u32 = 25;
@@ -41,7 +41,7 @@ pub struct CacheConfig {
impl Default for CacheConfig {
fn default() -> Self {
CacheConfig::new(64, 8, DEFAULT_BLOCK_QUEUE_SIZE_LIMIT_MB, DEFAULT_STATE_CACHE_SIZE)
CacheConfig::new(32, 8, DEFAULT_BLOCK_QUEUE_SIZE_LIMIT_MB, DEFAULT_STATE_CACHE_SIZE)
}
}
@@ -113,7 +113,7 @@ mod tests {
let config = CacheConfig::new_with_total_cache_size(200);
assert_eq!(config.db, 140);
assert_eq!(config.blockchain(), 20);
assert_eq!(config.queue(), 50);
assert_eq!(config.queue(), 40);
assert_eq!(config.state(), 30);
assert_eq!(config.jump_tables(), 10);
}
@@ -129,6 +129,6 @@ mod tests {
#[test]
fn test_cache_config_default() {
assert_eq!(CacheConfig::default(),
CacheConfig::new(64, 8, super::DEFAULT_BLOCK_QUEUE_SIZE_LIMIT_MB, super::DEFAULT_STATE_CACHE_SIZE));
CacheConfig::new(32, 8, super::DEFAULT_BLOCK_QUEUE_SIZE_LIMIT_MB, super::DEFAULT_STATE_CACHE_SIZE));
}
}

View File

@@ -7,6 +7,7 @@ release_track = "current"
public_node = false
no_download = false
no_consensus = false
no_persistent_txqueue = false
chain = "homestead"
base_path = "$HOME/.parity"
@@ -49,13 +50,21 @@ disable = false
port = 8545
interface = "local"
cors = "null"
apis = ["web3", "eth", "net", "parity", "traces", "rpc"]
apis = ["web3", "eth", "net", "parity", "traces", "rpc", "secretstore"]
hosts = ["none"]
[websockets]
disable = false
port = 8546
interface = "local"
origins = ["none"]
apis = ["web3", "eth", "net", "parity", "traces", "rpc", "secretstore"]
hosts = ["none"]
[ipc]
disable = false
path = "$HOME/.parity/jsonrpc.ipc"
apis = ["web3", "eth", "net", "parity", "parity_accounts", "personal", "traces", "rpc"]
apis = ["web3", "eth", "net", "parity", "parity_accounts", "personal", "traces", "rpc", "secretstore"]
[dapps]
disable = false

View File

@@ -24,6 +24,9 @@ allow_ips = "public"
reserved_only = true
reserved_peers = "./path/to/reserved_peers"
[websockets]
disable = true
origins = ["none"]
[rpc]
disable = true

View File

@@ -95,6 +95,8 @@ usage! {
flag_keys_path: String = "$BASE/keys", or |c: &Config| otry!(c.parity).keys_path.clone(),
flag_identity: String = "", or |c: &Config| otry!(c.parity).identity.clone(),
flag_light: bool = false, or |c: &Config| otry!(c.parity).light,
flag_no_persistent_txqueue: bool = false,
or |c: &Config| otry!(c.parity).no_persistent_txqueue,
// -- Account Options
flag_unlock: Option<String> = None,
@@ -163,19 +165,33 @@ 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",
flag_jsonrpc_apis: String = "web3,eth,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(",")),
flag_jsonrpc_threads: Option<usize> = None,
or |c: &Config| otry!(c.rpc).threads.map(Some),
// WS
flag_no_ws: bool = false,
or |c: &Config| otry!(c.websockets).disable.clone(),
flag_ws_port: u16 = 8546u16,
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",
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(",")),
flag_ws_hosts: String = "none",
or |c: &Config| otry!(c.websockets).hosts.as_ref().map(|vec| vec.join(",")),
// IPC
flag_no_ipc: bool = false,
or |c: &Config| otry!(c.ipc).disable.clone(),
flag_ipc_path: String = "$BASE/jsonrpc.ipc",
or |c: &Config| otry!(c.ipc).path.clone(),
flag_ipc_apis: String = "web3,eth,net,parity,parity_accounts,traces,rpc",
flag_ipc_apis: String = "web3,eth,net,parity,parity_accounts,traces,rpc,secretstore",
or |c: &Config| otry!(c.ipc).apis.as_ref().map(|vec| vec.join(",")),
// DAPPS
@@ -280,13 +296,13 @@ usage! {
or |c: &Config| otry!(c.footprint).pruning.clone(),
flag_pruning_history: u64 = 64u64,
or |c: &Config| otry!(c.footprint).pruning_history.clone(),
flag_pruning_memory: usize = 75usize,
flag_pruning_memory: usize = 32usize,
or |c: &Config| otry!(c.footprint).pruning_memory.clone(),
flag_cache_size_db: u32 = 64u32,
flag_cache_size_db: u32 = 32u32,
or |c: &Config| otry!(c.footprint).cache_size_db.clone(),
flag_cache_size_blocks: u32 = 8u32,
or |c: &Config| otry!(c.footprint).cache_size_blocks.clone(),
flag_cache_size_queue: u32 = 50u32,
flag_cache_size_queue: u32 = 40u32,
or |c: &Config| otry!(c.footprint).cache_size_queue.clone(),
flag_cache_size_state: u32 = 25u32,
or |c: &Config| otry!(c.footprint).cache_size_state.clone(),
@@ -331,7 +347,6 @@ usage! {
flag_no_color: bool = false,
or |c: &Config| otry!(c.misc).color.map(|c| !c).clone(),
// -- Legacy Options supported in configs
flag_dapps_port: Option<u16> = None,
or |c: &Config| otry!(c.dapps).port.clone().map(Some),
@@ -363,6 +378,7 @@ struct Config {
ui: Option<Ui>,
network: Option<Network>,
rpc: Option<Rpc>,
websockets: Option<Ws>,
ipc: Option<Ipc>,
dapps: Option<Dapps>,
secretstore: Option<SecretStore>,
@@ -391,6 +407,7 @@ struct Operating {
keys_path: Option<String>,
identity: Option<String>,
light: Option<bool>,
no_persistent_txqueue: Option<bool>,
}
#[derive(Default, Debug, PartialEq, RustcDecodable)]
@@ -440,6 +457,16 @@ struct Rpc {
threads: Option<usize>,
}
#[derive(Default, Debug, PartialEq, RustcDecodable)]
struct Ws {
disable: Option<bool>,
port: Option<u16>,
interface: Option<String>,
apis: Option<Vec<String>>,
origins: Option<Vec<String>>,
hosts: Option<Vec<String>>,
}
#[derive(Default, Debug, PartialEq, RustcDecodable)]
struct Ipc {
disable: Option<bool>,
@@ -554,7 +581,7 @@ struct Misc {
mod tests {
use super::{
Args, ArgsError,
Config, Operating, Account, Ui, Network, Rpc, Ipc, Dapps, Ipfs, Mining, Footprint,
Config, Operating, Account, Ui, Network, Ws, Rpc, Ipc, Dapps, Ipfs, Mining, Footprint,
Snapshots, VM, Misc, SecretStore,
};
use toml;
@@ -657,6 +684,7 @@ mod tests {
flag_keys_path: "$HOME/.parity/keys".into(),
flag_identity: "".into(),
flag_light: false,
flag_no_persistent_txqueue: false,
// -- Account Options
flag_unlock: Some("0xdeadbeefcafe0000000000000000000000000000".into()),
@@ -695,14 +723,22 @@ mod tests {
flag_jsonrpc_port: 8545u16,
flag_jsonrpc_interface: "local".into(),
flag_jsonrpc_cors: Some("null".into()),
flag_jsonrpc_apis: "web3,eth,net,parity,traces,rpc".into(),
flag_jsonrpc_apis: "web3,eth,net,parity,traces,rpc,secretstore".into(),
flag_jsonrpc_hosts: "none".into(),
flag_jsonrpc_threads: None,
// WS
flag_no_ws: false,
flag_ws_port: 8546u16,
flag_ws_interface: "local".into(),
flag_ws_apis: "web3,eth,net,parity,traces,rpc,secretstore".into(),
flag_ws_origins: "none".into(),
flag_ws_hosts: "none".into(),
// IPC
flag_no_ipc: false,
flag_ipc_path: "$HOME/.parity/jsonrpc.ipc".into(),
flag_ipc_apis: "web3,eth,net,parity,parity_accounts,personal,traces,rpc".into(),
flag_ipc_apis: "web3,eth,net,parity,parity_accounts,personal,traces,rpc,secretstore".into(),
// DAPPS
flag_dapps_path: "$HOME/.parity/dapps".into(),
@@ -868,6 +904,7 @@ mod tests {
keys_path: None,
identity: None,
light: None,
no_persistent_txqueue: None,
}),
account: Some(Account {
unlock: Some(vec!["0x1".into(), "0x2".into(), "0x3".into()]),
@@ -899,6 +936,14 @@ mod tests {
reserved_only: Some(true),
no_serve_light: None,
}),
websockets: Some(Ws {
disable: Some(true),
port: None,
interface: None,
apis: None,
origins: Some(vec!["none".into()]),
hosts: None,
}),
rpc: Some(Rpc {
disable: Some(true),
port: Some(8180),

View File

@@ -157,7 +157,28 @@ API and Console Options:
vectors. Special options: "all", "none",
(default: {flag_jsonrpc_hosts}).
--jsonrpc-threads THREADS Enables experimental faster implementation of JSON-RPC server.
Requires Dapps server to be disabled using --no-dapps. (default: {flag_jsonrpc_threads:?})
Requires Dapps server to be disabled
using --no-dapps. (default: {flag_jsonrpc_threads:?})
--no-ws Disable the WebSockets server. (default: {flag_no_ws})
--ws-port PORT Specify the port portion of the WebSockets server
(default: {flag_ws_port}).
--ws-interface IP Specify the hostname portion of the WebSockets
server, IP should be an interface's IP address, or
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,
parity, parity_set, traces, rpc, parity_accounts.
(default: {flag_ws_apis}).
--ws-origins URL Specify Origin header values allowed to connect.
Special options: "all", "none".
(default: {flag_ws_origins})
--ws-hosts HOSTS List of allowed Host header values. This option will
validate the Host header sent by the browser, it
is additional security against some attack
vectors. Special options: "all", "none",
(default: {flag_ws_hosts}).
--no-ipc Disable JSON-RPC over IPC service. (default: {flag_no_ipc})
--ipc-path PATH Specify custom path for JSON-RPC over IPC service
@@ -283,6 +304,9 @@ Sealing/Mining Options:
execution time limit. Also number of offending actions
have to reach the threshold within that time.
(default: {flag_tx_queue_ban_time} seconds)
--no-persistent-txqueue Don't save pending local transactions to disk to be
restored whenever the node restarts.
(default: {flag_no_persistent_txqueue}).
--remove-solved Move solved blocks from the work package queue
instead of cloning them. This gives a slightly
faster import speed, but means that extra solutions

View File

@@ -30,9 +30,9 @@ use ethcore::client::{VMType};
use ethcore::miner::{MinerOptions, Banning, StratumOptions};
use ethcore::verification::queue::VerifierSettings;
use rpc::{IpcConfiguration, HttpConfiguration};
use rpc::{IpcConfiguration, HttpConfiguration, WsConfiguration};
use rpc_apis::ApiSet;
use ethcore_rpc::NetworkSettings;
use parity_rpc::NetworkSettings;
use cache::CacheConfig;
use helpers::{to_duration, to_mode, to_block_id, to_u256, to_pending_set, to_price, replace_home, replace_home_for_db,
geth_ipc_path, parity_ipc_path, to_bootnodes, to_addresses, to_address, to_gas_limit, to_queue_strategy};
@@ -114,6 +114,7 @@ impl Configuration {
};
let update_policy = self.update_policy()?;
let logger_config = self.logger_config();
let ws_conf = self.ws_config()?;
let http_conf = self.http_config()?;
let ipc_conf = self.ipc_config()?;
let net_conf = self.net_config()?;
@@ -352,6 +353,7 @@ impl Configuration {
daemon: daemon,
logger_config: logger_config.clone(),
miner_options: miner_options,
ws_conf: ws_conf,
http_conf: http_conf,
ipc_conf: ipc_conf,
net_conf: net_conf,
@@ -386,6 +388,7 @@ impl Configuration {
verifier_settings: verifier_settings,
serve_light: !self.args.flag_no_serve_light,
light: self.args.flag_light,
no_persistent_txqueue: self.args.flag_no_persistent_txqueue,
};
Cmd::Run(run_cmd)
};
@@ -638,7 +641,7 @@ impl Configuration {
info!(
"Using a fixed conversion rate of Ξ1 = {} ({} wei/gas)",
Colour::White.bold().paint(format!("US${}", usd_per_eth)),
Colour::White.bold().paint(format!("US${:.2}", usd_per_eth)),
Colour::Yellow.bold().paint(format!("{}", wei_per_gas))
);
@@ -757,6 +760,14 @@ impl Configuration {
Self::hosts(&self.args.flag_jsonrpc_hosts)
}
fn ws_hosts(&self) -> Option<Vec<String>> {
Self::hosts(&self.args.flag_ws_hosts)
}
fn ws_origins(&self) -> Option<Vec<String>> {
Self::hosts(&self.args.flag_ws_origins)
}
fn ipfs_hosts(&self) -> Option<Vec<String>> {
Self::hosts(&self.args.flag_ipfs_api_hosts)
}
@@ -801,6 +812,19 @@ impl Configuration {
Ok(conf)
}
fn ws_config(&self) -> Result<WsConfiguration, String> {
let conf = WsConfiguration {
enabled: self.ws_enabled(),
interface: self.ws_interface(),
port: self.args.flag_ws_port,
apis: self.args.flag_ws_apis.parse()?,
hosts: self.ws_hosts(),
origins: self.ws_origins()
};
Ok(conf)
}
fn network_settings(&self) -> NetworkSettings {
NetworkSettings {
name: self.args.flag_identity.clone(),
@@ -913,6 +937,10 @@ impl Configuration {
Self::interface(&self.network_settings().rpc_interface)
}
fn ws_interface(&self) -> String {
Self::interface(&self.args.flag_ws_interface)
}
fn ipfs_interface(&self) -> String {
Self::interface(&self.args.flag_ipfs_api_interface)
}
@@ -965,6 +993,10 @@ impl Configuration {
!self.args.flag_jsonrpc_off && !self.args.flag_no_jsonrpc
}
fn ws_enabled(&self) -> bool {
!self.args.flag_no_ws
}
fn dapps_enabled(&self) -> bool {
!self.args.flag_dapps_off && !self.args.flag_no_dapps && self.rpc_enabled() && cfg!(feature = "dapps")
}
@@ -1000,7 +1032,7 @@ impl Configuration {
mod tests {
use super::*;
use cli::Args;
use ethcore_rpc::NetworkSettings;
use parity_rpc::NetworkSettings;
use ethcore::client::{VMType, BlockId};
use ethcore::miner::{MinerOptions, PrioritizationStrategy};
use helpers::{default_network_config};
@@ -1093,7 +1125,7 @@ mod tests {
format: Default::default(),
pruning: Default::default(),
pruning_history: 64,
pruning_memory: 75,
pruning_memory: 32,
compaction: Default::default(),
wal: true,
tracing: Default::default(),
@@ -1116,7 +1148,7 @@ mod tests {
file_path: Some("blockchain.json".into()),
pruning: Default::default(),
pruning_history: 64,
pruning_memory: 75,
pruning_memory: 32,
format: Default::default(),
compaction: Default::default(),
wal: true,
@@ -1139,7 +1171,7 @@ mod tests {
file_path: Some("state.json".into()),
pruning: Default::default(),
pruning_history: 64,
pruning_memory: 75,
pruning_memory: 32,
format: Default::default(),
compaction: Default::default(),
wal: true,
@@ -1164,7 +1196,7 @@ mod tests {
file_path: Some("blockchain.json".into()),
pruning: Default::default(),
pruning_history: 64,
pruning_memory: 75,
pruning_memory: 32,
format: Some(DataFormat::Hex),
compaction: Default::default(),
wal: true,
@@ -1200,10 +1232,11 @@ mod tests {
spec: Default::default(),
pruning: Default::default(),
pruning_history: 64,
pruning_memory: 75,
pruning_memory: 32,
daemon: None,
logger_config: Default::default(),
miner_options: Default::default(),
ws_conf: Default::default(),
http_conf: Default::default(),
ipc_conf: Default::default(),
net_conf: default_network_config(),
@@ -1238,6 +1271,7 @@ mod tests {
verifier_settings: Default::default(),
serve_light: true,
light: false,
no_persistent_txqueue: false,
};
expected.secretstore_conf.enabled = cfg!(feature = "secretstore");
assert_eq!(conf.into_command().unwrap().cmd, Cmd::Run(expected));
@@ -1337,13 +1371,13 @@ mod tests {
let conf0 = parse(&["parity"]);
let conf1 = parse(&["parity", "--jsonrpc-hosts", "none"]);
let conf2 = parse(&["parity", "--jsonrpc-hosts", "all"]);
let conf3 = parse(&["parity", "--jsonrpc-hosts", "ethcore.io,something.io"]);
let conf3 = parse(&["parity", "--jsonrpc-hosts", "parity.io,something.io"]);
// then
assert_eq!(conf0.rpc_hosts(), Some(Vec::new()));
assert_eq!(conf1.rpc_hosts(), Some(Vec::new()));
assert_eq!(conf2.rpc_hosts(), None);
assert_eq!(conf3.rpc_hosts(), Some(vec!["ethcore.io".into(), "something.io".into()]));
assert_eq!(conf3.rpc_hosts(), Some(vec!["parity.io".into(), "something.io".into()]));
}
#[test]
@@ -1354,13 +1388,13 @@ mod tests {
let conf0 = parse(&["parity"]);
let conf1 = parse(&["parity", "--ipfs-api-hosts", "none"]);
let conf2 = parse(&["parity", "--ipfs-api-hosts", "all"]);
let conf3 = parse(&["parity", "--ipfs-api-hosts", "ethcore.io,something.io"]);
let conf3 = parse(&["parity", "--ipfs-api-hosts", "parity.io,something.io"]);
// then
assert_eq!(conf0.ipfs_hosts(), Some(Vec::new()));
assert_eq!(conf1.ipfs_hosts(), Some(Vec::new()));
assert_eq!(conf2.ipfs_hosts(), None);
assert_eq!(conf3.ipfs_hosts(), Some(vec!["ethcore.io".into(), "something.io".into()]));
assert_eq!(conf3.ipfs_hosts(), Some(vec!["parity.io".into(), "something.io".into()]));
}
#[test]
@@ -1370,12 +1404,12 @@ mod tests {
// when
let conf0 = parse(&["parity"]);
let conf1 = parse(&["parity", "--ipfs-api-cors", "*"]);
let conf2 = parse(&["parity", "--ipfs-api-cors", "http://ethcore.io,http://something.io"]);
let conf2 = parse(&["parity", "--ipfs-api-cors", "http://parity.io,http://something.io"]);
// then
assert_eq!(conf0.ipfs_cors(), None);
assert_eq!(conf1.ipfs_cors(), Some(vec!["*".into()]));
assert_eq!(conf2.ipfs_cors(), Some(vec!["http://ethcore.io".into(),"http://something.io".into()]));
assert_eq!(conf2.ipfs_cors(), Some(vec!["http://parity.io".into(),"http://something.io".into()]));
}
#[test]

View File

@@ -109,7 +109,7 @@ pub use self::server::{SyncStatus, Middleware, dapps_middleware};
mod server {
use super::Dependencies;
use std::path::PathBuf;
use ethcore_rpc::{hyper, RequestMiddleware, RequestMiddlewareAction};
use parity_rpc::{hyper, RequestMiddleware, RequestMiddlewareAction};
pub type SyncStatus = Fn() -> bool;

View File

@@ -30,8 +30,8 @@ use ethcore::service::ClientIoMessage;
use ethcore::snapshot::service::Service as SnapshotService;
use ethcore::snapshot::{RestorationStatus, SnapshotService as SS};
use number_prefix::{binary_prefix, Standalone, Prefixed};
use ethcore_rpc::{is_major_importing};
use ethcore_rpc::informant::RpcStats;
use parity_rpc::{is_major_importing};
use parity_rpc::informant::RpcStats;
pub struct Informant {
report: RwLock<Option<ClientReport>>,

View File

@@ -51,18 +51,18 @@ extern crate ethcore_ipc_hypervisor as hypervisor;
extern crate ethcore_ipc_nano as nanoipc;
extern crate ethcore_light as light;
extern crate ethcore_logger;
extern crate ethcore_rpc;
extern crate ethcore_signer;
extern crate ethcore_util as util;
extern crate ethkey;
extern crate ethsync;
extern crate parity_hash_fetch as hash_fetch;
extern crate parity_ipfs_api;
extern crate parity_reactor;
extern crate parity_updater as updater;
extern crate parity_local_store as local_store;
extern crate rpc_cli;
extern crate parity_reactor;
extern crate parity_rpc;
extern crate parity_updater as updater;
extern crate path;
extern crate rpc_cli;
#[macro_use]
extern crate log as rlog;

View File

@@ -14,19 +14,20 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::{io, fmt};
use std::io;
use std::sync::Arc;
use dapps;
use dir::default_data_path;
use ethcore_rpc::informant::{RpcStats, Middleware};
use ethcore_rpc::{self as rpc, HttpServerError, Metadata, Origin, AccessControlAllowOrigin, Host};
use parity_rpc::informant::{RpcStats, Middleware};
use parity_rpc::{self as rpc, HttpServerError, Metadata, Origin, DomainsValidation};
use helpers::parity_ipc_path;
use jsonrpc_core::MetaIoHandler;
use jsonrpc_core::{futures, MetaIoHandler};
use parity_reactor::TokioRemote;
use rpc_apis::{self, ApiSet};
pub use ethcore_rpc::{IpcServer, HttpServer, RequestMiddleware};
pub use parity_rpc::{IpcServer, HttpServer, RequestMiddleware};
pub use parity_rpc::ws::Server as WsServer;
#[derive(Debug, Clone, PartialEq)]
pub struct HttpConfiguration {
@@ -71,12 +72,25 @@ impl Default for IpcConfiguration {
}
}
impl fmt::Display for IpcConfiguration {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.enabled {
write!(f, "endpoint address [{}], api list [{:?}]", self.socket_addr, self.apis)
} else {
write!(f, "disabled")
#[derive(Debug, PartialEq)]
pub struct WsConfiguration {
pub enabled: bool,
pub interface: String,
pub port: u16,
pub apis: ApiSet,
pub origins: Option<Vec<String>>,
pub hosts: Option<Vec<String>>,
}
impl Default for WsConfiguration {
fn default() -> Self {
WsConfiguration {
enabled: true,
interface: "127.0.0.1".into(),
port: 8546,
apis: ApiSet::UnsafeContext,
origins: Some(Vec::new()),
hosts: Some(Vec::new()),
}
}
}
@@ -112,12 +126,115 @@ 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
}
}
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
}
}
struct WsStats {
stats: Arc<RpcStats>,
}
impl rpc::ws::SessionStats for WsStats {
fn open_session(&self, _id: rpc::ws::SessionId) {
self.stats.open_session()
}
fn close_session(&self, _id: rpc::ws::SessionId) {
self.stats.close_session()
}
}
fn setup_apis<D>(apis: ApiSet, deps: &Dependencies<D>) -> MetaIoHandler<Metadata, Middleware<D::Notifier>>
where D: rpc_apis::Dependencies
{
rpc_apis::setup_rpc(deps.stats.clone(), &*deps.apis, apis)
}
pub fn new_ws<D: rpc_apis::Dependencies>(
conf: WsConfiguration,
deps: &Dependencies<D>,
) -> Result<Option<WsServer>, String> {
if !conf.enabled {
return Ok(None);
}
let url = format!("{}:{}", conf.interface, conf.port);
let addr = url.parse().map_err(|_| format!("Invalid WebSockets listen host/port given: {}", url))?;
let handler = setup_apis(conf.apis, deps);
let remote = deps.remote.clone();
let allowed_origins = into_domains(conf.origins);
let allowed_hosts = into_domains(conf.hosts);
let start_result = rpc::start_ws(
&addr,
handler,
remote.clone(),
allowed_origins,
allowed_hosts,
WsRpcExtractor {
remote: remote,
},
WsStats {
stats: deps.stats.clone(),
},
);
match start_result {
Ok(server) => Ok(Some(server)),
Err(rpc::ws::Error::Io(ref err)) if err.kind() == io::ErrorKind::AddrInUse => Err(
format!("WebSockets address {} is already in use, make sure that another instance of an Ethereum client is not running or change the address using the --ws-port and --ws-interface options.", url)
),
Err(e) => Err(format!("WebSockets error: {:?}", e)),
}
}
pub fn new_http<D: rpc_apis::Dependencies>(
conf: HttpConfiguration,
deps: &Dependencies<D>,
@@ -128,17 +245,17 @@ pub fn new_http<D: rpc_apis::Dependencies>(
}
let url = format!("{}:{}", conf.interface, conf.port);
let addr = url.parse().map_err(|_| format!("Invalid JSONRPC listen host/port given: {}", url))?;
let addr = url.parse().map_err(|_| format!("Invalid HTTP JSON-RPC listen host/port given: {}", url))?;
let handler = setup_apis(conf.apis, deps);
let remote = deps.remote.clone();
let cors_domains: Option<Vec<_>> = conf.cors.map(|domains| domains.into_iter().map(AccessControlAllowOrigin::from).collect());
let allowed_hosts: Option<Vec<_>> = conf.hosts.map(|hosts| hosts.into_iter().map(Host::from).collect());
let cors_domains = into_domains(conf.cors);
let allowed_hosts = into_domains(conf.hosts);
let start_result = rpc::start_http(
&addr,
cors_domains.into(),
allowed_hosts.into(),
cors_domains,
allowed_hosts,
handler,
remote,
RpcExtractor,
@@ -153,16 +270,17 @@ pub fn new_http<D: rpc_apis::Dependencies>(
match start_result {
Ok(server) => Ok(Some(server)),
Err(HttpServerError::Io(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)
),
_ => Err(format!("RPC io error: {}", err)),
},
Err(e) => Err(format!("RPC error: {:?}", e)),
Err(HttpServerError::Io(ref err)) if err.kind() == io::ErrorKind::AddrInUse => Err(
format!("HTTP 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)
),
Err(e) => Err(format!("HTTP error: {:?}", e)),
}
}
fn into_domains<T: From<String>>(items: Option<Vec<String>>) -> DomainsValidation<T> {
items.map(|vals| vals.into_iter().map(T::from).collect()).into()
}
pub fn new_ipc<D: rpc_apis::Dependencies>(
conf: IpcConfiguration,
dependencies: &Dependencies<D>
@@ -170,18 +288,26 @@ pub fn new_ipc<D: rpc_apis::Dependencies>(
if !conf.enabled {
return Ok(None);
}
let handler = setup_apis(conf.apis, dependencies);
let remote = dependencies.remote.clone();
match rpc::start_ipc(&conf.socket_addr, handler, remote, RpcExtractor) {
let ipc = rpc::start_ipc(
&conf.socket_addr,
handler,
remote,
RpcExtractor,
);
match ipc {
Ok(server) => Ok(Some(server)),
Err(io_error) => Err(format!("RPC io error: {}", io_error)),
Err(io_error) => Err(format!("IPC error: {}", io_error)),
}
}
#[cfg(test)]
mod tests {
use super::RpcExtractor;
use ethcore_rpc::{HttpMetaExtractor, Origin};
use parity_rpc::{HttpMetaExtractor, Origin};
#[test]
fn should_extract_rpc_origin() {

View File

@@ -20,22 +20,23 @@ use std::collections::HashSet;
use std::str::FromStr;
use std::sync::Arc;
pub use ethcore_rpc::SignerService;
pub use parity_rpc::SignerService;
use ethcore::account_provider::AccountProvider;
use ethcore::client::Client;
use ethcore::miner::{Miner, ExternalMiner};
use ethcore::snapshot::SnapshotService;
use ethcore_rpc::{Metadata, NetworkSettings};
use ethcore_rpc::informant::{ActivityNotifier, Middleware, RpcStats, ClientNotifier};
use ethcore_rpc::dispatch::{FullDispatcher, LightDispatcher};
use parity_rpc::{Metadata, NetworkSettings};
use parity_rpc::informant::{ActivityNotifier, Middleware, RpcStats, ClientNotifier};
use parity_rpc::dispatch::{FullDispatcher, LightDispatcher};
use ethsync::{ManageNetwork, SyncProvider, LightSync};
use hash_fetch::fetch::Client as FetchClient;
use jsonrpc_core::{MetaIoHandler};
use jsonrpc_core::{self as core, MetaIoHandler};
use light::{TransactionQueue as LightTransactionQueue, Cache as LightDataCache};
use updater::Updater;
use util::{Mutex, RwLock};
use ethcore_logger::RotatingLogger;
use parity_reactor;
#[derive(Debug, PartialEq, Clone, Eq, Hash)]
pub enum Api {
@@ -59,6 +60,8 @@ pub enum Api {
Traces,
/// Rpc (Safe)
Rpc,
/// SecretStore (Safe)
SecretStore,
}
impl FromStr for Api {
@@ -78,6 +81,7 @@ impl FromStr for Api {
"parity_set" => Ok(ParitySet),
"traces" => Ok(Traces),
"rpc" => Ok(Rpc),
"secretstore" => Ok(SecretStore),
api => Err(format!("Unknown api: {}", api))
}
}
@@ -156,6 +160,7 @@ fn to_modules(apis: &[Api]) -> BTreeMap<String, String> {
Api::ParitySet => ("parity_set", "1.0"),
Api::Traces => ("traces", "1.0"),
Api::Rpc => ("rpc", "1.0"),
Api::SecretStore => ("secretstore", "1.0"),
};
modules.insert(name.into(), version.into());
}
@@ -191,19 +196,17 @@ pub struct FullDependencies {
pub dapps_interface: Option<String>,
pub dapps_port: Option<u16>,
pub fetch: FetchClient,
pub remote: parity_reactor::Remote,
}
impl Dependencies for FullDependencies {
type Notifier = ClientNotifier;
fn activity_notifier(&self) -> ClientNotifier {
ClientNotifier {
client: self.client.clone(),
}
}
fn extend_with_set(&self, handler: &mut MetaIoHandler<Metadata, Middleware>, apis: &[Api]) {
use ethcore_rpc::v1::*;
impl FullDependencies {
fn extend_api<T: core::Middleware<Metadata>>(
&self,
handler: &mut MetaIoHandler<Metadata, T>,
apis: &[Api],
for_generic_pubsub: bool,
) {
use parity_rpc::v1::*;
macro_rules! add_signing_methods {
($namespace:ident, $handler:expr, $deps:expr) => {
@@ -244,10 +247,12 @@ impl Dependencies for FullDependencies {
);
handler.extend_with(client.to_delegate());
let filter_client = EthFilterClient::new(self.client.clone(), self.miner.clone());
handler.extend_with(filter_client.to_delegate());
if !for_generic_pubsub {
let filter_client = EthFilterClient::new(self.client.clone(), self.miner.clone());
handler.extend_with(filter_client.to_delegate());
add_signing_methods!(EthSigning, handler, self);
add_signing_methods!(EthSigning, handler, self);
}
},
Api::Personal => {
handler.extend_with(PersonalClient::new(&self.secret_store, dispatcher.clone(), self.geth_compatibility).to_delegate());
@@ -274,8 +279,14 @@ impl Dependencies for FullDependencies {
self.dapps_port,
).to_delegate());
add_signing_methods!(EthSigning, handler, self);
add_signing_methods!(ParitySigning, handler, self);
if !for_generic_pubsub {
let mut rpc = MetaIoHandler::default();
self.extend_api(&mut rpc, apis, true);
handler.extend_with(PubSubClient::new(rpc, self.remote.clone()).to_delegate());
add_signing_methods!(EthSigning, handler, self);
add_signing_methods!(ParitySigning, handler, self);
}
},
Api::ParityAccounts => {
handler.extend_with(ParityAccountsClient::new(&self.secret_store).to_delegate());
@@ -295,12 +306,29 @@ impl Dependencies for FullDependencies {
Api::Rpc => {
let modules = to_modules(&apis);
handler.extend_with(RpcClient::new(modules).to_delegate());
}
},
Api::SecretStore => {
handler.extend_with(SecretStoreClient::new(&self.secret_store).to_delegate());
},
}
}
}
}
impl Dependencies for FullDependencies {
type Notifier = ClientNotifier;
fn activity_notifier(&self) -> ClientNotifier {
ClientNotifier {
client: self.client.clone(),
}
}
fn extend_with_set(&self, handler: &mut MetaIoHandler<Metadata, Middleware<Self::Notifier>>, apis: &[Api]) {
self.extend_api(handler, apis, false)
}
}
/// Light client notifier. Doesn't do anything yet, but might in the future.
pub struct LightClientNotifier;
@@ -331,7 +359,7 @@ impl Dependencies for LightDependencies {
fn activity_notifier(&self) -> Self::Notifier { LightClientNotifier }
fn extend_with_set(&self, handler: &mut MetaIoHandler<Metadata, Middleware<Self::Notifier>>, apis: &[Api]) {
use ethcore_rpc::v1::*;
use parity_rpc::v1::*;
let dispatcher = LightDispatcher::new(
self.sync.clone(),
@@ -395,6 +423,7 @@ impl Dependencies for LightDependencies {
false => None,
};
handler.extend_with(light::ParityClient::new(
self.client.clone(),
Arc::new(dispatcher.clone()),
self.secret_store.clone(),
self.logger.clone(),
@@ -423,7 +452,11 @@ impl Dependencies for LightDependencies {
Api::Rpc => {
let modules = to_modules(&apis);
handler.extend_with(RpcClient::new(modules).to_delegate());
}
},
Api::SecretStore => {
let secret_store = Some(self.secret_store.clone());
handler.extend_with(SecretStoreClient::new(&secret_store).to_delegate());
},
}
}
}
@@ -437,7 +470,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::Web3, Api::Net, Api::Eth, Api::Parity, Api::Rpc, Api::SecretStore,
].into_iter().collect();
match *self {
ApiSet::List(ref apis) => apis.clone(),
@@ -495,6 +528,7 @@ mod test {
assert_eq!(Api::ParitySet, "parity_set".parse().unwrap());
assert_eq!(Api::Traces, "traces".parse().unwrap());
assert_eq!(Api::Rpc, "rpc".parse().unwrap());
assert_eq!(Api::SecretStore, "secretstore".parse().unwrap());
assert!("rp".parse::<Api>().is_err());
}
@@ -512,7 +546,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::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc, Api::SecretStore
].into_iter().collect();
assert_eq!(ApiSet::UnsafeContext.list_apis(), expected);
}
@@ -521,7 +555,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::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc, Api::SecretStore,
// semi-safe
Api::ParityAccounts
].into_iter().collect();
@@ -532,7 +566,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::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc, Api::SecretStore,
// semi-safe
Api::ParityAccounts,
// Unsafe
@@ -544,7 +578,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::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc, Api::SecretStore,
Api::ParityAccounts,
Api::ParitySet, Api::Signer,
Api::Personal
@@ -554,7 +588,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::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc, Api::SecretStore,
Api::ParityAccounts,
Api::ParitySet, Api::Signer,
].into_iter().collect()));
@@ -563,7 +597,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::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc, Api::SecretStore,
].into_iter().collect()));
}
}

View File

@@ -18,7 +18,7 @@ use std::sync::Arc;
use std::net::{TcpListener};
use ctrlc::CtrlC;
use fdlimit::raise_fd_limit;
use ethcore_rpc::{NetworkSettings, informant, is_major_importing};
use parity_rpc::{NetworkSettings, informant, is_major_importing};
use ethsync::NetworkConfiguration;
use util::{Colour, version, Mutex, Condvar};
use io::{MayPanic, ForwardPanic, PanicHandler};
@@ -80,6 +80,7 @@ pub struct RunCmd {
pub daemon: Option<String>,
pub logger_config: LogConfig,
pub miner_options: MinerOptions,
pub ws_conf: rpc::WsConfiguration,
pub http_conf: rpc::HttpConfiguration,
pub ipc_conf: rpc::IpcConfiguration,
pub net_conf: NetworkConfiguration,
@@ -114,6 +115,7 @@ pub struct RunCmd {
pub verifier_settings: VerifierSettings,
pub serve_light: bool,
pub light: bool,
pub no_persistent_txqueue: bool,
}
pub fn open_ui(signer_conf: &signer::Configuration) -> Result<(), String> {
@@ -141,15 +143,20 @@ pub fn open_dapp(dapps_conf: &dapps::Configuration, rpc_conf: &rpc::HttpConfigur
// node info fetcher for the local store.
struct FullNodeInfo {
miner: Arc<Miner>, // TODO: only TXQ needed, just use that after decoupling.
miner: Option<Arc<Miner>>, // TODO: only TXQ needed, just use that after decoupling.
}
impl ::local_store::NodeInfo for FullNodeInfo {
fn pending_transactions(&self) -> Vec<::ethcore::transaction::PendingTransaction> {
let local_txs = self.miner.local_transactions();
self.miner.pending_transactions()
let miner = match self.miner.as_ref() {
Some(m) => m,
None => return Vec::new(),
};
let local_txs = miner.local_transactions();
miner.pending_transactions()
.into_iter()
.chain(self.miner.future_transactions())
.chain(miner.future_transactions())
.filter(|tx| local_txs.contains_key(&tx.hash()))
.collect()
}
@@ -294,7 +301,8 @@ fn execute_light(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) ->
};
// start rpc servers
let _http_server = rpc::new_http(cmd.http_conf, &dependencies, None)?;
let _ws_server = rpc::new_ws(cmd.ws_conf, &dependencies)?;
let _http_server = rpc::new_http(cmd.http_conf.clone(), &dependencies, None)?;
let _ipc_server = rpc::new_ipc(cmd.ipc_conf, &dependencies)?;
// the signer server
@@ -512,11 +520,22 @@ pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) -> R
let store = {
let db = service.db();
let node_info = FullNodeInfo {
miner: miner.clone(),
miner: match cmd.no_persistent_txqueue {
true => None,
false => Some(miner.clone()),
}
};
let store = ::local_store::create(db, ::ethcore::db::COL_NODE_INFO, node_info);
if cmd.no_persistent_txqueue {
info!("Running without a persistent transaction queue.");
if let Err(e) = store.clear() {
warn!("Error clearing persistent transaction queue: {}", e);
}
}
// re-queue pending transactions.
match store.pending_transactions() {
Ok(pending) => {
@@ -611,6 +630,7 @@ 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 {
@@ -635,6 +655,7 @@ pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) -> R
let dapps_middleware = dapps::new(cmd.dapps_conf.clone(), dapps_deps)?;
// start rpc servers
let ws_server = rpc::new_ws(cmd.ws_conf, &dependencies)?;
let http_server = rpc::new_http(cmd.http_conf.clone(), &dependencies, dapps_middleware)?;
let ipc_server = rpc::new_ipc(cmd.ipc_conf, &dependencies)?;
@@ -715,7 +736,7 @@ pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) -> R
let restart = wait_for_exit(panic_handler, Some(updater), Some(client), can_restart);
// drop this stuff as soon as exit detected.
drop((http_server, ipc_server, signer_server, secretstore_key_server, ipfs_server, event_loop));
drop((ws_server, http_server, ipc_server, signer_server, secretstore_key_server, ipfs_server, event_loop));
info!("Finishing work, please wait...");

View File

@@ -96,9 +96,6 @@ mod server {
port: port,
})).collect(),
allow_connecting_to_higher_nodes: true,
encryption_config: ethcore_secretstore::EncryptionConfiguration {
key_check_timeout_ms: 1000,
},
},
};

View File

@@ -22,8 +22,8 @@ pub use ethcore_signer::Server as SignerServer;
use ansi_term::Colour;
use dir::default_data_path;
use ethcore_rpc::informant::RpcStats;
use ethcore_rpc::{self, ConfirmationsQueue};
use parity_rpc::informant::RpcStats;
use parity_rpc::{self, ConfirmationsQueue};
use ethcore_signer as signer;
use helpers::replace_home;
use parity_reactor::TokioRemote;
@@ -69,10 +69,10 @@ pub struct NewToken {
#[derive(Debug, Default, Clone)]
pub struct StandardExtractor;
impl signer::MetaExtractor<ethcore_rpc::Metadata> for StandardExtractor {
fn extract_metadata(&self, session: &H256) -> ethcore_rpc::Metadata {
let mut metadata = ethcore_rpc::Metadata::default();
metadata.origin = ethcore_rpc::Origin::Signer((*session).into());
impl signer::MetaExtractor<parity_rpc::Metadata> for StandardExtractor {
fn extract_metadata(&self, session: &H256) -> parity_rpc::Metadata {
let mut metadata = parity_rpc::Metadata::default();
metadata.origin = parity_rpc::Origin::Signer((*session).into());
metadata
}
}