Removing invalid transactions from queue

This commit is contained in:
Tomasz Drwięga 2016-03-17 12:17:20 +01:00
parent 22bc9f6458
commit c382fa7eab
5 changed files with 45 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,41 @@ 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 gas_limit = *b.block().header().gas_limit();
let mut gas_left = gas_limit;
let mut invalid_transactions = HashSet::new();
for tx in transactions { for tx in transactions {
let hash = tx.hash();
let gas = tx.gas;
// TODO [todr] It seems that calculating gas_left here doesn't really look nice. After moving this function
// to miner crate we should consider rewriting this logic in some better way.
if gas > gas_left {
trace!(target: "miner", "Skipping adding transaction to block because of gas limit: {:?}", hash);
continue;
}
let import = b.push_transaction(tx, None); let import = b.push_transaction(tx, None);
if let Err(e) = import { match import {
trace!("Error adding transaction to block: number={}. Error: {:?}", block_number, e); Err(e) => {
trace!(target: "miner", "Error adding transaction to block: number={}. transaction_hash={:?}, Error: {:?}",
block_number, hash, e);
invalid_transactions.insert(hash);
},
Ok(receipt) => {
gas_left = gas_limit - receipt.gas_used;
}
} }
} }
// 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,20 @@ impl MinerService for Miner {
self.extra_data(), self.extra_data(),
transactions, transactions,
); );
*self.sealing_block.lock().unwrap() = b;
match b {
None => {
*self.sealing_block.lock().unwrap() = None
},
Some((block, invalid_transactions)) => {
let mut queue = self.transaction_queue.lock().unwrap();
queue.remove_all(
&invalid_transactions.into_iter().collect::<Vec<H256>>(),
|a: &Address| chain.nonce(a)
);
*self.sealing_block.lock().unwrap() = Some(block)
}
}
} }
fn sealing_block(&self, chain: &BlockChainClient) -> &Mutex<Option<ClosedBlock>> { fn sealing_block(&self, chain: &BlockChainClient) -> &Mutex<Option<ClosedBlock>> {