diff --git a/core/src/core/transaction.rs b/core/src/core/transaction.rs index 0ff9779bf9..cd5070a6b4 100644 --- a/core/src/core/transaction.rs +++ b/core/src/core/transaction.rs @@ -964,6 +964,12 @@ impl Transaction { Ok(()) } + /// Can be used to compare txs by their fee/weight ratio. + /// Don't use these values for anything else though due to precision multiplier. + pub fn fee_to_weight(&self) -> u64 { + self.fee() * 1_000 / self.tx_weight() as u64 + } + /// Calculate transaction weight pub fn tx_weight(&self) -> usize { self.body.body_weight() diff --git a/pool/src/pool.rs b/pool/src/pool.rs index a7d355f928..757bfd0792 100644 --- a/pool/src/pool.rs +++ b/pool/src/pool.rs @@ -132,7 +132,7 @@ impl Pool { // Sort them by fees over weight, multiplying by 1000 to keep some precision // don't think we'll ever see a >max_u64/1000 fee transaction. // We want to select the txs with highest fee per unit of weight first. - tx_buckets.sort_unstable_by_key(|tx| tx.fee() * 1000 / tx.tx_weight() as u64); + tx_buckets.sort_unstable_by_key(|tx| tx.fee_to_weight()); // Iteratively apply the txs to the current chain state, // rejecting any that do not result in a valid state. @@ -364,8 +364,11 @@ impl Pool { // We found a single parent tx, so aggregate in the bucket // if the aggregate tx is a valid tx. // Otherwise discard and let the next block pick this tx up. - let current = tx_buckets[pos].clone(); - if let Ok(agg_tx) = transaction::aggregate(vec![current, entry.tx.clone()]) { + let ref current = tx_buckets[pos]; + + if let Ok(agg_tx) = + transaction::aggregate(vec![current.clone(), entry.tx.clone()]) + { if agg_tx .validate( Weighting::AsLimitedTransaction { max_weight }, @@ -373,7 +376,12 @@ impl Pool { ) .is_ok() { - tx_buckets[pos] = agg_tx; + // Only aggregate if it does not reduce the fee_to_weight ratio. + if agg_tx.fee_to_weight() >= current.fee_to_weight() { + tx_buckets[pos] = agg_tx; + } else { + tx_buckets.push(entry.tx.clone()); + } } else { // Aggregated tx is not valid so discard this new tx. is_rejected = true;