From 30f892d76d9a34167088e983fdc1ea42cb337de6 Mon Sep 17 00:00:00 2001 From: Roman Zeyde Date: Thu, 17 May 2018 13:45:58 +0300 Subject: [PATCH] Return actual mempool fee histogram from RPC Also, add this to the CLI tracker tool and improve logging. --- src/bin/tracker.rs | 27 ++++++++++++++++++--------- src/mempool.rs | 41 +++++++++++++++++++++++++++++------------ src/query.rs | 4 ++++ src/rpc.rs | 2 +- 4 files changed, 52 insertions(+), 22 deletions(-) diff --git a/src/bin/tracker.rs b/src/bin/tracker.rs index 9b9697a..a31f892 100644 --- a/src/bin/tracker.rs +++ b/src/bin/tracker.rs @@ -5,7 +5,7 @@ extern crate log; use indexrs::{daemon, mempool}; use std::thread; -use std::time::{Duration, Instant}; +use std::time::Duration; fn main() { use simplelog::*; @@ -18,14 +18,23 @@ fn main() { let daemon = daemon::Daemon::new("localhost:8332"); let mut tracker = mempool::Tracker::new(); loop { - let t = Instant::now(); tracker.update(&daemon).unwrap(); - let dt = t.elapsed(); - info!( - "update took {:.3} ms", - (dt.as_secs() as f64 + 1e-9f64 * dt.subsec_nanos() as f64) * 1e3 - ); - info!("histogram: {:?}", tracker.fee_histogram()); - thread::sleep(Duration::from_secs(1)); + let h = tracker.fee_histogram(); + let mut total_vsize = 0; + let mut limit = 0; + for (fee, vsize) in h { + total_vsize += vsize; + let new_limit = total_vsize as usize / 1_000_000; + if limit != new_limit { + limit = new_limit; + info!( + "{:.2}MB has fee >= {:.1} sat/vbyte", + total_vsize as f32 / 1e6, + fee + ); + } + } + info!("{:.2}MB total size", total_vsize as f32 / 1e6); + thread::sleep(Duration::from_secs(10)); } } diff --git a/src/mempool.rs b/src/mempool.rs index 1c378ff..f378ba8 100644 --- a/src/mempool.rs +++ b/src/mempool.rs @@ -1,8 +1,10 @@ use bitcoin::blockdata::transaction::Transaction; use bitcoin::util::hash::Sha256dHash; use daemon::{Daemon, MempoolEntry}; + use std::collections::{HashMap, HashSet}; use std::iter::FromIterator; +use std::time::{Duration, Instant}; error_chain!{} @@ -23,6 +25,16 @@ pub struct Tracker { stats: HashMap, } +trait InSeconds { + fn in_seconds(&self) -> f64; +} + +impl InSeconds for Duration { + fn in_seconds(&self) -> f64 { + self.as_secs() as f64 + (self.subsec_nanos() as f64) * 1e-9f64 + } +} + impl Tracker { pub fn new() -> Tracker { Tracker { @@ -56,31 +68,36 @@ impl Tracker { .getmempooltxids() .chain_err(|| "failed to update mempool from daemon")?); let old_txids = HashSet::from_iter(self.stats.keys().cloned()); - - let mut to_add = Vec::new(); + let t = Instant::now(); for &txid in new_txids.difference(&old_txids) { - let tx = match daemon.gettransaction(&txid) { - Ok(tx) => tx, - Err(err) => { - warn!("missing tx {}: {}", txid, err); - continue; - } - }; let entry = match daemon.getmempoolentry(&txid) { Ok(entry) => entry, Err(err) => { + // e.g. new block or RBF warn!("no mempool entry {}: {}", txid, err); continue; } }; + let tx = match daemon.gettransaction(&txid) { + Ok(tx) => tx, + Err(err) => { + // e.g. new block or RBF + warn!("missing tx {}: {}", txid, err); + continue; + } + }; trace!("new tx: {}, {:.3}", txid, entry.fee_per_vbyte(),); - to_add.push((txid, Stats::new(tx, entry))); + self.stats.insert(txid, Stats::new(tx, entry)); } - self.stats.extend(to_add); for txid in old_txids.difference(&new_txids) { self.stats.remove(txid); } - assert_eq!(new_txids, HashSet::from_iter(self.stats.keys().cloned())); + let dt = t.elapsed(); + debug!( + "mempool update took {:.1} ms ({} txns)", + dt.in_seconds() * 1e3, + self.stats.len() + ); Ok(()) } } diff --git a/src/query.rs b/src/query.rs index d3b650f..bed2c5d 100644 --- a/src/query.rs +++ b/src/query.rs @@ -216,4 +216,8 @@ impl<'a> Query<'a> { .update(self.daemon) .chain_err(|| "failed to update mempool") } + + pub fn get_fee_histogram(&self) -> Vec<(f32, u32)> { + self.tracker.read().unwrap().fee_histogram() + } } diff --git a/src/rpc.rs b/src/rpc.rs index 3a0fc59..399cc27 100644 --- a/src/rpc.rs +++ b/src/rpc.rs @@ -107,7 +107,7 @@ impl<'a> Handler<'a> { } fn mempool_get_fee_histogram(&self) -> Result { - Ok(json!([])) // TODO: consult with actual mempool + Ok(json!(self.query.get_fee_histogram())) } fn blockchain_block_get_chunk(&self, params: &[Value]) -> Result {