wip
This commit is contained in:
Generated
+1
@@ -3507,6 +3507,7 @@ dependencies = [
|
||||
"mixnode-common",
|
||||
"nym-bin-common",
|
||||
"nym-config",
|
||||
"nym-contracts-common",
|
||||
"nym-crypto",
|
||||
"nym-nonexhaustive-delayqueue",
|
||||
"nym-pemstore",
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
pub mod dealings;
|
||||
pub mod events;
|
||||
pub mod signing;
|
||||
pub mod types;
|
||||
|
||||
pub use types::*;
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use cosmwasm_std::{from_slice, to_vec, Addr, Coin, MessageInfo, StdResult};
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
pub type Nonce = u32;
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct MessageType(String);
|
||||
|
||||
impl<T> From<T> for MessageType
|
||||
where
|
||||
T: ToString,
|
||||
{
|
||||
fn from(value: T) -> Self {
|
||||
MessageType(value.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum SigningAlgorithm {
|
||||
#[default]
|
||||
Ed25519,
|
||||
Secp256k1,
|
||||
}
|
||||
|
||||
// TODO: maybe move this one to repo-wide common?
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct SignableMessage<T> {
|
||||
nonce: u32,
|
||||
algorithm: SigningAlgorithm,
|
||||
content: T,
|
||||
}
|
||||
|
||||
impl<T> SignableMessage<T> {
|
||||
pub fn new(nonce: u32, content: T) -> Self {
|
||||
SignableMessage {
|
||||
nonce,
|
||||
algorithm: SigningAlgorithm::Ed25519,
|
||||
content,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_signing_algorithm(mut self, algorithm: SigningAlgorithm) -> Self {
|
||||
self.algorithm = algorithm;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn to_plaintext(&self) -> StdResult<Vec<u8>>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
to_vec(self)
|
||||
}
|
||||
|
||||
pub fn to_string(&self) -> StdResult<String>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
// if you look into implementation of `serde_json_wasm::to_string` this [i.e. the String conversion]
|
||||
// CAN'T fail, but let's avoid this unnecessary unwrap either way
|
||||
self.to_plaintext()
|
||||
.map(|s| String::from_utf8(s).unwrap_or(String::from("SERIALIZATION FAILURE")))
|
||||
}
|
||||
|
||||
pub fn try_from_bytes(bytes: &[u8]) -> StdResult<SignableMessage<T>>
|
||||
where
|
||||
T: DeserializeOwned,
|
||||
{
|
||||
from_slice(bytes)
|
||||
}
|
||||
|
||||
pub fn try_from_string(raw: &str) -> StdResult<SignableMessage<T>>
|
||||
where
|
||||
T: DeserializeOwned,
|
||||
{
|
||||
Self::try_from_bytes(raw.as_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct ContractMessageContent<T> {
|
||||
message_type: MessageType,
|
||||
signer: Addr,
|
||||
proxy: Option<Addr>,
|
||||
funds: Vec<Coin>,
|
||||
data: T,
|
||||
}
|
||||
|
||||
impl<T> ContractMessageContent<T> {
|
||||
pub fn new(
|
||||
message_type: MessageType,
|
||||
signer: Addr,
|
||||
proxy: Option<Addr>,
|
||||
funds: Vec<Coin>,
|
||||
data: T,
|
||||
) -> Self {
|
||||
ContractMessageContent {
|
||||
message_type,
|
||||
signer,
|
||||
proxy,
|
||||
funds,
|
||||
data,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_with_info(
|
||||
message_type: MessageType,
|
||||
info: MessageInfo,
|
||||
signer: Addr,
|
||||
data: T,
|
||||
) -> Self {
|
||||
let proxy = if info.sender == signer {
|
||||
None
|
||||
} else {
|
||||
Some(info.sender)
|
||||
};
|
||||
|
||||
ContractMessageContent {
|
||||
message_type,
|
||||
signer,
|
||||
proxy,
|
||||
funds: info.funds,
|
||||
data,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ use crate::reward_params::{
|
||||
};
|
||||
use crate::{delegation, ContractStateParams, Layer, LayerAssignment, MixId, Percent};
|
||||
use crate::{Gateway, IdentityKey, MixNode};
|
||||
use contracts_common::signing::MessageType;
|
||||
use cosmwasm_std::Decimal;
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -240,6 +241,54 @@ pub enum ExecuteMsg {
|
||||
}
|
||||
|
||||
impl ExecuteMsg {
|
||||
pub fn message_type(&self) -> MessageType {
|
||||
match self {
|
||||
ExecuteMsg::AssignNodeLayer { .. } => {}
|
||||
ExecuteMsg::CreateFamily { .. } => {}
|
||||
ExecuteMsg::JoinFamily { .. } => {}
|
||||
ExecuteMsg::LeaveFamily { .. } => {}
|
||||
ExecuteMsg::KickFamilyMember { .. } => {}
|
||||
ExecuteMsg::CreateFamilyOnBehalf { .. } => {}
|
||||
ExecuteMsg::JoinFamilyOnBehalf { .. } => {}
|
||||
ExecuteMsg::LeaveFamilyOnBehalf { .. } => {}
|
||||
ExecuteMsg::KickFamilyMemberOnBehalf { .. } => {}
|
||||
ExecuteMsg::UpdateRewardingValidatorAddress { .. } => {}
|
||||
ExecuteMsg::UpdateContractStateParams { .. } => {}
|
||||
ExecuteMsg::UpdateActiveSetSize { .. } => {}
|
||||
ExecuteMsg::UpdateRewardingParams { .. } => {}
|
||||
ExecuteMsg::UpdateIntervalConfig { .. } => {}
|
||||
ExecuteMsg::BeginEpochTransition => {}
|
||||
ExecuteMsg::AdvanceCurrentEpoch { .. } => {}
|
||||
ExecuteMsg::ReconcileEpochEvents { .. } => {}
|
||||
ExecuteMsg::BondMixnode { .. } => {}
|
||||
ExecuteMsg::BondMixnodeOnBehalf { .. } => {}
|
||||
ExecuteMsg::PledgeMore { .. } => {}
|
||||
ExecuteMsg::PledgeMoreOnBehalf { .. } => {}
|
||||
ExecuteMsg::UnbondMixnode { .. } => {}
|
||||
ExecuteMsg::UnbondMixnodeOnBehalf { .. } => {}
|
||||
ExecuteMsg::UpdateMixnodeCostParams { .. } => {}
|
||||
ExecuteMsg::UpdateMixnodeCostParamsOnBehalf { .. } => {}
|
||||
ExecuteMsg::UpdateMixnodeConfig { .. } => {}
|
||||
ExecuteMsg::UpdateMixnodeConfigOnBehalf { .. } => {}
|
||||
ExecuteMsg::BondGateway { .. } => {}
|
||||
ExecuteMsg::BondGatewayOnBehalf { .. } => {}
|
||||
ExecuteMsg::UnbondGateway { .. } => {}
|
||||
ExecuteMsg::UnbondGatewayOnBehalf { .. } => {}
|
||||
ExecuteMsg::DelegateToMixnode { .. } => {}
|
||||
ExecuteMsg::DelegateToMixnodeOnBehalf { .. } => {}
|
||||
ExecuteMsg::UndelegateFromMixnode { .. } => {}
|
||||
ExecuteMsg::UndelegateFromMixnodeOnBehalf { .. } => {}
|
||||
ExecuteMsg::RewardMixnode { .. } => {}
|
||||
ExecuteMsg::WithdrawOperatorReward { .. } => {}
|
||||
ExecuteMsg::WithdrawOperatorRewardOnBehalf { .. } => {}
|
||||
ExecuteMsg::WithdrawDelegatorReward { .. } => {}
|
||||
ExecuteMsg::WithdrawDelegatorRewardOnBehalf { .. } => {}
|
||||
#[cfg(feature = "contract-testing")]
|
||||
ExecuteMsg::TestingResolveAllPendingEvents { .. } => {}
|
||||
}
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn default_memo(&self) -> String {
|
||||
match self {
|
||||
ExecuteMsg::AssignNodeLayer { mix_id, layer } => {
|
||||
|
||||
@@ -24,7 +24,7 @@ crate-type = ["cdylib", "rlib"]
|
||||
[dependencies]
|
||||
mixnet-contract-common = { path = "../../common/cosmwasm-smart-contracts/mixnet-contract", package = "nym-mixnet-contract-common", version = "0.2.0" }
|
||||
vesting-contract-common = { path = "../../common/cosmwasm-smart-contracts/vesting-contract", package = "nym-vesting-contract-common", version = "0.2.0" }
|
||||
#nym-config = { path = "../../common/config"}
|
||||
nym-contracts-common = { path = "../../common/cosmwasm-smart-contracts/contracts-common", version = "0.2.0" }
|
||||
|
||||
cosmwasm-std = "1.0.0"
|
||||
cosmwasm-storage = "1.0.0"
|
||||
@@ -41,7 +41,6 @@ semver = { version = "1.0.16", default-features = false }
|
||||
[dev-dependencies]
|
||||
cosmwasm-schema = "1.0.0"
|
||||
rand_chacha = "0.2"
|
||||
#rand = "0.7"
|
||||
nym-crypto = { path = "../../common/crypto", features = ["asymmetric", "rand"] }
|
||||
|
||||
[build-dependencies]
|
||||
|
||||
@@ -39,41 +39,43 @@ pub const FAMILIES_DEFAULT_RETRIEVAL_LIMIT: u32 = 10;
|
||||
pub const FAMILIES_MAX_RETRIEVAL_LIMIT: u32 = 20;
|
||||
|
||||
// storage keys
|
||||
pub(crate) const DELEGATION_PK_NAMESPACE: &str = "dl";
|
||||
pub(crate) const DELEGATION_OWNER_IDX_NAMESPACE: &str = "dlo";
|
||||
pub(crate) const DELEGATION_MIXNODE_IDX_NAMESPACE: &str = "dlm";
|
||||
pub const DELEGATION_PK_NAMESPACE: &str = "dl";
|
||||
pub const DELEGATION_OWNER_IDX_NAMESPACE: &str = "dlo";
|
||||
pub const DELEGATION_MIXNODE_IDX_NAMESPACE: &str = "dlm";
|
||||
|
||||
pub(crate) const GATEWAYS_PK_NAMESPACE: &str = "gt";
|
||||
pub(crate) const GATEWAYS_OWNER_IDX_NAMESPACE: &str = "gto";
|
||||
pub const GATEWAYS_PK_NAMESPACE: &str = "gt";
|
||||
pub const GATEWAYS_OWNER_IDX_NAMESPACE: &str = "gto";
|
||||
|
||||
pub(crate) const REWARDED_SET_KEY: &str = "rs";
|
||||
pub(crate) const CURRENT_EPOCH_STATUS_KEY: &str = "ces";
|
||||
pub(crate) const CURRENT_INTERVAL_KEY: &str = "ci";
|
||||
pub(crate) const EPOCH_EVENT_ID_COUNTER_KEY: &str = "eic";
|
||||
pub(crate) const INTERVAL_EVENT_ID_COUNTER_KEY: &str = "iic";
|
||||
pub(crate) const PENDING_EPOCH_EVENTS_NAMESPACE: &str = "pee";
|
||||
pub(crate) const PENDING_INTERVAL_EVENTS_NAMESPACE: &str = "pie";
|
||||
pub const REWARDED_SET_KEY: &str = "rs";
|
||||
pub const CURRENT_EPOCH_STATUS_KEY: &str = "ces";
|
||||
pub const CURRENT_INTERVAL_KEY: &str = "ci";
|
||||
pub const EPOCH_EVENT_ID_COUNTER_KEY: &str = "eic";
|
||||
pub const INTERVAL_EVENT_ID_COUNTER_KEY: &str = "iic";
|
||||
pub const PENDING_EPOCH_EVENTS_NAMESPACE: &str = "pee";
|
||||
pub const PENDING_INTERVAL_EVENTS_NAMESPACE: &str = "pie";
|
||||
|
||||
pub(crate) const LAST_EPOCH_EVENT_ID_KEY: &str = "lee";
|
||||
pub(crate) const LAST_INTERVAL_EVENT_ID_KEY: &str = "lie";
|
||||
pub const LAST_EPOCH_EVENT_ID_KEY: &str = "lee";
|
||||
pub const LAST_INTERVAL_EVENT_ID_KEY: &str = "lie";
|
||||
|
||||
pub(crate) const CONTRACT_STATE_KEY: &str = "state";
|
||||
pub const CONTRACT_STATE_KEY: &str = "state";
|
||||
|
||||
pub(crate) const LAYER_DISTRIBUTION_KEY: &str = "layers";
|
||||
pub(crate) const NODE_ID_COUNTER_KEY: &str = "nic";
|
||||
pub(crate) const MIXNODES_PK_NAMESPACE: &str = "mnn";
|
||||
pub(crate) const MIXNODES_OWNER_IDX_NAMESPACE: &str = "mno";
|
||||
pub(crate) const MIXNODES_IDENTITY_IDX_NAMESPACE: &str = "mni";
|
||||
pub(crate) const MIXNODES_SPHINX_IDX_NAMESPACE: &str = "mns";
|
||||
pub const LAYER_DISTRIBUTION_KEY: &str = "layers";
|
||||
pub const NODE_ID_COUNTER_KEY: &str = "nic";
|
||||
pub const MIXNODES_PK_NAMESPACE: &str = "mnn";
|
||||
pub const MIXNODES_OWNER_IDX_NAMESPACE: &str = "mno";
|
||||
pub const MIXNODES_IDENTITY_IDX_NAMESPACE: &str = "mni";
|
||||
pub const MIXNODES_SPHINX_IDX_NAMESPACE: &str = "mns";
|
||||
|
||||
pub(crate) const UNBONDED_MIXNODES_PK_NAMESPACE: &str = "ubm";
|
||||
pub(crate) const UNBONDED_MIXNODES_OWNER_IDX_NAMESPACE: &str = "umo";
|
||||
pub(crate) const UNBONDED_MIXNODES_IDENTITY_IDX_NAMESPACE: &str = "umi";
|
||||
pub const UNBONDED_MIXNODES_PK_NAMESPACE: &str = "ubm";
|
||||
pub const UNBONDED_MIXNODES_OWNER_IDX_NAMESPACE: &str = "umo";
|
||||
pub const UNBONDED_MIXNODES_IDENTITY_IDX_NAMESPACE: &str = "umi";
|
||||
|
||||
pub(crate) const REWARDING_PARAMS_KEY: &str = "rparams";
|
||||
pub(crate) const PENDING_REWARD_POOL_KEY: &str = "prp";
|
||||
pub(crate) const MIXNODES_REWARDING_PK_NAMESPACE: &str = "mnr";
|
||||
pub const REWARDING_PARAMS_KEY: &str = "rparams";
|
||||
pub const PENDING_REWARD_POOL_KEY: &str = "prp";
|
||||
pub const MIXNODES_REWARDING_PK_NAMESPACE: &str = "mnr";
|
||||
|
||||
pub(crate) const FAMILIES_INDEX_NAMESPACE: &str = "faml2";
|
||||
pub(crate) const FAMILIES_MAP_NAMESPACE: &str = "fam2";
|
||||
pub(crate) const MEMBERS_MAP_NAMESPACE: &str = "memb2";
|
||||
pub const FAMILIES_INDEX_NAMESPACE: &str = "faml2";
|
||||
pub const FAMILIES_MAP_NAMESPACE: &str = "fam2";
|
||||
pub const MEMBERS_MAP_NAMESPACE: &str = "memb2";
|
||||
|
||||
pub const SIGNING_NONCES_NAMESPACE: &str = "sn";
|
||||
|
||||
@@ -15,6 +15,7 @@ mod mixnodes;
|
||||
mod queued_migrations;
|
||||
mod rewards;
|
||||
mod support;
|
||||
mod signing;
|
||||
|
||||
#[cfg(feature = "contract-testing")]
|
||||
mod testing;
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::signing::storage;
|
||||
use cosmwasm_std::{Addr, Storage};
|
||||
use mixnet_contract_common::error::MixnetContractError;
|
||||
|
||||
fn construct_signed_message<T>(
|
||||
storage: &mut dyn Storage,
|
||||
signer: Addr,
|
||||
message: T,
|
||||
) -> Result<(), MixnetContractError> {
|
||||
// right now all signing is done with ed25519 so that simplifies things a bit
|
||||
let nonce = storage::get_and_update_signing_nonce(storage, signer)?;
|
||||
|
||||
todo!()
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod helpers;
|
||||
pub mod queries;
|
||||
pub mod storage;
|
||||
@@ -0,0 +1,11 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::signing::storage::get_signing_nonce;
|
||||
use cosmwasm_std::{Deps, StdResult};
|
||||
use nym_contracts_common::signing::Nonce;
|
||||
|
||||
pub fn try_get_current_signing_nonce(deps: Deps<'_>, address: String) -> StdResult<Nonce> {
|
||||
let address = deps.api.addr_validate(&address)?;
|
||||
get_signing_nonce(deps.storage, address)
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::constants::SIGNING_NONCES_NAMESPACE;
|
||||
use cosmwasm_std::{Addr, StdResult, Storage};
|
||||
use cw_storage_plus::Map;
|
||||
use nym_contracts_common::signing::Nonce;
|
||||
|
||||
pub const NONCES: Map<'_, Addr, Nonce> = Map::new(SIGNING_NONCES_NAMESPACE);
|
||||
|
||||
pub fn get_signing_nonce(storage: &dyn Storage, address: Addr) -> StdResult<Nonce> {
|
||||
let nonce = NONCES.may_load(storage, address)?.unwrap_or(0);
|
||||
Ok(nonce)
|
||||
}
|
||||
|
||||
pub fn update_signing_nonce(
|
||||
storage: &mut dyn Storage,
|
||||
address: Addr,
|
||||
value: Nonce,
|
||||
) -> StdResult<()> {
|
||||
NONCES.save(storage, address, &value)
|
||||
}
|
||||
|
||||
pub fn get_and_update_signing_nonce(storage: &mut dyn Storage, address: Addr) -> StdResult<Nonce> {
|
||||
// get the current nonce
|
||||
let nonce = get_signing_nonce(storage, address.clone())?;
|
||||
|
||||
// increment it for the next use
|
||||
update_signing_nonce(storage, address, nonce + 1)?;
|
||||
|
||||
Ok(nonce)
|
||||
}
|
||||
@@ -41,6 +41,7 @@ atty = "0.2"
|
||||
## internal
|
||||
nym-config = { path="../common/config" }
|
||||
nym-crypto = { path="../common/crypto" }
|
||||
nym-contracts-common = { path = "../common/cosmwasm-smart-contracts/contracts-common" }
|
||||
mixnet-client = { path="../common/client-libs/mixnet-client" }
|
||||
mixnode-common = { path="../common/mixnode-common" }
|
||||
nym-nonexhaustive-delayqueue = { path="../common/nonexhaustive-delayqueue" }
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user