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.
/// Sorting the buckets by fee_to_weight will therefore preserve dependency ordering,
/// 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 output_commits = HashMap::new();
let mut rejected = HashSet::new();

View file

@ -138,7 +138,13 @@ impl TransactionPool {
}
// 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.
// Validate tx accounting for max tx weight.
@ -171,9 +177,36 @@ impl TransactionPool {
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(())
}
// 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.
pub fn truncate_reorg_cache(&mut self, cutoff: DateTime<Utc>) {
let mut cache = self.reorg_cache.write();
@ -245,11 +278,10 @@ impl TransactionPool {
}
// Check that the stempool can accept this transaction
if stem {
if self.stempool.size() > self.config.max_stempool_size {
// TODO evict old/large transactions instead
return Err(PoolError::OverCapacity);
}
if stem && self.stempool.size() > self.config.max_stempool_size {
return Err(PoolError::OverCapacity);
} else if self.total_size() > self.config.max_pool_size {
return Err(PoolError::OverCapacity);
}
// 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.
#[derive(Debug, Fail)]
#[derive(Debug, Fail, PartialEq)]
pub enum PoolError {
/// An invalid pool entry caused by underlying tx validation error
#[fail(display = "Invalid Tx {}", _0)]