Merge pull request #752 from ethcore/tx_queue_invalid

Removing transactions that failed to be pushed to block.
This commit is contained in:
Gav Wood 2016-03-18 18:03:11 +01:00
commit a1fb0619bb
5 changed files with 42 additions and 9 deletions

View File

@ -391,7 +391,8 @@ impl<V> BlockChainClient for Client<V> where V: Verifier {
}
// TODO [todr] Should be moved to miner crate eventually.
fn prepare_sealing(&self, author: Address, gas_floor_target: U256, extra_data: Bytes, transactions: Vec<SignedTransaction>) -> Option<ClosedBlock> {
fn prepare_sealing(&self, author: Address, gas_floor_target: U256, extra_data: Bytes, transactions: Vec<SignedTransaction>)
-> Option<(ClosedBlock, HashSet<H256>)> {
let engine = self.engine.deref().deref();
let h = self.chain.best_block_hash();
@ -417,21 +418,40 @@ impl<V> BlockChainClient for Client<V> where V: Verifier {
// Add transactions
let block_number = b.block().header().number();
let min_tx_gas = U256::from(self.engine.schedule(&b.env_info()).tx_gas);
let mut invalid_transactions = HashSet::new();
for tx in transactions {
// Push transaction to block
let hash = tx.hash();
let import = b.push_transaction(tx, None);
if let Err(e) = import {
trace!("Error adding transaction to block: number={}. Error: {:?}", block_number, e);
match import {
Err(Error::Execution(ExecutionError::BlockGasLimitReached { gas_limit, gas_used, .. })) => {
trace!(target: "miner", "Skipping adding transaction to block because of gas limit: {:?}", hash);
// Exit early if gas left is smaller then min_tx_gas
if gas_limit - gas_used < min_tx_gas {
break;
}
},
Err(e) => {
invalid_transactions.insert(hash);
trace!(target: "miner",
"Error adding transaction to block: number={}. transaction_hash={:?}, Error: {:?}",
block_number, hash, e);
},
_ => {}
}
}
// And close
let b = b.close();
trace!("Sealing: number={}, hash={}, diff={}",
trace!(target: "miner", "Sealing: number={}, hash={}, diff={}",
b.block().header().number(),
b.hash(),
b.block().header().difficulty()
);
Some(b)
Some((b, invalid_transactions))
}
fn block_header(&self, id: BlockId) -> Option<Bytes> {

View File

@ -26,6 +26,7 @@ pub use self::config::{ClientConfig, BlockQueueConfig, BlockChainConfig};
pub use self::ids::{BlockId, TransactionId};
pub use self::test_client::{TestBlockChainClient, EachBlockWith};
use std::collections::HashSet;
use util::bytes::Bytes;
use util::hash::{Address, H256, H2048};
use util::numbers::U256;
@ -110,7 +111,8 @@ pub trait BlockChainClient : Sync + Send {
// TODO [todr] Should be moved to miner crate eventually.
/// Returns ClosedBlock prepared for sealing.
fn prepare_sealing(&self, author: Address, gas_floor_target: U256, extra_data: Bytes, transactions: Vec<SignedTransaction>) -> Option<ClosedBlock>;
fn prepare_sealing(&self, author: Address, gas_floor_target: U256, extra_data: Bytes, transactions: Vec<SignedTransaction>)
-> Option<(ClosedBlock, HashSet<H256>)>;
// TODO [todr] Should be moved to miner crate eventually.
/// Attempts to seal given block. Returns `SealedBlock` on success and the same block in case of error.

View File

@ -217,7 +217,7 @@ impl BlockChainClient for TestBlockChainClient {
unimplemented!();
}
fn prepare_sealing(&self, _author: Address, _gas_floor_target: U256, _extra_data: Bytes, _transactions: Vec<SignedTransaction>) -> Option<ClosedBlock> {
fn prepare_sealing(&self, _author: Address, _gas_floor_target: U256, _extra_data: Bytes, _transactions: Vec<SignedTransaction>) -> Option<(ClosedBlock, HashSet<H256>)> {
unimplemented!()
}

View File

@ -144,7 +144,7 @@ fn can_mine() {
let client_result = get_test_client_with_blocks(vec![dummy_blocks[0].clone()]);
let client = client_result.reference();
let b = client.prepare_sealing(Address::default(), x!(31415926), vec![], vec![]).unwrap();
let b = client.prepare_sealing(Address::default(), x!(31415926), vec![], vec![]).unwrap().0;
assert_eq!(*b.block().header().parent_hash(), BlockView::new(&dummy_blocks[0]).header_view().sha3());
assert!(client.try_seal(b, vec![]).is_ok());

View File

@ -132,7 +132,18 @@ impl MinerService for Miner {
self.extra_data(),
transactions,
);
*self.sealing_block.lock().unwrap() = b;
*self.sealing_block.lock().unwrap() = b.map(|(block, invalid_transactions)| {
let mut queue = self.transaction_queue.lock().unwrap();
queue.remove_all(
&invalid_transactions.into_iter().collect::<Vec<H256>>(),
|a: &Address| AccountDetails {
nonce: chain.nonce(a),
balance: chain.balance(a),
}
);
block
});
}
fn sealing_block(&self, chain: &BlockChainClient) -> &Mutex<Option<ClosedBlock>> {