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. // 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 engine = self.engine.deref().deref();
let h = self.chain.best_block_hash(); let h = self.chain.best_block_hash();
@ -417,21 +418,40 @@ impl<V> BlockChainClient for Client<V> where V: Verifier {
// Add transactions // Add transactions
let block_number = b.block().header().number(); 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 { for tx in transactions {
// Push transaction to block
let hash = tx.hash();
let import = b.push_transaction(tx, None); 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 // And close
let b = b.close(); let b = b.close();
trace!("Sealing: number={}, hash={}, diff={}", trace!(target: "miner", "Sealing: number={}, hash={}, diff={}",
b.block().header().number(), b.block().header().number(),
b.hash(), b.hash(),
b.block().header().difficulty() b.block().header().difficulty()
); );
Some(b) Some((b, invalid_transactions))
} }
fn block_header(&self, id: BlockId) -> Option<Bytes> { 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::ids::{BlockId, TransactionId};
pub use self::test_client::{TestBlockChainClient, EachBlockWith}; pub use self::test_client::{TestBlockChainClient, EachBlockWith};
use std::collections::HashSet;
use util::bytes::Bytes; use util::bytes::Bytes;
use util::hash::{Address, H256, H2048}; use util::hash::{Address, H256, H2048};
use util::numbers::U256; use util::numbers::U256;
@ -110,7 +111,8 @@ pub trait BlockChainClient : Sync + Send {
// TODO [todr] Should be moved to miner crate eventually. // TODO [todr] Should be moved to miner crate eventually.
/// Returns ClosedBlock prepared for sealing. /// 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. // 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. /// 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!(); 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!() 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_result = get_test_client_with_blocks(vec![dummy_blocks[0].clone()]);
let client = client_result.reference(); 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_eq!(*b.block().header().parent_hash(), BlockView::new(&dummy_blocks[0]).header_view().sha3());
assert!(client.try_seal(b, vec![]).is_ok()); assert!(client.try_seal(b, vec![]).is_ok());

View File

@ -132,7 +132,18 @@ impl MinerService for Miner {
self.extra_data(), self.extra_data(),
transactions, 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>> { fn sealing_block(&self, chain: &BlockChainClient) -> &Mutex<Option<ClosedBlock>> {