Merge with master

This commit is contained in:
Robert Habermeier
2016-06-29 14:46:29 +02:00
parent 3850ee64bb
commit 49024a4f28
235 changed files with 36456 additions and 4814 deletions

View File

@@ -25,10 +25,12 @@ Usage:
parity daemon <pid-file> [options]
parity account (new | list ) [options]
parity account import <path>... [options]
parity wallet import <path> --password FILE [options]
parity import [ <file> ] [options]
parity export [ <file> ] [options]
parity signer new-token [options]
parity [options]
parity ui [options]
Protocol Options:
--chain CHAIN Specify the blockchain type. CHAIN may be either a
@@ -40,6 +42,12 @@ Protocol Options:
--keys-path PATH Specify the path for JSON key files to be found
[default: $HOME/.parity/keys].
--identity NAME Specify your node's name.
--fork POLICY Specifies the client's fork policy. POLICY must be
one of:
dogmatic - sticks rigidly to the standard chain.
dao-soft - votes for the DAO-rescue soft-fork.
normal - goes with whatever fork is decided but
votes for none. [default: normal].
Account Options:
--unlock ACCOUNTS Unlock ACCOUNTS for the duration of the execution.
@@ -52,6 +60,7 @@ Account Options:
--no-import-keys Do not import keys from legacy clients.
Networking Options:
--no-network Disable p2p networking.
--port PORT Override the port on which the node should listen
[default: 30303].
--peers NUM Try to maintain that many peers [default: 25].
@@ -65,9 +74,13 @@ Networking Options:
--no-discovery Disable new peer discovery.
--node-key KEY Specify node secret key, either as 64-character hex
string or input to SHA3 operation.
--reserved-peers FILE Provide a file containing enodes, one per line.
These nodes will always have a reserved slot on top
of the normal maximum peers.
--reserved-only Connect only to reserved nodes.
API and Console Options:
--jsonrpc-off Disable the JSON-RPC API server.
--no-jsonrpc Disable the JSON-RPC API server.
--jsonrpc-port PORT Specify the port portion of the JSONRPC API server
[default: 8545].
--jsonrpc-interface IP Specify the hostname portion of the JSONRPC API
@@ -80,13 +93,13 @@ API and Console Options:
ethcore, ethcore_set, traces.
[default: web3,eth,net,ethcore,personal,traces].
--ipc-off Disable JSON-RPC over IPC service.
--no-ipc Disable JSON-RPC over IPC service.
--ipc-path PATH Specify custom path for JSON-RPC over IPC service
[default: $HOME/.parity/jsonrpc.ipc].
--ipc-apis APIS Specify custom API set available via JSON-RPC over
IPC [default: web3,eth,net,ethcore,personal,traces].
IPC [default: web3,eth,net,ethcore,personal,traces,rpc].
--dapps-off Disable the Dapps server (e.g. status page).
--no-dapps Disable the Dapps server (e.g. status page).
--dapps-port PORT Specify the port portion of the Dapps server
[default: 8080].
--dapps-interface IP Specify the hostname portion of the Dapps
@@ -102,15 +115,38 @@ API and Console Options:
[default: $HOME/.parity/dapps]
--signer Enable Trusted Signer WebSocket endpoint used by
Signer UIs.
Signer UIs. Default if run with ui command.
--no-signer Disable Trusted Signer WebSocket endpoint used by
Signer UIs. Default if no command is specified.
--signer-port PORT Specify the port of Trusted Signer server
[default: 8180].
--signer-path PATH Specify directory where Signer UIs tokens should
be stored. [default: $HOME/.parity/signer]
--no-token By default a new system UI security token will be
output on start up. This will prevent it.
Sealing/Mining Options:
--author ADDRESS Specify the block author (aka "coinbase") address
for sending block rewards from sealed blocks.
NOTE: MINING WILL NOT WORK WITHOUT THIS OPTION.
--force-sealing Force the node to author new blocks as if it were
always sealing/mining.
--reseal-on-txs SET Specify which transactions should force the node
to reseal a block. SET is one of:
none - never reseal on new transactions;
own - reseal only on a new local transaction;
ext - reseal only on a new external transaction;
all - reseal on all new transactions [default: all].
--tx-gas-limit GAS Apply a limit of GAS as the maximum amount of gas
a single transaction may have for it to be mined.
--relay-set SET Set of transactions to relay. SET may be:
cheap - Relay any transaction in the queue (this
may include invalid transactions);
strict - Relay only executed transactions (this
guarantees we don't relay invalid transactions, but
means we relay nothing if not mining);
lenient - Same as strict when mining, and cheap
when not [default: cheap].
--usd-per-tx USD Amount of USD to be paid for a basic transaction
[default: 0.005]. The minimum gas price is set
accordingly.
@@ -119,14 +155,13 @@ Sealing/Mining Options:
web service in turn and fallback on the last known
good value [default: auto].
--gas-floor-target GAS Amount of gas per block to target when sealing a new
block [default: 4712388].
--author ADDRESS Specify the block author (aka "coinbase") address
for sending block rewards from sealed blocks
[default: 0037a6b811ffeb6e072da21179d11b1406371c63].
block [default: 4700000].
--gas-cap GAS A cap on how large we will raise the gas limit per
block due to transaction volume [default: 6283184].
--extra-data STRING Specify a custom extra-data for authored blocks, no
more than 32 characters.
--tx-limit LIMIT Limit of transactions kept in the queue (waiting to
be included in next block) [default: 1024].
--tx-queue-size LIMIT Maximum amount of transactions in the queue (waiting
to be included in next block) [default: 1024].
Footprint Options:
--tracing BOOL Indicates if full transaction tracing should be
@@ -135,15 +170,11 @@ Footprint Options:
off. auto uses last used value of this option (off
if it does not exist) [default: auto].
--pruning METHOD Configure pruning of the state/storage trie. METHOD
may be one of auto, archive, fast, basic, light:
may be one of auto, archive, fast:
archive - keep all state trie data. No pruning.
fast - maintain journal overlay. Fast but 50MB used.
basic - reference count in disk DB. Slow, light, and
experimental!
light - early merges with partial tracking. Fast,
light, and experimental!
auto - use the method most recently synced or
default to archive if none synced [default: auto].
default to fast if none synced [default: auto].
--cache-pref-size BYTES Specify the prefered size of the blockchain cache in
bytes [default: 16384].
--cache-max-size BYTES Specify the maximum size of the blockchain cache in
@@ -154,6 +185,12 @@ Footprint Options:
the entire system, overrides other cache and queue
options.
Database Options:
--db-cache-size MB Override RocksDB database cache size.
--db-compaction TYPE Database compaction type. TYPE may be one of:
ssd - suitable for SSDs and fast HDDs;
hdd - suitable for slow HDDs [default: ssd].
Import/Export Options:
--from BLOCK Export from block BLOCK, which may be an index or
hash [default: 1].
@@ -166,9 +203,10 @@ Virtual Machine Options:
--jitvm Enable the JIT VM.
Legacy Options:
--geth Run in Geth-compatibility mode. Currently just sets
the IPC path to be the same as Geth's. Overrides
the --ipc-path/--ipcpath options.
--geth Run in Geth-compatibility mode. Sets the IPC path
to be the same as Geth's. Overrides the --ipc-path
and --ipcpath options. Alters RPCs to reflect Geth
bugs.
--testnet Geth-compatible testnet mode. Equivalent to --chain
testnet --keys-path $HOME/parity/testnet-keys.
Overrides the --keys-path option.
@@ -178,13 +216,16 @@ Legacy Options:
--nodekey KEY Equivalent to --node-key KEY.
--nodiscover Equivalent to --no-discovery.
-j --jsonrpc Does nothing; JSON-RPC is on by default now.
--jsonrpc-off Equivalent to --no-jsonrpc.
-w --webapp Does nothing; dapps server is on by default now.
--dapps-off Equivalent to --no-dapps.
--rpc Does nothing; JSON-RPC is on by default now.
--rpcaddr IP Equivalent to --jsonrpc-interface IP.
--rpcport PORT Equivalent to --jsonrpc-port PORT.
--rpcapi APIS Equivalent to --jsonrpc-apis APIS.
--rpccorsdomain URL Equivalent to --jsonrpc-cors URL.
--ipcdisable Equivalent to --ipc-off.
--ipcdisable Equivalent to --no-ipc.
--ipc-off Equivalent to --no-ipc.
--ipcapi APIS Equivalent to --ipc-apis APIS.
--ipcpath PATH Equivalent to --ipc-path PATH.
--gasprice WEI Minimum amount of Wei per GAS to be paid for a
@@ -205,18 +246,21 @@ Miscellaneous Options:
pub struct Args {
pub cmd_daemon: bool,
pub cmd_account: bool,
pub cmd_wallet: bool,
pub cmd_new: bool,
pub cmd_list: bool,
pub cmd_export: bool,
pub cmd_import: bool,
pub cmd_signer: bool,
pub cmd_new_token: bool,
pub cmd_ui: bool,
pub arg_pid_file: String,
pub arg_file: Option<String>,
pub arg_path: Vec<String>,
pub flag_chain: String,
pub flag_db_path: String,
pub flag_identity: String,
pub flag_fork: String,
pub flag_unlock: Option<String>,
pub flag_password: Vec<String>,
pub flag_cache: Option<usize>,
@@ -232,33 +276,41 @@ pub struct Args {
pub flag_no_discovery: bool,
pub flag_nat: String,
pub flag_node_key: Option<String>,
pub flag_reserved_peers: Option<String>,
pub flag_reserved_only: bool,
pub flag_cache_pref_size: usize,
pub flag_cache_max_size: usize,
pub flag_queue_max_size: usize,
pub flag_jsonrpc_off: bool,
pub flag_no_jsonrpc: bool,
pub flag_jsonrpc_interface: String,
pub flag_jsonrpc_port: u16,
pub flag_jsonrpc_cors: Option<String>,
pub flag_jsonrpc_apis: String,
pub flag_ipc_off: bool,
pub flag_no_ipc: bool,
pub flag_ipc_path: String,
pub flag_ipc_apis: String,
pub flag_dapps_off: bool,
pub flag_no_dapps: bool,
pub flag_dapps_port: u16,
pub flag_dapps_interface: String,
pub flag_dapps_user: Option<String>,
pub flag_dapps_pass: Option<String>,
pub flag_dapps_path: String,
pub flag_signer: bool,
pub flag_no_signer: bool,
pub flag_signer_port: u16,
pub flag_signer_path: String,
pub flag_no_token: bool,
pub flag_force_sealing: bool,
pub flag_author: String,
pub flag_reseal_on_txs: String,
pub flag_tx_gas_limit: Option<String>,
pub flag_relay_set: String,
pub flag_author: Option<String>,
pub flag_usd_per_tx: String,
pub flag_usd_per_eth: String,
pub flag_gas_floor_target: String,
pub flag_gas_cap: String,
pub flag_extra_data: Option<String>,
pub flag_tx_limit: usize,
pub flag_tx_queue_size: usize,
pub flag_logging: Option<String>,
pub flag_version: bool,
pub flag_from: String,
@@ -266,6 +318,7 @@ pub struct Args {
pub flag_format: Option<String>,
pub flag_jitvm: bool,
pub flag_no_color: bool,
pub flag_no_network: bool,
// legacy...
pub flag_geth: bool,
pub flag_nodekey: Option<String>,
@@ -285,8 +338,13 @@ pub struct Args {
pub flag_testnet: bool,
pub flag_networkid: Option<String>,
pub flag_ipcdisable: bool,
pub flag_ipc_off: bool,
pub flag_jsonrpc_off: bool,
pub flag_dapps_off: bool,
pub flag_ipcpath: Option<String>,
pub flag_ipcapi: Option<String>,
pub flag_db_cache_size: Option<usize>,
pub flag_db_compaction: String,
}
pub fn print_version() {

View File

@@ -24,9 +24,10 @@ use docopt::Docopt;
use die::*;
use util::*;
use util::keys::store::{ImportKeySet, AccountService};
use ethcore::account_provider::AccountProvider;
use util::network_settings::NetworkSettings;
use ethcore::client::{append_path, get_db_path, ClientConfig, Switch, VMType};
use ethcore::client::{append_path, get_db_path, ClientConfig, DatabaseCompactionProfile, Switch, VMType};
use ethcore::miner::{MinerOptions, PendingSet};
use ethcore::ethereum;
use ethcore::spec::Spec;
use ethsync::SyncConfig;
@@ -44,6 +45,13 @@ pub struct Directories {
pub signer: String,
}
#[derive(Eq, PartialEq, Debug)]
pub enum Policy {
DaoSoft,
Normal,
Dogmatic,
}
impl Configuration {
pub fn parse() -> Self {
Configuration {
@@ -67,18 +75,74 @@ impl Configuration {
self.args.flag_maxpeers.unwrap_or(self.args.flag_peers) as u32
}
pub fn author(&self) -> Address {
let d = self.args.flag_etherbase.as_ref().unwrap_or(&self.args.flag_author);
Address::from_str(clean_0x(d)).unwrap_or_else(|_| {
die!("{}: Invalid address for --author. Must be 40 hex characters, with or without the 0x at the beginning.", d)
})
fn decode_u256(d: &str, argument: &str) -> U256 {
U256::from_dec_str(d).unwrap_or_else(|_|
U256::from_str(clean_0x(d)).unwrap_or_else(|_|
die!("{}: Invalid numeric value for {}. Must be either a decimal or a hex number.", d, argument)
)
)
}
pub fn miner_options(&self) -> MinerOptions {
let (own, ext) = match self.args.flag_reseal_on_txs.as_str() {
"none" => (false, false),
"own" => (true, false),
"ext" => (false, true),
"all" => (true, true),
x => die!("{}: Invalid value for --reseal option. Use --help for more information.", x)
};
MinerOptions {
force_sealing: self.args.flag_force_sealing,
reseal_on_external_tx: ext,
reseal_on_own_tx: own,
tx_gas_limit: self.args.flag_tx_gas_limit.as_ref().map_or(!U256::zero(), |d| Self::decode_u256(d, "--tx-gas-limit")),
tx_queue_size: self.args.flag_tx_queue_size,
pending_set: match self.args.flag_relay_set.as_str() {
"cheap" => PendingSet::AlwaysQueue,
"strict" => PendingSet::AlwaysSealing,
"lenient" => PendingSet::SealingOrElseQueue,
x => die!("{}: Invalid value for --relay-set option. Use --help for more information.", x)
},
}
}
pub fn author(&self) -> Option<Address> {
self.args.flag_etherbase.as_ref()
.or(self.args.flag_author.as_ref())
.map(|d| Address::from_str(clean_0x(d)).unwrap_or_else(|_| {
die!("{}: Invalid address for --author. Must be 40 hex characters, with or without the 0x at the beginning.", d)
}))
}
pub fn policy(&self) -> Policy {
match self.args.flag_fork.as_str() {
"dao-soft" => Policy::DaoSoft,
"normal" => Policy::Normal,
"dogmatic" => Policy::Dogmatic,
x => die!("{}: Invalid value given for --policy option. Use --help for more info.", x)
}
}
pub fn gas_floor_target(&self) -> U256 {
let d = &self.args.flag_gas_floor_target;
U256::from_dec_str(d).unwrap_or_else(|_| {
die!("{}: Invalid target gas floor given. Must be a decimal unsigned 256-bit number.", d)
})
if self.policy() == Policy::DaoSoft {
3_141_592.into()
} else {
let d = &self.args.flag_gas_floor_target;
U256::from_dec_str(d).unwrap_or_else(|_| {
die!("{}: Invalid target gas floor given. Must be a decimal unsigned 256-bit number.", d)
})
}
}
pub fn gas_ceil_target(&self) -> U256 {
if self.policy() == Policy::DaoSoft {
3_141_592.into()
} else {
let d = &self.args.flag_gas_cap;
U256::from_dec_str(d).unwrap_or_else(|_| {
die!("{}: Invalid target gas ceiling given. Must be a decimal unsigned 256-bit number.", d)
})
}
}
pub fn gas_price(&self) -> U256 {
@@ -124,7 +188,7 @@ impl Configuration {
pub fn spec(&self) -> Spec {
match self.chain().as_str() {
"frontier" | "homestead" | "mainnet" => ethereum::new_frontier(),
"frontier" | "homestead" | "mainnet" => ethereum::new_frontier(self.policy() != Policy::Dogmatic),
"morden" | "testnet" => ethereum::new_morden(),
"olympic" => ethereum::new_olympic(),
f => Spec::load(contents(f).unwrap_or_else(|_| {
@@ -153,6 +217,25 @@ impl Configuration {
}
}
pub fn init_reserved_nodes(&self) -> Vec<String> {
use std::fs::File;
if let Some(ref path) = self.args.flag_reserved_peers {
let mut buffer = String::new();
let mut node_file = File::open(path).unwrap_or_else(|e| {
die!("Error opening reserved nodes file: {}", e);
});
node_file.read_to_string(&mut buffer).expect("Error reading reserved node file");
buffer.lines().map(|s| {
Self::normalize_enode(s).unwrap_or_else(|| {
die!("{}: Invalid node address format given for a reserved node.", s);
})
}).collect()
} else {
Vec::new()
}
}
pub fn net_addresses(&self) -> (Option<SocketAddr>, Option<SocketAddr>) {
let port = self.net_port();
let listen_address = Some(SocketAddr::new(IpAddr::from_str("0.0.0.0").unwrap(), port));
@@ -179,6 +262,11 @@ impl Configuration {
let mut net_path = PathBuf::from(&self.path());
net_path.push("network");
ret.config_path = Some(net_path.to_str().unwrap().to_owned());
ret.reserved_nodes = self.init_reserved_nodes();
if self.args.flag_reserved_only {
ret.non_reserved_mode = ::util::network::NonReservedPeerMode::Deny;
}
ret
}
@@ -187,7 +275,7 @@ impl Configuration {
let mut latest_era = None;
let jdb_types = [journaldb::Algorithm::Archive, journaldb::Algorithm::EarlyMerge, journaldb::Algorithm::OverlayRecent, journaldb::Algorithm::RefCounted];
for i in jdb_types.into_iter() {
let db = journaldb::new(&append_path(&get_db_path(Path::new(&self.path()), *i, spec.genesis_header().hash()), "state"), *i);
let db = journaldb::new(&append_path(&get_db_path(Path::new(&self.path()), *i, spec.genesis_header().hash()), "state"), *i, kvdb::DatabaseConfig::default());
trace!(target: "parity", "Looking for best DB: {} at {:?}", i, db.latest_era());
match (latest_era, db.latest_era()) {
(Some(best), Some(this)) if best >= this => {}
@@ -214,6 +302,8 @@ impl Configuration {
client_config.blockchain.max_cache_size = self.args.flag_cache_max_size;
}
}
// forced blockchain (blocks + extras) db cache size if provided
client_config.blockchain.db_cache_size = self.args.flag_db_cache_size.and_then(|cs| Some(cs / 2));
client_config.tracing.enabled = match self.args.flag_tracing.as_str() {
"auto" => Switch::Auto,
@@ -221,16 +311,28 @@ impl Configuration {
"off" => Switch::Off,
_ => { die!("Invalid tracing method given!") }
};
// forced trace db cache size if provided
client_config.tracing.db_cache_size = self.args.flag_db_cache_size.and_then(|cs| Some(cs / 4));
client_config.pruning = match self.args.flag_pruning.as_str() {
"archive" => journaldb::Algorithm::Archive,
"light" => journaldb::Algorithm::EarlyMerge,
"fast" => journaldb::Algorithm::OverlayRecent,
"basic" => journaldb::Algorithm::RefCounted,
"auto" => self.find_best_db(spec).unwrap_or(journaldb::Algorithm::Archive),
"auto" => self.find_best_db(spec).unwrap_or(journaldb::Algorithm::OverlayRecent),
_ => { die!("Invalid pruning method given."); }
};
// forced state db cache size if provided
client_config.db_cache_size = self.args.flag_db_cache_size.and_then(|cs| Some(cs / 4));
// compaction profile
client_config.db_compaction = match self.args.flag_db_compaction.as_str() {
"ssd" => DatabaseCompactionProfile::Default,
"hdd" => DatabaseCompactionProfile::HDD,
_ => { die!("Invalid compaction profile given (--db-compaction argument), expected hdd/default."); }
};
if self.args.flag_jitvm {
client_config.vm_type = VMType::jit().unwrap_or_else(|| die!("Parity built without jit vm."))
}
@@ -249,7 +351,10 @@ impl Configuration {
sync_config
}
pub fn account_service(&self) -> AccountService {
pub fn account_service(&self) -> AccountProvider {
use ethcore::ethstore::{import_accounts, EthStore};
use ethcore::ethstore::dir::{GethDirectory, DirectoryType, DiskDirectory};
// Secret Store
let passwords = self.args.flag_password.iter().flat_map(|filename| {
BufReader::new(&File::open(filename).unwrap_or_else(|_| die!("{} Unable to read password file. Ensure it exists and permissions are correct.", filename)))
@@ -258,18 +363,30 @@ impl Configuration {
.collect::<Vec<_>>()
.into_iter()
}).collect::<Vec<_>>();
let import_keys = match (self.args.flag_no_import_keys, self.args.flag_testnet) {
(true, _) => ImportKeySet::None,
(false, false) => ImportKeySet::Legacy,
(false, true) => ImportKeySet::LegacyTestnet,
};
let account_service = AccountService::with_security(Path::new(&self.keys_path()), self.keys_iterations(), import_keys);
if !self.args.flag_no_import_keys {
let dir_type = if self.args.flag_testnet {
DirectoryType::Testnet
} else {
DirectoryType::Main
};
let from = GethDirectory::open(dir_type);
let to = DiskDirectory::create(self.keys_path()).unwrap();
// ignore error, cause geth may not exist
let _ = import_accounts(&from, &to);
}
let dir = Box::new(DiskDirectory::create(self.keys_path()).unwrap());
let iterations = self.keys_iterations();
let account_service = AccountProvider::new(Box::new(EthStore::open_with_iterations(dir, iterations).unwrap()));
if let Some(ref unlocks) = self.args.flag_unlock {
for d in unlocks.split(',') {
let a = Address::from_str(clean_0x(d)).unwrap_or_else(|_| {
die!("{}: Invalid address for --unlock. Must be 40 hex characters, without the 0x at the beginning.", d)
});
if passwords.iter().find(|p| account_service.unlock_account_no_expire(&a, p).is_ok()).is_none() {
if passwords.iter().find(|p| account_service.unlock_account_permanently(a, (*p).clone()).is_ok()).is_none() {
die!("No password given to unlock account {}. Pass the password using `--password`.", a);
}
}
@@ -287,9 +404,14 @@ impl Configuration {
}
fn geth_ipc_path(&self) -> String {
if self.args.flag_testnet { path::ethereum::with_testnet("geth.ipc") }
else { path::ethereum::with_default("geth.ipc") }
.to_str().unwrap().to_owned()
if cfg!(windows) {
r"\\.\pipe\geth.ipc".to_owned()
}
else {
if self.args.flag_testnet { path::ethereum::with_testnet("geth.ipc") }
else { path::ethereum::with_default("geth.ipc") }
.to_str().unwrap().to_owned()
}
}
pub fn keys_iterations(&self) -> u32 {
@@ -298,7 +420,7 @@ impl Configuration {
pub fn ipc_settings(&self) -> IpcConfiguration {
IpcConfiguration {
enabled: !(self.args.flag_ipcdisable || self.args.flag_ipc_off),
enabled: !(self.args.flag_ipcdisable || self.args.flag_ipc_off || self.args.flag_no_ipc),
socket_addr: self.ipc_path(),
apis: self.args.flag_ipcapi.clone().unwrap_or(self.args.flag_ipc_apis.clone()),
}
@@ -311,7 +433,7 @@ impl Configuration {
chain: self.chain(),
max_peers: self.max_peers(),
network_port: self.net_port(),
rpc_enabled: !self.args.flag_jsonrpc_off,
rpc_enabled: !self.args.flag_jsonrpc_off && !self.args.flag_no_jsonrpc,
rpc_interface: self.args.flag_rpcaddr.clone().unwrap_or(self.args.flag_jsonrpc_interface.clone()),
rpc_port: self.args.flag_rpcport.unwrap_or(self.args.flag_jsonrpc_port),
}
@@ -357,17 +479,51 @@ impl Configuration {
}
fn ipc_path(&self) -> String {
if self.args.flag_geth { self.geth_ipc_path() }
else { Configuration::replace_home(&self.args.flag_ipcpath.clone().unwrap_or(self.args.flag_ipc_path.clone())) }
if self.args.flag_geth {
self.geth_ipc_path()
} else if cfg!(windows) {
r"\\.\pipe\parity.jsonrpc".to_owned()
} else {
Configuration::replace_home(&self.args.flag_ipcpath.clone().unwrap_or(self.args.flag_ipc_path.clone()))
}
}
pub fn have_color(&self) -> bool {
!self.args.flag_no_color && !cfg!(windows)
}
pub fn signer_port(&self) -> Option<u16> {
if self.args.flag_signer {
Some(self.args.flag_signer_port)
} else {
if !self.signer_enabled() {
None
} else {
Some(self.args.flag_signer_port)
}
}
pub fn rpc_interface(&self) -> String {
match self.network_settings().rpc_interface.as_str() {
"all" => "0.0.0.0",
"local" => "127.0.0.1",
x => x,
}.into()
}
pub fn dapps_interface(&self) -> String {
match self.args.flag_dapps_interface.as_str() {
"all" => "0.0.0.0",
"local" => "127.0.0.1",
x => x,
}.into()
}
pub fn dapps_enabled(&self) -> bool {
!self.args.flag_dapps_off && !self.args.flag_no_dapps
}
pub fn signer_enabled(&self) -> bool {
(self.args.cmd_ui && !self.args.flag_no_signer) ||
(!self.args.cmd_ui && self.args.flag_signer)
}
}
#[cfg(test)]

View File

@@ -45,12 +45,7 @@ pub fn new(configuration: Configuration, deps: Dependencies) -> Option<WebappSer
return None;
}
let interface = match configuration.interface.as_str() {
"all" => "0.0.0.0",
"local" => "127.0.0.1",
x => x,
};
let url = format!("{}:{}", interface, configuration.port);
let url = format!("{}:{}", configuration.interface, configuration.port);
let addr = SocketAddr::from_str(&url).unwrap_or_else(|_| die!("{}: Invalid Webapps listen host/port given.", url));
let auth = configuration.user.as_ref().map(|username| {

View File

@@ -14,38 +14,52 @@
// 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::sync::Arc;
use std::sync::{Arc, Weak};
use ethcore::client::Client;
use ethcore::service::NetSyncMessage;
use ethcore::service::{NetSyncMessage, SyncMessage};
use ethsync::EthSync;
use util::keys::store::AccountService;
use util::{TimerToken, IoHandler, IoContext};
use ethcore::account_provider::AccountProvider;
use util::{TimerToken, IoHandler, IoContext, NetworkService, NetworkIoMessage};
use informant::Informant;
const INFO_TIMER: TimerToken = 0;
const ACCOUNT_TICK_TIMER: TimerToken = 10;
const ACCOUNT_TICK_MS: u64 = 60000;
pub struct ClientIoHandler {
pub client: Arc<Client>,
pub sync: Arc<EthSync>,
pub accounts: Arc<AccountService>,
pub accounts: Arc<AccountProvider>,
pub info: Informant,
pub network: Weak<NetworkService<SyncMessage>>,
}
impl IoHandler<NetSyncMessage> for ClientIoHandler {
fn initialize(&self, io: &IoContext<NetSyncMessage>) {
io.register_timer(INFO_TIMER, 5000).expect("Error registering timer");
io.register_timer(ACCOUNT_TICK_TIMER, ACCOUNT_TICK_MS).expect("Error registering account timer");
}
fn timeout(&self, _io: &IoContext<NetSyncMessage>, timer: TimerToken) {
match timer {
INFO_TIMER => { self.info.tick(&self.client, Some(&self.sync)); }
ACCOUNT_TICK_TIMER => { self.accounts.tick(); },
_ => {}
if let INFO_TIMER = timer {
self.info.tick(&self.client, Some(&self.sync));
}
}
fn message(&self, _io: &IoContext<NetSyncMessage>, message: &NetSyncMessage) {
match *message {
NetworkIoMessage::User(SyncMessage::StartNetwork) => {
info!("Starting network");
if let Some(network) = self.network.upgrade() {
network.start().unwrap_or_else(|e| warn!("Error starting network: {:?}", e));
EthSync::register(&*network, self.sync.clone()).unwrap_or_else(|e| warn!("Error registering eth protocol handler: {}", e));
}
},
NetworkIoMessage::User(SyncMessage::StopNetwork) => {
info!("Stopping network");
if let Some(network) = self.network.upgrade() {
network.stop().unwrap_or_else(|e| warn!("Error stopping network: {:?}", e));
}
},
_ => {/* Ignore other messages */},
}
}
}

View File

@@ -32,6 +32,7 @@ extern crate log as rlog;
extern crate env_logger;
extern crate ctrlc;
extern crate fdlimit;
#[cfg(not(windows))]
extern crate daemonize;
extern crate time;
extern crate number_prefix;
@@ -67,6 +68,7 @@ mod configuration;
mod migration;
mod signer;
mod rpc_apis;
mod url;
use std::io::{Write, Read, BufReader, BufRead};
use std::ops::Deref;
@@ -78,7 +80,7 @@ use std::thread::sleep;
use std::time::Duration;
use rustc_serialize::hex::FromHex;
use ctrlc::CtrlC;
use util::{H256, ToPretty, NetworkConfiguration, PayloadInfo, Bytes};
use util::{H256, ToPretty, NetworkConfiguration, PayloadInfo, Bytes, UtilError};
use util::panics::{MayPanic, ForwardPanic, PanicHandler};
use ethcore::client::{BlockID, BlockChainClient, ClientConfig, get_db_path};
use ethcore::error::{Error, ImportError};
@@ -86,7 +88,6 @@ use ethcore::service::ClientService;
use ethcore::spec::Spec;
use ethsync::EthSync;
use ethcore::miner::{Miner, MinerService, ExternalMiner};
use daemonize::Daemonize;
use migration::migrate;
use informant::Informant;
@@ -109,17 +110,18 @@ fn execute(conf: Configuration) {
return;
}
if conf.args.cmd_signer {
execute_signer(conf);
return;
}
let spec = conf.spec();
let client_config = conf.client_config(&spec);
execute_upgrades(&conf, &spec, &client_config);
if conf.args.cmd_daemon {
Daemonize::new()
.pid_file(conf.args.arg_pid_file.clone())
.chown_pid_file(true)
.start()
.unwrap_or_else(|e| die!("Couldn't daemonize; {}", e));
daemonize(&conf);
}
if conf.args.cmd_account {
@@ -127,6 +129,11 @@ fn execute(conf: Configuration) {
return;
}
if conf.args.cmd_wallet {
execute_wallet_cli(conf);
return;
}
if conf.args.cmd_export {
execute_export(conf);
return;
@@ -137,14 +144,23 @@ fn execute(conf: Configuration) {
return;
}
if conf.args.cmd_signer {
execute_signer(conf);
return;
}
execute_client(conf, spec, client_config);
}
#[cfg(not(windows))]
fn daemonize(conf: &Configuration) {
use daemonize::Daemonize;
Daemonize::new()
.pid_file(conf.args.arg_pid_file.clone())
.chown_pid_file(true)
.start()
.unwrap_or_else(|e| die!("Couldn't daemonize; {}", e));
}
#[cfg(windows)]
fn daemonize(_conf: &Configuration) {
}
fn execute_upgrades(conf: &Configuration, spec: &Spec, client_config: &ClientConfig) {
match ::upgrade::upgrade(Some(&conf.path())) {
Ok(upgrades_applied) if upgrades_applied > 0 => {
@@ -175,20 +191,34 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig)
let net_settings = conf.net_settings(&spec);
let sync_config = conf.sync_config(&spec);
// Create and display a new token for UIs.
if conf.signer_enabled() && !conf.args.flag_no_token {
new_token(conf.directories().signer).unwrap_or_else(|e| {
die!("Error generating token: {:?}", e)
});
}
// Display warning about using unlock with signer
if conf.signer_enabled() && conf.args.flag_unlock.is_some() {
warn!("Using Trusted Signer and --unlock is not recommended!");
warn!("NOTE that Signer will not ask you to confirm transactions from unlocked account.");
}
// Secret Store
let account_service = Arc::new(conf.account_service());
// Miner
let miner = Miner::with_accounts(conf.args.flag_force_sealing, conf.spec(), account_service.clone());
miner.set_author(conf.author());
let miner = Miner::new(conf.miner_options(), conf.spec(), Some(account_service.clone()));
miner.set_author(conf.author().unwrap_or_default());
miner.set_gas_floor_target(conf.gas_floor_target());
miner.set_gas_ceil_target(conf.gas_ceil_target());
miner.set_extra_data(conf.extra_data());
miner.set_minimal_gas_price(conf.gas_price());
miner.set_transactions_limit(conf.args.flag_tx_limit);
miner.set_transactions_limit(conf.args.flag_tx_queue_size);
// Build client
let mut service = ClientService::start(
client_config, spec, net_settings, Path::new(&conf.path()), miner.clone()
client_config, spec, net_settings, Path::new(&conf.path()), miner.clone(), !conf.args.flag_no_network
).unwrap_or_else(|e| die_with_error("Client", e));
panic_handler.forward_from(&service);
@@ -198,7 +228,8 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig)
let network_settings = Arc::new(conf.network_settings());
// Sync
let sync = EthSync::register(service.network(), sync_config, client.clone());
let sync = EthSync::new(sync_config, client.clone());
EthSync::register(&*service.network(), sync.clone()).unwrap_or_else(|e| die_with_error("Error registering eth protocol handler", UtilError::from(e).into()));
let deps_for_rpc_apis = Arc::new(rpc_apis::Dependencies {
signer_port: conf.signer_port(),
@@ -210,6 +241,8 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig)
external_miner: external_miner.clone(),
logger: logger.clone(),
settings: network_settings.clone(),
allow_pending_receipt_query: !conf.args.flag_geth,
net_service: service.network(),
});
let dependencies = rpc::Dependencies {
@@ -220,7 +253,7 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig)
// Setup http rpc
let rpc_server = rpc::new_http(rpc::HttpConfiguration {
enabled: network_settings.rpc_enabled,
interface: network_settings.rpc_interface.clone(),
interface: conf.rpc_interface(),
port: network_settings.rpc_port,
apis: conf.rpc_apis(),
cors: conf.rpc_cors(),
@@ -228,11 +261,12 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig)
// setup ipc rpc
let _ipc_server = rpc::new_ipc(conf.ipc_settings(), &dependencies);
debug!("IPC: {}", conf.ipc_settings());
if conf.args.flag_webapp { println!("WARNING: Flag -w/--webapp is deprecated. Dapps server is now on by default. Ignoring."); }
let dapps_server = dapps::new(dapps::Configuration {
enabled: !conf.args.flag_dapps_off,
interface: conf.args.flag_dapps_interface.clone(),
enabled: conf.dapps_enabled(),
interface: conf.dapps_interface(),
port: conf.args.flag_dapps_port,
user: conf.args.flag_dapps_user.clone(),
pass: conf.args.flag_dapps_pass.clone(),
@@ -244,7 +278,7 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig)
// Set up a signer
let signer_server = signer::start(signer::Configuration {
enabled: deps_for_rpc_apis.signer_port.is_some(),
enabled: conf.signer_enabled(),
port: conf.args.flag_signer_port,
signer_path: conf.directories().signer,
}, signer::Dependencies {
@@ -255,11 +289,19 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig)
// Register IO handler
let io_handler = Arc::new(ClientIoHandler {
client: service.client(),
info: Informant::new(!conf.args.flag_no_color),
info: Informant::new(conf.have_color()),
sync: sync.clone(),
accounts: account_service.clone(),
network: Arc::downgrade(&service.network()),
});
service.io().register_handler(io_handler).expect("Error registering IO handler");
service.register_io_handler(io_handler).expect("Error registering IO handler");
if conf.args.cmd_ui {
if !conf.dapps_enabled() {
die_with_message("Cannot use UI command with Dapps turned off.");
}
url::open(&format!("http://{}:{}/", conf.dapps_interface(), conf.args.flag_dapps_port));
}
// Handle exit
wait_for_exit(panic_handler, rpc_server, dapps_server, signer_server);
@@ -289,16 +331,17 @@ fn execute_export(conf: Configuration) {
udp_port: None,
nat_enabled: false,
discovery_enabled: false,
pin: true,
boot_nodes: Vec::new(),
use_secret: None,
ideal_peers: 0,
reserved_nodes: Vec::new(),
non_reserved_mode: ::util::network::NonReservedPeerMode::Accept,
};
let client_config = conf.client_config(&spec);
// Build client
let service = ClientService::start(
client_config, spec, net_settings, Path::new(&conf.path()), Arc::new(Miner::default()),
client_config, spec, net_settings, Path::new(&conf.path()), Arc::new(Miner::with_spec(conf.spec())), false
).unwrap_or_else(|e| die_with_error("Client", e));
panic_handler.forward_from(&service);
@@ -360,33 +403,36 @@ fn execute_import(conf: Configuration) {
udp_port: None,
nat_enabled: false,
discovery_enabled: false,
pin: true,
boot_nodes: Vec::new(),
use_secret: None,
ideal_peers: 0,
reserved_nodes: Vec::new(),
non_reserved_mode: ::util::network::NonReservedPeerMode::Accept,
};
let client_config = conf.client_config(&spec);
// Build client
let service = ClientService::start(
client_config, spec, net_settings, Path::new(&conf.path()), Arc::new(Miner::default()),
client_config, spec, net_settings, Path::new(&conf.path()), Arc::new(Miner::with_spec(conf.spec())), false
).unwrap_or_else(|e| die_with_error("Client", e));
panic_handler.forward_from(&service);
let client = service.client();
let mut instream: Box<Read> = if let Some(f) = conf.args.arg_file {
let f = File::open(&f).unwrap_or_else(|_| die!("Cannot open the file given: {}", f));
let mut instream: Box<Read> = if let Some(ref f) = conf.args.arg_file {
let f = File::open(f).unwrap_or_else(|_| die!("Cannot open the file given: {}", f));
Box::new(f)
} else {
Box::new(::std::io::stdin())
};
let mut first_bytes: Bytes = vec![0; 3];
const READAHEAD_BYTES: usize = 8;
let mut first_bytes: Bytes = vec![0; READAHEAD_BYTES];
let mut first_read = 0;
let format = match conf.args.flag_format {
Some(x) => match x.deref() {
Some(ref x) => match x.deref() {
"binary" | "bin" => DataFormat::Binary,
"hex" => DataFormat::Hex,
x => die!("Invalid --format parameter given: {:?}", x),
@@ -407,7 +453,7 @@ fn execute_import(conf: Configuration) {
}
};
let informant = Informant::new(!conf.args.flag_no_color);
let informant = Informant::new(conf.have_color());
let do_import = |bytes| {
while client.queue_info().is_full() { sleep(Duration::from_secs(1)); }
@@ -422,13 +468,13 @@ fn execute_import(conf: Configuration) {
match format {
DataFormat::Binary => {
loop {
let mut bytes: Bytes = if first_read > 0 {first_bytes.clone()} else {vec![0; 3]};
let mut bytes: Bytes = if first_read > 0 {first_bytes.clone()} else {vec![0; READAHEAD_BYTES]};
let n = if first_read > 0 {first_read} else {instream.read(&mut(bytes[..])).unwrap_or_else(|_| die!("Error reading from the file/stream."))};
if n == 0 { break; }
first_read = 0;
let s = PayloadInfo::from(&(bytes[..])).unwrap_or_else(|e| die!("Invalid RLP in the file/stream: {:?}", e)).total();
bytes.resize(s, 0);
instream.read_exact(&mut(bytes[3..])).unwrap_or_else(|_| die!("Error reading from the file/stream."));
instream.read_exact(&mut(bytes[READAHEAD_BYTES..])).unwrap_or_else(|_| die!("Error reading from the file/stream."));
do_import(bytes);
}
}
@@ -457,9 +503,15 @@ fn execute_signer(conf: Configuration) {
}
fn execute_account_cli(conf: Configuration) {
use util::keys::store::SecretStore;
use ethcore::ethstore::{EthStore, import_accounts};
use ethcore::ethstore::dir::DiskDirectory;
use ethcore::account_provider::AccountProvider;
use rpassword::read_password;
let mut secret_store = SecretStore::with_security(Path::new(&conf.keys_path()), conf.keys_iterations());
let dir = Box::new(DiskDirectory::create(conf.keys_path()).unwrap());
let iterations = conf.keys_iterations();
let secret_store = AccountProvider::new(Box::new(EthStore::open_with_iterations(dir, iterations).unwrap()));
if conf.args.cmd_new {
println!("Please note that password is NOT RECOVERABLE.");
print!("Type password: ");
@@ -477,19 +529,50 @@ fn execute_account_cli(conf: Configuration) {
println!("{:?}", new_address);
return;
}
if conf.args.cmd_list {
println!("Known addresses:");
for &(addr, _) in &secret_store.accounts().unwrap() {
for addr in &secret_store.accounts() {
println!("{:?}", addr);
}
return;
}
if conf.args.cmd_import {
let imported = util::keys::import_keys_paths(&mut secret_store, &conf.args.arg_path).unwrap();
let to = DiskDirectory::create(conf.keys_path()).unwrap();
let mut imported = 0;
for path in &conf.args.arg_path {
let from = DiskDirectory::at(path);
imported += import_accounts(&from, &to).unwrap_or_else(|e| die!("Could not import accounts {}", e)).len();
}
println!("Imported {} keys", imported);
}
}
fn execute_wallet_cli(conf: Configuration) {
use ethcore::ethstore::{PresaleWallet, EthStore};
use ethcore::ethstore::dir::DiskDirectory;
use ethcore::account_provider::AccountProvider;
let wallet_path = conf.args.arg_path.first().unwrap();
let filename = conf.args.flag_password.first().unwrap();
let mut file = File::open(filename).unwrap_or_else(|_| die!("{} Unable to read password file.", filename));
let mut file_content = String::new();
file.read_to_string(&mut file_content).unwrap_or_else(|_| die!("{} Unable to read password file.", filename));
let dir = Box::new(DiskDirectory::create(conf.keys_path()).unwrap());
let iterations = conf.keys_iterations();
let store = AccountProvider::new(Box::new(EthStore::open_with_iterations(dir, iterations).unwrap()));
// remove eof
let pass = &file_content[..file_content.len() - 1];
let wallet = PresaleWallet::open(wallet_path).unwrap_or_else(|_| die!("Unable to open presale wallet."));
let kp = wallet.decrypt(pass).unwrap_or_else(|_| die!("Invalid password"));
let address = store.insert_account(kp.secret().clone(), pass).unwrap();
println!("Imported account: {}", address);
}
fn wait_for_exit(
panic_handler: Arc<PanicHandler>,
_rpc_server: Option<RpcServer>,

View File

@@ -20,7 +20,7 @@ use std::io::{Read, Write, Error as IoError, ErrorKind};
use std::path::PathBuf;
use std::fmt::{Display, Formatter, Error as FmtError};
use util::migration::{Manager as MigrationManager, Config as MigrationConfig, MigrationIterator};
use util::kvdb::{Database, DatabaseConfig};
use util::kvdb::{Database, DatabaseConfig, CompactionProfile};
use ethcore::migrations;
/// Database is assumed to be at default version, when no version file is found.
@@ -89,6 +89,7 @@ fn current_version(path: &PathBuf) -> Result<u32, Error> {
/// Writes current database version to the file.
/// Creates a new file if the version file does not exist yet.
fn update_version(path: &PathBuf) -> Result<(), Error> {
try!(fs::create_dir_all(path));
let mut file = try!(File::create(version_file_path(path)));
try!(file.write_all(format!("{}", CURRENT_VERSION).as_bytes()));
Ok(())
@@ -151,8 +152,6 @@ fn migrate_database(version: u32, path: PathBuf, migrations: MigrationManager) -
return Ok(())
}
println!("Migrating database {} from version {} to {}", path.to_string_lossy(), version, CURRENT_VERSION);
let temp_path = temp_database_path(&path);
let backup_path = backup_database_path(&path);
// remote the dir if it exists
@@ -163,6 +162,8 @@ fn migrate_database(version: u32, path: PathBuf, migrations: MigrationManager) -
let db_config = DatabaseConfig {
prefix_size: None,
max_open_files: 64,
cache_size: None,
compaction: CompactionProfile::default(),
};
// open old database
@@ -187,20 +188,26 @@ fn migrate_database(version: u32, path: PathBuf, migrations: MigrationManager) -
// remove backup
try!(fs::remove_dir_all(&backup_path));
println!("Migration finished");
Ok(())
}
fn exists(path: &PathBuf) -> bool {
fs::metadata(path).is_ok()
}
/// Migrates the database.
pub fn migrate(path: &PathBuf) -> Result<(), Error> {
// read version file.
let version = try!(current_version(path));
// migrate the databases.
if version != CURRENT_VERSION {
// main db directory may already exists, so let's check if we have blocks dir
if version != CURRENT_VERSION && exists(&blocks_database_path(path)) {
println!("Migrating database from version {} to {}", version, CURRENT_VERSION);
try!(migrate_database(version, blocks_database_path(path), try!(blocks_database_migrations())));
try!(migrate_database(version, extras_database_path(path), try!(extras_database_migrations())));
println!("Migration finished");
}
// update version file.

View File

@@ -22,6 +22,7 @@ use util::panics::PanicHandler;
use die::*;
use jsonipc;
use rpc_apis;
use std::fmt;
#[cfg(feature = "rpc")]
pub use ethcore_rpc::Server as RpcServer;
@@ -44,6 +45,17 @@ pub struct IpcConfiguration {
pub apis: String,
}
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")
}
}
}
pub struct Dependencies {
pub panic_handler: Arc<PanicHandler>,
pub apis: Arc<rpc_apis::Dependencies>,
@@ -54,24 +66,13 @@ pub fn new_http(conf: HttpConfiguration, deps: &Dependencies) -> Option<RpcServe
return None;
}
let interface = match conf.interface.as_str() {
"all" => "0.0.0.0",
"local" => "127.0.0.1",
x => x,
};
let apis = conf.apis.split(',').collect();
let url = format!("{}:{}", interface, conf.port);
let url = format!("{}:{}", conf.interface, conf.port);
let addr = SocketAddr::from_str(&url).unwrap_or_else(|_| die!("{}: Invalid JSONRPC listen host/port given.", url));
Some(setup_http_rpc_server(deps, &addr, conf.cors, apis))
}
pub fn new_ipc(conf: IpcConfiguration, deps: &Dependencies) -> Option<jsonipc::Server> {
if !conf.enabled { return None; }
let apis = conf.apis.split(',').collect();
Some(setup_ipc_rpc_server(deps, &conf.socket_addr, apis))
}
fn setup_rpc_server(apis: Vec<&str>, deps: &Dependencies) -> Server {
let apis = rpc_apis::from_str(apis);
let server = Server::new();
@@ -109,10 +110,18 @@ pub fn setup_http_rpc_server(
},
}
}
#[cfg(not(feature = "rpc"))]
pub fn setup_ipc_rpc_server(_dependencies: &Dependencies, _addr: &str, _apis: Vec<&str>) -> ! {
die!("Your Parity version has been compiled without JSON-RPC support.")
}
pub fn new_ipc(conf: IpcConfiguration, deps: &Dependencies) -> Option<jsonipc::Server> {
if !conf.enabled { return None; }
let apis = conf.apis.split(',').collect();
Some(setup_ipc_rpc_server(deps, &conf.socket_addr, apis))
}
#[cfg(feature = "rpc")]
pub fn setup_ipc_rpc_server(dependencies: &Dependencies, addr: &str, apis: Vec<&str>) -> jsonipc::Server {
let server = setup_rpc_server(apis, dependencies);

View File

@@ -23,8 +23,9 @@ use ethsync::EthSync;
use ethcore::miner::{Miner, ExternalMiner};
use ethcore::client::Client;
use util::RotatingLogger;
use util::keys::store::AccountService;
use ethcore::account_provider::AccountProvider;
use util::network_settings::NetworkSettings;
use util::network::NetworkService;
#[cfg(feature="rpc")]
pub use ethcore_rpc::ConfirmationsQueue;
@@ -83,11 +84,13 @@ pub struct Dependencies {
pub signer_queue: Arc<ConfirmationsQueue>,
pub client: Arc<Client>,
pub sync: Arc<EthSync>,
pub secret_store: Arc<AccountService>,
pub secret_store: Arc<AccountProvider>,
pub miner: Arc<Miner>,
pub external_miner: Arc<ExternalMiner>,
pub logger: Arc<RotatingLogger>,
pub settings: Arc<NetworkSettings>,
pub allow_pending_receipt_query: bool,
pub net_service: Arc<NetworkService<::ethcore::service::SyncMessage>>,
}
fn to_modules(apis: &[Api]) -> BTreeMap<String, String> {
@@ -122,10 +125,10 @@ fn list_apis(apis: ApiSet) -> Vec<Api> {
match apis {
ApiSet::List(apis) => apis,
ApiSet::UnsafeContext => {
vec![Api::Web3, Api::Net, Api::Eth, Api::Personal, Api::Ethcore, Api::EthcoreSet, Api::Traces, Api::Rpc]
vec![Api::Web3, Api::Net, Api::Eth, Api::Personal, Api::Ethcore, Api::Traces, Api::Rpc]
},
_ => {
vec![Api::Web3, Api::Net, Api::Eth, Api::Personal, Api::Signer, Api::Ethcore, Api::EthcoreSet, Api::Traces, Api::Rpc]
vec![Api::Web3, Api::Net, Api::Eth, Api::Personal, Api::Signer, Api::Ethcore, Api::Traces, Api::Rpc]
},
}
}
@@ -143,11 +146,11 @@ pub fn setup_rpc<T: Extendable>(server: T, deps: Arc<Dependencies>, apis: ApiSet
server.add_delegate(NetClient::new(&deps.sync).to_delegate());
},
Api::Eth => {
server.add_delegate(EthClient::new(&deps.client, &deps.sync, &deps.secret_store, &deps.miner, &deps.external_miner).to_delegate());
server.add_delegate(EthClient::new(&deps.client, &deps.sync, &deps.secret_store, &deps.miner, &deps.external_miner, deps.allow_pending_receipt_query).to_delegate());
server.add_delegate(EthFilterClient::new(&deps.client, &deps.miner).to_delegate());
if deps.signer_port.is_some() {
server.add_delegate(EthSigningQueueClient::new(&deps.signer_queue).to_delegate());
server.add_delegate(EthSigningQueueClient::new(&deps.signer_queue, &deps.client, &deps.miner, &deps.secret_store).to_delegate());
} else {
server.add_delegate(EthSigningUnsafeClient::new(&deps.client, &deps.secret_store, &deps.miner).to_delegate());
}
@@ -159,10 +162,11 @@ pub fn setup_rpc<T: Extendable>(server: T, deps: Arc<Dependencies>, apis: ApiSet
server.add_delegate(SignerClient::new(&deps.secret_store, &deps.client, &deps.miner, &deps.signer_queue).to_delegate());
},
Api::Ethcore => {
server.add_delegate(EthcoreClient::new(&deps.miner, deps.logger.clone(), deps.settings.clone()).to_delegate())
let queue = deps.signer_port.map(|_| deps.signer_queue.clone());
server.add_delegate(EthcoreClient::new(&deps.client, &deps.miner, deps.logger.clone(), deps.settings.clone(), queue).to_delegate())
},
Api::EthcoreSet => {
server.add_delegate(EthcoreSetClient::new(&deps.miner).to_delegate())
server.add_delegate(EthcoreSetClient::new(&deps.miner, &deps.net_service).to_delegate())
},
Api::Traces => {
server.add_delegate(TracesClient::new(&deps.client, &deps.miner).to_delegate())

View File

@@ -14,11 +14,13 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
extern crate ansi_term;
use self::ansi_term::Colour::White;
use std::io;
use std::path::PathBuf;
use std::sync::Arc;
use util::panics::{PanicHandler, ForwardPanic};
use util::keys::directory::restrict_permissions_owner;
use util::path::restrict_permissions_owner;
use die::*;
use rpc_apis;
@@ -65,8 +67,7 @@ pub fn new_token(path: String) -> io::Result<()> {
let mut codes = try!(signer::AuthCodes::from_file(&path));
let code = try!(codes.generate_new());
try!(codes.to_file(&path));
println!("New token has been generated. Copy the code below to your Signer UI:");
println!("{}", code);
println!("This key code will authorise your System Signer UI: {}", White.bold().paint(code));
Ok(())
}

59
parity/url.rs Normal file
View File

@@ -0,0 +1,59 @@
// 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/>.
//! Cross-platform open url in default browser
#[cfg(windows)]
mod shell {
extern crate winapi;
use self::winapi::*;
extern "system" {
pub fn ShellExecuteA(
hwnd: HWND, lpOperation: LPCSTR, lpFile: LPCSTR, lpParameters: LPCSTR, lpDirectory: LPCSTR,
nShowCmd: c_int
) -> HINSTANCE;
}
pub use self::winapi::SW_SHOWNORMAL as Normal;
}
#[cfg(windows)]
pub fn open(url: &str) {
use std::ffi::CString;
use std::ptr;
unsafe {
shell::ShellExecuteA(ptr::null_mut(),
CString::new("open").unwrap().as_ptr(),
CString::new(url.to_owned().replace("\n", "%0A")).unwrap().as_ptr(),
ptr::null(),
ptr::null(),
shell::Normal);
}
}
#[cfg(target_os="macos")]
pub fn open(url: &str) {
use std;
let _ = std::process::Command::new("open").arg(url).spawn();
}
#[cfg(target_os="linux")]
pub fn open(url: &str) {
use std;
let _ = std::process::Command::new("xdg-open").arg(url).spawn();
}