feat(util): add a `zebra-tip-height` utility (#4289)
* Move `init_tracing` to `lib.rs` Allow it to be reused by other binaries. * Fix `hex` dependency inclusion in `zebra-chain` It would previously fail because `hex` was being included without the `serde` feature, even though we required that for `transparent::Script`. * Implement `FromStr` for `Network` Make it easy to receive it as a command-line parameter. * Add `zebra-tip-height` utility Obtains the chain tip height of a directory containing Zebra state. * Remove Tokio dependency from `zebra-utils` It wasn't actually used by the `zebra-tip-height` utility. * Remove `BoxStateService` type alias It's not needed if we don't return the unused state service. This also allows removing the `tower` dependency. * Remove unnecessary attribute Leftover from copied code. * Make `cache_dir` argument optional Fallback to the default Zebra state cache directory. * Remove added newline Minor formatting fix, to avoid adding an unnecessary newline. * Move `tip-height` command into `zebrad` Make it available as a sub-command in `zebrad`. * Make some zebrad sub-commands only log warnings Co-authored-by: teor <teor@riseup.net>
This commit is contained in:
parent
f3f26ff85f
commit
9538ad29e5
|
@ -9,7 +9,7 @@ edition = "2021"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
proptest-impl = ["proptest", "proptest-derive", "zebra-test", "rand", "rand_chacha", "tokio", "hex/serde"]
|
proptest-impl = ["proptest", "proptest-derive", "zebra-test", "rand", "rand_chacha", "tokio"]
|
||||||
bench = ["zebra-test"]
|
bench = ["zebra-test"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
@ -29,7 +29,7 @@ fpe = "0.5.1"
|
||||||
futures = "0.3.21"
|
futures = "0.3.21"
|
||||||
group = "0.11.0"
|
group = "0.11.0"
|
||||||
halo2 = { package = "halo2_proofs", version = "=0.1.0-beta.4" }
|
halo2 = { package = "halo2_proofs", version = "=0.1.0-beta.4" }
|
||||||
hex = "0.4.3"
|
hex = { version = "0.4.3", features = ["serde"] }
|
||||||
incrementalmerkletree = "0.3.0-beta.2"
|
incrementalmerkletree = "0.3.0-beta.2"
|
||||||
itertools = "0.10.3"
|
itertools = "0.10.3"
|
||||||
jubjub = "0.8.0"
|
jubjub = "0.8.0"
|
||||||
|
@ -77,8 +77,6 @@ itertools = "0.10.3"
|
||||||
spandoc = "0.2.2"
|
spandoc = "0.2.2"
|
||||||
tracing = "0.1.31"
|
tracing = "0.1.31"
|
||||||
|
|
||||||
hex = { version = "0.4.3", features = ["serde"] }
|
|
||||||
|
|
||||||
proptest = "0.10.1"
|
proptest = "0.10.1"
|
||||||
proptest-derive = "0.3.0"
|
proptest-derive = "0.3.0"
|
||||||
rand = { version = "0.8.5", package = "rand" }
|
rand = { version = "0.8.5", package = "rand" }
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
use std::{convert::From, fmt};
|
use std::{convert::From, fmt, str::FromStr};
|
||||||
|
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::{block::Height, parameters::NetworkUpgrade::Canopy};
|
use crate::{block::Height, parameters::NetworkUpgrade::Canopy};
|
||||||
|
|
||||||
|
@ -117,3 +119,19 @@ impl Default for Network {
|
||||||
Network::Mainnet
|
Network::Mainnet
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl FromStr for Network {
|
||||||
|
type Err = InvalidNetworkError;
|
||||||
|
|
||||||
|
fn from_str(string: &str) -> Result<Self, Self::Err> {
|
||||||
|
match string.to_lowercase().as_str() {
|
||||||
|
"mainnet" => Ok(Network::Mainnet),
|
||||||
|
"testnet" => Ok(Network::Testnet),
|
||||||
|
_ => Err(InvalidNetworkError(string.to_owned())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Error)]
|
||||||
|
#[error("Invalid network: {0}")]
|
||||||
|
pub struct InvalidNetworkError(String);
|
||||||
|
|
|
@ -12,22 +12,15 @@ use color_eyre::eyre::{ensure, Result};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use std::process::Stdio;
|
use std::process::Stdio;
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
|
||||||
|
|
||||||
use zebra_chain::block;
|
use zebra_chain::block;
|
||||||
|
use zebra_utils::init_tracing;
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use std::os::unix::process::ExitStatusExt;
|
use std::os::unix::process::ExitStatusExt;
|
||||||
|
|
||||||
mod args;
|
mod args;
|
||||||
|
|
||||||
/// Initialise tracing using its defaults.
|
|
||||||
fn init_tracing() {
|
|
||||||
tracing_subscriber::Registry::default()
|
|
||||||
.with(tracing_error::ErrorLayer::default())
|
|
||||||
.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return a new `zcash-cli` command, including the `zebra-checkpoints`
|
/// Return a new `zcash-cli` command, including the `zebra-checkpoints`
|
||||||
/// passthrough arguments.
|
/// passthrough arguments.
|
||||||
fn passthrough_cmd() -> std::process::Command {
|
fn passthrough_cmd() -> std::process::Command {
|
||||||
|
|
|
@ -4,3 +4,12 @@
|
||||||
#![doc(html_favicon_url = "https://zfnd.org/wp-content/uploads/2022/03/zebra-favicon-128.png")]
|
#![doc(html_favicon_url = "https://zfnd.org/wp-content/uploads/2022/03/zebra-favicon-128.png")]
|
||||||
#![doc(html_logo_url = "https://zfnd.org/wp-content/uploads/2022/03/zebra-icon.png")]
|
#![doc(html_logo_url = "https://zfnd.org/wp-content/uploads/2022/03/zebra-icon.png")]
|
||||||
#![doc(html_root_url = "https://doc.zebra.zfnd.org/zebra_utils")]
|
#![doc(html_root_url = "https://doc.zebra.zfnd.org/zebra_utils")]
|
||||||
|
|
||||||
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||||
|
|
||||||
|
/// Initialise tracing using its defaults.
|
||||||
|
pub fn init_tracing() {
|
||||||
|
tracing_subscriber::Registry::default()
|
||||||
|
.with(tracing_error::ErrorLayer::default())
|
||||||
|
.init();
|
||||||
|
}
|
||||||
|
|
|
@ -342,14 +342,18 @@ impl Application for ZebradApp {
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.expect("config is loaded before register_components");
|
.expect("config is loaded before register_components");
|
||||||
|
|
||||||
let default_filter = if command.verbose { "debug" } else { "info" };
|
let default_filter = command
|
||||||
|
.command
|
||||||
|
.as_ref()
|
||||||
|
.map(|zcmd| zcmd.default_tracing_filter(command.verbose))
|
||||||
|
.unwrap_or("warn");
|
||||||
let is_server = command
|
let is_server = command
|
||||||
.command
|
.command
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(ZebradCmd::is_server)
|
.map(ZebradCmd::is_server)
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
|
|
||||||
// Ignore the tracing filter for short-lived commands
|
// Ignore the configured tracing filter for short-lived utility commands
|
||||||
let mut tracing_config = cfg_ref.tracing.clone();
|
let mut tracing_config = cfg_ref.tracing.clone();
|
||||||
if is_server {
|
if is_server {
|
||||||
// Override the default tracing filter based on the command-line verbosity.
|
// Override the default tracing filter based on the command-line verbosity.
|
||||||
|
|
|
@ -4,12 +4,13 @@ mod copy_state;
|
||||||
mod download;
|
mod download;
|
||||||
mod generate;
|
mod generate;
|
||||||
mod start;
|
mod start;
|
||||||
|
mod tip_height;
|
||||||
mod version;
|
mod version;
|
||||||
|
|
||||||
use self::ZebradCmd::*;
|
use self::ZebradCmd::*;
|
||||||
use self::{
|
use self::{
|
||||||
copy_state::CopyStateCmd, download::DownloadCmd, generate::GenerateCmd, start::StartCmd,
|
copy_state::CopyStateCmd, download::DownloadCmd, generate::GenerateCmd, start::StartCmd,
|
||||||
version::VersionCmd,
|
tip_height::TipHeightCmd, version::VersionCmd,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::config::ZebradConfig;
|
use crate::config::ZebradConfig;
|
||||||
|
@ -46,6 +47,10 @@ pub enum ZebradCmd {
|
||||||
#[options(help = "start the application")]
|
#[options(help = "start the application")]
|
||||||
Start(StartCmd),
|
Start(StartCmd),
|
||||||
|
|
||||||
|
/// The `tip-height` subcommand
|
||||||
|
#[options(help = "get the block height of Zebra's persisted chain state")]
|
||||||
|
TipHeight(TipHeightCmd),
|
||||||
|
|
||||||
/// The `version` subcommand
|
/// The `version` subcommand
|
||||||
#[options(help = "display version information")]
|
#[options(help = "display version information")]
|
||||||
Version(VersionCmd),
|
Version(VersionCmd),
|
||||||
|
@ -54,12 +59,41 @@ pub enum ZebradCmd {
|
||||||
impl ZebradCmd {
|
impl ZebradCmd {
|
||||||
/// Returns true if this command is a server command.
|
/// Returns true if this command is a server command.
|
||||||
///
|
///
|
||||||
|
/// Servers load extra components, and use the configured tracing filter.
|
||||||
|
///
|
||||||
/// For example, `Start` acts as a Zcash node.
|
/// For example, `Start` acts as a Zcash node.
|
||||||
pub(crate) fn is_server(&self) -> bool {
|
pub(crate) fn is_server(&self) -> bool {
|
||||||
match self {
|
|
||||||
// List all the commands, so new commands have to make a choice here
|
// List all the commands, so new commands have to make a choice here
|
||||||
|
match self {
|
||||||
|
// Commands that run as a configured server
|
||||||
CopyState(_) | Start(_) => true,
|
CopyState(_) | Start(_) => true,
|
||||||
Download(_) | Generate(_) | Help(_) | Version(_) => false,
|
|
||||||
|
// Utility commands that don't use server components
|
||||||
|
Download(_) | Generate(_) | Help(_) | TipHeight(_) | Version(_) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the default log level for this command, based on the `verbose` command line flag.
|
||||||
|
///
|
||||||
|
/// Some commands need to be quiet by default.
|
||||||
|
pub(crate) fn default_tracing_filter(&self, verbose: bool) -> &'static str {
|
||||||
|
let only_show_warnings = match self {
|
||||||
|
// Commands that generate quiet output by default.
|
||||||
|
// This output:
|
||||||
|
// - is used by automated tools, or
|
||||||
|
// - needs to be read easily.
|
||||||
|
Generate(_) | TipHeight(_) | Help(_) | Version(_) => true,
|
||||||
|
|
||||||
|
// Commands that generate informative logging output by default.
|
||||||
|
CopyState(_) | Download(_) | Start(_) => false,
|
||||||
|
};
|
||||||
|
|
||||||
|
if only_show_warnings && !verbose {
|
||||||
|
"warn"
|
||||||
|
} else if only_show_warnings || !verbose {
|
||||||
|
"info"
|
||||||
|
} else {
|
||||||
|
"debug"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,6 +106,7 @@ impl Runnable for ZebradCmd {
|
||||||
Generate(cmd) => cmd.run(),
|
Generate(cmd) => cmd.run(),
|
||||||
ZebradCmd::Help(cmd) => cmd.run(),
|
ZebradCmd::Help(cmd) => cmd.run(),
|
||||||
Start(cmd) => cmd.run(),
|
Start(cmd) => cmd.run(),
|
||||||
|
TipHeight(cmd) => cmd.run(),
|
||||||
Version(cmd) => cmd.run(),
|
Version(cmd) => cmd.run(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
//! `tip-height` subcommand - prints the block height of Zebra's persisted chain state.
|
||||||
|
//!
|
||||||
|
//! Prints the chain tip height stored in Zebra's state. This is useful for developers to inspect
|
||||||
|
//! Zebra state directories.
|
||||||
|
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use abscissa_core::{Command, Options, Runnable};
|
||||||
|
use color_eyre::eyre::{eyre, Result};
|
||||||
|
|
||||||
|
use zebra_chain::{block, chain_tip::ChainTip, parameters::Network};
|
||||||
|
use zebra_state::LatestChainTip;
|
||||||
|
|
||||||
|
use crate::prelude::app_config;
|
||||||
|
|
||||||
|
/// `zebra-tip-height` subcommand
|
||||||
|
#[derive(Command, Debug, Options)]
|
||||||
|
pub struct TipHeightCmd {
|
||||||
|
/// Path to Zebra's cached state.
|
||||||
|
#[options(help = "path to directory with the Zebra chain state")]
|
||||||
|
cache_dir: Option<PathBuf>,
|
||||||
|
|
||||||
|
/// The network to obtain the chain tip.
|
||||||
|
#[options(default = "mainnet", help = "the network of the chain to load")]
|
||||||
|
network: Network,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Runnable for TipHeightCmd {
|
||||||
|
/// `tip-height` sub-command entrypoint.
|
||||||
|
///
|
||||||
|
/// Reads the chain tip height from a cache directory with Zebra's state.
|
||||||
|
#[allow(clippy::print_stdout)]
|
||||||
|
fn run(&self) {
|
||||||
|
match self.load_tip_height() {
|
||||||
|
Ok(height) => println!("{}", height.0),
|
||||||
|
Err(error) => tracing::error!("Failed to read chain tip height from state: {error}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TipHeightCmd {
|
||||||
|
/// Load the chain tip height from the state cache directory.
|
||||||
|
fn load_tip_height(&self) -> Result<block::Height> {
|
||||||
|
let latest_chain_tip = self.load_latest_chain_tip();
|
||||||
|
|
||||||
|
latest_chain_tip
|
||||||
|
.best_tip_height()
|
||||||
|
.ok_or_else(|| eyre!("State directory doesn't have a chain tip block"))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Starts a state service using the `cache_dir` and `network` from the provided arguments.
|
||||||
|
fn load_latest_chain_tip(&self) -> LatestChainTip {
|
||||||
|
let mut config = app_config().state.clone();
|
||||||
|
|
||||||
|
if let Some(cache_dir) = self.cache_dir.clone() {
|
||||||
|
config.cache_dir = cache_dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
let (_state_service, _read_state_service, latest_chain_tip, _chain_tip_change) =
|
||||||
|
zebra_state::init(config, self.network);
|
||||||
|
|
||||||
|
latest_chain_tip
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue