mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-05-20 06:44:47 -07:00
query: fixes
This commit is contained in:
2
crates/brk_query/.gitignore
vendored
2
crates/brk_query/.gitignore
vendored
@@ -1 +1,3 @@
|
||||
*.txt
|
||||
/*.md
|
||||
!README.md
|
||||
|
||||
@@ -173,9 +173,8 @@ impl Query {
|
||||
|
||||
let prefix = u32::from(type_index).to_be_bytes();
|
||||
|
||||
// Match mempool.space's electrs cap: refuse addresses with >500 UTXOs.
|
||||
// Bounds worst-case work and response size, prevents heavy-address DDoS.
|
||||
const MAX_UTXOS: usize = 500;
|
||||
const MAX_UTXOS: usize = 1000;
|
||||
let outpoints: Vec<(TxIndex, Vout)> = store
|
||||
.prefix(prefix)
|
||||
.map(|(key, _): (AddrIndexOutPoint, Unit)| (key.tx_index(), key.vout()))
|
||||
|
||||
@@ -378,6 +378,50 @@ impl Query {
|
||||
})
|
||||
}
|
||||
|
||||
/// Recent RBF replacements across the whole mempool, matching
|
||||
/// mempool.space's `GET /api/v1/replacements` and
|
||||
/// `GET /api/v1/fullrbf/replacements`. Each entry is a complete
|
||||
/// replacement tree rooted at the latest replacer; same shape as
|
||||
/// `tx_rbf().replacements`. Sorted most-recent-first by root
|
||||
/// `time`. When `full_rbf_only` is true, only trees with at least
|
||||
/// one non-signaling predecessor are returned.
|
||||
pub fn recent_replacements(&self, full_rbf_only: bool) -> Result<Vec<ReplacementNode>> {
|
||||
let mempool = self.mempool().ok_or(Error::MempoolNotAvailable)?;
|
||||
let txs = mempool.txs();
|
||||
let entries = mempool.entries();
|
||||
let graveyard = mempool.graveyard();
|
||||
|
||||
// Collect every distinct tree-root replacer. A predecessor's
|
||||
// `by` may itself have been replaced; walk forward through
|
||||
// chained Replaced tombstones until reaching a tx that's no
|
||||
// longer flagged as replaced (live, Vanished, or unknown).
|
||||
let mut roots: FxHashSet<Txid> = FxHashSet::default();
|
||||
for (_, by) in graveyard.replaced_iter() {
|
||||
let mut root = by.clone();
|
||||
while let Some(TxRemoval::Replaced { by: next }) =
|
||||
graveyard.get(&root).map(TxTombstone::reason)
|
||||
{
|
||||
root = next.clone();
|
||||
}
|
||||
roots.insert(root);
|
||||
}
|
||||
|
||||
let mut trees: Vec<ReplacementNode> = roots
|
||||
.iter()
|
||||
.filter_map(|root| {
|
||||
Self::build_rbf_node(root, None, &txs, &entries, &graveyard).map(|mut node| {
|
||||
node.tx.full_rbf = Some(node.full_rbf);
|
||||
node.interval = None;
|
||||
node
|
||||
})
|
||||
})
|
||||
.filter(|node| !full_rbf_only || node.full_rbf)
|
||||
.collect();
|
||||
|
||||
trees.sort_by(|a, b| b.time.cmp(&a.time));
|
||||
Ok(trees)
|
||||
}
|
||||
|
||||
pub fn transaction_times(&self, txids: &[Txid]) -> Result<Vec<u64>> {
|
||||
let mempool = self.mempool().ok_or(Error::MempoolNotAvailable)?;
|
||||
let entries = mempool.entries();
|
||||
|
||||
@@ -9,7 +9,7 @@ use brk_mempool::Mempool;
|
||||
use brk_reader::Reader;
|
||||
use brk_rpc::Client;
|
||||
use brk_types::{BlockHash, BlockHashPrefix, Height, SyncStatus};
|
||||
use vecdb::{AnyVec, ReadOnlyClone, ReadableVec, Ro};
|
||||
use vecdb::{ReadOnlyClone, ReadableVec, Ro};
|
||||
|
||||
#[cfg(feature = "tokio")]
|
||||
mod r#async;
|
||||
@@ -63,8 +63,7 @@ impl Query {
|
||||
|
||||
/// Current computed height (series)
|
||||
pub fn computed_height(&self) -> Height {
|
||||
let len = self.computer().distribution.supply_state.len();
|
||||
Height::from(len.saturating_sub(1))
|
||||
Height::from(self.computer().distribution.supply_state.stamp())
|
||||
}
|
||||
|
||||
/// Minimum of indexed and computed heights
|
||||
@@ -73,11 +72,13 @@ impl Query {
|
||||
}
|
||||
|
||||
/// Tip block hash, cached in the indexer.
|
||||
#[inline]
|
||||
pub fn tip_blockhash(&self) -> BlockHash {
|
||||
self.indexer().tip_blockhash()
|
||||
}
|
||||
|
||||
/// Tip block hash prefix for cache etags.
|
||||
#[inline]
|
||||
pub fn tip_hash_prefix(&self) -> BlockHashPrefix {
|
||||
BlockHashPrefix::from(&self.tip_blockhash())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user