mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-05-19 06:14:47 -07:00
mempool: fixes
This commit is contained in:
@@ -32,7 +32,7 @@ fn main() -> Result<()> {
|
||||
"info.count={} txs={} unresolved={} addrs={} outpoints={} \
|
||||
graveyard.tombstones={} graveyard.order={} \
|
||||
snap.txs.len={} snap.blocks={} snap.blocks_txs={} \
|
||||
rebuilds={} skip.clean={}",
|
||||
rebuilds={}",
|
||||
info_count,
|
||||
stats.txs,
|
||||
stats.unresolved,
|
||||
@@ -44,7 +44,6 @@ fn main() -> Result<()> {
|
||||
snapshot.blocks.len(),
|
||||
blocks_tx_total,
|
||||
stats.rebuilds,
|
||||
stats.skip_cleans,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ pub struct MempoolStats {
|
||||
pub graveyard_tombstones: usize,
|
||||
pub graveyard_order: usize,
|
||||
pub rebuilds: u64,
|
||||
pub skip_cleans: u64,
|
||||
}
|
||||
|
||||
impl From<&Mempool> for MempoolStats {
|
||||
@@ -28,7 +27,6 @@ impl From<&Mempool> for MempoolStats {
|
||||
graveyard_tombstones: state.graveyard.tombstones_len(),
|
||||
graveyard_order: state.graveyard.order_len(),
|
||||
rebuilds: rebuilder.rebuild_count(),
|
||||
skip_cleans: rebuilder.skip_clean_count(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -354,9 +354,9 @@ impl Mempool {
|
||||
min_fee,
|
||||
} = Fetcher::fetch(client, state)?;
|
||||
let pulled = Preparer::prepare(&live_txids, new_entries, new_txs, state);
|
||||
let changed = Applier::apply(state, rebuilder, pulled);
|
||||
Applier::apply(state, rebuilder, pulled);
|
||||
Prevouts::fill(state, resolver);
|
||||
rebuilder.tick(state, changed, &gbt_txids, min_fee);
|
||||
rebuilder.tick(state, &gbt_txids, min_fee);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -14,23 +14,17 @@ use crate::{
|
||||
pub struct Applier;
|
||||
|
||||
impl Applier {
|
||||
/// Returns true iff anything changed.
|
||||
///
|
||||
/// `rebuilder` supplies the previous cycle's snapshot. Burial reads
|
||||
/// each tomb's `chunk_rate` from the snapshot (always-fresh,
|
||||
/// package-aware via local linearization). The fallback to
|
||||
/// `entry.fee_rate()` is unreachable in steady state - every burial
|
||||
/// target was alive at the previous tick, so the snapshot has it.
|
||||
pub fn apply(lock: &RwLock<State>, rebuilder: &Rebuilder, pulled: TxsPulled) -> bool {
|
||||
pub fn apply(lock: &RwLock<State>, rebuilder: &Rebuilder, pulled: TxsPulled) {
|
||||
let TxsPulled { added, removed } = pulled;
|
||||
let has_changes = !added.is_empty() || !removed.is_empty();
|
||||
|
||||
let mut state = lock.write();
|
||||
Self::bury_removals(&mut state, rebuilder, removed);
|
||||
Self::publish_additions(&mut state, added);
|
||||
state.graveyard.evict_old();
|
||||
|
||||
has_changes
|
||||
}
|
||||
|
||||
fn bury_removals(
|
||||
|
||||
@@ -2,7 +2,7 @@ use std::{
|
||||
collections::VecDeque,
|
||||
sync::{
|
||||
Arc,
|
||||
atomic::{AtomicBool, AtomicU64, Ordering},
|
||||
atomic::{AtomicU64, Ordering},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -29,31 +29,16 @@ pub struct Rebuilder {
|
||||
snapshot: RwLock<Arc<Snapshot>>,
|
||||
/// Past block-0 txid sets keyed by `next_block_hash`, oldest first.
|
||||
history: RwLock<VecDeque<(NextBlockHash, FxHashSet<Txid>)>>,
|
||||
dirty: AtomicBool,
|
||||
rebuild_count: AtomicU64,
|
||||
skip_clean: AtomicU64,
|
||||
}
|
||||
|
||||
impl Rebuilder {
|
||||
/// Mark dirty if the cycle changed mempool state, then rebuild iff
|
||||
/// the dirty bit is set. Cycle pacing is the driver loop's job; the
|
||||
/// rebuild itself is pure CPU on already-fetched data. The dirty
|
||||
/// bit is cleared only after the snapshot is published, so a panic
|
||||
/// in `build_snapshot` retries on the next cycle.
|
||||
pub fn tick(
|
||||
&self,
|
||||
lock: &RwLock<State>,
|
||||
changed: bool,
|
||||
gbt_txids: &[Txid],
|
||||
min_fee: FeeRate,
|
||||
) {
|
||||
if changed {
|
||||
self.dirty.store(true, Ordering::Release);
|
||||
}
|
||||
if !self.dirty.load(Ordering::Acquire) {
|
||||
self.skip_clean.fetch_add(1, Ordering::Relaxed);
|
||||
return;
|
||||
}
|
||||
/// Rebuild the snapshot every cycle. The build is pure CPU on
|
||||
/// already-fetched data and `min_fee` participates in the result,
|
||||
/// so a "skip if no add/remove" gate would freeze the served fees
|
||||
/// when Core's `mempoolminfee` drifts on a quiet pool. Cycle pacing
|
||||
/// is the driver loop's job.
|
||||
pub fn tick(&self, lock: &RwLock<State>, gbt_txids: &[Txid], min_fee: FeeRate) {
|
||||
let snap = Self::build_snapshot(lock, gbt_txids, min_fee);
|
||||
let block0_set: FxHashSet<Txid> = snap.block0_txids().collect();
|
||||
let next_hash = snap.next_block_hash;
|
||||
@@ -67,7 +52,6 @@ impl Rebuilder {
|
||||
}
|
||||
drop(hist);
|
||||
|
||||
self.dirty.store(false, Ordering::Release);
|
||||
self.rebuild_count.fetch_add(1, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
@@ -86,10 +70,6 @@ impl Rebuilder {
|
||||
self.rebuild_count.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
pub fn skip_clean_count(&self) -> u64 {
|
||||
self.skip_clean.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
fn build_snapshot(
|
||||
lock: &RwLock<State>,
|
||||
gbt_txids: &[Txid],
|
||||
|
||||
Reference in New Issue
Block a user