Skip to content

Commit 9a2a2a8

Browse files
author
Gabriel Comte
committed
Add per-field querying for getblockstats
1 parent 30f785d commit 9a2a2a8

File tree

3 files changed

+142
-0
lines changed

3 files changed

+142
-0
lines changed

client/src/client.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,14 @@ pub trait RpcApi: Sized {
443443
self.call("getblockstats", &[height.into()])
444444
}
445445

446+
fn get_block_stats_fields(&self, height: u64, fields: &Vec<bitcoincore_rpc_json::BlockStatsFields>) -> Result<json::GetBlockStatsResultPartial> {
447+
let fields: Vec<&str> = fields.iter()
448+
.map(|field| field.get_rpc_keyword())
449+
.collect();
450+
451+
self.call("getblockstats", &[height.into(), fields.into()])
452+
}
453+
446454
fn get_raw_transaction(
447455
&self,
448456
txid: &bitcoin::Txid,

integration_test/src/main.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ fn main() {
133133
test_get_block(&cl);
134134
test_get_block_header_get_block_header_info(&cl);
135135
test_get_block_stats(&cl);
136+
test_get_block_stats_partial(&cl);
136137
test_get_address_info(&cl);
137138
test_set_label(&cl);
138139
test_send_to_address(&cl);
@@ -299,6 +300,20 @@ fn test_get_block_stats(cl: &Client) {
299300
assert_eq!(tip, stats.height);
300301
}
301302

303+
fn test_get_block_stats_partial(cl: &Client) {
304+
use bitcoincore_rpc::bitcoincore_rpc_json::BlockStatsFields;
305+
let fields = vec![BlockStatsFields::BlockHash, BlockStatsFields::Height, BlockStatsFields::TotalFee];
306+
307+
let tip = cl.get_block_count().unwrap();
308+
let tip_hash = cl.get_best_block_hash().unwrap();
309+
let header = cl.get_block_header(&tip_hash).unwrap();
310+
let stats = cl.get_block_stats_fields(tip, &fields).unwrap();
311+
assert_eq!(header.block_hash(), stats.block_hash.unwrap());
312+
assert_eq!(tip, stats.height.unwrap());
313+
assert!(stats.total_fee.is_some());
314+
assert!(stats.avg_fee.is_none());
315+
}
316+
302317
fn test_get_address_info(cl: &Client) {
303318
let addr = cl.get_new_address(None, Some(json::AddressType::Legacy)).unwrap();
304319
let info = cl.get_address_info(&addr).unwrap();

json/src/lib.rs

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,57 @@ pub struct GetBlockStatsResult {
270270
pub utxo_size_inc: i32,
271271
}
272272

273+
#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
274+
pub struct GetBlockStatsResultPartial {
275+
#[serde(rename = "avgfee")]
276+
pub avg_fee: Option<u32>,
277+
#[serde(rename = "avgfeerate")]
278+
pub avg_fee_rate: Option<u32>,
279+
#[serde(rename = "avgtxsize")]
280+
pub avg_tx_size: Option<u32>,
281+
#[serde(rename = "blockhash")]
282+
pub block_hash: Option<bitcoin::BlockHash>,
283+
#[serde(rename = "feerate_percentiles")]
284+
pub fee_rate_percentiles: Option<FeeRatePercentiles>,
285+
pub height: Option<u64>,
286+
pub ins: Option<usize>,
287+
#[serde(rename = "maxfee")]
288+
pub max_fee: Option<u64>,
289+
#[serde(rename = "maxfeerate")]
290+
pub max_fee_rate: Option<u32>,
291+
#[serde(rename = "maxtxsize")]
292+
pub max_tx_size: Option<u32>,
293+
#[serde(rename = "medianfee")]
294+
pub median_fee: Option<u32>,
295+
#[serde(rename = "mediantime")]
296+
pub median_time: Option<u32>,
297+
#[serde(rename = "mediantxsize")]
298+
pub median_tx_size: Option<u32>,
299+
#[serde(rename = "minfee")]
300+
pub min_fee: Option<u32>,
301+
#[serde(rename = "minfeerate")]
302+
pub min_fee_rate: Option<u32>,
303+
#[serde(rename = "mintxsize")]
304+
pub min_tx_size: Option<u32>,
305+
pub outs: Option<usize>,
306+
pub subsidy: Option<u32>,
307+
#[serde(rename = "swtotal_size")]
308+
pub sw_total_size: Option<usize>,
309+
#[serde(rename = "swtotal_weight")]
310+
pub sw_total_weight: Option<usize>,
311+
#[serde(rename = "swtxs")]
312+
pub sw_txs: Option<usize>,
313+
pub time: Option<u32>,
314+
pub total_out: Option<usize>,
315+
pub total_size: Option<usize>,
316+
pub total_weight: Option<usize>,
317+
#[serde(rename = "totalfee")]
318+
pub total_fee: Option<u64>,
319+
pub txs: Option<usize>,
320+
pub utxo_increase: Option<i32>,
321+
pub utxo_size_inc: Option<i32>,
322+
}
323+
273324
#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
274325
pub struct FeeRatePercentiles {
275326
pub fr_10th: u32,
@@ -279,6 +330,74 @@ pub struct FeeRatePercentiles {
279330
pub fr_90th: u32,
280331
}
281332

333+
pub enum BlockStatsFields {
334+
AverageFee,
335+
AverageFeeRate,
336+
AverageTxSize,
337+
BlockHash,
338+
FeeRatePercentiles,
339+
Height,
340+
Ins,
341+
MaxFee,
342+
MaxFeeRate,
343+
MaxTxSize,
344+
MedianFee,
345+
MedianTime,
346+
MedianTxSize,
347+
MinFee,
348+
MinFeeRate,
349+
MinTxSize,
350+
Outs,
351+
Subsidy,
352+
SegWitTotalSize,
353+
SegWitTotalWeight,
354+
SegWitTxs,
355+
Time,
356+
TotalOut,
357+
TotalSize,
358+
TotalWeight,
359+
TotalFee,
360+
Txs,
361+
UtxoIncrease,
362+
UtxoSizeIncrease,
363+
}
364+
365+
impl BlockStatsFields {
366+
pub fn get_rpc_keyword(&self) -> &str {
367+
match *self {
368+
BlockStatsFields::AverageFee => "avgfee",
369+
BlockStatsFields::AverageFeeRate => "avgfeerate",
370+
BlockStatsFields::AverageTxSize => "avgtxsize",
371+
BlockStatsFields::BlockHash => "blockhash",
372+
BlockStatsFields::FeeRatePercentiles => "feerate_percentiles",
373+
BlockStatsFields::Height => "height",
374+
BlockStatsFields::Ins => "ins",
375+
BlockStatsFields::MaxFee => "maxfee",
376+
BlockStatsFields::MaxFeeRate => "maxfeerate",
377+
BlockStatsFields::MaxTxSize => "maxtxsize",
378+
BlockStatsFields::MedianFee => "medianfee",
379+
BlockStatsFields::MedianTime => "mediantime",
380+
BlockStatsFields::MedianTxSize => "mediantxsize",
381+
BlockStatsFields::MinFee => "minfee",
382+
BlockStatsFields::MinFeeRate => "minfeerate",
383+
BlockStatsFields::MinTxSize => "minfeerate",
384+
BlockStatsFields::Outs => "outs",
385+
BlockStatsFields::Subsidy => "subsidy",
386+
BlockStatsFields::SegWitTotalSize => "swtotal_size",
387+
BlockStatsFields::SegWitTotalWeight => "swtotal_weight",
388+
BlockStatsFields::SegWitTxs => "swtxs",
389+
BlockStatsFields::Time => "time",
390+
BlockStatsFields::TotalOut => "total_out",
391+
BlockStatsFields::TotalSize => "total_size",
392+
BlockStatsFields::TotalWeight => "total_weight",
393+
BlockStatsFields::TotalFee => "totalfee",
394+
BlockStatsFields::Txs => "txs",
395+
BlockStatsFields::UtxoIncrease => "utxo_increase",
396+
BlockStatsFields::UtxoSizeIncrease => "utxo_size_inc",
397+
}
398+
}
399+
}
400+
282401
#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
283402
#[serde(rename_all = "camelCase")]
284403
pub struct GetMiningInfoResult {

0 commit comments

Comments
 (0)