Merge branch 'engine-password' into auth-bft
This commit is contained in:
commit
8f641e67f3
8
Cargo.lock
generated
8
Cargo.lock
generated
@ -24,7 +24,7 @@ dependencies = [
|
|||||||
"ethcore-stratum 1.4.0",
|
"ethcore-stratum 1.4.0",
|
||||||
"ethcore-util 1.5.0",
|
"ethcore-util 1.5.0",
|
||||||
"ethsync 1.5.0",
|
"ethsync 1.5.0",
|
||||||
"fdlimit 0.1.0",
|
"fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"hyper 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"hyper 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -684,7 +684,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fdlimit"
|
name = "fdlimit"
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
@ -1270,7 +1271,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "parity-ui-precompiled"
|
name = "parity-ui-precompiled"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
source = "git+https://github.com/ethcore/js-precompiled.git#7700411d2b0ba1372e0d6cf72a84ecf873a181f3"
|
source = "git+https://github.com/ethcore/js-precompiled.git#3cf6c68b7d08be71d12ff142e255a42043e50c75"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
@ -2027,6 +2028,7 @@ dependencies = [
|
|||||||
"checksum env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "aba65b63ffcc17ffacd6cf5aa843da7c5a25e3bd4bbe0b7def8b214e411250e5"
|
"checksum env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "aba65b63ffcc17ffacd6cf5aa843da7c5a25e3bd4bbe0b7def8b214e411250e5"
|
||||||
"checksum eth-secp256k1 0.5.4 (git+https://github.com/ethcore/rust-secp256k1)" = "<none>"
|
"checksum eth-secp256k1 0.5.4 (git+https://github.com/ethcore/rust-secp256k1)" = "<none>"
|
||||||
"checksum ethabi 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0c53453517f620847be51943db329276ae52f2e210cfc659e81182864be2f"
|
"checksum ethabi 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0c53453517f620847be51943db329276ae52f2e210cfc659e81182864be2f"
|
||||||
|
"checksum fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b1ee15a7050e5580b3712877157068ea713b245b080ff302ae2ca973cfcd9baa"
|
||||||
"checksum flate2 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "3eeb481e957304178d2e782f2da1257f1434dfecbae883bafb61ada2a9fea3bb"
|
"checksum flate2 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "3eeb481e957304178d2e782f2da1257f1434dfecbae883bafb61ada2a9fea3bb"
|
||||||
"checksum gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)" = "91ecd03771effb0c968fd6950b37e89476a578aaf1c70297d8e92b6516ec3312"
|
"checksum gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)" = "91ecd03771effb0c968fd6950b37e89476a578aaf1c70297d8e92b6516ec3312"
|
||||||
"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
|
"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
|
||||||
|
@ -30,7 +30,7 @@ serde = "0.8.0"
|
|||||||
serde_json = "0.8.0"
|
serde_json = "0.8.0"
|
||||||
hyper = { version = "0.9", default-features = false }
|
hyper = { version = "0.9", default-features = false }
|
||||||
ctrlc = { git = "https://github.com/ethcore/rust-ctrlc.git" }
|
ctrlc = { git = "https://github.com/ethcore/rust-ctrlc.git" }
|
||||||
fdlimit = { path = "util/fdlimit" }
|
fdlimit = "0.1"
|
||||||
ethcore = { path = "ethcore" }
|
ethcore = { path = "ethcore" }
|
||||||
ethcore-util = { path = "util" }
|
ethcore-util = { path = "util" }
|
||||||
ethsync = { path = "sync" }
|
ethsync = { path = "sync" }
|
||||||
|
@ -200,6 +200,7 @@ pub struct BlockChain {
|
|||||||
pending_block_details: RwLock<HashMap<H256, BlockDetails>>,
|
pending_block_details: RwLock<HashMap<H256, BlockDetails>>,
|
||||||
pending_transaction_addresses: RwLock<HashMap<H256, Option<TransactionAddress>>>,
|
pending_transaction_addresses: RwLock<HashMap<H256, Option<TransactionAddress>>>,
|
||||||
|
|
||||||
|
// Used for block ordering.
|
||||||
engine: Arc<Engine>,
|
engine: Arc<Engine>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,10 +209,6 @@ impl Engine for AuthorityRound {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Apply the block reward on finalisation of the block.
|
|
||||||
/// This assumes that all uncles are valid uncles (i.e. of at least one generation before the current).
|
|
||||||
fn on_close_block(&self, _block: &mut ExecutedBlock) {}
|
|
||||||
|
|
||||||
fn is_sealer(&self, author: &Address) -> Option<bool> {
|
fn is_sealer(&self, author: &Address) -> Option<bool> {
|
||||||
let p = &self.our_params;
|
let p = &self.our_params;
|
||||||
Some(p.authorities.contains(author))
|
Some(p.authorities.contains(author))
|
||||||
|
@ -100,13 +100,8 @@ impl Engine for BasicAuthority {
|
|||||||
max(gas_floor_target, gas_limit - gas_limit / bound_divisor + 1.into())
|
max(gas_floor_target, gas_limit - gas_limit / bound_divisor + 1.into())
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// info!("ethash: populate_from_parent #{}: difficulty={} and gas_limit={}", header.number, header.difficulty, header.gas_limit);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Apply the block reward on finalisation of the block.
|
|
||||||
/// This assumes that all uncles are valid uncles (i.e. of at least one generation before the current).
|
|
||||||
fn on_close_block(&self, _block: &mut ExecutedBlock) {}
|
|
||||||
|
|
||||||
fn is_sealer(&self, author: &Address) -> Option<bool> {
|
fn is_sealer(&self, author: &Address) -> Option<bool> {
|
||||||
Some(self.our_params.authorities.contains(author))
|
Some(self.our_params.authorities.contains(author))
|
||||||
}
|
}
|
||||||
|
@ -184,17 +184,17 @@ pub trait Engine : Sync + Send {
|
|||||||
self.builtins().get(a).expect("attempted to execute nonexistent builtin").execute(input, output);
|
self.builtins().get(a).expect("attempted to execute nonexistent builtin").execute(input, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if new block should be chosen as the one in chain.
|
||||||
|
fn is_new_best_block(&self, best_total_difficulty: U256, _best_header: HeaderView, parent_details: &BlockDetails, new_header: &HeaderView) -> bool {
|
||||||
|
ethash::is_new_best_block(best_total_difficulty, parent_details, new_header)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Register an account which signs consensus messages.
|
||||||
|
fn set_signer(&self, _address: Address, _password: String) {}
|
||||||
|
|
||||||
/// Add a channel for communication with Client which can be used for sealing.
|
/// Add a channel for communication with Client which can be used for sealing.
|
||||||
fn register_message_channel(&self, _message_channel: IoChannel<ClientIoMessage>) {}
|
fn register_message_channel(&self, _message_channel: IoChannel<ClientIoMessage>) {}
|
||||||
|
|
||||||
/// Add an account provider useful for Engines that sign stuff.
|
/// Add an account provider useful for Engines that sign stuff.
|
||||||
fn register_account_provider(&self, _account_provider: Arc<AccountProvider>) {}
|
fn register_account_provider(&self, _account_provider: Arc<AccountProvider>) {}
|
||||||
|
|
||||||
/// Register an account which signs consensus messages.
|
|
||||||
fn set_signer(&self, _address: Address, _password: String) {}
|
|
||||||
|
|
||||||
/// Check if new block should be chosen as the one in chain.
|
|
||||||
fn is_new_best_block(&self, best_total_difficulty: U256, _best_header: HeaderView, parent_details: &BlockDetails, new_header: &HeaderView) -> bool {
|
|
||||||
ethash::is_new_best_block(best_total_difficulty, parent_details, new_header)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -328,12 +328,16 @@ impl Engine for Ethash {
|
|||||||
t.sender().map(|_|()) // Perform EC recovery and cache sender
|
t.sender().map(|_|()) // Perform EC recovery and cache sender
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if new block should be chosen as the one in chain.
|
|
||||||
fn is_new_best_block(&self, best_total_difficulty: U256, _best_header: HeaderView, parent_details: &BlockDetails, new_header: &HeaderView) -> bool {
|
fn is_new_best_block(&self, best_total_difficulty: U256, _best_header: HeaderView, parent_details: &BlockDetails, new_header: &HeaderView) -> bool {
|
||||||
is_new_best_block(best_total_difficulty, parent_details, new_header)
|
is_new_best_block(best_total_difficulty, parent_details, new_header)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if a new block should replace the best blockchain block.
|
||||||
|
pub fn is_new_best_block(best_total_difficulty: U256, parent_details: &BlockDetails, new_header: &HeaderView) -> bool {
|
||||||
|
parent_details.total_difficulty + new_header.difficulty() > best_total_difficulty
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature="dev", allow(wrong_self_convention))]
|
#[cfg_attr(feature="dev", allow(wrong_self_convention))]
|
||||||
impl Ethash {
|
impl Ethash {
|
||||||
fn calculate_difficulty(&self, header: &Header, parent: &Header) -> U256 {
|
fn calculate_difficulty(&self, header: &Header, parent: &Header) -> U256 {
|
||||||
@ -409,12 +413,6 @@ impl Ethash {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if a new block should replace the best blockchain block.
|
|
||||||
pub fn is_new_best_block(best_total_difficulty: U256, parent_details: &BlockDetails, new_header: &HeaderView) -> bool {
|
|
||||||
parent_details.total_difficulty + new_header.difficulty() > best_total_difficulty
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
impl Header {
|
impl Header {
|
||||||
/// Get the none field of the header.
|
/// Get the none field of the header.
|
||||||
pub fn nonce(&self) -> H64 {
|
pub fn nonce(&self) -> H64 {
|
||||||
|
@ -737,7 +737,7 @@ impl MinerService for Miner {
|
|||||||
*self.author.write() = author;
|
*self.author.write() = author;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_consensus_signer(&self, address: Address, password: String) -> Result<(), AccountError> {
|
fn set_engine_signer(&self, address: Address, password: String) -> Result<(), AccountError> {
|
||||||
if self.seals_internally {
|
if self.seals_internally {
|
||||||
if let Some(ref ap) = self.accounts {
|
if let Some(ref ap) = self.accounts {
|
||||||
try!(ap.sign(address.clone(), Some(password.clone()), Default::default()));
|
try!(ap.sign(address.clone(), Some(password.clone()), Default::default()));
|
||||||
|
@ -77,7 +77,7 @@ pub trait MinerService : Send + Sync {
|
|||||||
fn set_author(&self, author: Address);
|
fn set_author(&self, author: Address);
|
||||||
|
|
||||||
/// Set info necessary to sign consensus messages.
|
/// Set info necessary to sign consensus messages.
|
||||||
fn set_consensus_signer(&self, address: Address, password: String) -> Result<(), ::account_provider::Error>;
|
fn set_engine_signer(&self, address: Address, password: String) -> Result<(), ::account_provider::Error>;
|
||||||
|
|
||||||
/// Get the extra_data that we will seal blocks with.
|
/// Get the extra_data that we will seal blocks with.
|
||||||
fn extra_data(&self) -> Bytes;
|
fn extra_data(&self) -> Bytes;
|
||||||
|
@ -82,6 +82,7 @@ struct Restoration {
|
|||||||
struct RestorationParams<'a> {
|
struct RestorationParams<'a> {
|
||||||
manifest: ManifestData, // manifest to base restoration on.
|
manifest: ManifestData, // manifest to base restoration on.
|
||||||
pruning: Algorithm, // pruning algorithm for the database.
|
pruning: Algorithm, // pruning algorithm for the database.
|
||||||
|
engine: Arc<Engine>, // consensus engine of the chain.
|
||||||
db_path: PathBuf, // database path
|
db_path: PathBuf, // database path
|
||||||
db_config: &'a DatabaseConfig, // configuration for the database.
|
db_config: &'a DatabaseConfig, // configuration for the database.
|
||||||
writer: Option<LooseWriter>, // writer for recovered snapshot.
|
writer: Option<LooseWriter>, // writer for recovered snapshot.
|
||||||
@ -100,7 +101,7 @@ impl Restoration {
|
|||||||
let raw_db = Arc::new(try!(Database::open(params.db_config, &*params.db_path.to_string_lossy())
|
let raw_db = Arc::new(try!(Database::open(params.db_config, &*params.db_path.to_string_lossy())
|
||||||
.map_err(UtilError::SimpleString)));
|
.map_err(UtilError::SimpleString)));
|
||||||
|
|
||||||
let chain = BlockChain::new(Default::default(), params.genesis, raw_db.clone(), Spec::new_null().engine);
|
let chain = BlockChain::new(Default::default(), params.genesis, raw_db.clone(), params.engine);
|
||||||
let blocks = try!(BlockRebuilder::new(chain, raw_db.clone(), &manifest));
|
let blocks = try!(BlockRebuilder::new(chain, raw_db.clone(), &manifest));
|
||||||
|
|
||||||
let root = manifest.state_root.clone();
|
let root = manifest.state_root.clone();
|
||||||
@ -421,6 +422,7 @@ impl Service {
|
|||||||
let params = RestorationParams {
|
let params = RestorationParams {
|
||||||
manifest: manifest,
|
manifest: manifest,
|
||||||
pruning: self.pruning,
|
pruning: self.pruning,
|
||||||
|
engine: self.engine.clone(),
|
||||||
db_path: self.restoration_db(),
|
db_path: self.restoration_db(),
|
||||||
db_config: &self.db_config,
|
db_config: &self.db_config,
|
||||||
writer: writer,
|
writer: writer,
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
//! A queue of blocks. Sits between network or other I/O and the `BlockChain`.
|
//! A queue of blocks. Sits between network or other I/O and the `BlockChain`.
|
||||||
//! Sorts them ready for blockchain insertion.
|
//! Sorts them ready for blockchain insertion.
|
||||||
|
|
||||||
use std::thread::{JoinHandle, self};
|
use std::thread::{self, JoinHandle};
|
||||||
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering as AtomicOrdering};
|
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering as AtomicOrdering};
|
||||||
use std::sync::{Condvar as SCondvar, Mutex as SMutex};
|
use std::sync::{Condvar as SCondvar, Mutex as SMutex};
|
||||||
use util::*;
|
use util::*;
|
||||||
@ -64,35 +64,11 @@ impl Default for Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct VerifierHandle {
|
// pool states
|
||||||
deleting: Arc<AtomicBool>,
|
enum State {
|
||||||
sleep: Arc<AtomicBool>,
|
// all threads with id < inner value are to work.
|
||||||
thread: JoinHandle<()>,
|
Work(usize),
|
||||||
}
|
Exit,
|
||||||
|
|
||||||
impl VerifierHandle {
|
|
||||||
// signal to the verifier thread that it should sleep.
|
|
||||||
fn sleep(&self) {
|
|
||||||
self.sleep.store(true, AtomicOrdering::SeqCst);
|
|
||||||
}
|
|
||||||
|
|
||||||
// signal to the verifier thread that it should wake up.
|
|
||||||
fn wake_up(&self) {
|
|
||||||
self.sleep.store(false, AtomicOrdering::SeqCst);
|
|
||||||
self.thread.thread().unpark();
|
|
||||||
}
|
|
||||||
|
|
||||||
// signal to the verifier thread that it should conclude its
|
|
||||||
// operations.
|
|
||||||
fn conclude(&self) {
|
|
||||||
self.wake_up();
|
|
||||||
self.deleting.store(true, AtomicOrdering::Release);
|
|
||||||
}
|
|
||||||
|
|
||||||
// join the verifier thread.
|
|
||||||
fn join(self) {
|
|
||||||
self.thread.join().expect("Verifier thread panicked");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An item which is in the process of being verified.
|
/// An item which is in the process of being verified.
|
||||||
@ -131,7 +107,6 @@ pub struct VerificationQueue<K: Kind> {
|
|||||||
engine: Arc<Engine>,
|
engine: Arc<Engine>,
|
||||||
more_to_verify: Arc<SCondvar>,
|
more_to_verify: Arc<SCondvar>,
|
||||||
verification: Arc<Verification<K>>,
|
verification: Arc<Verification<K>>,
|
||||||
verifiers: Mutex<(Vec<VerifierHandle>, usize)>,
|
|
||||||
deleting: Arc<AtomicBool>,
|
deleting: Arc<AtomicBool>,
|
||||||
ready_signal: Arc<QueueSignal>,
|
ready_signal: Arc<QueueSignal>,
|
||||||
empty: Arc<SCondvar>,
|
empty: Arc<SCondvar>,
|
||||||
@ -139,6 +114,8 @@ pub struct VerificationQueue<K: Kind> {
|
|||||||
ticks_since_adjustment: AtomicUsize,
|
ticks_since_adjustment: AtomicUsize,
|
||||||
max_queue_size: usize,
|
max_queue_size: usize,
|
||||||
max_mem_use: usize,
|
max_mem_use: usize,
|
||||||
|
verifier_handles: Vec<JoinHandle<()>>,
|
||||||
|
state: Arc<(Mutex<State>, Condvar)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct QueueSignal {
|
struct QueueSignal {
|
||||||
@ -224,40 +201,39 @@ impl<K: Kind> VerificationQueue<K> {
|
|||||||
|
|
||||||
let max_verifiers = min(::num_cpus::get(), MAX_VERIFIERS);
|
let max_verifiers = min(::num_cpus::get(), MAX_VERIFIERS);
|
||||||
let default_amount = max(::num_cpus::get(), 3) - 2;
|
let default_amount = max(::num_cpus::get(), 3) - 2;
|
||||||
let mut verifiers = Vec::with_capacity(max_verifiers);
|
let state = Arc::new((Mutex::new(State::Work(default_amount)), Condvar::new()));
|
||||||
|
let mut verifier_handles = Vec::with_capacity(max_verifiers);
|
||||||
|
|
||||||
debug!(target: "verification", "Allocating {} verifiers, {} initially active", max_verifiers, default_amount);
|
debug!(target: "verification", "Allocating {} verifiers, {} initially active", max_verifiers, default_amount);
|
||||||
|
|
||||||
for i in 0..max_verifiers {
|
for i in 0..max_verifiers {
|
||||||
debug!(target: "verification", "Adding verification thread #{}", i);
|
debug!(target: "verification", "Adding verification thread #{}", i);
|
||||||
|
|
||||||
let deleting = deleting.clone();
|
|
||||||
let panic_handler = panic_handler.clone();
|
let panic_handler = panic_handler.clone();
|
||||||
let verification = verification.clone();
|
let verification = verification.clone();
|
||||||
let engine = engine.clone();
|
let engine = engine.clone();
|
||||||
let wait = more_to_verify.clone();
|
let wait = more_to_verify.clone();
|
||||||
let ready = ready_signal.clone();
|
let ready = ready_signal.clone();
|
||||||
let empty = empty.clone();
|
let empty = empty.clone();
|
||||||
|
let state = state.clone();
|
||||||
|
|
||||||
// enable only the first few verifiers.
|
let handle = thread::Builder::new()
|
||||||
let sleep = if i < default_amount {
|
.name(format!("Verifier #{}", i))
|
||||||
Arc::new(AtomicBool::new(false))
|
.spawn(move || {
|
||||||
} else {
|
panic_handler.catch_panic(move || {
|
||||||
Arc::new(AtomicBool::new(true))
|
VerificationQueue::verify(
|
||||||
};
|
verification,
|
||||||
|
engine,
|
||||||
verifiers.push(VerifierHandle {
|
wait,
|
||||||
deleting: deleting.clone(),
|
ready,
|
||||||
sleep: sleep.clone(),
|
empty,
|
||||||
thread: thread::Builder::new()
|
state,
|
||||||
.name(format!("Verifier #{}", i))
|
i,
|
||||||
.spawn(move || {
|
)
|
||||||
panic_handler.catch_panic(move || {
|
}).unwrap()
|
||||||
VerificationQueue::verify(verification, engine, wait, ready, deleting, empty, sleep)
|
})
|
||||||
}).unwrap()
|
.expect("Failed to create verifier thread.");
|
||||||
})
|
verifier_handles.push(handle);
|
||||||
.expect("Failed to create verifier thread.")
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VerificationQueue {
|
VerificationQueue {
|
||||||
@ -266,13 +242,14 @@ impl<K: Kind> VerificationQueue<K> {
|
|||||||
ready_signal: ready_signal,
|
ready_signal: ready_signal,
|
||||||
more_to_verify: more_to_verify,
|
more_to_verify: more_to_verify,
|
||||||
verification: verification,
|
verification: verification,
|
||||||
verifiers: Mutex::new((verifiers, default_amount)),
|
|
||||||
deleting: deleting,
|
deleting: deleting,
|
||||||
processing: RwLock::new(HashSet::new()),
|
processing: RwLock::new(HashSet::new()),
|
||||||
empty: empty,
|
empty: empty,
|
||||||
ticks_since_adjustment: AtomicUsize::new(0),
|
ticks_since_adjustment: AtomicUsize::new(0),
|
||||||
max_queue_size: max(config.max_queue_size, MIN_QUEUE_LIMIT),
|
max_queue_size: max(config.max_queue_size, MIN_QUEUE_LIMIT),
|
||||||
max_mem_use: max(config.max_mem_use, MIN_MEM_LIMIT),
|
max_mem_use: max(config.max_mem_use, MIN_MEM_LIMIT),
|
||||||
|
verifier_handles: verifier_handles,
|
||||||
|
state: state,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,23 +258,30 @@ impl<K: Kind> VerificationQueue<K> {
|
|||||||
engine: Arc<Engine>,
|
engine: Arc<Engine>,
|
||||||
wait: Arc<SCondvar>,
|
wait: Arc<SCondvar>,
|
||||||
ready: Arc<QueueSignal>,
|
ready: Arc<QueueSignal>,
|
||||||
deleting: Arc<AtomicBool>,
|
|
||||||
empty: Arc<SCondvar>,
|
empty: Arc<SCondvar>,
|
||||||
sleep: Arc<AtomicBool>,
|
state: Arc<(Mutex<State>, Condvar)>,
|
||||||
|
id: usize,
|
||||||
) {
|
) {
|
||||||
while !deleting.load(AtomicOrdering::Acquire) {
|
loop {
|
||||||
|
// check current state.
|
||||||
{
|
{
|
||||||
while sleep.load(AtomicOrdering::SeqCst) {
|
let mut cur_state = state.0.lock();
|
||||||
trace!(target: "verification", "Verifier sleeping");
|
while let State::Work(x) = *cur_state {
|
||||||
::std::thread::park();
|
// sleep until this thread is required.
|
||||||
trace!(target: "verification", "Verifier waking up");
|
if id < x { break }
|
||||||
|
|
||||||
if deleting.load(AtomicOrdering::Acquire) {
|
debug!(target: "verification", "verifier {} sleeping", id);
|
||||||
return;
|
state.1.wait(&mut cur_state);
|
||||||
}
|
debug!(target: "verification", "verifier {} waking up", id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let State::Exit = *cur_state {
|
||||||
|
debug!(target: "verification", "verifier {} exiting", id);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// wait for work if empty.
|
||||||
{
|
{
|
||||||
let mut more_to_verify = verification.more_to_verify.lock().unwrap();
|
let mut more_to_verify = verification.more_to_verify.lock().unwrap();
|
||||||
|
|
||||||
@ -305,15 +289,22 @@ impl<K: Kind> VerificationQueue<K> {
|
|||||||
empty.notify_all();
|
empty.notify_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
while verification.unverified.lock().is_empty() && !deleting.load(AtomicOrdering::Acquire) {
|
while verification.unverified.lock().is_empty() {
|
||||||
|
if let State::Exit = *state.0.lock() {
|
||||||
|
debug!(target: "verification", "verifier {} exiting", id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
more_to_verify = wait.wait(more_to_verify).unwrap();
|
more_to_verify = wait.wait(more_to_verify).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
if deleting.load(AtomicOrdering::Acquire) {
|
if let State::Exit = *state.0.lock() {
|
||||||
|
debug!(target: "verification", "verifier {} exiting", id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// do work.
|
||||||
let item = {
|
let item = {
|
||||||
// acquire these locks before getting the item to verify.
|
// acquire these locks before getting the item to verify.
|
||||||
let mut unverified = verification.unverified.lock();
|
let mut unverified = verification.unverified.lock();
|
||||||
@ -568,6 +559,14 @@ impl<K: Kind> VerificationQueue<K> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the current number of working verifiers.
|
||||||
|
pub fn num_verifiers(&self) -> usize {
|
||||||
|
match *self.state.0.lock() {
|
||||||
|
State::Work(x) => x,
|
||||||
|
State::Exit => panic!("state only set to exit on drop; queue live now; qed"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Optimise memory footprint of the heap fields, and adjust the number of threads
|
/// Optimise memory footprint of the heap fields, and adjust the number of threads
|
||||||
/// to better suit the workload.
|
/// to better suit the workload.
|
||||||
pub fn collect_garbage(&self) {
|
pub fn collect_garbage(&self) {
|
||||||
@ -604,7 +603,7 @@ impl<K: Kind> VerificationQueue<K> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let current = self.verifiers.lock().1;
|
let current = self.num_verifiers();
|
||||||
|
|
||||||
let diff = (v_len - u_len).abs();
|
let diff = (v_len - u_len).abs();
|
||||||
let total = v_len + u_len;
|
let total = v_len + u_len;
|
||||||
@ -626,27 +625,14 @@ impl<K: Kind> VerificationQueue<K> {
|
|||||||
// possible, never going over the amount of initially allocated threads
|
// possible, never going over the amount of initially allocated threads
|
||||||
// or below 1.
|
// or below 1.
|
||||||
fn scale_verifiers(&self, target: usize) {
|
fn scale_verifiers(&self, target: usize) {
|
||||||
let mut verifiers = self.verifiers.lock();
|
let current = self.num_verifiers();
|
||||||
let &mut (ref mut verifiers, ref mut verifier_count) = &mut *verifiers;
|
let target = min(self.verifier_handles.len(), target);
|
||||||
|
|
||||||
let target = min(verifiers.len(), target);
|
|
||||||
let target = max(1, target);
|
let target = max(1, target);
|
||||||
|
|
||||||
debug!(target: "verification", "Scaling from {} to {} verifiers", verifier_count, target);
|
debug!(target: "verification", "Scaling from {} to {} verifiers", current, target);
|
||||||
|
|
||||||
// scaling up
|
*self.state.0.lock() = State::Work(target);
|
||||||
for i in *verifier_count..target {
|
self.state.1.notify_all();
|
||||||
debug!(target: "verification", "Waking up verifier {}", i);
|
|
||||||
verifiers[i].wake_up();
|
|
||||||
}
|
|
||||||
|
|
||||||
// scaling down.
|
|
||||||
for i in target..*verifier_count {
|
|
||||||
debug!(target: "verification", "Putting verifier {} to sleep", i);
|
|
||||||
verifiers[i].sleep();
|
|
||||||
}
|
|
||||||
|
|
||||||
*verifier_count = target;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -660,22 +646,18 @@ impl<K: Kind> Drop for VerificationQueue<K> {
|
|||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
trace!(target: "shutdown", "[VerificationQueue] Closing...");
|
trace!(target: "shutdown", "[VerificationQueue] Closing...");
|
||||||
self.clear();
|
self.clear();
|
||||||
self.deleting.store(true, AtomicOrdering::Release);
|
self.deleting.store(true, AtomicOrdering::SeqCst);
|
||||||
|
|
||||||
let mut verifiers = self.verifiers.get_mut();
|
// set exit state; should be done before `more_to_verify` notification.
|
||||||
let mut verifiers = &mut verifiers.0;
|
*self.state.0.lock() = State::Exit;
|
||||||
|
self.state.1.notify_all();
|
||||||
// first pass to signal conclusion. must be done before
|
|
||||||
// notify or deadlock possible.
|
|
||||||
for handle in verifiers.iter() {
|
|
||||||
handle.conclude();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// wake up all threads waiting for more work.
|
||||||
self.more_to_verify.notify_all();
|
self.more_to_verify.notify_all();
|
||||||
|
|
||||||
// second pass to join.
|
// wait for all verifier threads to join.
|
||||||
for handle in verifiers.drain(..) {
|
for thread in self.verifier_handles.drain(..) {
|
||||||
handle.join();
|
thread.join().expect("Propagating verifier thread panic on shutdown");
|
||||||
}
|
}
|
||||||
|
|
||||||
trace!(target: "shutdown", "[VerificationQueue] Closed.");
|
trace!(target: "shutdown", "[VerificationQueue] Closed.");
|
||||||
@ -687,7 +669,7 @@ mod tests {
|
|||||||
use util::*;
|
use util::*;
|
||||||
use io::*;
|
use io::*;
|
||||||
use spec::*;
|
use spec::*;
|
||||||
use super::{BlockQueue, Config};
|
use super::{BlockQueue, Config, State};
|
||||||
use super::kind::blocks::Unverified;
|
use super::kind::blocks::Unverified;
|
||||||
use tests::helpers::*;
|
use tests::helpers::*;
|
||||||
use error::*;
|
use error::*;
|
||||||
@ -784,11 +766,11 @@ mod tests {
|
|||||||
let queue = get_test_queue();
|
let queue = get_test_queue();
|
||||||
queue.scale_verifiers(MAX_VERIFIERS + 1);
|
queue.scale_verifiers(MAX_VERIFIERS + 1);
|
||||||
|
|
||||||
assert!(queue.verifiers.lock().1 < MAX_VERIFIERS + 1);
|
assert!(queue.num_verifiers() < MAX_VERIFIERS + 1);
|
||||||
|
|
||||||
queue.scale_verifiers(0);
|
queue.scale_verifiers(0);
|
||||||
|
|
||||||
assert!(queue.verifiers.lock().1 == 1);
|
assert!(queue.num_verifiers() == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -797,14 +779,7 @@ mod tests {
|
|||||||
|
|
||||||
// put all the verifiers to sleep to ensure
|
// put all the verifiers to sleep to ensure
|
||||||
// the test isn't timing sensitive.
|
// the test isn't timing sensitive.
|
||||||
let num_verifiers = {
|
*queue.state.0.lock() = State::Work(0);
|
||||||
let verifiers = queue.verifiers.lock();
|
|
||||||
for i in 0..verifiers.1 {
|
|
||||||
verifiers.0[i].sleep();
|
|
||||||
}
|
|
||||||
|
|
||||||
verifiers.1
|
|
||||||
};
|
|
||||||
|
|
||||||
for block in get_good_dummy_block_seq(5000) {
|
for block in get_good_dummy_block_seq(5000) {
|
||||||
queue.import(Unverified::new(block)).expect("Block good by definition; qed");
|
queue.import(Unverified::new(block)).expect("Block good by definition; qed");
|
||||||
@ -812,20 +787,12 @@ mod tests {
|
|||||||
|
|
||||||
// almost all unverified == bump verifier count.
|
// almost all unverified == bump verifier count.
|
||||||
queue.collect_garbage();
|
queue.collect_garbage();
|
||||||
assert_eq!(queue.verifiers.lock().1, num_verifiers + 1);
|
assert_eq!(queue.num_verifiers(), 1);
|
||||||
|
|
||||||
// wake them up again and verify everything.
|
|
||||||
{
|
|
||||||
let verifiers = queue.verifiers.lock();
|
|
||||||
for i in 0..verifiers.1 {
|
|
||||||
verifiers.0[i].wake_up();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
queue.flush();
|
queue.flush();
|
||||||
|
|
||||||
// nothing to verify == use minimum number of verifiers.
|
// nothing to verify == use minimum number of verifiers.
|
||||||
queue.collect_garbage();
|
queue.collect_garbage();
|
||||||
assert_eq!(queue.verifiers.lock().1, 1);
|
assert_eq!(queue.num_verifiers(), 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "parity.js",
|
"name": "parity.js",
|
||||||
"version": "0.2.91",
|
"version": "0.2.92",
|
||||||
"main": "release/index.js",
|
"main": "release/index.js",
|
||||||
"jsnext:main": "src/index.js",
|
"jsnext:main": "src/index.js",
|
||||||
"author": "Parity Team <admin@parity.io>",
|
"author": "Parity Team <admin@parity.io>",
|
||||||
|
@ -457,6 +457,14 @@ class MethodDecoding extends Component {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { signature, paramdata } = api.util.decodeCallData(input);
|
||||||
|
this.setState({ methodSignature: signature, methodParams: paramdata });
|
||||||
|
|
||||||
|
if (!signature || signature === CONTRACT_CREATE || transaction.creates) {
|
||||||
|
this.setState({ isDeploy: true });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (contractAddress === '0x') {
|
if (contractAddress === '0x') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -472,14 +480,6 @@ class MethodDecoding extends Component {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { signature, paramdata } = api.util.decodeCallData(input);
|
|
||||||
this.setState({ methodSignature: signature, methodParams: paramdata });
|
|
||||||
|
|
||||||
if (!signature || signature === CONTRACT_CREATE || transaction.creates) {
|
|
||||||
this.setState({ isDeploy: true });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Contracts.get()
|
return Contracts.get()
|
||||||
.signatureReg
|
.signatureReg
|
||||||
.lookup(signature)
|
.lookup(signature)
|
||||||
|
@ -61,6 +61,7 @@ pass = "test_pass"
|
|||||||
|
|
||||||
[mining]
|
[mining]
|
||||||
author = "0xdeadbeefcafe0000000000000000000000000001"
|
author = "0xdeadbeefcafe0000000000000000000000000001"
|
||||||
|
engine_signer = "0xdeadbeefcafe0000000000000000000000000001"
|
||||||
force_sealing = true
|
force_sealing = true
|
||||||
reseal_on_txs = "all"
|
reseal_on_txs = "all"
|
||||||
reseal_min_period = 4000
|
reseal_min_period = 4000
|
||||||
|
@ -40,6 +40,7 @@ pass = "password"
|
|||||||
|
|
||||||
[mining]
|
[mining]
|
||||||
author = "0xdeadbeefcafe0000000000000000000000000001"
|
author = "0xdeadbeefcafe0000000000000000000000000001"
|
||||||
|
engine_signer = "0xdeadbeefcafe0000000000000000000000000001"
|
||||||
force_sealing = true
|
force_sealing = true
|
||||||
reseal_on_txs = "all"
|
reseal_on_txs = "all"
|
||||||
reseal_min_period = 4000
|
reseal_min_period = 4000
|
||||||
|
@ -178,6 +178,8 @@ usage! {
|
|||||||
// -- Sealing/Mining Options
|
// -- Sealing/Mining Options
|
||||||
flag_author: Option<String> = None,
|
flag_author: Option<String> = None,
|
||||||
or |c: &Config| otry!(c.mining).author.clone().map(Some),
|
or |c: &Config| otry!(c.mining).author.clone().map(Some),
|
||||||
|
flag_engine_signer: Option<String> = None,
|
||||||
|
or |c: &Config| otry!(c.mining).engine_signer.clone().map(Some),
|
||||||
flag_force_sealing: bool = false,
|
flag_force_sealing: bool = false,
|
||||||
or |c: &Config| otry!(c.mining).force_sealing.clone(),
|
or |c: &Config| otry!(c.mining).force_sealing.clone(),
|
||||||
flag_reseal_on_txs: String = "own",
|
flag_reseal_on_txs: String = "own",
|
||||||
@ -367,6 +369,7 @@ struct Dapps {
|
|||||||
#[derive(Default, Debug, PartialEq, RustcDecodable)]
|
#[derive(Default, Debug, PartialEq, RustcDecodable)]
|
||||||
struct Mining {
|
struct Mining {
|
||||||
author: Option<String>,
|
author: Option<String>,
|
||||||
|
engine_signer: Option<String>,
|
||||||
force_sealing: Option<bool>,
|
force_sealing: Option<bool>,
|
||||||
reseal_on_txs: Option<String>,
|
reseal_on_txs: Option<String>,
|
||||||
reseal_min_period: Option<u64>,
|
reseal_min_period: Option<u64>,
|
||||||
@ -569,6 +572,7 @@ mod tests {
|
|||||||
|
|
||||||
// -- Sealing/Mining Options
|
// -- Sealing/Mining Options
|
||||||
flag_author: Some("0xdeadbeefcafe0000000000000000000000000001".into()),
|
flag_author: Some("0xdeadbeefcafe0000000000000000000000000001".into()),
|
||||||
|
flag_engine_signer: Some("0xdeadbeefcafe0000000000000000000000000001".into()),
|
||||||
flag_force_sealing: true,
|
flag_force_sealing: true,
|
||||||
flag_reseal_on_txs: "all".into(),
|
flag_reseal_on_txs: "all".into(),
|
||||||
flag_reseal_min_period: 4000u64,
|
flag_reseal_min_period: 4000u64,
|
||||||
@ -738,6 +742,7 @@ mod tests {
|
|||||||
}),
|
}),
|
||||||
mining: Some(Mining {
|
mining: Some(Mining {
|
||||||
author: Some("0xdeadbeefcafe0000000000000000000000000001".into()),
|
author: Some("0xdeadbeefcafe0000000000000000000000000001".into()),
|
||||||
|
engine_signer: Some("0xdeadbeefcafe0000000000000000000000000001".into()),
|
||||||
force_sealing: Some(true),
|
force_sealing: Some(true),
|
||||||
reseal_on_txs: Some("all".into()),
|
reseal_on_txs: Some("all".into()),
|
||||||
reseal_min_period: Some(4000),
|
reseal_min_period: Some(4000),
|
||||||
|
@ -149,6 +149,10 @@ Sealing/Mining Options:
|
|||||||
for sending block rewards from sealed blocks.
|
for sending block rewards from sealed blocks.
|
||||||
NOTE: MINING WILL NOT WORK WITHOUT THIS OPTION.
|
NOTE: MINING WILL NOT WORK WITHOUT THIS OPTION.
|
||||||
(default: {flag_author:?})
|
(default: {flag_author:?})
|
||||||
|
--engine-signer ADDRESS Specify the address which should be used to
|
||||||
|
sign consensus messages and issue blocks.
|
||||||
|
Relevant only to non-PoW chains.
|
||||||
|
(default: {flag_engine_signer:?})
|
||||||
--force-sealing Force the node to author new blocks as if it were
|
--force-sealing Force the node to author new blocks as if it were
|
||||||
always sealing/mining.
|
always sealing/mining.
|
||||||
(default: {flag_force_sealing})
|
(default: {flag_force_sealing})
|
||||||
|
@ -300,6 +300,7 @@ impl Configuration {
|
|||||||
gas_floor_target: try!(to_u256(&self.args.flag_gas_floor_target)),
|
gas_floor_target: try!(to_u256(&self.args.flag_gas_floor_target)),
|
||||||
gas_ceil_target: try!(to_u256(&self.args.flag_gas_cap)),
|
gas_ceil_target: try!(to_u256(&self.args.flag_gas_cap)),
|
||||||
transactions_limit: self.args.flag_tx_queue_size,
|
transactions_limit: self.args.flag_tx_queue_size,
|
||||||
|
engine_signer: try!(self.engine_signer()),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(extras)
|
Ok(extras)
|
||||||
@ -309,6 +310,10 @@ impl Configuration {
|
|||||||
to_address(self.args.flag_etherbase.clone().or(self.args.flag_author.clone()))
|
to_address(self.args.flag_etherbase.clone().or(self.args.flag_author.clone()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn engine_signer(&self) -> Result<Address, String> {
|
||||||
|
to_address(self.args.flag_engine_signer.clone())
|
||||||
|
}
|
||||||
|
|
||||||
fn format(&self) -> Result<Option<DataFormat>, String> {
|
fn format(&self) -> Result<Option<DataFormat>, String> {
|
||||||
match self.args.flag_format {
|
match self.args.flag_format {
|
||||||
Some(ref f) => Ok(Some(try!(f.parse()))),
|
Some(ref f) => Ok(Some(try!(f.parse()))),
|
||||||
|
@ -300,14 +300,14 @@ pub fn password_prompt() -> Result<String, String> {
|
|||||||
|
|
||||||
/// Read a password from password file.
|
/// Read a password from password file.
|
||||||
pub fn password_from_file(path: String) -> Result<String, String> {
|
pub fn password_from_file(path: String) -> Result<String, String> {
|
||||||
let passwords = try!(passwords_from_files(vec![path]));
|
let passwords = try!(passwords_from_files(&[path]));
|
||||||
// use only first password from the file
|
// use only first password from the file
|
||||||
passwords.get(0).map(String::to_owned)
|
passwords.get(0).map(String::to_owned)
|
||||||
.ok_or_else(|| "Password file seems to be empty.".to_owned())
|
.ok_or_else(|| "Password file seems to be empty.".to_owned())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads passwords from files. Treats each line as a separate password.
|
/// Reads passwords from files. Treats each line as a separate password.
|
||||||
pub fn passwords_from_files(files: Vec<String>) -> Result<Vec<String>, String> {
|
pub fn passwords_from_files(files: &[String]) -> Result<Vec<String>, String> {
|
||||||
let passwords = files.iter().map(|filename| {
|
let passwords = files.iter().map(|filename| {
|
||||||
let file = try!(File::open(filename).map_err(|_| format!("{} Unable to read password file. Ensure it exists and permissions are correct.", filename)));
|
let file = try!(File::open(filename).map_err(|_| format!("{} Unable to read password file. Ensure it exists and permissions are correct.", filename)));
|
||||||
let reader = BufReader::new(&file);
|
let reader = BufReader::new(&file);
|
||||||
|
@ -204,6 +204,7 @@ pub struct MinerExtras {
|
|||||||
pub gas_floor_target: U256,
|
pub gas_floor_target: U256,
|
||||||
pub gas_ceil_target: U256,
|
pub gas_ceil_target: U256,
|
||||||
pub transactions_limit: usize,
|
pub transactions_limit: usize,
|
||||||
|
pub engine_signer: Address,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for MinerExtras {
|
impl Default for MinerExtras {
|
||||||
@ -213,7 +214,8 @@ impl Default for MinerExtras {
|
|||||||
extra_data: version_data(),
|
extra_data: version_data(),
|
||||||
gas_floor_target: U256::from(4_700_000),
|
gas_floor_target: U256::from(4_700_000),
|
||||||
gas_ceil_target: U256::from(6_283_184),
|
gas_ceil_target: U256::from(6_283_184),
|
||||||
transactions_limit: 2048,
|
transactions_limit: 1024,
|
||||||
|
engine_signer: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -205,8 +205,13 @@ pub fn execute(cmd: RunCmd, logger: Arc<RotatingLogger>) -> Result<(), String> {
|
|||||||
sync_config.warp_sync = cmd.warp_sync;
|
sync_config.warp_sync = cmd.warp_sync;
|
||||||
sync_config.download_old_blocks = cmd.download_old_blocks;
|
sync_config.download_old_blocks = cmd.download_old_blocks;
|
||||||
|
|
||||||
|
let passwords = try!(passwords_from_files(&cmd.acc_conf.password_files));
|
||||||
|
|
||||||
// prepare account provider
|
// prepare account provider
|
||||||
let account_provider = Arc::new(try!(prepare_account_provider(&cmd.dirs, cmd.acc_conf)));
|
let account_provider = Arc::new(try!(prepare_account_provider(&cmd.dirs, cmd.acc_conf, &passwords)));
|
||||||
|
|
||||||
|
// let the Engine access the accounts
|
||||||
|
spec.engine.register_account_provider(account_provider.clone());
|
||||||
|
|
||||||
// let the Engine access the accounts
|
// let the Engine access the accounts
|
||||||
spec.engine.register_account_provider(account_provider.clone());
|
spec.engine.register_account_provider(account_provider.clone());
|
||||||
@ -218,6 +223,10 @@ pub fn execute(cmd: RunCmd, logger: Arc<RotatingLogger>) -> Result<(), String> {
|
|||||||
miner.set_gas_ceil_target(cmd.miner_extras.gas_ceil_target);
|
miner.set_gas_ceil_target(cmd.miner_extras.gas_ceil_target);
|
||||||
miner.set_extra_data(cmd.miner_extras.extra_data);
|
miner.set_extra_data(cmd.miner_extras.extra_data);
|
||||||
miner.set_transactions_limit(cmd.miner_extras.transactions_limit);
|
miner.set_transactions_limit(cmd.miner_extras.transactions_limit);
|
||||||
|
let engine_signer = cmd.miner_extras.engine_signer;
|
||||||
|
if !passwords.into_iter().any(|p| miner.set_engine_signer(engine_signer, p).is_ok()) {
|
||||||
|
return Err(format!("No password found for the consensus signer {}. Make sure valid password is present in files passed using `--password`.", cmd.miner_extras.engine_signer));
|
||||||
|
}
|
||||||
|
|
||||||
// create client config
|
// create client config
|
||||||
let client_config = to_client_config(
|
let client_config = to_client_config(
|
||||||
@ -424,19 +433,17 @@ fn daemonize(_pid_file: String) -> Result<(), String> {
|
|||||||
Err("daemon is no supported on windows".into())
|
Err("daemon is no supported on windows".into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prepare_account_provider(dirs: &Directories, cfg: AccountsConfig) -> Result<AccountProvider, String> {
|
fn prepare_account_provider(dirs: &Directories, cfg: AccountsConfig, passwords: &[String]) -> Result<AccountProvider, String> {
|
||||||
use ethcore::ethstore::EthStore;
|
use ethcore::ethstore::EthStore;
|
||||||
use ethcore::ethstore::dir::DiskDirectory;
|
use ethcore::ethstore::dir::DiskDirectory;
|
||||||
|
|
||||||
let passwords = try!(passwords_from_files(cfg.password_files));
|
|
||||||
|
|
||||||
let dir = Box::new(try!(DiskDirectory::create(dirs.keys.clone()).map_err(|e| format!("Could not open keys directory: {}", e))));
|
let dir = Box::new(try!(DiskDirectory::create(dirs.keys.clone()).map_err(|e| format!("Could not open keys directory: {}", e))));
|
||||||
let account_service = AccountProvider::new(Box::new(
|
let account_service = AccountProvider::new(Box::new(
|
||||||
try!(EthStore::open_with_iterations(dir, cfg.iterations).map_err(|e| format!("Could not open keys directory: {}", e)))
|
try!(EthStore::open_with_iterations(dir, cfg.iterations).map_err(|e| format!("Could not open keys directory: {}", e)))
|
||||||
));
|
));
|
||||||
|
|
||||||
for a in cfg.unlocked_accounts {
|
for a in cfg.unlocked_accounts {
|
||||||
if passwords.iter().find(|p| account_service.unlock_account_permanently(a, (*p).clone()).is_ok()).is_none() {
|
if !passwords.iter().any(|p| account_service.unlock_account_permanently(a, (*p).clone()).is_ok()) {
|
||||||
return Err(format!("No password found to unlock account {}. Make sure valid password is present in files passed using `--password`.", a));
|
return Err(format!("No password found to unlock account {}. Make sure valid password is present in files passed using `--password`.", a));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,9 +116,9 @@ impl<C, M, F> ParitySet for ParitySetClient<C, M, F> where
|
|||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_consensus_signer(&self, address: H160, password: String) -> Result<bool, Error> {
|
fn set_engine_signer(&self, address: H160, password: String) -> Result<bool, Error> {
|
||||||
try!(self.active());
|
try!(self.active());
|
||||||
try!(take_weak!(self.miner).set_consensus_signer(address.into(), password).map_err(Into::into).map_err(errors::from_password_error));
|
try!(take_weak!(self.miner).set_engine_signer(address.into(), password).map_err(Into::into).map_err(errors::from_password_error));
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ impl MinerService for TestMinerService {
|
|||||||
*self.author.write() = author;
|
*self.author.write() = author;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_consensus_signer(&self, address: Address, password: String) -> Result<(), AccountError> {
|
fn set_engine_signer(&self, address: Address, password: String) -> Result<(), AccountError> {
|
||||||
*self.author.write() = address;
|
*self.author.write() = address;
|
||||||
*self.password.write() = password;
|
*self.password.write() = password;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -107,14 +107,14 @@ fn rpc_parity_set_author() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rpc_parity_set_consensus_signer() {
|
fn rpc_parity_set_engine_signer() {
|
||||||
let miner = miner_service();
|
let miner = miner_service();
|
||||||
let client = client_service();
|
let client = client_service();
|
||||||
let network = network_service();
|
let network = network_service();
|
||||||
let io = IoHandler::new();
|
let io = IoHandler::new();
|
||||||
io.add_delegate(parity_set_client(&client, &miner, &network).to_delegate());
|
io.add_delegate(parity_set_client(&client, &miner, &network).to_delegate());
|
||||||
|
|
||||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_setConsensusSigner", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681", "password"], "id": 1}"#;
|
let request = r#"{"jsonrpc": "2.0", "method": "parity_setEngineSigner", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681", "password"], "id": 1}"#;
|
||||||
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
||||||
|
|
||||||
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
|
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
|
||||||
|
@ -45,8 +45,8 @@ build_rpc_trait! {
|
|||||||
fn set_author(&self, H160) -> Result<bool, Error>;
|
fn set_author(&self, H160) -> Result<bool, Error>;
|
||||||
|
|
||||||
/// Sets account for signing consensus messages.
|
/// Sets account for signing consensus messages.
|
||||||
#[rpc(name = "parity_setConsensusSigner")]
|
#[rpc(name = "parity_setEngineSigner")]
|
||||||
fn set_consensus_signer(&self, H160, String) -> Result<bool, Error>;
|
fn set_engine_signer(&self, H160, String) -> Result<bool, Error>;
|
||||||
|
|
||||||
/// Sets the limits for transaction queue.
|
/// Sets the limits for transaction queue.
|
||||||
#[rpc(name = "parity_setTransactionsLimit")]
|
#[rpc(name = "parity_setTransactionsLimit")]
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
[package]
|
|
||||||
description = "Utility function to raise file descriptor limit on OS X"
|
|
||||||
homepage = "http://ethcore.io"
|
|
||||||
license = "GPL-3.0"
|
|
||||||
name = "fdlimit"
|
|
||||||
version = "0.1.0"
|
|
||||||
authors = ["Ethcore <admin@ethcore.io>"]
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
libc = "0.2"
|
|
@ -1,19 +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/>.extern crate libc;
|
|
||||||
|
|
||||||
extern crate libc;
|
|
||||||
mod raise_fd_limit;
|
|
||||||
pub use raise_fd_limit::raise_fd_limit;
|
|
@ -1,88 +0,0 @@
|
|||||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
|
||||||
// file at the top-level directory of this distribution and at
|
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
||||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
||||||
// option. This file may not be copied, modified, or distributed
|
|
||||||
// except according to those terms.
|
|
||||||
|
|
||||||
/// darwin_fd_limit exists to work around an issue where launchctl on Mac OS X
|
|
||||||
/// defaults the rlimit maxfiles to 256/unlimited. The default soft limit of 256
|
|
||||||
/// ends up being far too low for our multithreaded scheduler testing, depending
|
|
||||||
/// on the number of cores available.
|
|
||||||
///
|
|
||||||
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
|
||||||
#[allow(non_camel_case_types)]
|
|
||||||
pub fn raise_fd_limit() {
|
|
||||||
use libc;
|
|
||||||
use std::cmp;
|
|
||||||
use std::io;
|
|
||||||
use std::mem::size_of_val;
|
|
||||||
use std::ptr::null_mut;
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
static CTL_KERN: libc::c_int = 1;
|
|
||||||
static KERN_MAXFILESPERPROC: libc::c_int = 29;
|
|
||||||
|
|
||||||
// The strategy here is to fetch the current resource limits, read the
|
|
||||||
// kern.maxfilesperproc sysctl value, and bump the soft resource limit for
|
|
||||||
// maxfiles up to the sysctl value.
|
|
||||||
|
|
||||||
// Fetch the kern.maxfilesperproc value
|
|
||||||
let mut mib: [libc::c_int; 2] = [CTL_KERN, KERN_MAXFILESPERPROC];
|
|
||||||
let mut maxfiles: libc::c_int = 0;
|
|
||||||
let mut size: libc::size_t = size_of_val(&maxfiles) as libc::size_t;
|
|
||||||
if libc::sysctl(&mut mib[0], 2, &mut maxfiles as *mut _ as *mut _, &mut size,
|
|
||||||
null_mut(), 0) != 0 {
|
|
||||||
let err = io::Error::last_os_error();
|
|
||||||
panic!("raise_fd_limit: error calling sysctl: {}", err);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch the current resource limits
|
|
||||||
let mut rlim = libc::rlimit{rlim_cur: 0, rlim_max: 0};
|
|
||||||
if libc::getrlimit(libc::RLIMIT_NOFILE, &mut rlim) != 0 {
|
|
||||||
let err = io::Error::last_os_error();
|
|
||||||
panic!("raise_fd_limit: error calling getrlimit: {}", err);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bump the soft limit to the smaller of kern.maxfilesperproc and the hard
|
|
||||||
// limit
|
|
||||||
rlim.rlim_cur = cmp::min(maxfiles as libc::rlim_t, rlim.rlim_max);
|
|
||||||
|
|
||||||
// Set our newly-increased resource limit
|
|
||||||
if libc::setrlimit(libc::RLIMIT_NOFILE, &rlim) != 0 {
|
|
||||||
let err = io::Error::last_os_error();
|
|
||||||
panic!("raise_fd_limit: error calling setrlimit: {}", err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(any(target_os = "linux"))]
|
|
||||||
#[allow(non_camel_case_types)]
|
|
||||||
pub fn raise_fd_limit() {
|
|
||||||
use libc;
|
|
||||||
use std::io;
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
// Fetch the current resource limits
|
|
||||||
let mut rlim = libc::rlimit{rlim_cur: 0, rlim_max: 0};
|
|
||||||
if libc::getrlimit(libc::RLIMIT_NOFILE, &mut rlim) != 0 {
|
|
||||||
let err = io::Error::last_os_error();
|
|
||||||
panic!("raise_fd_limit: error calling getrlimit: {}", err);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set soft limit to hard imit
|
|
||||||
rlim.rlim_cur = rlim.rlim_max;
|
|
||||||
|
|
||||||
// Set our newly-increased resource limit
|
|
||||||
if libc::setrlimit(libc::RLIMIT_NOFILE, &rlim) != 0 {
|
|
||||||
let err = io::Error::last_os_error();
|
|
||||||
panic!("raise_fd_limit: error calling setrlimit: {}", err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "linux")))]
|
|
||||||
pub fn raise_fd_limit() {}
|
|
Loading…
Reference in New Issue
Block a user