Skip to content

Commit

Permalink
Compiles!
Browse files Browse the repository at this point in the history
  • Loading branch information
tomusdrw committed Feb 23, 2018
1 parent fc4a0aa commit e595e83
Show file tree
Hide file tree
Showing 8 changed files with 172 additions and 128 deletions.
95 changes: 56 additions & 39 deletions ethcore/src/miner/miner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,10 @@ 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.
/// may be empty if the node is not actively mining or has no force_sealing enabled.
AlwaysSealing,
// TODO [ToDr] Enable mining if AlwaysSealing
/// Takes from sealing if mining, from queue otherwise.
SealingOrElseQueue,
}

// /// Transaction queue banning settings.
Expand Down Expand Up @@ -107,8 +108,6 @@ pub struct MinerOptions {

// / Strategy to use for prioritizing transactions in the queue.
// pub tx_queue_strategy: PrioritizationStrategy,
// / Banning settings.
// pub tx_queue_banning: Banning,
/// Do we refuse to accept service transactions even if sender is certified.
pub refuse_service_transactions: bool,
/// Transaction pool limits.
Expand Down Expand Up @@ -246,15 +245,26 @@ impl Miner {
}, GasPricer::new_fixed(minimal_gas_price), spec, accounts)
}

fn forced_sealing(&self) -> bool {
self.options.force_sealing || !self.listeners.read().is_empty()
}

/// Clear all pending block states
pub fn clear(&self) {
self.sealing.lock().queue.reset();
}

/// Updates transaction queue verification limits.
///
/// Limits consist of current block gas limit and minimal gas price.
pub fn update_transaction_queue_limits(&self, block_gas_limit: U256) {
debug!(target: "miner", "minimal_gas_price: recalibrating...");
let txq = self.transaction_queue.clone();
let mut options = self.options.pool_verification_options.clone();
self.gas_pricer.lock().recalibrate(move |gas_price| {
debug!(target: "miner", "minimal_gas_price: Got gas price! {}", gas_price);
options.minimal_gas_price = gas_price;
options.block_gas_limit = block_gas_limit;
txq.set_verifier_options(options);
});
}

/// Get `Some` `clone()` of the current pending block's state or `None` if we're not sealing.
pub fn pending_state(&self, latest_block_number: BlockNumber) -> Option<State<::state_db::StateDB>> {
self.map_existing_pending_block(|b| b.state().clone(), latest_block_number)
Expand Down Expand Up @@ -287,8 +297,10 @@ impl Miner {
// TODO [ToDr] Get rid of this method.
//
// We should never fall back to client, this can be handled on RPC level by returning Option<>
fn from_pending_block<H, F, G>(&self, latest_block_number: BlockNumber, from_chain: F, map_block: G) -> H
where F: Fn() -> H, G: FnOnce(&ClosedBlock) -> H {
fn from_pending_block<H, F, G>(&self, latest_block_number: BlockNumber, from_chain: F, map_block: G) -> H where
F: Fn() -> H,
G: FnOnce(&ClosedBlock) -> H,
{
let sealing = self.sealing.lock();
sealing.queue.peek_last_ref().map_or_else(
|| from_chain(),
Expand Down Expand Up @@ -471,6 +483,10 @@ impl Miner {
(block, original_work_hash)
}

fn forced_sealing(&self) -> bool {
self.options.force_sealing || !self.listeners.read().is_empty()
}

/// Check is reseal is allowed and necessary.
fn requires_reseal(&self, best_block: BlockNumber) -> bool {
let mut sealing = self.sealing.lock();
Expand Down Expand Up @@ -620,18 +636,6 @@ impl Miner {
}
}

fn update_transaction_queue_limits(&self, block_gas_limit: U256) {
debug!(target: "miner", "minimal_gas_price: recalibrating...");
let txq = self.transaction_queue.clone();
let mut options = self.options.pool_verification_options.clone();
self.gas_pricer.lock().recalibrate(move |gas_price| {
debug!(target: "miner", "minimal_gas_price: Got gas price! {}", gas_price);
options.minimal_gas_price = gas_price;
options.block_gas_limit = block_gas_limit;
txq.set_verifier_options(options);
});
}

/// Returns true if we had to prepare new pending block.
fn prepare_pending_block(&self, client: &MiningBlockChainClient) -> bool {
trace!(target: "miner", "prepare_pending_block: entering");
Expand Down Expand Up @@ -789,27 +793,40 @@ impl MinerService for Miner {

fn ready_transactions(&self, chain: &MiningBlockChainClient) -> Vec<Arc<VerifiedTransaction>> {
let chain_info = chain.chain_info();
match self.options.pending_set {
PendingSet::AlwaysQueue => {
let client = self.client(chain);

self.transaction_queue.pending(
client,
chain_info.best_block_number,
chain_info.best_block_timestamp,
|transactions| transactions.collect(),
let from_queue = || {
let client = self.client(chain);

self.transaction_queue.pending(
client,
chain_info.best_block_number,
chain_info.best_block_timestamp,
|transactions| transactions.collect(),
)
};

let from_pending = || {
self.from_pending_block(
chain_info.best_block_number,
|| None,
|sealing| Some(sealing.transactions()
.iter()
.map(|signed| pool::VerifiedTransaction::from_pending_block_transaction(signed.clone()))
.map(Arc::new)
.collect()
)
)
};

match self.options.pending_set {
PendingSet::AlwaysQueue => {
from_queue()
},
PendingSet::AlwaysSealing => {
self.from_pending_block(
chain_info.best_block_number,
Vec::new,
|sealing| sealing.transactions()
.iter()
.map(|signed| pool::VerifiedTransaction::from_pending_block_transaction(signed.clone()))
.map(Arc::new)
.collect()
)
from_pending().unwrap_or_default()
},
PendingSet::SealingOrElseQueue => {
from_pending().unwrap_or_else(from_queue)
},
}
}
Expand Down
14 changes: 13 additions & 1 deletion miner/src/pool/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@ pub mod verifier;
pub use self::queue::{TransactionQueue, Status as QueueStatus};
pub use self::txpool::{VerifiedTransaction as PoolVerifiedTransaction, Options};

// TODO [ToDr] Actually use that parameter and implement more strategies.

/// How to prioritize transactions in the pool
pub enum PrioritizationStrategy {
/// Simple gas-price based prioritization.
GasPrice,
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub(crate) enum Priority {
Local,
Expand Down Expand Up @@ -60,7 +68,11 @@ pub struct VerifiedTransaction {
}

impl VerifiedTransaction {
// Hack?
/// Create `VerifiedTransaction` directly from `SignedTransaction`.
///
/// This method should be used only:
/// 1. for tests
/// 2. In case we are converting pending block transactions that are already in the queue to match function signature.
pub fn from_pending_block_transaction(tx: transaction::SignedTransaction) -> Self {
let hash = tx.hash();
let sender = tx.sender();
Expand Down
17 changes: 16 additions & 1 deletion miner/src/pool/queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ impl TransactionQueue {
.map(|result| match result {
Ok(verified) => match self.pool.write().import(verified) {
Ok(_imported) => Ok(()),
Err(txpool::Error(kind, _)) => unimplemented!(),
Err(err) => Err(convert_error(err)),
},
Err(err) => Err(err),
})
Expand Down Expand Up @@ -232,6 +232,21 @@ impl TransactionQueue {
}
}


fn convert_error(err: txpool::Error) -> transaction::Error {
use self::txpool::ErrorKind;

match *err.kind() {
ErrorKind::AlreadyImported(..) => transaction::Error::AlreadyImported,
ErrorKind::TooCheapToEnter(..) => transaction::Error::LimitReached,
ErrorKind::TooCheapToReplace(..) => transaction::Error::TooCheapToReplace,
ref e => {
warn!(target: "txqueue", "Unknown import error: {:?}", e);
transaction::Error::NotAllowed
},
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
4 changes: 3 additions & 1 deletion parity/blockchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,9 @@ fn start_client(
&client_path,
&snapshot_path,
&dirs.ipc_path(),
Arc::new(Miner::with_spec(&spec)),
// It's fine to use test version here,
// since we don't care about miner parameters at all
Arc::new(Miner::new_for_tests(&spec, None)),
).map_err(|e| format!("Client service error: {:?}", e))?;

drop(spec);
Expand Down
77 changes: 45 additions & 32 deletions parity/configuration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,16 @@ use ansi_term::Colour;
use ethsync::{NetworkConfiguration, validate_node_url, self};
use ethcore::ethstore::ethkey::{Secret, Public};
use ethcore::client::{VMType};
use ethcore::miner::{MinerOptions, Banning, StratumOptions};
use ethcore::miner::{stratum, MinerOptions};
use ethcore::verification::queue::VerifierSettings;
use miner::pool;

use rpc::{IpcConfiguration, HttpConfiguration, WsConfiguration, UiConfiguration};
use rpc_apis::ApiSet;
use parity_rpc::NetworkSettings;
use cache::CacheConfig;
use helpers::{to_duration, to_mode, to_block_id, to_u256, to_pending_set, to_price, geth_ipc_path, parity_ipc_path,
to_bootnodes, to_addresses, to_address, to_gas_limit, to_queue_strategy};
to_bootnodes, to_addresses, to_address, to_queue_strategy};
use dir::helpers::{replace_home, replace_home_and_local};
use params::{ResealPolicy, AccountsConfig, GasPricerConfig, MinerExtras, SpecType};
use ethcore_logger::Config as LogConfig;
Expand Down Expand Up @@ -394,12 +395,14 @@ impl Configuration {
}

fn miner_extras(&self) -> Result<MinerExtras, String> {
let floor = to_u256(&self.args.arg_gas_floor_target)?;
let ceil = to_u256(&self.args.arg_gas_cap)?;
let extras = MinerExtras {
author: self.author()?,
extra_data: self.extra_data()?,
gas_floor_target: to_u256(&self.args.arg_gas_floor_target)?,
gas_ceil_target: to_u256(&self.args.arg_gas_cap)?,
gas_range_target: (floor, ceil),
engine_signer: self.engine_signer()?,
work_notify: self.work_notify(),
};

Ok(extras)
Expand Down Expand Up @@ -496,9 +499,9 @@ impl Configuration {
Ok(cfg)
}

fn stratum_options(&self) -> Result<Option<StratumOptions>, String> {
fn stratum_options(&self) -> Result<Option<stratum::Options>, String> {
if self.args.flag_stratum {
Ok(Some(StratumOptions {
Ok(Some(stratum::Options {
io_path: self.directories().db,
listen_addr: self.stratum_interface(),
port: self.args.arg_ports_shift + self.args.arg_stratum_port,
Expand All @@ -513,44 +516,59 @@ impl Configuration {
return Err("Force sealing can't be used with reseal_min_period = 0".into());
}

if let Some(_) = self.args.arg_tx_time_limit {
warn!("Banning is not available in this version.");
}

let reseal = self.args.arg_reseal_on_txs.parse::<ResealPolicy>()?;

let options = MinerOptions {
new_work_notify: self.work_notify(),
force_sealing: self.args.flag_force_sealing,
reseal_on_external_tx: reseal.external,
reseal_on_own_tx: reseal.own,
reseal_on_uncle: self.args.flag_reseal_on_uncle,
tx_gas_limit: match self.args.arg_tx_gas_limit {
Some(ref d) => to_u256(d)?,
None => U256::max_value(),
},
tx_queue_size: self.args.arg_tx_queue_size,
tx_queue_memory_limit: if self.args.arg_tx_queue_mem_limit > 0 {
Some(self.args.arg_tx_queue_mem_limit as usize * 1024 * 1024)
} else { None },
tx_queue_gas_limit: to_gas_limit(&self.args.arg_tx_queue_gas)?,
tx_queue_strategy: to_queue_strategy(&self.args.arg_tx_queue_strategy)?,
pending_set: to_pending_set(&self.args.arg_relay_set)?,
reseal_min_period: Duration::from_millis(self.args.arg_reseal_min_period),
reseal_max_period: Duration::from_millis(self.args.arg_reseal_max_period),

pending_set: to_pending_set(&self.args.arg_relay_set)?,
work_queue_size: self.args.arg_work_queue_size,
enable_resubmission: !self.args.flag_remove_solved,
tx_queue_banning: match self.args.arg_tx_time_limit {
Some(limit) => Banning::Enabled {
min_offends: self.args.arg_tx_queue_ban_count,
offend_threshold: Duration::from_millis(limit),
ban_duration: Duration::from_secs(self.args.arg_tx_queue_ban_time as u64),
},
None => Banning::Disabled,
},
refuse_service_transactions: self.args.flag_refuse_service_transactions,
infinite_pending_block: self.args.flag_infinite_pending_block,

refuse_service_transactions: self.args.flag_refuse_service_transactions,

pool_limits: self.pool_limits()?,
pool_verification_options: self.pool_verification_options()?,
};

Ok(options)
}

fn pool_limits(&self) -> Result<pool::Options, String> {
Ok(pool::Options {
max_count: self.args.arg_tx_queue_size,
// TODO [ToDr] Add seperate parameter for that!
max_per_sender: self.args.arg_tx_queue_size,
max_mem_usage: if self.args.arg_tx_queue_mem_limit > 0 {
self.args.arg_tx_queue_mem_limit as usize * 1024 * 1024
} else {
usize::max_value()
},
})
}

fn pool_verification_options(&self) -> Result<pool::verifier::Options, String>{
Ok(pool::verifier::Options {
// NOTE min_gas_price and block_gas_limit will be overwritten right after start.
minimal_gas_price: U256::from(20_000_000) * 1_000u32,
block_gas_limit: to_u256(&self.args.arg_gas_floor_target)?,
tx_gas_limit: match self.args.arg_tx_gas_limit {
Some(ref d) => to_u256(d)?,
None => U256::max_value(),
},
})
}

fn ui_port(&self) -> u16 {
self.args.arg_ports_shift + self.args.arg_ui_port
}
Expand Down Expand Up @@ -667,12 +685,7 @@ impl Configuration {

let usd_per_tx = to_price(&self.args.arg_usd_per_tx)?;
if "auto" == self.args.arg_usd_per_eth.as_str() {
// Just a very rough estimate to avoid accepting
// ZGP transactions before the price is fetched
// if user does not want it.
let last_known_usd_per_eth = 10.0;
return Ok(GasPricerConfig::Calibrated {
initial_minimum: wei_per_gas(usd_per_tx, last_known_usd_per_eth),
usd_per_tx: usd_per_tx,
recalibration_period: to_duration(self.args.arg_price_update_period.as_str())?,
});
Expand Down
16 changes: 3 additions & 13 deletions parity/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ use ethereum_types::{U256, clean_0x, Address};
use kvdb_rocksdb::CompactionProfile;
use journaldb::Algorithm;
use ethcore::client::{Mode, BlockId, VMType, DatabaseCompactionProfile, ClientConfig, VerifierType};
use ethcore::miner::{PendingSet, GasLimit};
use miner::transaction_queue::PrioritizationStrategy;
use ethcore::miner::PendingSet;
use miner::pool::PrioritizationStrategy;
use cache::CacheConfig;
use dir::DatabaseDirectories;
use dir::helpers::replace_home;
Expand Down Expand Up @@ -97,19 +97,9 @@ pub fn to_pending_set(s: &str) -> Result<PendingSet, String> {
}
}

pub fn to_gas_limit(s: &str) -> Result<GasLimit, String> {
match s {
"auto" => Ok(GasLimit::Auto),
"off" => Ok(GasLimit::None),
other => Ok(GasLimit::Fixed(to_u256(other)?)),
}
}

pub fn to_queue_strategy(s: &str) -> Result<PrioritizationStrategy, String> {
match s {
"gas" => Ok(PrioritizationStrategy::GasAndGasPrice),
"gas_price" => Ok(PrioritizationStrategy::GasPriceOnly),
"gas_factor" => Ok(PrioritizationStrategy::GasFactorAndGasPrice),
"gas_price" => Ok(PrioritizationStrategy::GasPrice),
other => Err(format!("Invalid queue strategy: {}", other)),
}
}
Expand Down
Loading

0 comments on commit e595e83

Please sign in to comment.