diff --git a/toolkit/cli/commands/src/address_association_signatures.rs b/toolkit/cli/commands/src/address_association_signatures.rs index 25225554e9..64fc4f059e 100644 --- a/toolkit/cli/commands/src/address_association_signatures.rs +++ b/toolkit/cli/commands/src/address_association_signatures.rs @@ -9,22 +9,25 @@ use serde_json::json; use sidechain_domain::*; use std::str::FromStr; +/// Generates Ed25519 signatures to associate Cardano stake addresses with Partner Chain addresses. +/// Generic over address type to support different Partner Chain implementations. #[derive(Clone, Debug, Parser)] #[command(author, version, about, long_about = None)] pub struct AddressAssociationSignaturesCmd< PartnerchainAddress: Clone + Sync + Send + FromStr + 'static, > { - /// Genesis UTXO of the target Partner Chain + /// Genesis UTXO that identifies the target Partner Chain #[arg(long)] pub genesis_utxo: UtxoId, - /// Partner Chain address to be associated with the Cardano address + /// Partner Chain address to be associated with the Cardano stake address #[arg(long, value_parser=parse_pc_address::)] pub partnerchain_address: PartnerchainAddress, - /// Cardano Stake Signing Key bytes in hex format. Its public key will be associated with partnerchain_address. + /// Ed25519 signing key for the Cardano stake address. Its public key will be associated with partnerchain_address. #[arg(long)] pub signing_key: StakeSigningKeyParam, } +/// Parses Partner Chain address from string format. fn parse_pc_address(s: &str) -> Result { T::from_str(s).map_err(|_| "Failed to parse Partner Chain address".to_owned()) } @@ -33,6 +36,7 @@ impl AddressAssociationSignaturesCmd where PartnerchainAddress: Serialize + Clone + Sync + Send + FromStr + Encode + 'static, { + /// Generates signature and outputs JSON to stdout. pub fn execute(&self) -> anyhow::Result<()> { let signature = self.sign(); let output = json!({ @@ -45,6 +49,7 @@ where Ok(()) } + /// Signs SCALE-encoded address association message with Ed25519. fn sign(&self) -> ByteString { let msg = AddressAssociationSignedMessage { stake_public_key: self.signing_key.vkey(), diff --git a/toolkit/cli/commands/src/block_producer_metadata_signatures.rs b/toolkit/cli/commands/src/block_producer_metadata_signatures.rs index f60fe2d418..5130a82487 100644 --- a/toolkit/cli/commands/src/block_producer_metadata_signatures.rs +++ b/toolkit/cli/commands/src/block_producer_metadata_signatures.rs @@ -9,21 +9,23 @@ use sidechain_domain::*; use sp_block_producer_metadata::MetadataSignedMessage; use std::io::{BufReader, Read}; +/// Generates ECDSA signatures for block producer metadata using cross-chain keys. #[derive(Clone, Debug, Parser)] #[command(author, version, about, long_about = None)] pub struct BlockProducerMetadataSignatureCmd { - /// Genesis UTXO of the target Partner Chain + /// Genesis UTXO that uniquely identifies the target Partner Chain #[arg(long)] pub genesis_utxo: UtxoId, - /// Path of the file containing the metadata in JSON format + /// Path to JSON file containing the metadata to be signed #[arg(long)] pub metadata_file: String, - /// ECDSA signing key of the block producer, corresponding to the public key that will be associated with new metadata + /// ECDSA private key for cross-chain operations, corresponding to the block producer's identity #[arg(long)] pub cross_chain_signing_key: CrossChainSigningKeyParam, } impl BlockProducerMetadataSignatureCmd { + /// Reads metadata file, generates signatures, and outputs JSON to stdout. pub fn execute(&self) -> anyhow::Result<()> { let file = std::fs::File::open(self.metadata_file.clone()) .map_err(|err| anyhow!("Failed to open file {}: {err}", self.metadata_file))?; @@ -35,6 +37,7 @@ impl BlockProducerMetadataSignatureCmd { Ok(()) } + /// Generates ECDSA signatures for JSON metadata from reader. pub fn get_output( &self, metadata_reader: impl Read, diff --git a/toolkit/cli/commands/src/get_genesis_utxo.rs b/toolkit/cli/commands/src/get_genesis_utxo.rs index b3ec68fcf3..d9724d0b65 100644 --- a/toolkit/cli/commands/src/get_genesis_utxo.rs +++ b/toolkit/cli/commands/src/get_genesis_utxo.rs @@ -5,8 +5,7 @@ use sp_runtime::traits::Block as BlockT; use sp_sidechain::GetGenesisUtxo; use std::sync::Arc; -/// Retrieves the genesis UTXO from the on-chain storage. -/// This function should be used by a CLI command. +/// Queries the genesis UTXO from Partner Chain storage via runtime API. pub async fn execute(client: Arc) -> Result where B: BlockT, @@ -22,7 +21,9 @@ where Ok(output) } +/// Output structure for genesis UTXO query results. #[derive(serde::Serialize, serde::Deserialize, Clone, PartialEq, Debug)] struct Output { + /// The genesis UTXO that uniquely identifies this Partner Chain instance pub genesis_utxo: UtxoId, } diff --git a/toolkit/cli/commands/src/key_params.rs b/toolkit/cli/commands/src/key_params.rs index d1c97451bf..0e8179ba4f 100644 --- a/toolkit/cli/commands/src/key_params.rs +++ b/toolkit/cli/commands/src/key_params.rs @@ -1,3 +1,5 @@ +//! CLI parameter wrappers for cryptographic keys with secure parsing and validation. + use sidechain_domain::*; use std::convert::Infallible; use std::fmt::Display; @@ -5,10 +7,12 @@ use std::io; use std::io::ErrorKind; use std::str::FromStr; +/// ECDSA private key wrapper for Partner Chain validator operations. #[derive(Clone, Debug)] pub struct SidechainSigningKeyParam(pub secp256k1::SecretKey); impl SidechainSigningKeyParam { + /// Derives the corresponding ECDSA public key. pub fn to_pub_key(&self) -> secp256k1::PublicKey { secp256k1::PublicKey::from_secret_key_global(&self.0) } @@ -24,6 +28,7 @@ impl FromStr for SidechainSigningKeyParam { } } +/// ECDSA public key wrapper for Partner Chain operations. #[derive(Clone, Debug)] pub struct SidechainPublicKeyParam(pub SidechainPublicKey); @@ -43,6 +48,7 @@ impl FromStr for SidechainPublicKeyParam { } } +/// Generic string wrapper for public keys without cryptographic validation. #[derive(Clone, Debug)] pub struct PlainPublicKeyParam(pub String); @@ -60,10 +66,13 @@ impl FromStr for PlainPublicKeyParam { } } +/// Error types that can occur during Ed25519 signing key parsing. #[derive(Debug, thiserror::Error)] pub enum Ed25519SigningKeyError { + /// Hexadecimal decoding error #[error("{0}")] HexError(#[from] hex::FromHexError), + /// Ed25519 key validation error #[error("{0}")] Ed25519Error(#[from] ed25519_zebra::Error), } @@ -74,6 +83,7 @@ impl From for io::Error { } } +/// Parses hex string into Ed25519 signing key with validation. pub(crate) fn parse_zebra_signing_key( s: &str, ) -> Result { @@ -81,6 +91,7 @@ pub(crate) fn parse_zebra_signing_key( Ok(ed25519_zebra::SigningKey::try_from(hex::decode(trimmed)?.as_slice())?) } +/// Ed25519 private key wrapper for Cardano stake pool operations. #[derive(Clone, Debug)] pub struct StakePoolSigningKeyParam(pub ed25519_zebra::SigningKey); @@ -93,17 +104,20 @@ impl FromStr for StakePoolSigningKeyParam { } impl From<[u8; 32]> for StakePoolSigningKeyParam { + /// Creates signing key from 32-byte array. fn from(key: [u8; 32]) -> Self { Self(ed25519_zebra::SigningKey::from(key)) } } impl StakePoolSigningKeyParam { + /// Derives the corresponding public key. pub fn vkey(&self) -> StakePoolPublicKey { StakePoolPublicKey(ed25519_zebra::VerificationKey::from(&self.0).into()) } } +/// Ed25519 private key wrapper for Cardano staking operations. #[derive(Clone, Debug)] pub struct StakeSigningKeyParam(pub ed25519_zebra::SigningKey); @@ -116,11 +130,13 @@ impl FromStr for StakeSigningKeyParam { } impl StakeSigningKeyParam { + /// Derives the corresponding public key. pub fn vkey(&self) -> StakePublicKey { StakePublicKey(ed25519_zebra::VerificationKey::from(&self.0).into()) } } +/// ECDSA private key wrapper for cross-chain operations. #[derive(Clone, Debug)] pub struct CrossChainSigningKeyParam(pub k256::SecretKey); @@ -133,6 +149,7 @@ impl FromStr for CrossChainSigningKeyParam { } impl CrossChainSigningKeyParam { + /// Derives the corresponding ECDSA public key. pub fn vkey(&self) -> CrossChainPublicKey { CrossChainPublicKey(self.0.public_key().to_sec1_bytes().to_vec()) } diff --git a/toolkit/cli/commands/src/lib.rs b/toolkit/cli/commands/src/lib.rs index 9354b936b5..7278f024e7 100644 --- a/toolkit/cli/commands/src/lib.rs +++ b/toolkit/cli/commands/src/lib.rs @@ -1,3 +1,8 @@ +//! CLI command structures for Partner Chains cryptographic operations. +//! +//! Provides clap-based commands for signature generation, address association, +//! and blockchain queries. Used by `partner-chains-node-commands`. + pub mod address_association_signatures; pub mod block_producer_metadata_signatures; pub mod get_genesis_utxo; diff --git a/toolkit/cli/commands/src/registration_signatures.rs b/toolkit/cli/commands/src/registration_signatures.rs index 52062d7b74..20e99ceee3 100644 --- a/toolkit/cli/commands/src/registration_signatures.rs +++ b/toolkit/cli/commands/src/registration_signatures.rs @@ -10,21 +10,26 @@ use sidechain_domain::{ }; use std::fmt::{Display, Formatter}; +/// Generates dual signatures (Ed25519 + ECDSA) for Partner Chain validator registration. #[derive(Clone, Debug, Parser)] #[command(author, version, about, long_about = None)] pub struct RegistrationSignaturesCmd { + /// Genesis UTXO that uniquely identifies the target Partner Chain #[arg(long)] pub genesis_utxo: UtxoId, /// Bytes of the Cardano Stake Pool Signing Key. Bytes of 'cbor' field of a Cardano key file content, after dropping the '5820' prefix. #[arg(long)] pub mainchain_signing_key: StakePoolSigningKeyParam, + /// ECDSA private key for the Partner Chain validator #[arg(long)] pub sidechain_signing_key: SidechainSigningKeyParam, + /// UTXO to be spend during validator registration transaction #[arg(long)] pub registration_utxo: UtxoId, } impl RegistrationSignaturesCmd { + /// Creates the structured message that will be signed by both mainchain and sidechain keys. pub fn to_register_validator_message(&self, genesis_utxo: UtxoId) -> RegisterValidatorMessage { RegisterValidatorMessage::new( genesis_utxo, @@ -33,6 +38,7 @@ impl RegistrationSignaturesCmd { ) } + /// Generates mainchain and sidechain signatures with public keys. pub fn execute(&self) -> RegistrationCmdOutput { self.to_register_validator_message(self.genesis_utxo) .sign_and_prepare_registration_cmd_output( @@ -42,11 +48,16 @@ impl RegistrationSignaturesCmd { } } +/// Complete registration output with signatures and public keys for both chains. #[derive(Clone, Debug, Serialize)] pub struct RegistrationCmdOutput { + /// Ed25519 public key of the Cardano stake pool operator pub spo_public_key: StakePoolPublicKey, + /// Ed25519 signature from the stake pool operator pub spo_signature: MainchainSignature, + /// ECDSA public key for Partner Chain operations pub sidechain_public_key: SidechainPublicKey, + /// ECDSA signature from the Partner Chain validator key pub sidechain_signature: SidechainSignature, } @@ -59,14 +70,19 @@ impl Display for RegistrationCmdOutput { } } +/// Message structure for validator registration signatures. #[derive(Clone, Debug, ToDatum)] pub struct RegisterValidatorMessage { + /// Genesis UTXO identifying the specific Partner Chain instance pub genesis_utxo: UtxoId, + /// ECDSA public key for the validator on the Partner Chain pub sidechain_pub_key: SidechainPublicKey, + /// UTXO consumed in the registration transaction for uniqueness pub registration_utxo: UtxoId, } impl RegisterValidatorMessage { + /// Creates new validator registration message. pub fn new( genesis_utxo: UtxoId, pub_key: secp256k1::PublicKey, @@ -79,6 +95,7 @@ impl RegisterValidatorMessage { } } + /// Signs message with both mainchain and sidechain keys. pub fn sign_and_prepare_registration_cmd_output( &self, mainchain_key: ed25519_zebra::SigningKey,