feature(rpc): add real data to `getinfo` method (#3660)

* feature(rpc): add getinfo subversion field and getinfo docs

* feature(rpc): add getinfo build field

* refactor(rpc): replace the lazy_static

* docs(rpc): fic typo, add link to zcashd ticket

* tests(rpc): add getinfo unit test

* docs(rpc): complete comment
This commit is contained in:
Alfredo Garcia 2022-03-01 00:32:32 -03:00 committed by GitHub
parent a8a52125d0
commit b3eb38d279
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 71 additions and 11 deletions

2
Cargo.lock generated
View File

@ -5708,6 +5708,8 @@ dependencies = [
"tokio",
"tracing",
"tracing-futures",
"zebra-network",
"zebra-test",
]
[[package]]

View File

@ -9,6 +9,8 @@ edition = "2021"
[dependencies]
zebra-network = { path = "../zebra-network" }
futures = "0.3"
# lightwalletd sends JSON-RPC requests over HTTP 1.1
@ -24,3 +26,7 @@ tracing = "0.1"
tracing-futures = "0.2"
serde = { version = "1", features = ["serde_derive"] }
[dev-dependencies]
zebra-test = { path = "../zebra-test/" }

View File

@ -9,15 +9,34 @@
use jsonrpc_core::{self, Result};
use jsonrpc_derive::rpc;
use zebra_network::constants::USER_AGENT;
#[cfg(test)]
mod tests;
#[rpc(server)]
/// RPC method signatures.
pub trait Rpc {
/// getinfo
///
/// TODO: explain what the method does
/// link to the zcashd RPC reference
/// list the arguments and fields that lightwalletd uses
/// note any other lightwalletd changes
/// Returns software information from the RPC server running Zebra.
///
/// zcashd reference: <https://zcash.github.io/rpc/getinfo.html>
///
/// Result:
/// {
/// "build": String, // Full application version
/// "subversion", String, // Zebra user agent
/// }
///
/// Note 1: We only expose 2 fields as they are the only ones needed for
/// lightwalletd: <https://github.com/zcash/lightwalletd/blob/v0.4.9/common/common.go#L91-L95>
///
/// Note 2: <https://zcash.github.io/rpc/getinfo.html> is outdated so it does not
/// show the fields we are exposing. However, this fields are part of the output
/// as shown in the following zcashd code:
/// <https://github.com/zcash/zcash/blob/v4.6.0-1/src/rpc/misc.cpp#L86-L87>
/// Zcash open ticket to add this fields to the docs: <https://github.com/zcash/zcash/issues/5606>
#[rpc(name = "getinfo")]
fn get_info(&self) -> Result<GetInfo>;
@ -32,13 +51,16 @@ pub trait Rpc {
}
/// RPC method implementations.
pub struct RpcImpl;
pub struct RpcImpl {
/// Zebra's application version.
pub app_version: String,
}
impl Rpc for RpcImpl {
fn get_info(&self) -> Result<GetInfo> {
// TODO: dummy output data, fix in the context of #3142
let response = GetInfo {
build: "TODO: Zebra v1.0.0 ...".into(),
subversion: "TODO: /Zebra:1.0.0-beta.../".into(),
build: self.app_version.clone(),
subversion: USER_AGENT.into(),
};
Ok(response)

View File

@ -0,0 +1,2 @@
//! Test code for RPC methods
mod vectors;

View File

@ -0,0 +1,23 @@
//! Fixed test vectors for RPC methods.
use super::super::*;
use zebra_network::constants::USER_AGENT;
#[test]
fn rpc_getinfo() {
zebra_test::init();
let rpc = RpcImpl {
app_version: "Zebra version test".to_string(),
};
let get_info = rpc.get_info().expect("We should have a GetInfo struct");
// make sure there is a `build` field in the response,
// and that is equal to the provided string.
assert_eq!(get_info.build, "Zebra version test");
// make sure there is a `subversion` field,
// and that is equal to the Zebra user agent.
assert_eq!(get_info.subversion, USER_AGENT);
}

View File

@ -24,14 +24,17 @@ pub struct RpcServer;
impl RpcServer {
/// Start a new RPC server endpoint
pub fn spawn(config: Config) -> tokio::task::JoinHandle<()> {
pub fn spawn(config: Config, app_version: String) -> tokio::task::JoinHandle<()> {
if let Some(listen_addr) = config.listen_addr {
info!("Trying to open RPC endpoint at {}...", listen_addr,);
// Initialize the rpc methods with the zebra version
let rpc_impl = RpcImpl { app_version };
// Create handler compatible with V1 and V2 RPC protocols
let mut io =
jsonrpc_core::IoHandler::with_compatibility(jsonrpc_core::Compatibility::Both);
io.extend_with(RpcImpl.to_delegate());
io.extend_with(rpc_impl.to_delegate());
let server = ServerBuilder::new(io)
// use the same tokio executor as the rest of Zebra
@ -54,6 +57,7 @@ impl RpcServer {
info!("Stopping RPC endpoint");
})
};
tokio::task::spawn_blocking(server)
} else {
// There is no RPC port, so the RPC task does nothing.

View File

@ -75,6 +75,7 @@ use zebra_consensus::CheckpointList;
use zebra_rpc::server::RpcServer;
use crate::{
application::app_version,
components::{
inbound::{self, InboundSetupData},
mempool::{self, Mempool},
@ -196,7 +197,7 @@ impl StartCmd {
.in_current_span(),
);
let rpc_task_handle = RpcServer::spawn(config.rpc);
let rpc_task_handle = RpcServer::spawn(config.rpc, app_version().to_string());
info!("spawned initial Zebra tasks");