Return actual mempool fee histogram from RPC

Also, add this to the CLI tracker tool and improve logging.
This commit is contained in:
Roman Zeyde 2018-05-17 13:45:58 +03:00
parent b6d664c580
commit 30f892d76d
No known key found for this signature in database
GPG Key ID: 87CAE5FA46917CBB
4 changed files with 52 additions and 22 deletions

View File

@ -5,7 +5,7 @@ extern crate log;
use indexrs::{daemon, mempool}; use indexrs::{daemon, mempool};
use std::thread; use std::thread;
use std::time::{Duration, Instant}; use std::time::Duration;
fn main() { fn main() {
use simplelog::*; use simplelog::*;
@ -18,14 +18,23 @@ fn main() {
let daemon = daemon::Daemon::new("localhost:8332"); let daemon = daemon::Daemon::new("localhost:8332");
let mut tracker = mempool::Tracker::new(); let mut tracker = mempool::Tracker::new();
loop { loop {
let t = Instant::now();
tracker.update(&daemon).unwrap(); tracker.update(&daemon).unwrap();
let dt = t.elapsed(); 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!( info!(
"update took {:.3} ms", "{:.2}MB has fee >= {:.1} sat/vbyte",
(dt.as_secs() as f64 + 1e-9f64 * dt.subsec_nanos() as f64) * 1e3 total_vsize as f32 / 1e6,
fee
); );
info!("histogram: {:?}", tracker.fee_histogram()); }
thread::sleep(Duration::from_secs(1)); }
info!("{:.2}MB total size", total_vsize as f32 / 1e6);
thread::sleep(Duration::from_secs(10));
} }
} }

View File

@ -1,8 +1,10 @@
use bitcoin::blockdata::transaction::Transaction; use bitcoin::blockdata::transaction::Transaction;
use bitcoin::util::hash::Sha256dHash; use bitcoin::util::hash::Sha256dHash;
use daemon::{Daemon, MempoolEntry}; use daemon::{Daemon, MempoolEntry};
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::iter::FromIterator; use std::iter::FromIterator;
use std::time::{Duration, Instant};
error_chain!{} error_chain!{}
@ -23,6 +25,16 @@ pub struct Tracker {
stats: HashMap<Sha256dHash, Stats>, stats: HashMap<Sha256dHash, Stats>,
} }
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 { impl Tracker {
pub fn new() -> Tracker { pub fn new() -> Tracker {
Tracker { Tracker {
@ -56,31 +68,36 @@ impl Tracker {
.getmempooltxids() .getmempooltxids()
.chain_err(|| "failed to update mempool from daemon")?); .chain_err(|| "failed to update mempool from daemon")?);
let old_txids = HashSet::from_iter(self.stats.keys().cloned()); let old_txids = HashSet::from_iter(self.stats.keys().cloned());
let t = Instant::now();
let mut to_add = Vec::new();
for &txid in new_txids.difference(&old_txids) { 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) { let entry = match daemon.getmempoolentry(&txid) {
Ok(entry) => entry, Ok(entry) => entry,
Err(err) => { Err(err) => {
// e.g. new block or RBF
warn!("no mempool entry {}: {}", txid, err); warn!("no mempool entry {}: {}", txid, err);
continue; continue;
} }
}; };
trace!("new tx: {}, {:.3}", txid, entry.fee_per_vbyte(),); let tx = match daemon.gettransaction(&txid) {
to_add.push((txid, Stats::new(tx, entry))); 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(),);
self.stats.insert(txid, Stats::new(tx, entry));
} }
self.stats.extend(to_add);
for txid in old_txids.difference(&new_txids) { for txid in old_txids.difference(&new_txids) {
self.stats.remove(txid); 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(()) Ok(())
} }
} }

View File

@ -216,4 +216,8 @@ impl<'a> Query<'a> {
.update(self.daemon) .update(self.daemon)
.chain_err(|| "failed to update mempool") .chain_err(|| "failed to update mempool")
} }
pub fn get_fee_histogram(&self) -> Vec<(f32, u32)> {
self.tracker.read().unwrap().fee_histogram()
}
} }

View File

@ -107,7 +107,7 @@ impl<'a> Handler<'a> {
} }
fn mempool_get_fee_histogram(&self) -> Result<Value> { fn mempool_get_fee_histogram(&self) -> Result<Value> {
Ok(json!([])) // TODO: consult with actual mempool Ok(json!(self.query.get_fee_histogram()))
} }
fn blockchain_block_get_chunk(&self, params: &[Value]) -> Result<Value> { fn blockchain_block_get_chunk(&self, params: &[Value]) -> Result<Value> {