nym_cli_commands/validator/mixnet/operators/identity_key/
mod.rs

1use clap::{Args, Parser, Subcommand};
2use nym_bin_common::output_format::OutputFormat;
3use nym_crypto::asymmetric::ed25519;
4use nym_types::helpers::ConsoleSigningOutput;
5use nym_validator_client::nyxd::error::NyxdError;
6use std::path::PathBuf;
7
8#[derive(Debug, Args)]
9#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)]
10pub struct MixnetOperatorsIdentityKey {
11    #[clap(subcommand)]
12    pub command: MixnetOperatorsIdentityKeyCommands,
13}
14
15#[derive(Debug, Subcommand)]
16pub enum MixnetOperatorsIdentityKeyCommands {
17    /// Register a name alias for a nym address
18    Sign(SignArgs),
19}
20
21#[derive(Debug, Parser)]
22pub struct SignArgs {
23    /// Path to private identity key (example: private_identity_key.pem)
24    #[clap(long)]
25    private_key: PathBuf,
26
27    /// Base58 encoded message to sign
28    #[clap(long)]
29    base58_msg: String,
30
31    #[clap(short, long, default_value_t = OutputFormat::default())]
32    output: OutputFormat,
33}
34
35pub async fn sign(args: SignArgs) -> Result<(), NyxdError> {
36    eprintln!(">>> loading: {}", args.private_key.display());
37    let private_identity_key: ed25519::PrivateKey =
38        nym_pemstore::load_key(args.private_key).expect("failed to load key");
39
40    print_signed_msg(&private_identity_key, &args.base58_msg, args.output);
41    Ok(())
42}
43
44fn print_signed_msg(private_key: &ed25519::PrivateKey, raw_msg: &str, output: OutputFormat) {
45    let trimmed = raw_msg.trim();
46    eprintln!(">>> attempting to sign: {trimmed}");
47
48    let Ok(decoded) = bs58::decode(trimmed).into_vec() else {
49        println!("failed to base58 decode the message, did you copy it correctly?");
50        return;
51    };
52
53    eprintln!(">>> decoding the message...");
54
55    // we don't really care about what particular information is embedded inside of it,
56    // we just want to know if user correctly copied the string, i.e. whether it's a valid bs58 encoded json
57    if serde_json::from_slice::<serde_json::Value>(&decoded).is_err() {
58        println!("failed to parse the message after decoding, did you copy it correctly?");
59        return;
60    };
61
62    // if this is a valid json, it MUST be a valid string
63    let decoded_string = String::from_utf8(decoded.clone()).unwrap();
64    let signature = private_key.sign(&decoded).to_base58_string();
65
66    let sign_output = ConsoleSigningOutput::new(decoded_string, signature);
67    println!("{}", output.format(&sign_output));
68}