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

View File

@ -106,7 +106,7 @@ impl ChainTip for MockChainTip {
} }
fn best_tip_mined_transaction_ids(&self) -> Arc<[transaction::Hash]> { 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( 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>> { fn get_mining_info(&self) -> BoxFuture<Result<get_mining_info::Response>> {
let network = self.network.clone(); 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); let solution_rate_fut = self.get_network_sol_ps(None, None);
async move { 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( Ok(get_mining_info::Response::new(
tip_height,
current_block_size,
current_block_tx,
network, network,
solution_rate_fut.await?, solution_rate_fut.await?,
)) ))

View File

@ -5,6 +5,18 @@ use zebra_chain::parameters::Network;
/// Response to a `getmininginfo` RPC request. /// Response to a `getmininginfo` RPC request.
#[derive(Debug, Default, PartialEq, Eq, serde::Serialize)] #[derive(Debug, Default, PartialEq, Eq, serde::Serialize)]
pub struct Response { 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. /// The estimated network solution rate in Sol/s.
networksolps: u64, networksolps: u64,
@ -20,8 +32,17 @@ pub struct Response {
impl Response { impl Response {
/// Creates a new `getmininginfo` 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 { Self {
tip_height,
current_block_size,
current_block_tx,
networksolps, networksolps,
networkhashps: networksolps, networkhashps: networksolps,
chain: network.bip70_network_name(), 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 expression: get_mining_info
--- ---
{ {
"blocks": 1687104,
"currentblocksize": 1617,
"networksolps": 2, "networksolps": 2,
"networkhashps": 2, "networkhashps": 2,
"chain": "main", "chain": "main",

View File

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

View File

@ -1063,6 +1063,11 @@ pub enum ReadRequest {
/// Returns [`ReadResponse::ValidBlockProposal`] when successful, or an error if /// Returns [`ReadResponse::ValidBlockProposal`] when successful, or an error if
/// the block fails contextual validation. /// the block fails contextual validation.
CheckBlockProposalValidity(SemanticallyVerifiedBlock), 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 { impl ReadRequest {
@ -1098,6 +1103,8 @@ impl ReadRequest {
ReadRequest::SolutionRate { .. } => "solution_rate", ReadRequest::SolutionRate { .. } => "solution_rate",
#[cfg(feature = "getblocktemplate-rpcs")] #[cfg(feature = "getblocktemplate-rpcs")]
ReadRequest::CheckBlockProposalValidity(_) => "check_block_proposal_validity", 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")] #[cfg(feature = "getblocktemplate-rpcs")]
/// Response to [`ReadRequest::CheckBlockProposalValidity`] /// Response to [`ReadRequest::CheckBlockProposalValidity`]
ValidBlockProposal, 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. /// 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), ReadResponse::ValidBlockProposal => Ok(Response::ValidBlockProposal),
#[cfg(feature = "getblocktemplate-rpcs")] #[cfg(feature = "getblocktemplate-rpcs")]
ReadResponse::ChainInfo(_) | ReadResponse::SolutionRate(_) => { ReadResponse::ChainInfo(_) | ReadResponse::SolutionRate(_) | ReadResponse::TipBlockSize(_) => {
Err("there is no corresponding Response for this ReadResponse") Err("there is no corresponding Response for this ReadResponse")
} }
} }

View File

@ -39,6 +39,9 @@ use zebra_chain::{
subtree::NoteCommitmentSubtreeIndex, subtree::NoteCommitmentSubtreeIndex,
}; };
#[cfg(feature = "getblocktemplate-rpcs")]
use zebra_chain::{block::Height, serialization::ZcashSerialize};
use crate::{ use crate::{
constants::{ constants::{
MAX_FIND_BLOCK_HASHES_RESULTS, MAX_FIND_BLOCK_HEADERS_RESULTS_FOR_ZEBRA, MAX_FIND_BLOCK_HASHES_RESULTS, MAX_FIND_BLOCK_HEADERS_RESULTS_FOR_ZEBRA,
@ -1905,6 +1908,46 @@ impl Service<ReadRequest> for ReadStateService {
}) })
.wait_for_panics() .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()
}
} }
} }
} }