diff --git a/Cargo.lock b/Cargo.lock index 0871785..1309729 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -232,7 +232,7 @@ dependencies = [ [[package]] name = "btcnode-metrics" -version = "2.0.7" +version = "2.29.0" dependencies = [ "anyhow", "axum", diff --git a/Cargo.toml b/Cargo.toml index 5336a43..9f72390 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "btcnode-metrics" edition = "2024" -version = "2.0.7" +version = "2.29.0" description = "The Bitcoin node metrics exporter for Prometheus based on Rust Bitcoin Community's crate for Bitcoin JSON-RPC." license-file = "LICENSE" homepage = "https://github.com/AltaModaTech/btcnode-metrics" diff --git a/src/btcnode_metrics_gatherer/collector.rs b/src/btcnode_metrics_gatherer/collector.rs index 0f65fec..47fcd95 100644 --- a/src/btcnode_metrics_gatherer/collector.rs +++ b/src/btcnode_metrics_gatherer/collector.rs @@ -256,8 +256,7 @@ impl MetricsCollector { mod tests { use super::*; use crate::btcnode_metrics_gatherer::Error; - use crate::btcnode_metrics_gatherer::node::{ChainTxStats, MiningInfo}; - use corepc_client::types::v28::*; + use corepc_client::types::v29::*; struct MockNode; @@ -270,6 +269,8 @@ mod tests { best_block_hash: String::from( "0000000000000000000000000000000000000000000000000000000000000000" ), + bits: String::from("1703255b"), + target: String::from("00000000000000000003255b0000000000000000000000000000000000000000"), difficulty: 53_911_173_001_054.59, time: 1_700_000_000, median_time: 1_699_999_000, @@ -281,7 +282,7 @@ mod tests { prune_height: None, automatic_pruning: None, prune_target_size: None, - softforks: Default::default(), + signet_challenge: None, warnings: vec![], }) } @@ -416,21 +417,30 @@ mod tests { ])) } - fn get_mining_info(&self) -> Result { - Ok(MiningInfo { + fn get_mining_info(&self) -> Result { + Ok(GetMiningInfo { blocks: 800_000, current_block_weight: Some(3_993_000), current_block_tx: Some(2_500), + bits: String::from("1703255b"), difficulty: 53_911_173_001_054.59, + target: String::from("00000000000000000003255b0000000000000000000000000000000000000000"), network_hash_ps: 4.5e17, pooled_tx: 5000, chain: "main".into(), + signet_challenge: None, + next: NextBlockInfo { + height: 800_001, + bits: String::from("1703255b"), + difficulty: 53_911_173_001_054.59, + target: String::from("00000000000000000003255b0000000000000000000000000000000000000000"), + }, warnings: vec![], }) } - fn get_chain_tx_stats(&self) -> Result { - Ok(ChainTxStats { + fn get_chain_tx_stats(&self) -> Result { + Ok(GetChainTxStats { time: 1_700_000_000, tx_count: 900_000_000, window_final_block_hash: "0000000000000000000000000000000000000000000000000000000000000000".into(), @@ -645,11 +655,11 @@ mod tests { MockNode.get_peer_info() } - fn get_mining_info(&self) -> Result { + fn get_mining_info(&self) -> Result { MockNode.get_mining_info() } - fn get_chain_tx_stats(&self) -> Result { + fn get_chain_tx_stats(&self) -> Result { MockNode.get_chain_tx_stats() } diff --git a/src/btcnode_metrics_gatherer/node.rs b/src/btcnode_metrics_gatherer/node.rs index 02e8d4c..99c86a9 100644 --- a/src/btcnode_metrics_gatherer/node.rs +++ b/src/btcnode_metrics_gatherer/node.rs @@ -2,63 +2,22 @@ // SPDX-FileCopyrightText: 2026 AltaModa Technologies, LLC // SPDX-FileCopyrightText: Contributors to the btcnode-metrics project. -use corepc_client::client_sync::{v28::Client, Auth}; -use corepc_client::types::v28::{ - EstimateSmartFee, GetBlockStats, GetBlockchainInfo, GetChainTips, GetMempoolInfo, GetNetTotals, - GetNetworkInfo, GetPeerInfo, +use corepc_client::client_sync::{v29::Client, Auth}; +use corepc_client::types::v29::{ + EstimateSmartFee, GetBlockStats, GetBlockchainInfo, GetChainTips, GetChainTxStats, + GetMempoolInfo, GetMiningInfo, GetNetTotals, GetNetworkInfo, GetPeerInfo, }; -use serde::Deserialize; use super::Error; use super::config::NodeConfig; -/// Custom type for `getmininginfo` that fixes `network_hash_ps` from `i64` to `f64`. -/// -/// Bitcoin Core returns `networkhashps` as a floating-point number (e.g. `1.02e+21`) -/// but the upstream `corepc-types` crate incorrectly declares the field as `i64`, -/// which causes deserialization to fail on mainnet. -#[derive(Clone, Debug, Deserialize)] -pub struct MiningInfo { - pub blocks: u64, - #[serde(rename = "currentblockweight")] - pub current_block_weight: Option, - #[serde(rename = "currentblocktx")] - pub current_block_tx: Option, - pub difficulty: f64, - #[serde(rename = "networkhashps")] - pub network_hash_ps: f64, - #[serde(rename = "pooledtx")] - pub pooled_tx: i64, - pub chain: String, - pub warnings: Vec, -} - -/// Custom type for `getchaintxstats` that fixes `tx_rate` from `Option` to `Option`. -/// -/// Bitcoin Core returns `txrate` as a floating-point number (e.g. `4.56`) -/// but the upstream `corepc-types` crate incorrectly declares the field as `Option`, -/// which causes deserialization to fail. -#[derive(Clone, Debug, Deserialize)] -pub struct ChainTxStats { - pub time: i64, - #[serde(rename = "txcount")] - pub tx_count: i64, - pub window_final_block_hash: String, - pub window_final_block_height: i64, - pub window_block_count: i64, - pub window_tx_count: Option, - pub window_interval: Option, - #[serde(rename = "txrate")] - pub tx_rate: Option, -} - pub trait NodeClient: Send + Sync { fn get_blockchain_info(&self) -> Result; fn get_mempool_info(&self) -> Result; fn get_network_info(&self) -> Result; fn get_peer_info(&self) -> Result; - fn get_mining_info(&self) -> Result; - fn get_chain_tx_stats(&self) -> Result; + fn get_mining_info(&self) -> Result; + fn get_chain_tx_stats(&self) -> Result; fn get_net_totals(&self) -> Result; fn estimate_smart_fee(&self, conf_target: u32) -> Result; fn get_chain_tips(&self) -> Result; @@ -96,16 +55,12 @@ impl NodeClient for BitcoinNode { Ok(self.client.get_peer_info()?) } - fn get_mining_info(&self) -> Result { - // Bypass upstream GetMiningInfo (which declares network_hash_ps as i64) - // and deserialize directly into our corrected MiningInfo type. - Ok(self.client.call::("getmininginfo", &[])?) + fn get_mining_info(&self) -> Result { + Ok(self.client.get_mining_info()?) } - fn get_chain_tx_stats(&self) -> Result { - // Bypass upstream GetChainTxStats (which declares tx_rate as Option) - // and deserialize directly into our corrected ChainTxStats type. - Ok(self.client.call::("getchaintxstats", &[])?) + fn get_chain_tx_stats(&self) -> Result { + Ok(self.client.get_chain_tx_stats()?) } fn get_net_totals(&self) -> Result {