Skip to content

[docs] cli node commands #818

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
173 changes: 162 additions & 11 deletions toolkit/cli/node-commands/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,28 @@
//! # Partner Chains Node Commands
//!
//! This crate provides a comprehensive set of command-line interface (CLI) commands for
//! interacting with Partner Chains nodes. It serves as the primary interface for node
//! operators, validators, and developers to manage and interact with Partner Chain infrastructure.
//!
//! ## Architecture
//!
//! The crate is built around the [`PartnerChainsSubcommand`] enum, which defines all available
//! commands. Each command is implemented as a separate struct with its own configuration and
//! execution logic. The main entry point is the [`run`] function, which dispatches commands
//! to their appropriate handlers.
//!
//! ## Usage
//!
//! ```rust,no_run
//! use partner_chains_node_commands::{PartnerChainsSubcommand, run};
//!
//! // In your main CLI handler
//! match cli.subcommand {
//! Some(subcommand) => run(&cli, get_deps, subcommand),
//! None => // handle default case
//! }
//! ```

use authority_selection_inherents::authority_selection_inputs::AuthoritySelectionDataSource;
use authority_selection_inherents::authority_selection_inputs::AuthoritySelectionInputs;
use authority_selection_inherents::filter_invalid_candidates::CandidateValidationApi;
Expand Down Expand Up @@ -30,11 +55,21 @@ use std::future::Future;
use std::str::FromStr;
use std::sync::Arc;

/// Command for retrieving Ariadne protocol parameters effective at a specific mainchain epoch.
///
/// Ariadne controls committee selection for Partner Chain consensus.
///
/// # Example
///
/// ```bash
/// partner-chains-node ariadne-parameters --mc-epoch-number 586
/// ```
#[derive(Debug, Clone, Parser)]
pub struct AriadneParametersCmd {
/// The mainchain epoch number for which to retrieve Ariadne parameters
#[arg(long)]
pub mc_epoch_number: McEpochNumber,
#[allow(missing_docs)]
/// Shared CLI parameters for configuration
#[clap(flatten)]
pub shared_params: SharedParams,
}
Expand All @@ -45,9 +80,19 @@ impl CliConfiguration for AriadneParametersCmd {
}
}

/// Command for retrieving sidechain parameters.
///
/// This command returns the sidechain's genesis UTXO, which is the
/// foundational UTXO that identifies the Partner Chain.
///
/// # Example
///
/// ```bash
/// partner-chains-node sidechain-params
/// ```
#[derive(Debug, Clone, Parser)]
pub struct SidechainParamsCmd {
#[allow(missing_docs)]
/// Shared CLI parameters for configuration
#[clap(flatten)]
pub shared_params: SharedParams,
}
Expand All @@ -58,14 +103,36 @@ impl CliConfiguration for SidechainParamsCmd {
}
}

/// Command for checking validator registration status on the Partner Chain.
///
/// This command verifies whether a validator's registration has been successfully
/// processed and is recognized by the Partner Chain. It's essential for validator
/// operators to confirm their registration before attempting to participate in
/// committee selection.
///
/// # Important Notes
///
/// - If registration was included in Cardano block in epoch N, it should be visible
/// when querying epoch N+1 or later
/// - If registration doesn't appear after a few minutes, debugging may be required
/// - The `mainchain-pub-key` alias is provided for backward compatibility
///
/// # Example
///
/// ```bash
/// partner-chains-node registration-status \
/// --stake-pool-pub-key 0x702b81ab2e86cf73a87062af1eb0da666d451976d9d91c63a119ed94e6a33dc0 \
/// --mc-epoch-number 586
/// ```
#[derive(Debug, Clone, Parser)]
pub struct RegistrationStatusCmd {
#[arg(long)]
/// The stake pool public key (mainchain public key) to check registration for
#[arg(long, alias = "mainchain-pub-key")]
pub stake_pool_pub_key: StakePoolPublicKey,
/// The mainchain epoch number to check registration status at
#[arg(long)]
pub mc_epoch_number: McEpochNumber,
#[allow(missing_docs)]
/// Shared CLI parameters for configuration
#[clap(flatten)]
pub shared_params: SharedParams,
}
Expand All @@ -76,13 +143,35 @@ impl CliConfiguration for RegistrationStatusCmd {
}
}

/// Enumeration of all available Partner Chains node commands.
///
/// This enum defines the complete set of commands available for Partner Chain operations.
/// Each variant corresponds to a specific command with its own parameters and functionality.
/// The enum is generic over runtime bindings and address types to support different
/// Partner Chain configurations.
///
/// # Type Parameters
///
/// - `RuntimeBindings`: Partner Chain runtime bindings implementing required traits
/// - `PartnerchainAddress`: Address format specific to the Partner Chain implementation
///
/// # Commands
///
/// - [`SidechainParams`]: Query sidechain parameters
/// - [`RegistrationStatus`]: Check validator registration status
/// - [`AriadneParameters`]: Retrieve Ariadne protocol parameters
/// - [`RegistrationSignatures`]: Generate registration signatures
/// - [`SignAddressAssociation`]: Sign address associations
/// - [`SignBlockProducerMetadata`]: Sign block producer metadata
/// - [`SmartContracts`]: Interact with smart contracts on Cardano
/// - [`Wizards`]: Access interactive setup wizards
#[derive(Clone, Debug, clap::Subcommand)]
#[allow(clippy::large_enum_variant)]
pub enum PartnerChainsSubcommand<
RuntimeBindings: PartnerChainRuntime + PartnerChainRuntimeBindings,
PartnerchainAddress: Clone + Sync + Send + FromStr + 'static,
> {
/// Returns sidechain parameters
/// Returns partner chain genesis UTXO
SidechainParams(SidechainParamsCmd),

/// Returns registration status for a given mainchain public key and epoch number.
Expand All @@ -94,13 +183,12 @@ pub enum PartnerChainsSubcommand<
RegistrationStatus(RegistrationStatusCmd),

/// Returns ariadne parameters effective at given mainchain epoch number.
/// Parameters are effective two epochs after the block their change is included in.
AriadneParameters(AriadneParametersCmd),

/// Generates registration signatures for partner chains committee candidates
RegistrationSignatures(RegistrationSignaturesCmd),

/// Signs address association
/// Signs address association between different chain contexts
SignAddressAssociation(AddressAssociationSignaturesCmd<PartnerchainAddress>),

/// Signs block producer metadata for submitting to the runtime
Expand All @@ -110,11 +198,48 @@ pub enum PartnerChainsSubcommand<
#[command(subcommand)]
SmartContracts(SmartContractsCmd),

/// Partner Chains text "wizards" for setting up chain
/// Partner Chains text "wizards" for setting up chain configuration
#[command(subcommand)]
Wizards(partner_chains_cli::Command<RuntimeBindings>),
}

/// Main command execution function for Partner Chains node commands.
///
/// This function serves as the primary entry point for executing Partner Chain CLI commands.
/// It takes a CLI interface, dependency provider, and a specific command, then dispatches
/// the command to its appropriate handler.
///
/// # Type Parameters
///
/// - `Cli`: The CLI interface implementing [`SubstrateCli`]
/// - `Block`: The blockchain block type implementing [`BlockT`]
/// - `CommitteeMember`: Committee member type for validator management
/// - `Client`: Blockchain client providing runtime API access
/// - `BlockProducerMetadata`: Metadata type for block producer operations
/// - `RuntimeBindings`: Partner Chain runtime bindings
/// - `PartnerchainAddress`: Address format for the specific Partner Chain
///
/// # Arguments
///
/// - `cli`: Reference to the CLI interface
/// - `get_deps`: Closure that provides necessary dependencies (client, task manager, data source)
/// - `cmd`: The specific Partner Chain command to execute
///
/// # Returns
///
/// Returns `sc_cli::Result<()>` indicating success or failure of command execution.
///
/// # Example
///
/// ```rust,no_run
/// use partner_chains_node_commands::{PartnerChainsSubcommand, run};
///
/// let result = run(&cli, get_dependencies, command);
/// match result {
/// Ok(()) => println!("Command executed successfully"),
/// Err(e) => eprintln!("Command failed: {}", e),
/// }
/// ```
#[allow(deprecated)]
pub fn run<
Cli,
Expand Down Expand Up @@ -210,8 +335,7 @@ where
}
}

/// This sets logging to stderr, leaving stdout for smart-contracts JSON outputs.
/// Ogmios interactions are logged to a file.
/// Configures logging to route general logs to stderr and Ogmios logs to a file.
fn setup_log4rs() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let stderr = log4rs::append::console::ConsoleAppender::builder()
.target(log4rs::append::console::Target::Stderr)
Expand All @@ -234,6 +358,32 @@ fn setup_log4rs() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
Ok(())
}

/// Utility function for printing command execution results.
///
/// This function awaits the result of an asynchronous command future and prints
/// the result to stdout. It handles both success and error cases gracefully,
/// ensuring that error messages are displayed to the user.
///
/// # Arguments
///
/// - `command_future`: A future that resolves to either a success string or error string
///
/// # Returns
///
/// Always returns `Ok(())` since errors are printed rather than propagated.
///
/// # Example
///
/// ```rust,no_run
/// use partner_chains_node_commands::print_result;
///
/// async fn example_command() -> Result<String, String> {
/// Ok("Command completed successfully".to_string())
/// }
///
/// let result = print_result(example_command()).await;
/// assert!(result.is_ok());
/// ```
async fn print_result<FIn>(command_future: FIn) -> Result<(), sc_cli::Error>
where
FIn: Future<Output = Result<String, String>>,
Expand All @@ -245,14 +395,15 @@ where

#[cfg(test)]
mod tests {
use super::*;

async fn some_err() -> Result<String, String> {
Err("some err".to_string())
}

#[tokio::test]
async fn print_async_doesnt_fail_if_result_is_error() {
let result = super::print_result(some_err()).await;
let result = print_result(some_err()).await;
assert!(result.is_ok());
}
}
Loading