use anyhow::{Error, anyhow};
use async_trait::async_trait;
use clap::Parser;
use tari_common_types::epoch::VnEpoch;
use tari_core::chain_storage::ValidatorNodeRegistrationInfo;
use tari_utilities::hex::{Hex, to_hex};
use super::{CommandContext, HandleCommand};
use crate::table::Table;
#[derive(Debug, Parser)]
pub struct Args {
epoch: Option<VnEpoch>,
}
#[async_trait]
impl HandleCommand<Args> for CommandContext {
async fn handle_command(&mut self, args: Args) -> Result<(), Error> {
self.list_validator_nodes(args).await
}
}
impl CommandContext {
async fn print_validator_nodes_list(&mut self, vns: &[ValidatorNodeRegistrationInfo]) {
let num_vns = vns.len();
let mut table = Table::new();
table.set_titles(vec!["Public Key", "VN Network", "Shard ID"]);
for ValidatorNodeRegistrationInfo {
public_key,
sidechain_id: validator_network,
shard_key,
..
} in vns
{
table.add_row(row![
public_key,
validator_network
.as_ref()
.map(|v| v.to_hex())
.unwrap_or_else(|| "<default>".to_string()),
to_hex(shard_key),
]);
}
table.print_stdout();
println!();
println!("{num_vns} active validator(s)");
}
}
impl CommandContext {
pub async fn list_validator_nodes(&mut self, args: Args) -> Result<(), Error> {
let metadata = self.blockchain_db.get_chain_metadata().await?;
let constants = self.consensus_rules.consensus_constants(metadata.best_block_height());
let height = args
.epoch
.map(|epoch| constants.epoch_to_block_height(epoch))
.unwrap_or_else(|| metadata.best_block_height());
let current_epoch = constants.block_height_to_epoch(height);
let next_epoch = VnEpoch(current_epoch.as_u64() + 1);
let next_epoch_height = constants.epoch_to_block_height(next_epoch);
let header = self
.blockchain_db
.fetch_header(height)
.await?
.ok_or_else(|| anyhow!("Block at height {height} not found"))?;
let vns = self.blockchain_db.fetch_all_active_validator_nodes(height).await?;
let next_vns = self
.blockchain_db
.fetch_all_active_validator_nodes(next_epoch_height)
.await?;
println!();
println!("Registered validator nodes for epoch {}", current_epoch.as_u64());
println!("Merkle root: {}", header.validator_node_mr);
println!("----------------------------------");
if vns.is_empty() {
println!("No active validator nodes.");
} else {
println!();
self.print_validator_nodes_list(&vns).await;
}
println!();
println!("Registered validator nodes for next epoch {}", next_epoch.as_u64());
println!("----------------------------------");
if next_vns.is_empty() {
println!("No active validator nodes.");
} else {
println!();
self.print_validator_nodes_list(&next_vns).await;
}
Ok(())
}
}