merge with master
This commit is contained in:
@@ -170,6 +170,10 @@ Sealing/Mining Options:
|
||||
amount in USD, a web service or 'auto' to use each
|
||||
web service in turn and fallback on the last known
|
||||
good value [default: auto].
|
||||
--price-update-period T T will be allowed to pass between each gas price
|
||||
update. T may be daily, hourly, a number of seconds,
|
||||
or a time string of the form "2 days", "30 minutes"
|
||||
etc. [default: hourly].
|
||||
--gas-floor-target GAS Amount of gas per block to target when sealing a new
|
||||
block [default: 4700000].
|
||||
--gas-cap GAS A cap on how large we will raise the gas limit per
|
||||
@@ -335,6 +339,7 @@ pub struct Args {
|
||||
pub flag_author: Option<String>,
|
||||
pub flag_usd_per_tx: String,
|
||||
pub flag_usd_per_eth: String,
|
||||
pub flag_price_update_period: String,
|
||||
pub flag_gas_floor_target: String,
|
||||
pub flag_gas_cap: String,
|
||||
pub flag_extra_data: Option<String>,
|
||||
|
||||
@@ -29,11 +29,10 @@ use util::log::Colour::*;
|
||||
use ethcore::account_provider::AccountProvider;
|
||||
use util::network_settings::NetworkSettings;
|
||||
use ethcore::client::{append_path, get_db_path, Mode, ClientConfig, DatabaseCompactionProfile, Switch, VMType};
|
||||
use ethcore::miner::{MinerOptions, PendingSet};
|
||||
use ethcore::miner::{MinerOptions, PendingSet, GasPricer, GasPriceCalibratorOptions};
|
||||
use ethcore::ethereum;
|
||||
use ethcore::spec::Spec;
|
||||
use ethsync::SyncConfig;
|
||||
use price_info::PriceInfo;
|
||||
use rpc::IpcConfiguration;
|
||||
|
||||
pub struct Configuration {
|
||||
@@ -154,35 +153,52 @@ impl Configuration {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn gas_price(&self) -> U256 {
|
||||
fn to_duration(s: &str) -> Duration {
|
||||
let bad = |_| {
|
||||
die!("{}: Invalid duration given. See parity --help for more information.", s)
|
||||
};
|
||||
Duration::from_secs(match s {
|
||||
"twice-daily" => 12 * 60 * 60,
|
||||
"half-hourly" => 30 * 60,
|
||||
"1second" | "1 second" | "second" => 1,
|
||||
"1minute" | "1 minute" | "minute" => 60,
|
||||
"hourly" | "1hour" | "1 hour" | "hour" => 60 * 60,
|
||||
"daily" | "1day" | "1 day" | "day" => 24 * 60 * 60,
|
||||
x if x.ends_with("seconds") => FromStr::from_str(&x[0..x.len() - 7]).unwrap_or_else(bad),
|
||||
x if x.ends_with("minutes") => FromStr::from_str(&x[0..x.len() - 7]).unwrap_or_else(bad) * 60,
|
||||
x if x.ends_with("hours") => FromStr::from_str(&x[0..x.len() - 5]).unwrap_or_else(bad) * 60 * 60,
|
||||
x if x.ends_with("days") => FromStr::from_str(&x[0..x.len() - 4]).unwrap_or_else(bad) * 24 * 60 * 60,
|
||||
x => FromStr::from_str(x).unwrap_or_else(bad),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn gas_pricer(&self) -> GasPricer {
|
||||
match self.args.flag_gasprice.as_ref() {
|
||||
Some(d) => {
|
||||
U256::from_dec_str(d).unwrap_or_else(|_| {
|
||||
GasPricer::Fixed(U256::from_dec_str(d).unwrap_or_else(|_| {
|
||||
die!("{}: Invalid gas price given. Must be a decimal unsigned 256-bit number.", d)
|
||||
})
|
||||
}))
|
||||
}
|
||||
_ => {
|
||||
let usd_per_tx: f32 = FromStr::from_str(&self.args.flag_usd_per_tx).unwrap_or_else(|_| {
|
||||
die!("{}: Invalid basic transaction price given in USD. Must be a decimal number.", self.args.flag_usd_per_tx)
|
||||
});
|
||||
let usd_per_eth = match self.args.flag_usd_per_eth.as_str() {
|
||||
"auto" => PriceInfo::get().map_or_else(|| {
|
||||
let last_known_good = 9.69696;
|
||||
// TODO: use #1083 to read last known good value.
|
||||
last_known_good
|
||||
}, |x| x.ethusd),
|
||||
"etherscan" => PriceInfo::get().map_or_else(|| {
|
||||
die!("Unable to retrieve USD value of ETH from etherscan. Rerun with a different value for --usd-per-eth.")
|
||||
}, |x| x.ethusd),
|
||||
x => FromStr::from_str(x).unwrap_or_else(|_| die!("{}: Invalid ether price given in USD. Must be a decimal number.", x))
|
||||
};
|
||||
// TODO: use #1083 to write last known good value as use_per_eth.
|
||||
|
||||
let wei_per_usd: f32 = 1.0e18 / usd_per_eth;
|
||||
let gas_per_tx: f32 = 21000.0;
|
||||
let wei_per_gas: f32 = wei_per_usd * usd_per_tx / gas_per_tx;
|
||||
info!("Using a conversion rate of Ξ1 = {} ({} wei/gas)", format!("US${}", usd_per_eth).apply(White.bold()), format!("{}", wei_per_gas).apply(Yellow.bold()));
|
||||
U256::from_dec_str(&format!("{:.0}", wei_per_gas)).unwrap()
|
||||
match self.args.flag_usd_per_eth.as_str() {
|
||||
"auto" => {
|
||||
GasPricer::new_calibrated(GasPriceCalibratorOptions {
|
||||
usd_per_tx: usd_per_tx,
|
||||
recalibration_period: Self::to_duration(self.args.flag_price_update_period.as_str()),
|
||||
})
|
||||
},
|
||||
x => {
|
||||
let usd_per_eth: f32 = FromStr::from_str(x).unwrap_or_else(|_| die!("{}: Invalid ether price given in USD. Must be a decimal number.", x));
|
||||
let wei_per_usd: f32 = 1.0e18 / usd_per_eth;
|
||||
let gas_per_tx: f32 = 21000.0;
|
||||
let wei_per_gas: f32 = wei_per_usd * usd_per_tx / gas_per_tx;
|
||||
info!("Using a fixed conversion rate of Ξ1 = {} ({} wei/gas)", format!("US${}", usd_per_eth).apply(White.bold()), format!("{}", wei_per_gas).apply(Yellow.bold()));
|
||||
GasPricer::Fixed(U256::from_dec_str(&format!("{:.0}", wei_per_gas)).unwrap())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,166 +0,0 @@
|
||||
// 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/>.
|
||||
|
||||
//! Parity interprocess hypervisor module
|
||||
|
||||
// while not included in binary
|
||||
#![allow(dead_code)]
|
||||
#![cfg_attr(feature="dev", allow(used_underscore_binding))]
|
||||
|
||||
pub mod service;
|
||||
|
||||
/// Default value for hypervisor ipc listener
|
||||
pub const HYPERVISOR_IPC_URL: &'static str = "ipc:///tmp/parity-internal-hyper-status.ipc";
|
||||
|
||||
use nanoipc;
|
||||
use std::sync::{Arc,RwLock};
|
||||
use hypervisor::service::*;
|
||||
use std::process::{Command,Child};
|
||||
use std::collections::HashMap;
|
||||
|
||||
type BinaryId = &'static str;
|
||||
|
||||
const BLOCKCHAIN_DB_BINARY: BinaryId = "blockchain";
|
||||
|
||||
pub struct Hypervisor {
|
||||
ipc_addr: String,
|
||||
service: Arc<HypervisorService>,
|
||||
ipc_worker: RwLock<nanoipc::Worker<HypervisorService>>,
|
||||
processes: RwLock<HashMap<BinaryId, Child>>,
|
||||
}
|
||||
|
||||
impl Default for Hypervisor {
|
||||
fn default() -> Self {
|
||||
Hypervisor::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Hypervisor {
|
||||
/// initializes the Hypervisor service with the open ipc socket for incoming clients
|
||||
pub fn new() -> Hypervisor {
|
||||
Hypervisor::with_url(HYPERVISOR_IPC_URL)
|
||||
}
|
||||
|
||||
/// Starts on the specified address for ipc listener
|
||||
fn with_url(addr: &str) -> Hypervisor{
|
||||
Hypervisor::with_url_and_service(addr, HypervisorService::new())
|
||||
}
|
||||
|
||||
/// Starts with the specified address for the ipc listener and
|
||||
/// the specified list of modules in form of created service
|
||||
fn with_url_and_service(addr: &str, service: Arc<HypervisorService>) -> Hypervisor {
|
||||
let worker = nanoipc::Worker::new(&service);
|
||||
Hypervisor{
|
||||
ipc_addr: addr.to_owned(),
|
||||
service: service,
|
||||
ipc_worker: RwLock::new(worker),
|
||||
processes: RwLock::new(HashMap::new()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Since one binary can host multiple modules
|
||||
/// we match binaries
|
||||
fn match_module(module_id: &IpcModuleId) -> Option<BinaryId> {
|
||||
match *module_id {
|
||||
BLOCKCHAIN_MODULE_ID => Some(BLOCKCHAIN_DB_BINARY),
|
||||
// none means the module is inside the main binary
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates IPC listener and starts all binaries
|
||||
fn start(&self) {
|
||||
let mut worker = self.ipc_worker.write().unwrap();
|
||||
worker.add_reqrep(&self.ipc_addr).unwrap_or_else(|e| panic!("Hypervisor ipc worker can not start - critical! ({:?})", e));
|
||||
|
||||
for module_id in self.service.module_ids() {
|
||||
self.start_module(module_id);
|
||||
}
|
||||
}
|
||||
|
||||
/// Start binary for the specified module
|
||||
/// Does nothing when it is already started on module is inside the
|
||||
/// main binary
|
||||
fn start_module(&self, module_id: IpcModuleId) {
|
||||
Self::match_module(&module_id).map(|binary_id| {
|
||||
let mut processes = self.processes.write().unwrap();
|
||||
{
|
||||
if processes.get(binary_id).is_some() {
|
||||
// already started for another module
|
||||
return;
|
||||
}
|
||||
}
|
||||
let child = Command::new(binary_id).spawn().unwrap_or_else(
|
||||
|e| panic!("Hypervisor cannot start binary: {}", e));
|
||||
processes.insert(binary_id, child);
|
||||
});
|
||||
}
|
||||
|
||||
/// Reports if all modules are checked in
|
||||
pub fn modules_ready(&self) -> bool {
|
||||
self.service.unchecked_count() == 0
|
||||
}
|
||||
|
||||
/// Waits for every required module to check in
|
||||
pub fn wait_for_startup(&self) {
|
||||
let mut worker = self.ipc_worker.write().unwrap();
|
||||
while !self.modules_ready() {
|
||||
worker.poll()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::sync::atomic::{AtomicBool,Ordering};
|
||||
use std::sync::Arc;
|
||||
use super::service::*;
|
||||
use nanoipc;
|
||||
|
||||
#[test]
|
||||
fn can_init() {
|
||||
let url = "ipc:///tmp/test-parity-hypervisor-10.ipc";
|
||||
let test_module_id = 8080u64;
|
||||
|
||||
let hypervisor = Hypervisor::with_url_and_service(url, HypervisorService::with_modules(vec![test_module_id]));
|
||||
assert_eq!(false, hypervisor.modules_ready());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_wait_for_startup() {
|
||||
let url = "ipc:///tmp/test-parity-hypervisor-20.ipc";
|
||||
let test_module_id = 8080u64;
|
||||
|
||||
let hypervisor_ready = Arc::new(AtomicBool::new(false));
|
||||
let hypervisor_ready_local = hypervisor_ready.clone();
|
||||
|
||||
::std::thread::spawn(move || {
|
||||
while !hypervisor_ready.load(Ordering::Relaxed) { }
|
||||
|
||||
let client = nanoipc::init_client::<HypervisorServiceClient<_>>(url).unwrap();
|
||||
client.handshake().unwrap();
|
||||
client.module_ready(test_module_id);
|
||||
});
|
||||
|
||||
let hypervisor = Hypervisor::with_url_and_service(url, HypervisorService::with_modules(vec![test_module_id]));
|
||||
hypervisor.start();
|
||||
hypervisor_ready_local.store(true, Ordering::Relaxed);
|
||||
hypervisor.wait_for_startup();
|
||||
|
||||
assert_eq!(true, hypervisor.modules_ready());
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
// 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/>.
|
||||
|
||||
//! Parity interprocess hypervisor IPC service
|
||||
#![allow(dead_code, unused_assignments, unused_variables)] // codegen issues
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/hypervisor_service_cg.rs"));
|
||||
@@ -1,71 +0,0 @@
|
||||
// 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/>.
|
||||
|
||||
use std::sync::{RwLock,Arc};
|
||||
use ipc::IpcConfig;
|
||||
use std::collections::HashMap;
|
||||
use std::mem;
|
||||
use ipc::binary::BinaryConvertError;
|
||||
use std::collections::VecDeque;
|
||||
|
||||
pub type IpcModuleId = u64;
|
||||
|
||||
/// Blockhain database module id
|
||||
pub const BLOCKCHAIN_MODULE_ID: IpcModuleId = 2000;
|
||||
|
||||
/// IPC service that handles module management
|
||||
pub struct HypervisorService {
|
||||
check_list: RwLock<HashMap<IpcModuleId, bool>>,
|
||||
}
|
||||
|
||||
#[derive(Ipc)]
|
||||
impl HypervisorService {
|
||||
fn module_ready(&self, module_id: u64) -> bool {
|
||||
let mut check_list = self.check_list.write().unwrap();
|
||||
check_list.get_mut(&module_id).map(|mut status| *status = true);
|
||||
check_list.iter().any(|(_, status)| !status)
|
||||
}
|
||||
}
|
||||
|
||||
impl HypervisorService {
|
||||
/// New service with the default list of modules
|
||||
pub fn new() -> Arc<HypervisorService> {
|
||||
HypervisorService::with_modules(vec![])
|
||||
}
|
||||
|
||||
/// New service with list of modules that will report for being ready
|
||||
pub fn with_modules(module_ids: Vec<IpcModuleId>) -> Arc<HypervisorService> {
|
||||
let mut check_list = HashMap::new();
|
||||
for module_id in module_ids {
|
||||
check_list.insert(module_id, false);
|
||||
}
|
||||
Arc::new(HypervisorService {
|
||||
check_list: RwLock::new(check_list),
|
||||
})
|
||||
}
|
||||
|
||||
/// Number of modules still being waited for check-in
|
||||
pub fn unchecked_count(&self) -> usize {
|
||||
self.check_list.read().unwrap().iter().filter(|&(_, status)| !status).count()
|
||||
}
|
||||
|
||||
/// List of all modules within this service
|
||||
pub fn module_ids(&self) -> Vec<IpcModuleId> {
|
||||
self.check_list.read().unwrap().iter().map(|(module_id, _)| module_id).cloned().collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl ::ipc::IpcConfig for HypervisorService {}
|
||||
@@ -22,7 +22,7 @@ use std::time::{Instant, Duration};
|
||||
use std::sync::RwLock;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use ethsync::{EthSync, SyncProvider};
|
||||
use util::{Uint, NetworkService};
|
||||
use util::{Uint, RwLockable, NetworkService};
|
||||
use ethcore::client::*;
|
||||
use number_prefix::{binary_prefix, Standalone, Prefixed};
|
||||
|
||||
@@ -75,20 +75,19 @@ impl Informant {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature="dev", allow(match_bool))]
|
||||
pub fn tick<Message>(&self, client: &Client, maybe_sync: Option<(&EthSync, &NetworkService<Message>)>) where Message: Send + Sync + Clone + 'static {
|
||||
let elapsed = self.last_tick.read().unwrap().elapsed();
|
||||
let elapsed = self.last_tick.unwrapped_read().elapsed();
|
||||
if elapsed < Duration::from_secs(5) {
|
||||
return;
|
||||
}
|
||||
|
||||
*self.last_tick.write().unwrap() = Instant::now();
|
||||
*self.last_tick.unwrapped_write() = Instant::now();
|
||||
|
||||
let chain_info = client.chain_info();
|
||||
let queue_info = client.queue_info();
|
||||
let cache_info = client.blockchain_cache_info();
|
||||
|
||||
let mut write_report = self.report.write().unwrap();
|
||||
let mut write_report = self.report.unwrapped_write();
|
||||
let report = client.report();
|
||||
|
||||
let paint = |c: Style, t: String| match self.with_color {
|
||||
@@ -97,8 +96,8 @@ impl Informant {
|
||||
};
|
||||
|
||||
if let (_, _, &Some(ref last_report)) = (
|
||||
self.chain_info.read().unwrap().deref(),
|
||||
self.cache_info.read().unwrap().deref(),
|
||||
self.chain_info.unwrapped_read().deref(),
|
||||
self.cache_info.unwrapped_read().deref(),
|
||||
write_report.deref()
|
||||
) {
|
||||
println!("{} {} {} blk/s {} tx/s {} Mgas/s {}{}+{} Qed {} db {} chain {} queue{}",
|
||||
@@ -139,8 +138,8 @@ impl Informant {
|
||||
);
|
||||
}
|
||||
|
||||
*self.chain_info.write().unwrap().deref_mut() = Some(chain_info);
|
||||
*self.cache_info.write().unwrap().deref_mut() = Some(cache_info);
|
||||
*self.chain_info.unwrapped_write().deref_mut() = Some(chain_info);
|
||||
*self.cache_info.unwrapped_write().deref_mut() = Some(cache_info);
|
||||
*write_report.deref_mut() = Some(report);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,14 +49,12 @@ impl IoHandler<NetSyncMessage> for ClientIoHandler {
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#![cfg_attr(feature="dev", feature(plugin))]
|
||||
#![cfg_attr(feature="dev", plugin(clippy))]
|
||||
#![cfg_attr(feature="dev", allow(useless_format))]
|
||||
#![cfg_attr(feature="dev", allow(match_bool))]
|
||||
|
||||
extern crate docopt;
|
||||
extern crate num_cpus;
|
||||
@@ -44,6 +45,8 @@ extern crate ethcore_ipc_nano as nanoipc;
|
||||
extern crate hyper; // for price_info.rs
|
||||
extern crate json_ipc_server as jsonipc;
|
||||
|
||||
extern crate ethcore_ipc_hypervisor as hypervisor;
|
||||
|
||||
#[cfg(feature = "rpc")]
|
||||
extern crate ethcore_rpc;
|
||||
|
||||
@@ -55,9 +58,7 @@ extern crate ethcore_signer;
|
||||
|
||||
#[macro_use]
|
||||
mod die;
|
||||
mod price_info;
|
||||
mod upgrade;
|
||||
mod hypervisor;
|
||||
mod setup_log;
|
||||
mod rpc;
|
||||
mod dapps;
|
||||
@@ -80,7 +81,7 @@ use std::thread::sleep;
|
||||
use std::time::Duration;
|
||||
use rustc_serialize::hex::FromHex;
|
||||
use ctrlc::CtrlC;
|
||||
use util::{H256, ToPretty, NetworkConfiguration, PayloadInfo, Bytes, UtilError, Colour, Applyable, version, journaldb};
|
||||
use util::{Lockable, H256, ToPretty, NetworkConfiguration, PayloadInfo, Bytes, UtilError, Colour, Applyable, version, journaldb};
|
||||
use util::panics::{MayPanic, ForwardPanic, PanicHandler};
|
||||
use ethcore::client::{Mode, BlockID, BlockChainClient, ClientConfig, get_db_path, BlockImportError};
|
||||
use ethcore::error::{ImportError};
|
||||
@@ -212,7 +213,7 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig)
|
||||
|
||||
// Check fork settings.
|
||||
if conf.policy() != Policy::None {
|
||||
warn!("Value given for --policy, yet no proposed forks exist. Ignoring.");
|
||||
warn!("Value given for --policy, yet no proposed forks exist. Ignoring.");
|
||||
}
|
||||
|
||||
let net_settings = conf.net_settings(&spec);
|
||||
@@ -222,12 +223,11 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig)
|
||||
let account_service = Arc::new(conf.account_service());
|
||||
|
||||
// Miner
|
||||
let miner = Miner::new(conf.miner_options(), conf.spec(), Some(account_service.clone()));
|
||||
let miner = Miner::new(conf.miner_options(), conf.gas_pricer(), 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_queue_size);
|
||||
|
||||
// Build client
|
||||
@@ -614,7 +614,7 @@ fn wait_for_exit(
|
||||
|
||||
// Wait for signal
|
||||
let mutex = Mutex::new(());
|
||||
let _ = exit.wait(mutex.lock().unwrap()).unwrap();
|
||||
let _ = exit.wait(mutex.locked()).unwrap();
|
||||
info!("Finishing work, please wait...");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
// 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/>.
|
||||
|
||||
use rustc_serialize::json::Json;
|
||||
use std::io::Read;
|
||||
use hyper::Client;
|
||||
use hyper::header::Connection;
|
||||
use std::str::FromStr;
|
||||
|
||||
pub struct PriceInfo {
|
||||
pub ethusd: f32,
|
||||
}
|
||||
|
||||
impl PriceInfo {
|
||||
pub fn get() -> Option<PriceInfo> {
|
||||
let mut body = String::new();
|
||||
// TODO: Handle each error type properly
|
||||
let mut client = Client::new();
|
||||
client.set_read_timeout(Some(::std::time::Duration::from_secs(3)));
|
||||
client.get("http://api.etherscan.io/api?module=stats&action=ethprice")
|
||||
.header(Connection::close())
|
||||
.send()
|
||||
.ok()
|
||||
.and_then(|mut s| s.read_to_string(&mut body).ok())
|
||||
.and_then(|_| Json::from_str(&body).ok())
|
||||
.and_then(|json| json.find_path(&["result", "ethusd"])
|
||||
.and_then(|obj| match *obj {
|
||||
Json::String(ref s) => Some(PriceInfo {
|
||||
ethusd: FromStr::from_str(s).unwrap()
|
||||
}),
|
||||
_ => None
|
||||
}))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user