feat(rpc): Add more fields to `getmininginfo` call (#8860)

* add additional fields to getmininginfo

* update openapi spec

* fix zebra-state standalone build

* make sure fields are not present when tip is 0
This commit is contained in:
Alfredo Garcia 2024-09-18 08:05:25 -03:00 committed by GitHub
parent 082cdad1c1
commit 3f94303bb2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 141 additions and 32 deletions

View File

@ -28,7 +28,7 @@ paths:
default: getinfo
id:
type: string
default: dX2SRjFwfc
default: uf2E54tQkk
params:
type: array
items: {}
@ -61,7 +61,7 @@ paths:
default: getblockchaininfo
id:
type: string
default: LoRrjyRM4l
default: Sbre3vivr8
params:
type: array
items: {}
@ -99,7 +99,7 @@ paths:
default: getaddressbalance
id:
type: string
default: WWIvpPiJo0
default: f5qarOBgzK
params:
type: array
items: {}
@ -147,7 +147,7 @@ paths:
default: sendrawtransaction
id:
type: string
default: '5tVg2R9ZeI'
default: IlNHvAcSMS
params:
type: array
items: {}
@ -196,7 +196,7 @@ paths:
default: getblock
id:
type: string
default: vZ5KPOdiue
default: s9678BM3Lc
params:
type: array
items: {}
@ -239,7 +239,7 @@ paths:
default: getbestblockhash
id:
type: string
default: IifeYgN2ZK
default: FGQPJY8Tp8
params:
type: array
items: {}
@ -272,7 +272,7 @@ paths:
default: getbestblockheightandhash
id:
type: string
default: tNLKsWqtNW
default: c2MfkL7xP9
params:
type: array
items: {}
@ -305,7 +305,7 @@ paths:
default: getrawmempool
id:
type: string
default: IZ6todle9t
default: BugnNFhJpA
params:
type: array
items: {}
@ -343,7 +343,7 @@ paths:
default: z_gettreestate
id:
type: string
default: SSZAwyUO6t
default: fCUQvR1BVa
params:
type: array
items: {}
@ -393,7 +393,7 @@ paths:
default: z_getsubtreesbyindex
id:
type: string
default: '3fJMQ0Hfxt'
default: TtPnptV6EU
params:
type: array
items: {}
@ -432,7 +432,7 @@ paths:
default: getrawtransaction
id:
type: string
default: RTdE1YnNxy
default: QqYeOGSzje
params:
type: array
items: {}
@ -480,7 +480,7 @@ paths:
default: getaddresstxids
id:
type: string
default: ifahwzVoYe
default: AsWWVyqp8x
params:
type: array
items: {}
@ -528,7 +528,7 @@ paths:
default: getaddressutxos
id:
type: string
default: PcPdZ7aiKy
default: Qscn5dUFgD
params:
type: array
items: {}
@ -571,7 +571,7 @@ paths:
default: stop
id:
type: string
default: rWlJLGe7VJ
default: WuIaPXV5fO
params:
type: array
items: {}
@ -604,7 +604,7 @@ paths:
default: getblockcount
id:
type: string
default: f4p3Cb4sDu
default: '5F9M7Wp0oI'
params:
type: array
items: {}
@ -642,7 +642,7 @@ paths:
default: getblockhash
id:
type: string
default: '3QXvqbEWqb'
default: f7hdgVjctr
params:
type: array
items: {}
@ -690,7 +690,7 @@ paths:
default: getblocktemplate
id:
type: string
default: GXKjn81k0D
default: pq0uXn3YGs
params:
type: array
items: {}
@ -728,7 +728,7 @@ paths:
default: submitblock
id:
type: string
default: cwGy92Mwn9
default: bs4v4JmVw3
params:
type: array
items: {}
@ -761,7 +761,7 @@ paths:
default: getmininginfo
id:
type: string
default: '4ZFY9ljh5I'
default: pp5xV6v3pm
params:
type: array
items: {}
@ -776,7 +776,7 @@ paths:
properties:
result:
type: object
default: '{"networksolps":0,"networkhashps":0,"chain":"","testnet":false}'
default: '{"blocks":0,"networksolps":0,"networkhashps":0,"chain":"","testnet":false}'
/getnetworksolps:
post:
tags:
@ -794,7 +794,7 @@ paths:
default: getnetworksolps
id:
type: string
default: tJlKGzARjU
default: '7bU98TeCV6'
params:
type: array
items: {}
@ -827,7 +827,7 @@ paths:
default: getnetworkhashps
id:
type: string
default: '7pUkOt26PB'
default: fskOJeXqjo
params:
type: array
items: {}
@ -860,7 +860,7 @@ paths:
default: getpeerinfo
id:
type: string
default: JjnSrPKeyS
default: jPV8ufjDdt
params:
type: array
items: {}
@ -898,7 +898,7 @@ paths:
default: validateaddress
id:
type: string
default: pxZQt6VQ9U
default: xOyxICseV9
params:
type: array
items: {}
@ -936,7 +936,7 @@ paths:
default: z_validateaddress
id:
type: string
default: x2R2oRhdZE
default: xa6PoC4uN6
params:
type: array
items: {}
@ -974,7 +974,7 @@ paths:
default: getblocksubsidy
id:
type: string
default: vkhYJS3FH8
default: vYEVtnVK9o
params:
type: array
items: {}
@ -1017,7 +1017,7 @@ paths:
default: getdifficulty
id:
type: string
default: bC6q9c3xYO
default: tVzSTZu2sD
params:
type: array
items: {}
@ -1055,7 +1055,7 @@ paths:
default: z_listunifiedreceivers
id:
type: string
default: EQvPXkcJC2
default: le2NmJBmPt
params:
type: array
items: {}
@ -1093,7 +1093,7 @@ paths:
default: generate
id:
type: string
default: w41FKROii3
default: vVVOWxHqlN
params:
type: array
items: {}

View File

@ -106,7 +106,7 @@ impl ChainTip for MockChainTip {
}
fn best_tip_mined_transaction_ids(&self) -> Arc<[transaction::Hash]> {
unreachable!("Method not used in tests");
Arc::new([])
}
fn estimate_distance_to_network_chain_tip(

View File

@ -1012,9 +1012,39 @@ where
fn get_mining_info(&self) -> BoxFuture<Result<get_mining_info::Response>> {
let network = self.network.clone();
let mut state = self.state.clone();
let chain_tip = self.latest_chain_tip.clone();
let tip_height = chain_tip.best_tip_height().unwrap_or(Height(0)).0;
let mut current_block_tx = None;
if tip_height > 0 {
let mined_tx_ids = chain_tip.best_tip_mined_transaction_ids();
current_block_tx =
(!mined_tx_ids.is_empty()).then(|| mined_tx_ids.len().saturating_sub(1));
}
let solution_rate_fut = self.get_network_sol_ps(None, None);
async move {
// Get the current block size.
let mut current_block_size = None;
if tip_height > 0 {
let request = zebra_state::ReadRequest::TipBlockSize;
let response: zebra_state::ReadResponse = state
.ready()
.and_then(|service| service.call(request))
.await
.map_server_error()?;
current_block_size = match response {
zebra_state::ReadResponse::TipBlockSize(Some(block_size)) => Some(block_size),
_ => None,
};
}
Ok(get_mining_info::Response::new(
tip_height,
current_block_size,
current_block_tx,
network,
solution_rate_fut.await?,
))

View File

@ -5,6 +5,18 @@ use zebra_chain::parameters::Network;
/// Response to a `getmininginfo` RPC request.
#[derive(Debug, Default, PartialEq, Eq, serde::Serialize)]
pub struct Response {
/// The current tip height.
#[serde(rename = "blocks")]
tip_height: u32,
/// The size of the last mined block if any.
#[serde(rename = "currentblocksize", skip_serializing_if = "Option::is_none")]
current_block_size: Option<usize>,
/// The number of transactions in the last mined block if any.
#[serde(rename = "currentblocktx", skip_serializing_if = "Option::is_none")]
current_block_tx: Option<usize>,
/// The estimated network solution rate in Sol/s.
networksolps: u64,
@ -20,8 +32,17 @@ pub struct Response {
impl Response {
/// Creates a new `getmininginfo` response
pub fn new(network: Network, networksolps: u64) -> Self {
pub fn new(
tip_height: u32,
current_block_size: Option<usize>,
current_block_tx: Option<usize>,
network: Network,
networksolps: u64,
) -> Self {
Self {
tip_height,
current_block_size,
current_block_tx,
networksolps,
networkhashps: networksolps,
chain: network.bip70_network_name(),

View File

@ -3,6 +3,8 @@ source: zebra-rpc/src/methods/tests/snapshot/get_block_template_rpcs.rs
expression: get_mining_info
---
{
"blocks": 1687104,
"currentblocksize": 1617,
"networksolps": 2,
"networkhashps": 2,
"chain": "main",

View File

@ -3,6 +3,8 @@ source: zebra-rpc/src/methods/tests/snapshot/get_block_template_rpcs.rs
expression: get_mining_info
---
{
"blocks": 1842420,
"currentblocksize": 1618,
"networksolps": 0,
"networkhashps": 0,
"chain": "test",

View File

@ -1063,6 +1063,11 @@ pub enum ReadRequest {
/// Returns [`ReadResponse::ValidBlockProposal`] when successful, or an error if
/// the block fails contextual validation.
CheckBlockProposalValidity(SemanticallyVerifiedBlock),
#[cfg(feature = "getblocktemplate-rpcs")]
/// Returns [`ReadResponse::TipBlockSize(usize)`](ReadResponse::TipBlockSize)
/// with the current best chain tip block size in bytes.
TipBlockSize,
}
impl ReadRequest {
@ -1098,6 +1103,8 @@ impl ReadRequest {
ReadRequest::SolutionRate { .. } => "solution_rate",
#[cfg(feature = "getblocktemplate-rpcs")]
ReadRequest::CheckBlockProposalValidity(_) => "check_block_proposal_validity",
#[cfg(feature = "getblocktemplate-rpcs")]
ReadRequest::TipBlockSize => "tip_block_size",
}
}

View File

@ -229,6 +229,10 @@ pub enum ReadResponse {
#[cfg(feature = "getblocktemplate-rpcs")]
/// Response to [`ReadRequest::CheckBlockProposalValidity`]
ValidBlockProposal,
#[cfg(feature = "getblocktemplate-rpcs")]
/// Response to [`ReadRequest::TipBlockSize`]
TipBlockSize(Option<usize>),
}
/// A structure with the information needed from the state to build a `getblocktemplate` RPC response.
@ -315,7 +319,7 @@ impl TryFrom<ReadResponse> for Response {
ReadResponse::ValidBlockProposal => Ok(Response::ValidBlockProposal),
#[cfg(feature = "getblocktemplate-rpcs")]
ReadResponse::ChainInfo(_) | ReadResponse::SolutionRate(_) => {
ReadResponse::ChainInfo(_) | ReadResponse::SolutionRate(_) | ReadResponse::TipBlockSize(_) => {
Err("there is no corresponding Response for this ReadResponse")
}
}

View File

@ -39,6 +39,9 @@ use zebra_chain::{
subtree::NoteCommitmentSubtreeIndex,
};
#[cfg(feature = "getblocktemplate-rpcs")]
use zebra_chain::{block::Height, serialization::ZcashSerialize};
use crate::{
constants::{
MAX_FIND_BLOCK_HASHES_RESULTS, MAX_FIND_BLOCK_HEADERS_RESULTS_FOR_ZEBRA,
@ -1905,6 +1908,46 @@ impl Service<ReadRequest> for ReadStateService {
})
.wait_for_panics()
}
#[cfg(feature = "getblocktemplate-rpcs")]
ReadRequest::TipBlockSize => {
let state = self.clone();
tokio::task::spawn_blocking(move || {
span.in_scope(move || {
// Get the best chain tip height.
let tip_height = state
.non_finalized_state_receiver
.with_watch_data(|non_finalized_state| {
read::tip_height(non_finalized_state.best_chain(), &state.db)
})
.unwrap_or(Height(0));
// Get the block at the best chain tip height.
let block = state.non_finalized_state_receiver.with_watch_data(
|non_finalized_state| {
read::block(
non_finalized_state.best_chain(),
&state.db,
tip_height.into(),
)
},
);
// The work is done in the future.
timer.finish(module_path!(), line!(), "ReadRequest::TipBlockSize");
// Respond with the length of the obtained block if any.
match block {
Some(b) => Ok(ReadResponse::TipBlockSize(Some(
b.zcash_serialize_to_vec()?.len(),
))),
None => Ok(ReadResponse::TipBlockSize(None)),
}
})
})
.wait_for_panics()
}
}
}
}