This commit is contained in:
nym21
2025-12-22 16:22:09 +01:00
parent 02d635d48b
commit d30344ee3c
8 changed files with 26 additions and 478 deletions

View File

@@ -6,13 +6,11 @@ use crate::types::PoolIndex;
/// Entry in the priority heap for transaction selection.
///
/// Stores a snapshot of the score at insertion time.
/// The generation field detects stale entries after ancestor updates.
#[derive(Clone, Copy)]
pub struct HeapEntry {
pub pool_index: PoolIndex,
ancestor_fee: Sats,
ancestor_vsize: VSize,
pub generation: u32,
}
impl HeapEntry {
@@ -21,23 +19,18 @@ impl HeapEntry {
pool_index: node.pool_index,
ancestor_fee: node.ancestor_fee,
ancestor_vsize: node.ancestor_vsize,
generation: node.generation,
}
}
/// Returns true if this entry is outdated.
#[inline]
pub fn is_stale(&self, node: &TxNode) -> bool {
self.generation != node.generation
}
/// Compare fee rates: self > other?
#[inline]
fn has_higher_fee_rate_than(&self, other: &Self) -> bool {
// Cross multiply to avoid division:
// fee_a/vsize_a > fee_b/vsize_b ⟺ fee_a * vsize_b > fee_b * vsize_a
let self_score = u64::from(self.ancestor_fee) as u128 * u64::from(other.ancestor_vsize) as u128;
let other_score = u64::from(other.ancestor_fee) as u128 * u64::from(self.ancestor_vsize) as u128;
let self_score =
u64::from(self.ancestor_fee) as u128 * u64::from(other.ancestor_vsize) as u128;
let other_score =
u64::from(other.ancestor_fee) as u128 * u64::from(self.ancestor_vsize) as u128;
self_score > other_score
}
}

View File

@@ -4,10 +4,10 @@ use brk_types::FeeRate;
use rustc_hash::FxHashSet;
use smallvec::SmallVec;
use super::BLOCK_VSIZE;
use super::graph::Graph;
use super::heap_entry::HeapEntry;
use super::package::Package;
use super::BLOCK_VSIZE;
use crate::types::PoolIndex;
/// Select transactions from the graph and group into CPFP packages.
@@ -25,7 +25,7 @@ pub fn select_packages(graph: &mut Graph, num_blocks: usize) -> Vec<Package> {
let node = &graph[entry.pool_index];
// Skip if already selected or entry is stale
if node.selected || entry.is_stale(node) {
if node.selected {
continue;
}
@@ -80,13 +80,18 @@ fn select_with_ancestors(graph: &mut Graph, pool_idx: PoolIndex) -> SmallVec<[Po
}
/// Update descendants' ancestor scores after selecting a tx.
fn update_descendants(graph: &mut Graph, selected_idx: PoolIndex, heap: &mut BinaryHeap<HeapEntry>) {
fn update_descendants(
graph: &mut Graph,
selected_idx: PoolIndex,
heap: &mut BinaryHeap<HeapEntry>,
) {
let selected_fee = graph[selected_idx].fee;
let selected_vsize = graph[selected_idx].vsize;
// Track visited to avoid double-updates in diamond patterns
let mut visited: FxHashSet<PoolIndex> = FxHashSet::default();
let mut stack: SmallVec<[PoolIndex; 16]> = graph[selected_idx].children.iter().copied().collect();
let mut stack: SmallVec<[PoolIndex; 16]> =
graph[selected_idx].children.iter().copied().collect();
while let Some(child_idx) = stack.pop() {
if !visited.insert(child_idx) {