Merge branch 'master' of github.com:ethcore/parity into tests_for_views
This commit is contained in:
commit
2462193df8
@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
//! Blockchain database client.
|
//! Blockchain database client.
|
||||||
|
|
||||||
use std::marker::PhantomData;
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrdering};
|
use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrdering};
|
||||||
use util::*;
|
use util::*;
|
||||||
@ -30,7 +29,8 @@ use engine::Engine;
|
|||||||
use views::HeaderView;
|
use views::HeaderView;
|
||||||
use service::{NetSyncMessage, SyncMessage};
|
use service::{NetSyncMessage, SyncMessage};
|
||||||
use env_info::LastHashes;
|
use env_info::LastHashes;
|
||||||
use verification::*;
|
use verification;
|
||||||
|
use verification::{PreverifiedBlock, Verifier};
|
||||||
use block::*;
|
use block::*;
|
||||||
use transaction::{LocalizedTransaction, SignedTransaction, Action};
|
use transaction::{LocalizedTransaction, SignedTransaction, Action};
|
||||||
use blockchain::extras::TransactionAddress;
|
use blockchain::extras::TransactionAddress;
|
||||||
@ -83,7 +83,7 @@ impl ClientReport {
|
|||||||
|
|
||||||
/// Blockchain database client backed by a persistent database. Owns and manages a blockchain and a block queue.
|
/// Blockchain database client backed by a persistent database. Owns and manages a blockchain and a block queue.
|
||||||
/// Call `import_block()` to import a block asynchronously; `flush_queue()` flushes the queue.
|
/// Call `import_block()` to import a block asynchronously; `flush_queue()` flushes the queue.
|
||||||
pub struct Client<V = CanonVerifier> where V: Verifier {
|
pub struct Client {
|
||||||
chain: Arc<BlockChain>,
|
chain: Arc<BlockChain>,
|
||||||
tracedb: Arc<TraceDB<BlockChain>>,
|
tracedb: Arc<TraceDB<BlockChain>>,
|
||||||
engine: Arc<Box<Engine>>,
|
engine: Arc<Box<Engine>>,
|
||||||
@ -92,7 +92,7 @@ pub struct Client<V = CanonVerifier> where V: Verifier {
|
|||||||
report: RwLock<ClientReport>,
|
report: RwLock<ClientReport>,
|
||||||
import_lock: Mutex<()>,
|
import_lock: Mutex<()>,
|
||||||
panic_handler: Arc<PanicHandler>,
|
panic_handler: Arc<PanicHandler>,
|
||||||
verifier: PhantomData<V>,
|
verifier: Box<Verifier>,
|
||||||
vm_factory: Arc<EvmFactory>,
|
vm_factory: Arc<EvmFactory>,
|
||||||
miner: Arc<Miner>,
|
miner: Arc<Miner>,
|
||||||
io_channel: IoChannel<NetSyncMessage>,
|
io_channel: IoChannel<NetSyncMessage>,
|
||||||
@ -107,13 +107,6 @@ const HISTORY: u64 = 1200;
|
|||||||
// of which you actually want force an upgrade.
|
// of which you actually want force an upgrade.
|
||||||
const CLIENT_DB_VER_STR: &'static str = "5.3";
|
const CLIENT_DB_VER_STR: &'static str = "5.3";
|
||||||
|
|
||||||
impl Client<CanonVerifier> {
|
|
||||||
/// Create a new client with given spec and DB path.
|
|
||||||
pub fn new(config: ClientConfig, spec: Spec, path: &Path, miner: Arc<Miner>, message_channel: IoChannel<NetSyncMessage> ) -> Result<Arc<Client>, ClientError> {
|
|
||||||
Client::<CanonVerifier>::new_with_verifier(config, spec, path, miner, message_channel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the path for the databases given the root path and information on the databases.
|
/// Get the path for the databases given the root path and information on the databases.
|
||||||
pub fn get_db_path(path: &Path, pruning: journaldb::Algorithm, genesis_hash: H256) -> PathBuf {
|
pub fn get_db_path(path: &Path, pruning: journaldb::Algorithm, genesis_hash: H256) -> PathBuf {
|
||||||
let mut dir = path.to_path_buf();
|
let mut dir = path.to_path_buf();
|
||||||
@ -131,15 +124,15 @@ pub fn append_path(path: &Path, item: &str) -> String {
|
|||||||
p.to_str().unwrap().to_owned()
|
p.to_str().unwrap().to_owned()
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V> Client<V> where V: Verifier {
|
impl Client {
|
||||||
/// Create a new client with given spec and DB path and custom verifier.
|
/// Create a new client with given spec and DB path and custom verifier.
|
||||||
pub fn new_with_verifier(
|
pub fn new(
|
||||||
config: ClientConfig,
|
config: ClientConfig,
|
||||||
spec: Spec,
|
spec: Spec,
|
||||||
path: &Path,
|
path: &Path,
|
||||||
miner: Arc<Miner>,
|
miner: Arc<Miner>,
|
||||||
message_channel: IoChannel<NetSyncMessage>)
|
message_channel: IoChannel<NetSyncMessage>)
|
||||||
-> Result<Arc<Client<V>>, ClientError>
|
-> Result<Arc<Client>, ClientError>
|
||||||
{
|
{
|
||||||
let path = get_db_path(path, config.pruning, spec.genesis_header().hash());
|
let path = get_db_path(path, config.pruning, spec.genesis_header().hash());
|
||||||
let gb = spec.genesis_block();
|
let gb = spec.genesis_block();
|
||||||
@ -158,7 +151,8 @@ impl<V> Client<V> where V: Verifier {
|
|||||||
let mut state_db = journaldb::new(
|
let mut state_db = journaldb::new(
|
||||||
&append_path(&path, "state"),
|
&append_path(&path, "state"),
|
||||||
config.pruning,
|
config.pruning,
|
||||||
state_db_config);
|
state_db_config
|
||||||
|
);
|
||||||
|
|
||||||
if state_db.is_empty() && spec.ensure_db_good(state_db.as_hashdb_mut()) {
|
if state_db.is_empty() && spec.ensure_db_good(state_db.as_hashdb_mut()) {
|
||||||
state_db.commit(0, &spec.genesis_header().hash(), None).expect("Error commiting genesis state to state DB");
|
state_db.commit(0, &spec.genesis_header().hash(), None).expect("Error commiting genesis state to state DB");
|
||||||
@ -179,7 +173,7 @@ impl<V> Client<V> where V: Verifier {
|
|||||||
report: RwLock::new(Default::default()),
|
report: RwLock::new(Default::default()),
|
||||||
import_lock: Mutex::new(()),
|
import_lock: Mutex::new(()),
|
||||||
panic_handler: panic_handler,
|
panic_handler: panic_handler,
|
||||||
verifier: PhantomData,
|
verifier: verification::new(config.verifier_type),
|
||||||
vm_factory: Arc::new(EvmFactory::new(config.vm_type)),
|
vm_factory: Arc::new(EvmFactory::new(config.vm_type)),
|
||||||
miner: miner,
|
miner: miner,
|
||||||
io_channel: message_channel,
|
io_channel: message_channel,
|
||||||
@ -221,7 +215,7 @@ impl<V> Client<V> where V: Verifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Verify Block Family
|
// Verify Block Family
|
||||||
let verify_family_result = V::verify_block_family(&header, &block.bytes, engine, self.chain.deref());
|
let verify_family_result = self.verifier.verify_block_family(&header, &block.bytes, engine, self.chain.deref());
|
||||||
if let Err(e) = verify_family_result {
|
if let Err(e) = verify_family_result {
|
||||||
warn!(target: "client", "Stage 3 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e);
|
warn!(target: "client", "Stage 3 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e);
|
||||||
return Err(());
|
return Err(());
|
||||||
@ -247,7 +241,7 @@ impl<V> Client<V> where V: Verifier {
|
|||||||
|
|
||||||
// Final Verification
|
// Final Verification
|
||||||
let locked_block = enact_result.unwrap();
|
let locked_block = enact_result.unwrap();
|
||||||
if let Err(e) = V::verify_block_final(&header, locked_block.block().header()) {
|
if let Err(e) = self.verifier.verify_block_final(&header, locked_block.block().header()) {
|
||||||
warn!(target: "client", "Stage 4 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e);
|
warn!(target: "client", "Stage 4 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e);
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
@ -482,7 +476,7 @@ impl<V> Client<V> where V: Verifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V> BlockChainClient for Client<V> where V: Verifier {
|
impl BlockChainClient for Client {
|
||||||
fn call(&self, t: &SignedTransaction, analytics: CallAnalytics) -> Result<Executed, ExecutionError> {
|
fn call(&self, t: &SignedTransaction, analytics: CallAnalytics) -> Result<Executed, ExecutionError> {
|
||||||
let header = self.block_header(BlockID::Latest).unwrap();
|
let header = self.block_header(BlockID::Latest).unwrap();
|
||||||
let view = HeaderView::new(&header);
|
let view = HeaderView::new(&header);
|
||||||
@ -800,12 +794,12 @@ impl<V> BlockChainClient for Client<V> where V: Verifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn all_transactions(&self) -> Vec<SignedTransaction> {
|
fn pending_transactions(&self) -> Vec<SignedTransaction> {
|
||||||
self.miner.all_transactions()
|
self.miner.pending_transactions()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V> MiningBlockChainClient for Client<V> where V: Verifier {
|
impl MiningBlockChainClient for Client {
|
||||||
fn prepare_open_block(&self, author: Address, gas_range_target: (U256, U256), extra_data: Bytes) -> OpenBlock {
|
fn prepare_open_block(&self, author: Address, gas_range_target: (U256, U256), extra_data: Bytes) -> OpenBlock {
|
||||||
let engine = self.engine.deref().deref();
|
let engine = self.engine.deref().deref();
|
||||||
let h = self.chain.best_block_hash();
|
let h = self.chain.best_block_hash();
|
||||||
|
@ -18,6 +18,7 @@ pub use block_queue::BlockQueueConfig;
|
|||||||
pub use blockchain::Config as BlockChainConfig;
|
pub use blockchain::Config as BlockChainConfig;
|
||||||
pub use trace::{Config as TraceConfig, Switch};
|
pub use trace::{Config as TraceConfig, Switch};
|
||||||
pub use evm::VMType;
|
pub use evm::VMType;
|
||||||
|
pub use verification::VerifierType;
|
||||||
use util::journaldb;
|
use util::journaldb;
|
||||||
|
|
||||||
/// Client state db compaction profile
|
/// Client state db compaction profile
|
||||||
@ -52,4 +53,6 @@ pub struct ClientConfig {
|
|||||||
pub db_cache_size: Option<usize>,
|
pub db_cache_size: Option<usize>,
|
||||||
/// State db compaction profile
|
/// State db compaction profile
|
||||||
pub db_compaction: DatabaseCompactionProfile,
|
pub db_compaction: DatabaseCompactionProfile,
|
||||||
|
/// Type of block verifier used by client.
|
||||||
|
pub verifier_type: VerifierType,
|
||||||
}
|
}
|
||||||
|
@ -197,7 +197,7 @@ pub trait BlockChainClient : Sync + Send {
|
|||||||
fn queue_transactions(&self, transactions: Vec<Bytes>);
|
fn queue_transactions(&self, transactions: Vec<Bytes>);
|
||||||
|
|
||||||
/// list all transactions
|
/// list all transactions
|
||||||
fn all_transactions(&self) -> Vec<SignedTransaction>;
|
fn pending_transactions(&self) -> Vec<SignedTransaction>;
|
||||||
|
|
||||||
/// Get the gas price distribution.
|
/// Get the gas price distribution.
|
||||||
fn gas_price_statistics(&self, sample_size: usize, distribution_size: usize) -> Result<Vec<U256>, ()> {
|
fn gas_price_statistics(&self, sample_size: usize, distribution_size: usize) -> Result<Vec<U256>, ()> {
|
||||||
|
@ -500,7 +500,7 @@ impl BlockChainClient for TestBlockChainClient {
|
|||||||
self.import_transactions(tx);
|
self.import_transactions(tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn all_transactions(&self) -> Vec<SignedTransaction> {
|
fn pending_transactions(&self) -> Vec<SignedTransaction> {
|
||||||
self.miner.all_transactions()
|
self.miner.pending_transactions()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,48 @@ use spec::Spec;
|
|||||||
use engine::Engine;
|
use engine::Engine;
|
||||||
use miner::{MinerService, MinerStatus, TransactionQueue, AccountDetails, TransactionImportResult, TransactionOrigin};
|
use miner::{MinerService, MinerStatus, TransactionQueue, AccountDetails, TransactionImportResult, TransactionOrigin};
|
||||||
|
|
||||||
|
/// Different possible definitions for pending transaction set.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum PendingSet {
|
||||||
|
/// Always just the transactions in the queue. These have had only cheap checks.
|
||||||
|
AlwaysQueue,
|
||||||
|
/// Always just the transactions in the sealing block. These have had full checks but
|
||||||
|
/// may be empty if the node is not actively mining or has force_sealing enabled.
|
||||||
|
AlwaysSealing,
|
||||||
|
/// Try the sealing block, but if it is not currently sealing, fallback to the queue.
|
||||||
|
SealingOrElseQueue,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Configures the behaviour of the miner.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct MinerOptions {
|
||||||
|
/// Force the miner to reseal, even when nobody has asked for work.
|
||||||
|
pub force_sealing: bool,
|
||||||
|
/// Reseal on receipt of new external transactions.
|
||||||
|
pub reseal_on_external_tx: bool,
|
||||||
|
/// Reseal on receipt of new local transactions.
|
||||||
|
pub reseal_on_own_tx: bool,
|
||||||
|
/// Maximum amount of gas to bother considering for block insertion.
|
||||||
|
pub tx_gas_limit: U256,
|
||||||
|
/// Maximum size of the transaction queue.
|
||||||
|
pub tx_queue_size: usize,
|
||||||
|
/// Whether we should fallback to providing all the queue's transactions or just pending.
|
||||||
|
pub pending_set: PendingSet,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for MinerOptions {
|
||||||
|
fn default() -> Self {
|
||||||
|
MinerOptions {
|
||||||
|
force_sealing: false,
|
||||||
|
reseal_on_external_tx: true,
|
||||||
|
reseal_on_own_tx: true,
|
||||||
|
tx_gas_limit: !U256::zero(),
|
||||||
|
tx_queue_size: 1024,
|
||||||
|
pending_set: PendingSet::AlwaysQueue,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Keeps track of transactions using priority queue and holds currently mined block.
|
/// Keeps track of transactions using priority queue and holds currently mined block.
|
||||||
pub struct Miner {
|
pub struct Miner {
|
||||||
// NOTE [ToDr] When locking always lock in this order!
|
// NOTE [ToDr] When locking always lock in this order!
|
||||||
@ -36,7 +78,7 @@ pub struct Miner {
|
|||||||
sealing_work: Mutex<UsingQueue<ClosedBlock>>,
|
sealing_work: Mutex<UsingQueue<ClosedBlock>>,
|
||||||
|
|
||||||
// for sealing...
|
// for sealing...
|
||||||
force_sealing: bool,
|
options: MinerOptions,
|
||||||
sealing_enabled: AtomicBool,
|
sealing_enabled: AtomicBool,
|
||||||
sealing_block_last_request: Mutex<u64>,
|
sealing_block_last_request: Mutex<u64>,
|
||||||
gas_range_target: RwLock<(U256, U256)>,
|
gas_range_target: RwLock<(U256, U256)>,
|
||||||
@ -52,7 +94,7 @@ impl Miner {
|
|||||||
pub fn with_spec(spec: Spec) -> Miner {
|
pub fn with_spec(spec: Spec) -> Miner {
|
||||||
Miner {
|
Miner {
|
||||||
transaction_queue: Mutex::new(TransactionQueue::new()),
|
transaction_queue: Mutex::new(TransactionQueue::new()),
|
||||||
force_sealing: false,
|
options: Default::default(),
|
||||||
sealing_enabled: AtomicBool::new(false),
|
sealing_enabled: AtomicBool::new(false),
|
||||||
sealing_block_last_request: Mutex::new(0),
|
sealing_block_last_request: Mutex::new(0),
|
||||||
sealing_work: Mutex::new(UsingQueue::new(5)),
|
sealing_work: Mutex::new(UsingQueue::new(5)),
|
||||||
@ -65,11 +107,11 @@ impl Miner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Creates new instance of miner
|
/// Creates new instance of miner
|
||||||
pub fn new(force_sealing: bool, spec: Spec, accounts: Option<Arc<AccountProvider>>) -> Arc<Miner> {
|
pub fn new(options: MinerOptions, spec: Spec, accounts: Option<Arc<AccountProvider>>) -> Arc<Miner> {
|
||||||
Arc::new(Miner {
|
Arc::new(Miner {
|
||||||
transaction_queue: Mutex::new(TransactionQueue::new()),
|
transaction_queue: Mutex::new(TransactionQueue::with_limits(options.tx_queue_size, options.tx_gas_limit)),
|
||||||
force_sealing: force_sealing,
|
sealing_enabled: AtomicBool::new(options.force_sealing),
|
||||||
sealing_enabled: AtomicBool::new(force_sealing),
|
options: options,
|
||||||
sealing_block_last_request: Mutex::new(0),
|
sealing_block_last_request: Mutex::new(0),
|
||||||
sealing_work: Mutex::new(UsingQueue::new(5)),
|
sealing_work: Mutex::new(UsingQueue::new(5)),
|
||||||
gas_range_target: RwLock::new((U256::zero(), U256::zero())),
|
gas_range_target: RwLock::new((U256::zero(), U256::zero())),
|
||||||
@ -356,6 +398,10 @@ impl MinerService for Miner {
|
|||||||
self.transaction_queue.lock().unwrap().set_limit(limit)
|
self.transaction_queue.lock().unwrap().set_limit(limit)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_tx_gas_limit(&self, limit: U256) {
|
||||||
|
self.transaction_queue.lock().unwrap().set_tx_gas_limit(limit)
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the author that we will seal blocks as.
|
/// Get the author that we will seal blocks as.
|
||||||
fn author(&self) -> Address {
|
fn author(&self) -> Address {
|
||||||
*self.author.read().unwrap()
|
*self.author.read().unwrap()
|
||||||
@ -385,7 +431,7 @@ impl MinerService for Miner {
|
|||||||
.map(|tx| transaction_queue.add(tx, &fetch_account, TransactionOrigin::External))
|
.map(|tx| transaction_queue.add(tx, &fetch_account, TransactionOrigin::External))
|
||||||
.collect()
|
.collect()
|
||||||
};
|
};
|
||||||
if !results.is_empty() {
|
if !results.is_empty() && self.options.reseal_on_external_tx {
|
||||||
self.update_sealing(chain);
|
self.update_sealing(chain);
|
||||||
}
|
}
|
||||||
results
|
results
|
||||||
@ -420,7 +466,7 @@ impl MinerService for Miner {
|
|||||||
import
|
import
|
||||||
};
|
};
|
||||||
|
|
||||||
if imported.is_ok() {
|
if imported.is_ok() && self.options.reseal_on_own_tx {
|
||||||
// Make sure to do it after transaction is imported and lock is droped.
|
// Make sure to do it after transaction is imported and lock is droped.
|
||||||
// We need to create pending block and enable sealing
|
// We need to create pending block and enable sealing
|
||||||
let prepared = self.enable_and_prepare_sealing(chain);
|
let prepared = self.enable_and_prepare_sealing(chain);
|
||||||
@ -434,26 +480,6 @@ impl MinerService for Miner {
|
|||||||
imported
|
imported
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pending_transactions_hashes(&self) -> Vec<H256> {
|
|
||||||
let queue = self.transaction_queue.lock().unwrap();
|
|
||||||
match (self.sealing_enabled.load(atomic::Ordering::Relaxed), self.sealing_work.lock().unwrap().peek_last_ref()) {
|
|
||||||
(true, Some(pending)) => pending.transactions().iter().map(|t| t.hash()).collect(),
|
|
||||||
_ => {
|
|
||||||
queue.pending_hashes()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn transaction(&self, hash: &H256) -> Option<SignedTransaction> {
|
|
||||||
let queue = self.transaction_queue.lock().unwrap();
|
|
||||||
match (self.sealing_enabled.load(atomic::Ordering::Relaxed), self.sealing_work.lock().unwrap().peek_last_ref()) {
|
|
||||||
(true, Some(pending)) => pending.transactions().iter().find(|t| &t.hash() == hash).cloned(),
|
|
||||||
_ => {
|
|
||||||
queue.find(hash)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn all_transactions(&self) -> Vec<SignedTransaction> {
|
fn all_transactions(&self) -> Vec<SignedTransaction> {
|
||||||
let queue = self.transaction_queue.lock().unwrap();
|
let queue = self.transaction_queue.lock().unwrap();
|
||||||
queue.top_transactions()
|
queue.top_transactions()
|
||||||
@ -461,12 +487,41 @@ impl MinerService for Miner {
|
|||||||
|
|
||||||
fn pending_transactions(&self) -> Vec<SignedTransaction> {
|
fn pending_transactions(&self) -> Vec<SignedTransaction> {
|
||||||
let queue = self.transaction_queue.lock().unwrap();
|
let queue = self.transaction_queue.lock().unwrap();
|
||||||
|
let sw = self.sealing_work.lock().unwrap();
|
||||||
// TODO: should only use the sealing_work when it's current (it could be an old block)
|
// TODO: should only use the sealing_work when it's current (it could be an old block)
|
||||||
match (self.sealing_enabled.load(atomic::Ordering::Relaxed), self.sealing_work.lock().unwrap().peek_last_ref()) {
|
let sealing_set = match self.sealing_enabled.load(atomic::Ordering::Relaxed) {
|
||||||
(true, Some(pending)) => pending.transactions().clone(),
|
true => sw.peek_last_ref(),
|
||||||
_ => {
|
false => None,
|
||||||
queue.top_transactions()
|
};
|
||||||
}
|
match (&self.options.pending_set, sealing_set) {
|
||||||
|
(&PendingSet::AlwaysQueue, _) | (&PendingSet::SealingOrElseQueue, None) => queue.top_transactions(),
|
||||||
|
(_, sealing) => sealing.map_or_else(Vec::new, |s| s.transactions().clone()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pending_transactions_hashes(&self) -> Vec<H256> {
|
||||||
|
let queue = self.transaction_queue.lock().unwrap();
|
||||||
|
let sw = self.sealing_work.lock().unwrap();
|
||||||
|
let sealing_set = match self.sealing_enabled.load(atomic::Ordering::Relaxed) {
|
||||||
|
true => sw.peek_last_ref(),
|
||||||
|
false => None,
|
||||||
|
};
|
||||||
|
match (&self.options.pending_set, sealing_set) {
|
||||||
|
(&PendingSet::AlwaysQueue, _) | (&PendingSet::SealingOrElseQueue, None) => queue.pending_hashes(),
|
||||||
|
(_, sealing) => sealing.map_or_else(Vec::new, |s| s.transactions().iter().map(|t| t.hash()).collect()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn transaction(&self, hash: &H256) -> Option<SignedTransaction> {
|
||||||
|
let queue = self.transaction_queue.lock().unwrap();
|
||||||
|
let sw = self.sealing_work.lock().unwrap();
|
||||||
|
let sealing_set = match self.sealing_enabled.load(atomic::Ordering::Relaxed) {
|
||||||
|
true => sw.peek_last_ref(),
|
||||||
|
false => None,
|
||||||
|
};
|
||||||
|
match (&self.options.pending_set, sealing_set) {
|
||||||
|
(&PendingSet::AlwaysQueue, _) | (&PendingSet::SealingOrElseQueue, None) => queue.find(hash),
|
||||||
|
(_, sealing) => sealing.and_then(|s| s.transactions().iter().find(|t| &t.hash() == hash).cloned()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -494,7 +549,7 @@ impl MinerService for Miner {
|
|||||||
let current_no = chain.chain_info().best_block_number;
|
let current_no = chain.chain_info().best_block_number;
|
||||||
let has_local_transactions = self.transaction_queue.lock().unwrap().has_local_pending_transactions();
|
let has_local_transactions = self.transaction_queue.lock().unwrap().has_local_pending_transactions();
|
||||||
let last_request = *self.sealing_block_last_request.lock().unwrap();
|
let last_request = *self.sealing_block_last_request.lock().unwrap();
|
||||||
let should_disable_sealing = !self.force_sealing
|
let should_disable_sealing = !self.options.force_sealing
|
||||||
&& !has_local_transactions
|
&& !has_local_transactions
|
||||||
&& current_no > last_request
|
&& current_no > last_request
|
||||||
&& current_no - last_request > SEALING_TIMEOUT_IN_BLOCKS;
|
&& current_no - last_request > SEALING_TIMEOUT_IN_BLOCKS;
|
||||||
|
@ -47,7 +47,7 @@ mod external;
|
|||||||
mod transaction_queue;
|
mod transaction_queue;
|
||||||
|
|
||||||
pub use self::transaction_queue::{TransactionQueue, AccountDetails, TransactionImportResult, TransactionOrigin};
|
pub use self::transaction_queue::{TransactionQueue, AccountDetails, TransactionImportResult, TransactionOrigin};
|
||||||
pub use self::miner::{Miner};
|
pub use self::miner::{Miner, MinerOptions, PendingSet};
|
||||||
pub use self::external::{ExternalMiner, ExternalMinerService};
|
pub use self::external::{ExternalMiner, ExternalMinerService};
|
||||||
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
@ -101,6 +101,9 @@ pub trait MinerService : Send + Sync {
|
|||||||
/// Set maximal number of transactions kept in the queue (both current and future).
|
/// Set maximal number of transactions kept in the queue (both current and future).
|
||||||
fn set_transactions_limit(&self, limit: usize);
|
fn set_transactions_limit(&self, limit: usize);
|
||||||
|
|
||||||
|
/// Set maximum amount of gas allowed for any single transaction to mine.
|
||||||
|
fn set_tx_gas_limit(&self, limit: U256);
|
||||||
|
|
||||||
/// Imports transactions to transaction queue.
|
/// Imports transactions to transaction queue.
|
||||||
fn import_transactions<T>(&self, chain: &MiningBlockChainClient, transactions: Vec<SignedTransaction>, fetch_account: T) ->
|
fn import_transactions<T>(&self, chain: &MiningBlockChainClient, transactions: Vec<SignedTransaction>, fetch_account: T) ->
|
||||||
Vec<Result<TransactionImportResult, Error>>
|
Vec<Result<TransactionImportResult, Error>>
|
||||||
|
@ -334,6 +334,8 @@ const GAS_LIMIT_HYSTERESIS: usize = 10; // %
|
|||||||
pub struct TransactionQueue {
|
pub struct TransactionQueue {
|
||||||
/// Gas Price threshold for transactions that can be imported to this queue (defaults to 0)
|
/// Gas Price threshold for transactions that can be imported to this queue (defaults to 0)
|
||||||
minimal_gas_price: U256,
|
minimal_gas_price: U256,
|
||||||
|
/// The maximum amount of gas any individual transaction may use.
|
||||||
|
tx_gas_limit: U256,
|
||||||
/// Current gas limit (block gas limit * factor). Transactions above the limit will not be accepted (default to !0)
|
/// Current gas limit (block gas limit * factor). Transactions above the limit will not be accepted (default to !0)
|
||||||
gas_limit: U256,
|
gas_limit: U256,
|
||||||
/// Priority queue for transactions that can go to block
|
/// Priority queue for transactions that can go to block
|
||||||
@ -355,11 +357,11 @@ impl Default for TransactionQueue {
|
|||||||
impl TransactionQueue {
|
impl TransactionQueue {
|
||||||
/// Creates new instance of this Queue
|
/// Creates new instance of this Queue
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self::with_limit(1024)
|
Self::with_limits(1024, !U256::zero())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create new instance of this Queue with specified limits
|
/// Create new instance of this Queue with specified limits
|
||||||
pub fn with_limit(limit: usize) -> Self {
|
pub fn with_limits(limit: usize, tx_gas_limit: U256) -> Self {
|
||||||
let current = TransactionSet {
|
let current = TransactionSet {
|
||||||
by_priority: BTreeSet::new(),
|
by_priority: BTreeSet::new(),
|
||||||
by_address: Table::new(),
|
by_address: Table::new(),
|
||||||
@ -374,6 +376,7 @@ impl TransactionQueue {
|
|||||||
|
|
||||||
TransactionQueue {
|
TransactionQueue {
|
||||||
minimal_gas_price: U256::zero(),
|
minimal_gas_price: U256::zero(),
|
||||||
|
tx_gas_limit: tx_gas_limit,
|
||||||
gas_limit: !U256::zero(),
|
gas_limit: !U256::zero(),
|
||||||
current: current,
|
current: current,
|
||||||
future: future,
|
future: future,
|
||||||
@ -418,6 +421,12 @@ impl TransactionQueue {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the new limit for the amount of gas any individual transaction may have.
|
||||||
|
/// Any transaction already imported to the queue is not affected.
|
||||||
|
pub fn set_tx_gas_limit(&mut self, limit: U256) {
|
||||||
|
self.tx_gas_limit = limit;
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns current status for this queue
|
/// Returns current status for this queue
|
||||||
pub fn status(&self) -> TransactionQueueStatus {
|
pub fn status(&self) -> TransactionQueueStatus {
|
||||||
TransactionQueueStatus {
|
TransactionQueueStatus {
|
||||||
@ -435,7 +444,9 @@ impl TransactionQueue {
|
|||||||
if tx.gas_price < self.minimal_gas_price {
|
if tx.gas_price < self.minimal_gas_price {
|
||||||
trace!(target: "miner",
|
trace!(target: "miner",
|
||||||
"Dropping transaction below minimal gas price threshold: {:?} (gp: {} < {})",
|
"Dropping transaction below minimal gas price threshold: {:?} (gp: {} < {})",
|
||||||
tx.hash(), tx.gas_price, self.minimal_gas_price
|
tx.hash(),
|
||||||
|
tx.gas_price,
|
||||||
|
self.minimal_gas_price
|
||||||
);
|
);
|
||||||
|
|
||||||
return Err(Error::Transaction(TransactionError::InsufficientGasPrice {
|
return Err(Error::Transaction(TransactionError::InsufficientGasPrice {
|
||||||
@ -446,10 +457,13 @@ impl TransactionQueue {
|
|||||||
|
|
||||||
try!(tx.check_low_s());
|
try!(tx.check_low_s());
|
||||||
|
|
||||||
if tx.gas > self.gas_limit {
|
if tx.gas > self.gas_limit || tx.gas > self.tx_gas_limit {
|
||||||
trace!(target: "miner",
|
trace!(target: "miner",
|
||||||
"Dropping transaction above gas limit: {:?} ({} > {})",
|
"Dropping transaction above gas limit: {:?} ({} > min({}, {}))",
|
||||||
tx.hash(), tx.gas, self.gas_limit
|
tx.hash(),
|
||||||
|
tx.gas,
|
||||||
|
self.gas_limit,
|
||||||
|
self.tx_gas_limit
|
||||||
);
|
);
|
||||||
|
|
||||||
return Err(Error::Transaction(TransactionError::GasLimitExceeded {
|
return Err(Error::Transaction(TransactionError::GasLimitExceeded {
|
||||||
@ -463,8 +477,13 @@ impl TransactionQueue {
|
|||||||
|
|
||||||
let cost = vtx.transaction.value + vtx.transaction.gas_price * vtx.transaction.gas;
|
let cost = vtx.transaction.value + vtx.transaction.gas_price * vtx.transaction.gas;
|
||||||
if client_account.balance < cost {
|
if client_account.balance < cost {
|
||||||
trace!(target: "miner", "Dropping transaction without sufficient balance: {:?} ({} < {})",
|
trace!(target: "miner",
|
||||||
vtx.hash(), client_account.balance, cost);
|
"Dropping transaction without sufficient balance: {:?} ({} < {})",
|
||||||
|
vtx.hash(),
|
||||||
|
client_account.balance,
|
||||||
|
cost
|
||||||
|
);
|
||||||
|
|
||||||
return Err(Error::Transaction(TransactionError::InsufficientBalance {
|
return Err(Error::Transaction(TransactionError::InsufficientBalance {
|
||||||
cost: cost,
|
cost: cost,
|
||||||
balance: client_account.balance
|
balance: client_account.balance
|
||||||
@ -1288,7 +1307,7 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn should_drop_old_transactions_when_hitting_the_limit() {
|
fn should_drop_old_transactions_when_hitting_the_limit() {
|
||||||
// given
|
// given
|
||||||
let mut txq = TransactionQueue::with_limit(1);
|
let mut txq = TransactionQueue::with_limits(1, !U256::zero());
|
||||||
let (tx, tx2) = new_txs(U256::one());
|
let (tx, tx2) = new_txs(U256::one());
|
||||||
let sender = tx.sender().unwrap();
|
let sender = tx.sender().unwrap();
|
||||||
let nonce = tx.nonce;
|
let nonce = tx.nonce;
|
||||||
@ -1310,7 +1329,7 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn should_return_correct_nonces_when_dropped_because_of_limit() {
|
fn should_return_correct_nonces_when_dropped_because_of_limit() {
|
||||||
// given
|
// given
|
||||||
let mut txq = TransactionQueue::with_limit(2);
|
let mut txq = TransactionQueue::with_limits(2, !U256::zero());
|
||||||
let tx = new_tx();
|
let tx = new_tx();
|
||||||
let (tx1, tx2) = new_txs(U256::one());
|
let (tx1, tx2) = new_txs(U256::one());
|
||||||
let sender = tx1.sender().unwrap();
|
let sender = tx1.sender().unwrap();
|
||||||
@ -1331,7 +1350,7 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_limit_future_transactions() {
|
fn should_limit_future_transactions() {
|
||||||
let mut txq = TransactionQueue::with_limit(1);
|
let mut txq = TransactionQueue::with_limits(1, !U256::zero());
|
||||||
txq.current.set_limit(10);
|
txq.current.set_limit(10);
|
||||||
let (tx1, tx2) = new_txs_with_gas_price_diff(U256::from(4), U256::from(1));
|
let (tx1, tx2) = new_txs_with_gas_price_diff(U256::from(4), U256::from(1));
|
||||||
let (tx3, tx4) = new_txs_with_gas_price_diff(U256::from(4), U256::from(2));
|
let (tx3, tx4) = new_txs_with_gas_price_diff(U256::from(4), U256::from(2));
|
||||||
@ -1591,7 +1610,7 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn should_keep_right_order_in_future() {
|
fn should_keep_right_order_in_future() {
|
||||||
// given
|
// given
|
||||||
let mut txq = TransactionQueue::with_limit(1);
|
let mut txq = TransactionQueue::with_limits(1, !U256::zero());
|
||||||
let (tx1, tx2) = new_txs(U256::from(1));
|
let (tx1, tx2) = new_txs(U256::from(1));
|
||||||
let prev_nonce = |a: &Address| AccountDetails { nonce: default_nonce(a).nonce - U256::one(), balance:
|
let prev_nonce = |a: &Address| AccountDetails { nonce: default_nonce(a).nonce - U256::one(), balance:
|
||||||
default_nonce(a).balance };
|
default_nonce(a).balance };
|
||||||
|
@ -24,11 +24,11 @@ use super::verification;
|
|||||||
pub struct CanonVerifier;
|
pub struct CanonVerifier;
|
||||||
|
|
||||||
impl Verifier for CanonVerifier {
|
impl Verifier for CanonVerifier {
|
||||||
fn verify_block_family(header: &Header, bytes: &[u8], engine: &Engine, bc: &BlockProvider) -> Result<(), Error> {
|
fn verify_block_family(&self, header: &Header, bytes: &[u8], engine: &Engine, bc: &BlockProvider) -> Result<(), Error> {
|
||||||
verification::verify_block_family(header, bytes, engine, bc)
|
verification::verify_block_family(header, bytes, engine, bc)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn verify_block_final(expected: &Header, got: &Header) -> Result<(), Error> {
|
fn verify_block_final(&self, expected: &Header, got: &Header) -> Result<(), Error> {
|
||||||
verification::verify_block_final(expected, got)
|
verification::verify_block_final(expected, got)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,11 +17,32 @@
|
|||||||
pub mod verification;
|
pub mod verification;
|
||||||
pub mod verifier;
|
pub mod verifier;
|
||||||
mod canon_verifier;
|
mod canon_verifier;
|
||||||
#[cfg(test)]
|
|
||||||
mod noop_verifier;
|
mod noop_verifier;
|
||||||
|
|
||||||
pub use self::verification::*;
|
pub use self::verification::*;
|
||||||
pub use self::verifier::Verifier;
|
pub use self::verifier::Verifier;
|
||||||
pub use self::canon_verifier::CanonVerifier;
|
pub use self::canon_verifier::CanonVerifier;
|
||||||
#[cfg(test)]
|
|
||||||
pub use self::noop_verifier::NoopVerifier;
|
pub use self::noop_verifier::NoopVerifier;
|
||||||
|
|
||||||
|
/// Verifier type.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum VerifierType {
|
||||||
|
/// Verifies block normally.
|
||||||
|
Canon,
|
||||||
|
/// Does not verify block at all.
|
||||||
|
/// Used in tests.
|
||||||
|
Noop,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for VerifierType {
|
||||||
|
fn default() -> Self {
|
||||||
|
VerifierType::Canon
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(v: VerifierType) -> Box<Verifier> {
|
||||||
|
match v {
|
||||||
|
VerifierType::Canon => Box::new(CanonVerifier),
|
||||||
|
VerifierType::Noop => Box::new(NoopVerifier),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -24,11 +24,11 @@ use super::Verifier;
|
|||||||
pub struct NoopVerifier;
|
pub struct NoopVerifier;
|
||||||
|
|
||||||
impl Verifier for NoopVerifier {
|
impl Verifier for NoopVerifier {
|
||||||
fn verify_block_family(_header: &Header, _bytes: &[u8], _engine: &Engine, _bc: &BlockProvider) -> Result<(), Error> {
|
fn verify_block_family(&self, _header: &Header, _bytes: &[u8], _engine: &Engine, _bc: &BlockProvider) -> Result<(), Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn verify_block_final(_expected: &Header, _got: &Header) -> Result<(), Error> {
|
fn verify_block_final(&self, _expected: &Header, _got: &Header) -> Result<(), Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,6 @@ use header::Header;
|
|||||||
|
|
||||||
/// Should be used to verify blocks.
|
/// Should be used to verify blocks.
|
||||||
pub trait Verifier: Send + Sync {
|
pub trait Verifier: Send + Sync {
|
||||||
fn verify_block_family(header: &Header, bytes: &[u8], engine: &Engine, bc: &BlockProvider) -> Result<(), Error>;
|
fn verify_block_family(&self, header: &Header, bytes: &[u8], engine: &Engine, bc: &BlockProvider) -> Result<(), Error>;
|
||||||
fn verify_block_final(expected: &Header, got: &Header) -> Result<(), Error>;
|
fn verify_block_final(&self, expected: &Header, got: &Header) -> Result<(), Error>;
|
||||||
}
|
}
|
||||||
|
@ -133,6 +133,22 @@ Sealing/Mining Options:
|
|||||||
NOTE: MINING WILL NOT WORK WITHOUT THIS OPTION.
|
NOTE: MINING WILL NOT WORK WITHOUT THIS OPTION.
|
||||||
--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.
|
||||||
|
--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
|
--usd-per-tx USD Amount of USD to be paid for a basic transaction
|
||||||
[default: 0.005]. The minimum gas price is set
|
[default: 0.005]. The minimum gas price is set
|
||||||
accordingly.
|
accordingly.
|
||||||
@ -146,8 +162,8 @@ Sealing/Mining Options:
|
|||||||
block due to transaction volume [default: 3141592].
|
block due to transaction volume [default: 3141592].
|
||||||
--extra-data STRING Specify a custom extra-data for authored blocks, no
|
--extra-data STRING Specify a custom extra-data for authored blocks, no
|
||||||
more than 32 characters.
|
more than 32 characters.
|
||||||
--tx-limit LIMIT Limit of transactions kept in the queue (waiting to
|
--tx-queue-size LIMIT Maximum amount of transactions in the queue (waiting
|
||||||
be included in next block) [default: 1024].
|
to be included in next block) [default: 1024].
|
||||||
|
|
||||||
Footprint Options:
|
Footprint Options:
|
||||||
--tracing BOOL Indicates if full transaction tracing should be
|
--tracing BOOL Indicates if full transaction tracing should be
|
||||||
@ -288,13 +304,16 @@ pub struct Args {
|
|||||||
pub flag_signer_path: String,
|
pub flag_signer_path: String,
|
||||||
pub flag_no_token: bool,
|
pub flag_no_token: bool,
|
||||||
pub flag_force_sealing: bool,
|
pub flag_force_sealing: bool,
|
||||||
|
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_author: Option<String>,
|
||||||
pub flag_usd_per_tx: String,
|
pub flag_usd_per_tx: String,
|
||||||
pub flag_usd_per_eth: String,
|
pub flag_usd_per_eth: String,
|
||||||
pub flag_gas_floor_target: String,
|
pub flag_gas_floor_target: String,
|
||||||
pub flag_gas_cap: String,
|
pub flag_gas_cap: String,
|
||||||
pub flag_extra_data: Option<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_logging: Option<String>,
|
||||||
pub flag_version: bool,
|
pub flag_version: bool,
|
||||||
pub flag_from: String,
|
pub flag_from: String,
|
||||||
|
@ -27,6 +27,7 @@ use util::*;
|
|||||||
use ethcore::account_provider::AccountProvider;
|
use ethcore::account_provider::AccountProvider;
|
||||||
use util::network_settings::NetworkSettings;
|
use util::network_settings::NetworkSettings;
|
||||||
use ethcore::client::{append_path, get_db_path, ClientConfig, DatabaseCompactionProfile, Switch, VMType};
|
use ethcore::client::{append_path, get_db_path, ClientConfig, DatabaseCompactionProfile, Switch, VMType};
|
||||||
|
use ethcore::miner::{MinerOptions, PendingSet};
|
||||||
use ethcore::ethereum;
|
use ethcore::ethereum;
|
||||||
use ethcore::spec::Spec;
|
use ethcore::spec::Spec;
|
||||||
use ethsync::SyncConfig;
|
use ethsync::SyncConfig;
|
||||||
@ -67,6 +68,37 @@ impl Configuration {
|
|||||||
self.args.flag_maxpeers.unwrap_or(self.args.flag_peers) as u32
|
self.args.flag_maxpeers.unwrap_or(self.args.flag_peers) as u32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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> {
|
pub fn author(&self) -> Option<Address> {
|
||||||
self.args.flag_etherbase.as_ref()
|
self.args.flag_etherbase.as_ref()
|
||||||
.or(self.args.flag_author.as_ref())
|
.or(self.args.flag_author.as_ref())
|
||||||
|
@ -208,13 +208,13 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig)
|
|||||||
let account_service = Arc::new(conf.account_service());
|
let account_service = Arc::new(conf.account_service());
|
||||||
|
|
||||||
// Miner
|
// Miner
|
||||||
let miner = Miner::new(conf.args.flag_force_sealing, conf.spec(), Some(account_service.clone()));
|
let miner = Miner::new(conf.miner_options(), conf.spec(), Some(account_service.clone()));
|
||||||
miner.set_author(conf.author().unwrap_or_default());
|
miner.set_author(conf.author().unwrap_or_default());
|
||||||
miner.set_gas_floor_target(conf.gas_floor_target());
|
miner.set_gas_floor_target(conf.gas_floor_target());
|
||||||
miner.set_gas_ceil_target(conf.gas_ceil_target());
|
miner.set_gas_ceil_target(conf.gas_ceil_target());
|
||||||
miner.set_extra_data(conf.extra_data());
|
miner.set_extra_data(conf.extra_data());
|
||||||
miner.set_minimal_gas_price(conf.gas_price());
|
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
|
// Build client
|
||||||
let mut service = ClientService::start(
|
let mut service = ClientService::start(
|
||||||
|
@ -22,7 +22,7 @@ use jsonrpc_core::*;
|
|||||||
use ethcore::miner::MinerService;
|
use ethcore::miner::MinerService;
|
||||||
use ethcore::service::SyncMessage;
|
use ethcore::service::SyncMessage;
|
||||||
use v1::traits::EthcoreSet;
|
use v1::traits::EthcoreSet;
|
||||||
use v1::types::{Bytes};
|
use v1::types::Bytes;
|
||||||
|
|
||||||
/// Ethcore-specific rpc interface for operations altering the settings.
|
/// Ethcore-specific rpc interface for operations altering the settings.
|
||||||
pub struct EthcoreSetClient<M> where
|
pub struct EthcoreSetClient<M> where
|
||||||
@ -86,6 +86,13 @@ impl<M> EthcoreSet for EthcoreSetClient<M> where M: MinerService + 'static {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_tx_gas_limit(&self, params: Params) -> Result<Value, Error> {
|
||||||
|
from_params::<(U256,)>(params).and_then(|(limit,)| {
|
||||||
|
take_weak!(self.miner).set_tx_gas_limit(limit.into());
|
||||||
|
to_value(&true)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn add_reserved_peer(&self, params: Params) -> Result<Value, Error> {
|
fn add_reserved_peer(&self, params: Params) -> Result<Value, Error> {
|
||||||
from_params::<(String,)>(params).and_then(|(peer,)| {
|
from_params::<(String,)>(params).and_then(|(peer,)| {
|
||||||
match take_weak!(self.net).add_reserved_peer(&peer) {
|
match take_weak!(self.net).add_reserved_peer(&peer) {
|
||||||
|
@ -24,12 +24,12 @@ use ethcore::spec::{Genesis, Spec};
|
|||||||
use ethcore::block::Block;
|
use ethcore::block::Block;
|
||||||
use ethcore::views::BlockView;
|
use ethcore::views::BlockView;
|
||||||
use ethcore::ethereum;
|
use ethcore::ethereum;
|
||||||
use ethcore::miner::{MinerService, ExternalMiner, Miner};
|
use ethcore::miner::{MinerOptions, MinerService, ExternalMiner, Miner, PendingSet};
|
||||||
use ethcore::account_provider::AccountProvider;
|
use ethcore::account_provider::AccountProvider;
|
||||||
use devtools::RandomTempPath;
|
use devtools::RandomTempPath;
|
||||||
use util::Hashable;
|
use util::Hashable;
|
||||||
use util::io::IoChannel;
|
use util::io::IoChannel;
|
||||||
use util::{U256, H256};
|
use util::{U256, H256, Uint};
|
||||||
use jsonrpc_core::IoHandler;
|
use jsonrpc_core::IoHandler;
|
||||||
use ethjson::blockchain::BlockChain;
|
use ethjson::blockchain::BlockChain;
|
||||||
|
|
||||||
@ -49,7 +49,18 @@ fn sync_provider() -> Arc<TestSyncProvider> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn miner_service(spec: Spec, accounts: Arc<AccountProvider>) -> Arc<Miner> {
|
fn miner_service(spec: Spec, accounts: Arc<AccountProvider>) -> Arc<Miner> {
|
||||||
Miner::new(true, spec, Some(accounts))
|
Miner::new(
|
||||||
|
MinerOptions {
|
||||||
|
force_sealing: true,
|
||||||
|
reseal_on_external_tx: true,
|
||||||
|
reseal_on_own_tx: true,
|
||||||
|
tx_queue_size: 1024,
|
||||||
|
tx_gas_limit: !U256::zero(),
|
||||||
|
pending_set: PendingSet::SealingOrElseQueue,
|
||||||
|
},
|
||||||
|
spec,
|
||||||
|
Some(accounts)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_spec(chain: &BlockChain) -> Spec {
|
fn make_spec(chain: &BlockChain) -> Spec {
|
||||||
|
@ -43,6 +43,7 @@ pub struct TestMinerService {
|
|||||||
author: RwLock<Address>,
|
author: RwLock<Address>,
|
||||||
extra_data: RwLock<Bytes>,
|
extra_data: RwLock<Bytes>,
|
||||||
limit: RwLock<usize>,
|
limit: RwLock<usize>,
|
||||||
|
tx_gas_limit: RwLock<U256>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for TestMinerService {
|
impl Default for TestMinerService {
|
||||||
@ -58,6 +59,7 @@ impl Default for TestMinerService {
|
|||||||
author: RwLock::new(Address::zero()),
|
author: RwLock::new(Address::zero()),
|
||||||
extra_data: RwLock::new(vec![1, 2, 3, 4]),
|
extra_data: RwLock::new(vec![1, 2, 3, 4]),
|
||||||
limit: RwLock::new(1024),
|
limit: RwLock::new(1024),
|
||||||
|
tx_gas_limit: RwLock::new(!U256::zero()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -99,6 +101,10 @@ impl MinerService for TestMinerService {
|
|||||||
*self.limit.write().unwrap() = limit;
|
*self.limit.write().unwrap() = limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_tx_gas_limit(&self, limit: U256) {
|
||||||
|
*self.tx_gas_limit.write().unwrap() = limit;
|
||||||
|
}
|
||||||
|
|
||||||
fn transactions_limit(&self) -> usize {
|
fn transactions_limit(&self) -> usize {
|
||||||
*self.limit.read().unwrap()
|
*self.limit.read().unwrap()
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,9 @@ pub trait EthcoreSet: Sized + Send + Sync + 'static {
|
|||||||
/// Sets the limits for transaction queue.
|
/// Sets the limits for transaction queue.
|
||||||
fn set_transactions_limit(&self, _: Params) -> Result<Value, Error>;
|
fn set_transactions_limit(&self, _: Params) -> Result<Value, Error>;
|
||||||
|
|
||||||
|
/// Sets the maximum amount of gas a single transaction may consume.
|
||||||
|
fn set_tx_gas_limit(&self, _: Params) -> Result<Value, Error>;
|
||||||
|
|
||||||
/// Add a reserved peer.
|
/// Add a reserved peer.
|
||||||
fn add_reserved_peer(&self, _: Params) -> Result<Value, Error>;
|
fn add_reserved_peer(&self, _: Params) -> Result<Value, Error>;
|
||||||
|
|
||||||
@ -60,6 +63,7 @@ pub trait EthcoreSet: Sized + Send + Sync + 'static {
|
|||||||
delegate.add_method("ethcore_setGasCeilTarget", EthcoreSet::set_gas_ceil_target);
|
delegate.add_method("ethcore_setGasCeilTarget", EthcoreSet::set_gas_ceil_target);
|
||||||
delegate.add_method("ethcore_setExtraData", EthcoreSet::set_extra_data);
|
delegate.add_method("ethcore_setExtraData", EthcoreSet::set_extra_data);
|
||||||
delegate.add_method("ethcore_setAuthor", EthcoreSet::set_author);
|
delegate.add_method("ethcore_setAuthor", EthcoreSet::set_author);
|
||||||
|
delegate.add_method("ethcore_setMaxTransactionGas", EthcoreSet::set_tx_gas_limit);
|
||||||
delegate.add_method("ethcore_setTransactionsLimit", EthcoreSet::set_transactions_limit);
|
delegate.add_method("ethcore_setTransactionsLimit", EthcoreSet::set_transactions_limit);
|
||||||
delegate.add_method("ethcore_addReservedPeer", EthcoreSet::add_reserved_peer);
|
delegate.add_method("ethcore_addReservedPeer", EthcoreSet::add_reserved_peer);
|
||||||
delegate.add_method("ethcore_removeReservedPeer", EthcoreSet::remove_reserved_peer);
|
delegate.add_method("ethcore_removeReservedPeer", EthcoreSet::remove_reserved_peer);
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use serde::{Serialize, Serializer};
|
use serde::{Serialize, Serializer, Deserialize, Deserializer};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
/// Optional value
|
/// Optional value
|
||||||
@ -26,13 +26,22 @@ pub enum OptionalValue<T> where T: Serialize {
|
|||||||
Null
|
Null
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Default for OptionalValue<T> where T: Serialize {
|
impl<T> Default for OptionalValue<T> where T: Serialize + Deserialize {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
OptionalValue::Null
|
OptionalValue::Null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Serialize for OptionalValue<T> where T: Serialize {
|
impl<T> Into<Option<T>> for OptionalValue<T> where T: Serialize + Deserialize {
|
||||||
|
fn into(self) -> Option<T> {
|
||||||
|
match self {
|
||||||
|
OptionalValue::Null => None,
|
||||||
|
OptionalValue::Value(t) => Some(t),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Serialize for OptionalValue<T> where T: Serialize + Deserialize {
|
||||||
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
||||||
where S: Serializer {
|
where S: Serializer {
|
||||||
match *self {
|
match *self {
|
||||||
@ -42,6 +51,17 @@ impl<T> Serialize for OptionalValue<T> where T: Serialize {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> Deserialize for OptionalValue<T> where T: Serialize + Deserialize {
|
||||||
|
fn deserialize<D>(deserializer: &mut D) -> Result<OptionalValue<T>, D::Error>
|
||||||
|
where D: Deserializer {
|
||||||
|
let deser_result: Result<T, D::Error> = Deserialize::deserialize(deserializer);
|
||||||
|
match deser_result {
|
||||||
|
Ok(t) => Ok(OptionalValue::Value(t)),
|
||||||
|
Err(_) => Ok(OptionalValue::Null),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use serde_json;
|
use serde_json;
|
||||||
|
@ -1314,7 +1314,7 @@ impl ChainSync {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut transactions = io.chain().all_transactions();
|
let mut transactions = io.chain().pending_transactions();
|
||||||
if transactions.is_empty() {
|
if transactions.is_empty() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@
|
|||||||
//! let mut service = NetworkService::new(NetworkConfiguration::new()).unwrap();
|
//! let mut service = NetworkService::new(NetworkConfiguration::new()).unwrap();
|
||||||
//! service.start().unwrap();
|
//! service.start().unwrap();
|
||||||
//! let dir = env::temp_dir();
|
//! let dir = env::temp_dir();
|
||||||
//! let miner = Miner::new(false, ethereum::new_frontier(true), None);
|
//! let miner = Miner::new(Default::default(), ethereum::new_frontier(true), None);
|
||||||
//! let client = Client::new(
|
//! let client = Client::new(
|
||||||
//! ClientConfig::default(),
|
//! ClientConfig::default(),
|
||||||
//! ethereum::new_frontier(true),
|
//! ethereum::new_frontier(true),
|
||||||
|
@ -557,7 +557,7 @@ macro_rules! construct_uint {
|
|||||||
($name:ident, $n_words:expr) => (
|
($name:ident, $n_words:expr) => (
|
||||||
/// Little-endian large integer type
|
/// Little-endian large integer type
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
||||||
pub struct $name(pub [u64; $n_words]);
|
pub struct $name(pub [u64; $n_words]);
|
||||||
|
|
||||||
impl Uint for $name {
|
impl Uint for $name {
|
||||||
@ -1126,14 +1126,6 @@ macro_rules! construct_uint {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature="dev", allow(derive_hash_xor_eq))] // We are pretty sure it's ok.
|
|
||||||
impl Hash for $name {
|
|
||||||
fn hash<H>(&self, state: &mut H) where H: Hasher {
|
|
||||||
unsafe { state.write(::std::slice::from_raw_parts(self.0.as_ptr() as *mut u8, self.0.len() * 8)); }
|
|
||||||
state.finish();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,15 +132,10 @@ macro_rules! impl_hash {
|
|||||||
$size
|
$size
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: remove once slice::clone_from_slice is stable
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn clone_from_slice(&mut self, src: &[u8]) -> usize {
|
fn clone_from_slice(&mut self, src: &[u8]) -> usize {
|
||||||
let min = ::std::cmp::min($size, src.len());
|
let min = cmp::min($size, src.len());
|
||||||
let dst = &mut self.deref_mut()[.. min];
|
self.0[..min].copy_from_slice(&src[..min]);
|
||||||
let src = &src[.. min];
|
|
||||||
for i in 0..min {
|
|
||||||
dst[i] = src[i];
|
|
||||||
}
|
|
||||||
min
|
min
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,7 +146,7 @@ macro_rules! impl_hash {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn copy_to(&self, dest: &mut[u8]) {
|
fn copy_to(&self, dest: &mut[u8]) {
|
||||||
let min = ::std::cmp::min($size, dest.len());
|
let min = cmp::min($size, dest.len());
|
||||||
dest[..min].copy_from_slice(&self.0[..min]);
|
dest[..min].copy_from_slice(&self.0[..min]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,14 +258,7 @@ impl <T>FromBytes for T where T: FixedHash {
|
|||||||
Ordering::Equal => ()
|
Ordering::Equal => ()
|
||||||
};
|
};
|
||||||
|
|
||||||
unsafe {
|
Ok(T::from_slice(bytes))
|
||||||
use std::{mem, ptr};
|
|
||||||
|
|
||||||
let mut res: T = mem::uninitialized();
|
|
||||||
ptr::copy(bytes.as_ptr(), res.as_slice_mut().as_mut_ptr(), T::len());
|
|
||||||
|
|
||||||
Ok(res)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user