Evict transaction from transaction pool (#2797)

* Evict transaction from transaction pool

* Remove Result from evict function
This commit is contained in:
Quentin Le Sceller 2019-05-13 18:03:47 -04:00 committed by Ignotus Peverell
parent 15b56a97f5
commit 59db5e3bd1
3 changed files with 40 additions and 8 deletions

View file

@ -310,7 +310,7 @@ impl Pool {
/// containing the tx it depends on. /// containing the tx it depends on.
/// Sorting the buckets by fee_to_weight will therefore preserve dependency ordering, /// Sorting the buckets by fee_to_weight will therefore preserve dependency ordering,
/// maximizing both cut-through and overall fees. /// maximizing both cut-through and overall fees.
fn bucket_transactions(&self, weighting: Weighting) -> Vec<Transaction> { pub fn bucket_transactions(&self, weighting: Weighting) -> Vec<Transaction> {
let mut tx_buckets: Vec<Bucket> = Vec::new(); let mut tx_buckets: Vec<Bucket> = Vec::new();
let mut output_commits = HashMap::new(); let mut output_commits = HashMap::new();
let mut rejected = HashSet::new(); let mut rejected = HashSet::new();

View file

@ -138,7 +138,13 @@ impl TransactionPool {
} }
// Do we have the capacity to accept this transaction? // Do we have the capacity to accept this transaction?
self.is_acceptable(&tx, stem)?; let acceptability = self.is_acceptable(&tx, stem);
let mut evict = false;
if !stem && acceptability.as_ref().err() == Some(&PoolError::OverCapacity) {
evict = true;
} else if acceptability.is_err() {
return acceptability;
}
// Make sure the transaction is valid before anything else. // Make sure the transaction is valid before anything else.
// Validate tx accounting for max tx weight. // Validate tx accounting for max tx weight.
@ -171,9 +177,36 @@ impl TransactionPool {
self.adapter.tx_accepted(&entry.tx); self.adapter.tx_accepted(&entry.tx);
} }
// Transaction passed all the checks but we have to make space for it
if evict {
self.evict_from_txpool();
}
Ok(()) Ok(())
} }
// Remove the last transaction from the flattened bucket transactions.
// No other tx depends on it, it has low fee_to_weight and is unlikely to participate in any cut-through.
pub fn evict_from_txpool(&mut self) {
// Get bucket transactions
let bucket_transactions = self.txpool.bucket_transactions(Weighting::NoLimit);
// Get last transaction and remove it
match bucket_transactions.last() {
Some(evictable_transaction) => {
// Remove transaction
self.txpool.entries = self
.txpool
.entries
.iter()
.filter(|x| x.tx != *evictable_transaction)
.map(|x| x.clone())
.collect::<Vec<_>>();
}
None => (),
}
}
// Old txs will "age out" after 30 mins. // Old txs will "age out" after 30 mins.
pub fn truncate_reorg_cache(&mut self, cutoff: DateTime<Utc>) { pub fn truncate_reorg_cache(&mut self, cutoff: DateTime<Utc>) {
let mut cache = self.reorg_cache.write(); let mut cache = self.reorg_cache.write();
@ -245,11 +278,10 @@ impl TransactionPool {
} }
// Check that the stempool can accept this transaction // Check that the stempool can accept this transaction
if stem { if stem && self.stempool.size() > self.config.max_stempool_size {
if self.stempool.size() > self.config.max_stempool_size { return Err(PoolError::OverCapacity);
// TODO evict old/large transactions instead } else if self.total_size() > self.config.max_pool_size {
return Err(PoolError::OverCapacity); return Err(PoolError::OverCapacity);
}
} }
// for a basic transaction (1 input, 2 outputs) - // for a basic transaction (1 input, 2 outputs) -

View file

@ -162,7 +162,7 @@ pub struct TxSource {
} }
/// Possible errors when interacting with the transaction pool. /// Possible errors when interacting with the transaction pool.
#[derive(Debug, Fail)] #[derive(Debug, Fail, PartialEq)]
pub enum PoolError { pub enum PoolError {
/// An invalid pool entry caused by underlying tx validation error /// An invalid pool entry caused by underlying tx validation error
#[fail(display = "Invalid Tx {}", _0)] #[fail(display = "Invalid Tx {}", _0)]