This commit is contained in:
Jędrzej Stuczyński
2023-02-22 17:18:37 +00:00
parent c904d245d2
commit aa9609ec6d
13 changed files with 309 additions and 37 deletions
+26 -5
View File
@@ -6,7 +6,7 @@ use std::convert::TryFrom;
use crate::commands::validate_bech32_address_or_exit;
use crate::config::{persistence::pathfinder::MixNodePathfinder, Config};
use crate::node::MixNode;
use anyhow::{anyhow, Result};
use anyhow::{bail, Result};
use clap::{ArgGroup, Args};
use log::error;
use nym_config::NymConfig;
@@ -16,7 +16,7 @@ use validator_client::nyxd;
use super::version_check;
#[derive(Args, Clone)]
#[clap(group(ArgGroup::new("sign").required(true).args(&["wallet_address", "text"])))]
#[clap(group(ArgGroup::new("sign").required(true).args(&["wallet_address", "text", "contract_msg"])))]
pub(crate) struct Sign {
/// The id of the mixnode you want to sign with
#[clap(long)]
@@ -30,11 +30,16 @@ pub(crate) struct Sign {
/// Signs an arbitrary piece of text with your identity key
#[clap(long)]
text: Option<String>,
/// Signs a transaction-specific payload, that is going to be sent to the smart contract, with your identity key
#[clap(long)]
contract_msg: Option<String>,
}
enum SignedTarget {
Text(String),
Address(nyxd::AccountId),
ContractMsg(String),
}
impl TryFrom<Sign> for SignedTarget {
@@ -45,11 +50,13 @@ impl TryFrom<Sign> for SignedTarget {
Ok(SignedTarget::Text(text))
} else if let Some(address) = args.wallet_address {
Ok(SignedTarget::Address(address))
} else if let Some(msg) = args.contract_msg {
Ok(SignedTarget::ContractMsg(msg))
} else {
// This is unreachable, and hopefully clap will support it explicitly by outputting an
// enum from the ArgGroup in the future.
// See: https://github.com/clap-rs/clap/issues/2621
Err(anyhow!("Error: missing signed target flag"))
bail!("Error: missing signed target flag")
}
}
}
@@ -70,14 +77,25 @@ fn print_signed_text(private_key: &identity::PrivateKey, text: &str) {
println!("The base58-encoded signature on '{text}' is: {signature}");
}
fn print_signed_contract_msg(private_key: &identity::PrivateKey, raw_msg: &str) {
// we don't really care about what particular information is embedded inside of it,
// we just want to know if user correctly copied the string, i.e. whether it's a valid json
if serde_json::from_str::<serde_json::Value>(raw_msg).is_err() {
println!("it seems you have incorrectly copied the message to sign. Make sure you didn't accidentally skip any characters")
} else {
let msg = raw_msg.trim();
let signature = private_key.sign(msg.trim().as_bytes()).to_base58_string();
println!("The base58-encoded signature on\n{msg}\nis:\n{signature}");
}
}
pub(crate) fn execute(args: &Sign) {
let config = match Config::load_from_file(&args.id) {
Ok(cfg) => cfg,
Err(err) => {
error!(
"Failed to load config for {}. Are you sure you have run `init` before? (Error was: {})",
"Failed to load config for {}. Are you sure you have run `init` before? (Error was: {err})",
args.id,
err,
);
return;
}
@@ -101,5 +119,8 @@ pub(crate) fn execute(args: &Sign) {
match signed_target {
SignedTarget::Text(text) => print_signed_text(identity_keypair.private_key(), &text),
SignedTarget::Address(addr) => print_signed_address(identity_keypair.private_key(), addr),
SignedTarget::ContractMsg(raw_msg) => {
print_signed_contract_msg(identity_keypair.private_key(), &raw_msg)
}
}
}