Parameter to allow user to force the sealing mechanism (#918)
* Allow block sealing mechanism to be forced, even when not mining. * Fix deadlock in dispatch_transaction. Fix tests. * Horrible workaround for transaction importing. * Reduce tracing. Cleanups. * Remove logging. * Remove broken code inherited from dodgy implementation. * pre-query tx queue nonce also if any * remove outside nonce queries * remove queue nonces
This commit is contained in:
parent
edf4735542
commit
c48374dbc6
@ -30,6 +30,7 @@ pub struct Miner {
|
|||||||
transaction_queue: Mutex<TransactionQueue>,
|
transaction_queue: Mutex<TransactionQueue>,
|
||||||
|
|
||||||
// for sealing...
|
// for sealing...
|
||||||
|
force_sealing: bool,
|
||||||
sealing_enabled: AtomicBool,
|
sealing_enabled: AtomicBool,
|
||||||
sealing_block_last_request: Mutex<u64>,
|
sealing_block_last_request: Mutex<u64>,
|
||||||
sealing_work: Mutex<UsingQueue<ClosedBlock>>,
|
sealing_work: Mutex<UsingQueue<ClosedBlock>>,
|
||||||
@ -42,6 +43,7 @@ impl Default for Miner {
|
|||||||
fn default() -> Miner {
|
fn default() -> Miner {
|
||||||
Miner {
|
Miner {
|
||||||
transaction_queue: Mutex::new(TransactionQueue::new()),
|
transaction_queue: Mutex::new(TransactionQueue::new()),
|
||||||
|
force_sealing: false,
|
||||||
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)),
|
||||||
@ -54,8 +56,17 @@ impl Default for Miner {
|
|||||||
|
|
||||||
impl Miner {
|
impl Miner {
|
||||||
/// Creates new instance of miner
|
/// Creates new instance of miner
|
||||||
pub fn new() -> Arc<Miner> {
|
pub fn new(force_sealing: bool) -> Arc<Miner> {
|
||||||
Arc::new(Miner::default())
|
Arc::new(Miner {
|
||||||
|
transaction_queue: Mutex::new(TransactionQueue::new()),
|
||||||
|
force_sealing: force_sealing,
|
||||||
|
sealing_enabled: AtomicBool::new(force_sealing),
|
||||||
|
sealing_block_last_request: Mutex::new(0),
|
||||||
|
sealing_work: Mutex::new(UsingQueue::new(5)),
|
||||||
|
gas_floor_target: RwLock::new(U256::zero()),
|
||||||
|
author: RwLock::new(Address::default()),
|
||||||
|
extra_data: RwLock::new(Vec::new()),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the author that we will seal blocks as.
|
/// Get the author that we will seal blocks as.
|
||||||
@ -241,7 +252,7 @@ impl MinerService for Miner {
|
|||||||
if self.sealing_enabled.load(atomic::Ordering::Relaxed) {
|
if self.sealing_enabled.load(atomic::Ordering::Relaxed) {
|
||||||
let current_no = chain.chain_info().best_block_number;
|
let current_no = chain.chain_info().best_block_number;
|
||||||
let last_request = *self.sealing_block_last_request.lock().unwrap();
|
let last_request = *self.sealing_block_last_request.lock().unwrap();
|
||||||
let should_disable_sealing = current_no > last_request && current_no - last_request > SEALING_TIMEOUT_IN_BLOCKS;
|
let should_disable_sealing = !self.force_sealing && current_no > last_request && current_no - last_request > SEALING_TIMEOUT_IN_BLOCKS;
|
||||||
|
|
||||||
if should_disable_sealing {
|
if should_disable_sealing {
|
||||||
trace!(target: "miner", "Miner sleeping (current {}, last {})", current_no, last_request);
|
trace!(target: "miner", "Miner sleeping (current {}, last {})", current_no, last_request);
|
||||||
|
@ -383,19 +383,19 @@ impl TransactionQueue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let vtx = try!(VerifiedTransaction::new(tx));
|
let vtx = try!(VerifiedTransaction::new(tx));
|
||||||
let account = fetch_account(&vtx.sender());
|
let client_account = fetch_account(&vtx.sender());
|
||||||
|
|
||||||
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 account.balance < cost {
|
if client_account.balance < cost {
|
||||||
trace!(target: "miner", "Dropping transaction without sufficient balance: {:?} ({} < {})",
|
trace!(target: "miner", "Dropping transaction without sufficient balance: {:?} ({} < {})",
|
||||||
vtx.hash(), account.balance, cost);
|
vtx.hash(), client_account.balance, cost);
|
||||||
return Err(Error::Transaction(TransactionError::InsufficientBalance {
|
return Err(Error::Transaction(TransactionError::InsufficientBalance {
|
||||||
cost: cost,
|
cost: cost,
|
||||||
balance: account.balance
|
balance: client_account.balance
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.import_tx(vtx, account.nonce).map_err(Error::Transaction)
|
self.import_tx(vtx, client_account.nonce).map_err(Error::Transaction)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes all transactions identified by hashes given in slice
|
/// Removes all transactions identified by hashes given in slice
|
||||||
@ -1188,6 +1188,7 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_replace_same_transaction_when_has_higher_fee() {
|
fn should_replace_same_transaction_when_has_higher_fee() {
|
||||||
|
init_log();
|
||||||
// given
|
// given
|
||||||
let mut txq = TransactionQueue::new();
|
let mut txq = TransactionQueue::new();
|
||||||
let keypair = KeyPair::create().unwrap();
|
let keypair = KeyPair::create().unwrap();
|
||||||
@ -1264,7 +1265,7 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn should_return_none_when_transaction_from_given_address_does_not_exist() {
|
fn should_return_none_when_transaction_from_given_address_does_not_exist() {
|
||||||
// given
|
// given
|
||||||
let mut txq = TransactionQueue::new();
|
let txq = TransactionQueue::new();
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assert_eq!(txq.last_nonce(&Address::default()), None);
|
assert_eq!(txq.last_nonce(&Address::default()), None);
|
||||||
@ -1277,7 +1278,7 @@ mod test {
|
|||||||
let tx = new_tx();
|
let tx = new_tx();
|
||||||
let from = tx.sender().unwrap();
|
let from = tx.sender().unwrap();
|
||||||
let nonce = tx.nonce;
|
let nonce = tx.nonce;
|
||||||
let details = |a: &Address| AccountDetails { nonce: nonce, balance: !U256::zero() };
|
let details = |_a: &Address| AccountDetails { nonce: nonce, balance: !U256::zero() };
|
||||||
|
|
||||||
// when
|
// when
|
||||||
txq.add(tx, &details).unwrap();
|
txq.add(tx, &details).unwrap();
|
||||||
|
@ -152,6 +152,8 @@ API and Console Options:
|
|||||||
conjunction with --webapp-user.
|
conjunction with --webapp-user.
|
||||||
|
|
||||||
Sealing/Mining Options:
|
Sealing/Mining Options:
|
||||||
|
--force-sealing Force the node to author new blocks as if it were
|
||||||
|
always sealing/mining.
|
||||||
--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.
|
||||||
@ -239,6 +241,7 @@ struct Args {
|
|||||||
flag_webapp_interface: String,
|
flag_webapp_interface: String,
|
||||||
flag_webapp_user: Option<String>,
|
flag_webapp_user: Option<String>,
|
||||||
flag_webapp_pass: Option<String>,
|
flag_webapp_pass: Option<String>,
|
||||||
|
flag_force_sealing: bool,
|
||||||
flag_author: String,
|
flag_author: String,
|
||||||
flag_usd_per_tx: String,
|
flag_usd_per_tx: String,
|
||||||
flag_usd_per_eth: String,
|
flag_usd_per_eth: String,
|
||||||
@ -657,7 +660,7 @@ impl Configuration {
|
|||||||
let client = service.client();
|
let client = service.client();
|
||||||
|
|
||||||
// Miner
|
// Miner
|
||||||
let miner = Miner::new();
|
let miner = Miner::new(self.args.flag_force_sealing);
|
||||||
miner.set_author(self.author());
|
miner.set_author(self.author());
|
||||||
miner.set_gas_floor_target(self.gas_floor_target());
|
miner.set_gas_floor_target(self.gas_floor_target());
|
||||||
miner.set_extra_data(self.extra_data());
|
miner.set_extra_data(self.extra_data());
|
||||||
|
@ -26,6 +26,7 @@ use ethminer::{MinerService, AccountDetails};
|
|||||||
use jsonrpc_core::*;
|
use jsonrpc_core::*;
|
||||||
use util::numbers::*;
|
use util::numbers::*;
|
||||||
use util::sha3::*;
|
use util::sha3::*;
|
||||||
|
use util::bytes::{ToPretty};
|
||||||
use util::rlp::{encode, UntrustedRlp, View};
|
use util::rlp::{encode, UntrustedRlp, View};
|
||||||
use ethcore::client::*;
|
use ethcore::client::*;
|
||||||
use ethcore::block::IsBlock;
|
use ethcore::block::IsBlock;
|
||||||
@ -191,9 +192,13 @@ impl<C, S, A, M, EM> EthClient<C, S, A, M, EM>
|
|||||||
|
|
||||||
let import = {
|
let import = {
|
||||||
let client = take_weak!(self.client);
|
let client = take_weak!(self.client);
|
||||||
take_weak!(self.miner).import_transactions(vec![signed_transaction], |a: &Address| AccountDetails {
|
let miner = take_weak!(self.miner);
|
||||||
nonce: client.nonce(a),
|
|
||||||
balance: client.balance(a),
|
miner.import_transactions(vec![signed_transaction], |a: &Address| {
|
||||||
|
AccountDetails {
|
||||||
|
nonce: client.nonce(&a),
|
||||||
|
balance: client.balance(&a),
|
||||||
|
}
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -499,6 +504,7 @@ impl<C, S, A, M, EM> Eth for EthClient<C, S, A, M, EM>
|
|||||||
data: request.data.map_or_else(Vec::new, |d| d.to_vec()),
|
data: request.data.map_or_else(Vec::new, |d| d.to_vec()),
|
||||||
}.sign(&secret)
|
}.sign(&secret)
|
||||||
};
|
};
|
||||||
|
trace!(target: "miner", "send_transaction: dispatching tx: {}", encode(&signed_transaction).to_vec().pretty());
|
||||||
self.dispatch_transaction(signed_transaction)
|
self.dispatch_transaction(signed_transaction)
|
||||||
},
|
},
|
||||||
Err(_) => { to_value(&H256::zero()) }
|
Err(_) => { to_value(&H256::zero()) }
|
||||||
|
@ -1476,7 +1476,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn dummy_sync_with_peer(peer_latest_hash: H256) -> ChainSync {
|
fn dummy_sync_with_peer(peer_latest_hash: H256) -> ChainSync {
|
||||||
let mut sync = ChainSync::new(SyncConfig::default(), Miner::new());
|
let mut sync = ChainSync::new(SyncConfig::default(), Miner::new(false));
|
||||||
sync.peers.insert(0,
|
sync.peers.insert(0,
|
||||||
PeerInfo {
|
PeerInfo {
|
||||||
protocol_version: 0,
|
protocol_version: 0,
|
||||||
|
@ -45,7 +45,7 @@
|
|||||||
//! let mut service = NetworkService::start(NetworkConfiguration::new()).unwrap();
|
//! let mut service = NetworkService::start(NetworkConfiguration::new()).unwrap();
|
||||||
//! let dir = env::temp_dir();
|
//! let dir = env::temp_dir();
|
||||||
//! let client = Client::new(ClientConfig::default(), ethereum::new_frontier(), &dir, service.io().channel()).unwrap();
|
//! let client = Client::new(ClientConfig::default(), ethereum::new_frontier(), &dir, service.io().channel()).unwrap();
|
||||||
//! let miner = Miner::new();
|
//! let miner = Miner::new(false);
|
||||||
//! EthSync::register(&mut service, SyncConfig::default(), client, miner);
|
//! EthSync::register(&mut service, SyncConfig::default(), client, miner);
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
|
@ -93,7 +93,7 @@ impl TestNet {
|
|||||||
for _ in 0..n {
|
for _ in 0..n {
|
||||||
net.peers.push(TestPeer {
|
net.peers.push(TestPeer {
|
||||||
chain: TestBlockChainClient::new(),
|
chain: TestBlockChainClient::new(),
|
||||||
sync: ChainSync::new(SyncConfig::default(), Miner::new()),
|
sync: ChainSync::new(SyncConfig::default(), Miner::new(false)),
|
||||||
queue: VecDeque::new(),
|
queue: VecDeque::new(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user