in-wallet verification of mix bonding signature
This commit is contained in:
@@ -43,6 +43,7 @@ pub use cosmrs::tendermint::Time as TendermintTime;
|
||||
pub use cosmrs::tx::{self, Gas};
|
||||
pub use cosmrs::Coin as CosmosCoin;
|
||||
pub use cosmrs::{bip32, AccountId, Decimal, Denom};
|
||||
use cosmwasm_std::Addr;
|
||||
pub use cosmwasm_std::Coin as CosmWasmCoin;
|
||||
pub use fee::{gas_price::GasPrice, GasAdjustable, GasAdjustment};
|
||||
pub use signing_client::Client as SigningNyxdClient;
|
||||
@@ -369,6 +370,15 @@ where
|
||||
&self.client_address.as_ref().unwrap()[0]
|
||||
}
|
||||
|
||||
pub fn cw_address(&self) -> Addr
|
||||
where
|
||||
C: SigningCosmWasmClient,
|
||||
{
|
||||
// the call to unchecked is fine here as we're converting directly from `AccountId`
|
||||
// which must have been a valid bech32 address
|
||||
Addr::unchecked(self.address().as_ref())
|
||||
}
|
||||
|
||||
pub fn signer(&self) -> &DirectSecp256k1HdWallet
|
||||
where
|
||||
C: SigningCosmWasmClient,
|
||||
|
||||
@@ -6,6 +6,7 @@ use crate::nyxd::error::NyxdError;
|
||||
use crate::nyxd::NyxdClient;
|
||||
use async_trait::async_trait;
|
||||
use cosmrs::AccountId;
|
||||
use nym_contracts_common::signing::Nonce;
|
||||
use nym_mixnet_contract_common::delegation::{MixNodeDelegationResponse, OwnerProxySubKey};
|
||||
use nym_mixnet_contract_common::families::Family;
|
||||
use nym_mixnet_contract_common::mixnode::{
|
||||
@@ -390,6 +391,13 @@ pub trait MixnetQueryClient {
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_signing_nonce(&self, address: &AccountId) -> Result<Nonce, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetSigningNonce {
|
||||
address: address.to_string(),
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_node_family_by_label(&self, label: &str) -> Result<Option<Family>, NyxdError> {
|
||||
self.query_mixnet_contract(MixnetQueryMsg::GetFamilyByLabel {
|
||||
label: label.to_string(),
|
||||
|
||||
@@ -3,14 +3,90 @@
|
||||
|
||||
use cosmwasm_std::{from_slice, to_vec, Addr, Coin, MessageInfo, StdResult};
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
pub type Nonce = u32;
|
||||
|
||||
// define this type explicitly for [hopefully] better usability
|
||||
// (so you wouldn't need to worry about whether you should use bytes, bs58, etc.)
|
||||
#[derive(Clone)]
|
||||
pub struct MessageSignature(Vec<u8>);
|
||||
|
||||
impl MessageSignature {
|
||||
pub fn as_bs58_string(&self) -> String {
|
||||
bs58::encode(&self.0).into_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a [u8]> for MessageSignature {
|
||||
fn from(value: &'a [u8]) -> Self {
|
||||
MessageSignature(value.to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec<u8>> for MessageSignature {
|
||||
fn from(value: Vec<u8>) -> Self {
|
||||
MessageSignature(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<String> for MessageSignature {
|
||||
type Error = bs58::decode::Error;
|
||||
|
||||
fn try_from(value: String) -> Result<Self, Self::Error> {
|
||||
Ok(MessageSignature(bs58::decode(value).into_vec()?))
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for MessageSignature {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for MessageSignature {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let inner = String::deserialize(deserializer)?;
|
||||
let bytes = bs58::decode(inner).into_vec().map_err(de::Error::custom)?;
|
||||
Ok(MessageSignature(bytes))
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for MessageSignature {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let bs58_encoded = self.as_bs58_string();
|
||||
bs58_encoded.serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for MessageSignature {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.as_bs58_string())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait SigningPurpose {
|
||||
fn message_type() -> MessageType;
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct MessageType(String);
|
||||
|
||||
impl MessageType {
|
||||
pub fn new<S: Into<String>>(typ: S) -> Self {
|
||||
MessageType(typ.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<T> for MessageType
|
||||
where
|
||||
T: ToString,
|
||||
@@ -20,7 +96,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Serialize, Deserialize)]
|
||||
#[derive(Default, Debug, Serialize, Deserialize, Copy, Clone)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum SigningAlgorithm {
|
||||
#[default]
|
||||
@@ -28,12 +104,20 @@ pub enum SigningAlgorithm {
|
||||
Secp256k1,
|
||||
}
|
||||
|
||||
impl SigningAlgorithm {
|
||||
pub fn is_ed25519(&self) -> bool {
|
||||
matches!(self, SigningAlgorithm::Ed25519)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: maybe move this one to repo-wide common?
|
||||
// TODO: should it perhaps also include the public key itself?
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct SignableMessage<T> {
|
||||
nonce: u32,
|
||||
algorithm: SigningAlgorithm,
|
||||
content: T,
|
||||
pub nonce: u32,
|
||||
pub algorithm: SigningAlgorithm,
|
||||
|
||||
pub content: T,
|
||||
}
|
||||
|
||||
impl<T> SignableMessage<T> {
|
||||
@@ -83,24 +167,21 @@ impl<T> SignableMessage<T> {
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct ContractMessageContent<T> {
|
||||
message_type: MessageType,
|
||||
signer: Addr,
|
||||
proxy: Option<Addr>,
|
||||
funds: Vec<Coin>,
|
||||
data: T,
|
||||
pub struct ContractMessageContent<T> {
|
||||
pub message_type: MessageType,
|
||||
pub signer: Addr,
|
||||
pub proxy: Option<Addr>,
|
||||
pub funds: Vec<Coin>,
|
||||
pub data: T,
|
||||
}
|
||||
|
||||
impl<T> ContractMessageContent<T> {
|
||||
pub fn new(
|
||||
message_type: MessageType,
|
||||
signer: Addr,
|
||||
proxy: Option<Addr>,
|
||||
funds: Vec<Coin>,
|
||||
data: T,
|
||||
) -> Self {
|
||||
impl<T> ContractMessageContent<T>
|
||||
where
|
||||
T: SigningPurpose,
|
||||
{
|
||||
pub fn new(signer: Addr, proxy: Option<Addr>, funds: Vec<Coin>, data: T) -> Self {
|
||||
ContractMessageContent {
|
||||
message_type,
|
||||
message_type: T::message_type(),
|
||||
signer,
|
||||
proxy,
|
||||
funds,
|
||||
@@ -108,12 +189,7 @@ impl<T> ContractMessageContent<T> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_with_info(
|
||||
message_type: MessageType,
|
||||
info: MessageInfo,
|
||||
signer: Addr,
|
||||
data: T,
|
||||
) -> Self {
|
||||
pub fn new_with_info(info: MessageInfo, signer: Addr, data: T) -> Self {
|
||||
let proxy = if info.sender == signer {
|
||||
None
|
||||
} else {
|
||||
@@ -121,7 +197,7 @@ impl<T> ContractMessageContent<T> {
|
||||
};
|
||||
|
||||
ContractMessageContent {
|
||||
message_type,
|
||||
message_type: T::message_type(),
|
||||
signer,
|
||||
proxy,
|
||||
funds: info.funds,
|
||||
|
||||
@@ -17,6 +17,7 @@ mod msg;
|
||||
pub mod pending_events;
|
||||
pub mod reward_params;
|
||||
pub mod rewarding;
|
||||
pub mod signing_types;
|
||||
mod types;
|
||||
|
||||
pub use contracts_common::types::*;
|
||||
@@ -43,4 +44,5 @@ pub use pending_events::{
|
||||
PendingIntervalEventData, PendingIntervalEventKind,
|
||||
};
|
||||
pub use reward_params::{IntervalRewardParams, IntervalRewardingParamsUpdate, RewardingParams};
|
||||
pub use signing_types::*;
|
||||
pub use types::*;
|
||||
|
||||
@@ -10,7 +10,6 @@ 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};
|
||||
@@ -241,54 +240,6 @@ 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 } => {
|
||||
@@ -549,6 +500,11 @@ pub enum QueryMsg {
|
||||
start_after: Option<u32>,
|
||||
},
|
||||
GetNumberOfPendingEvents {},
|
||||
|
||||
// signing-related
|
||||
GetSigningNonce {
|
||||
address: String,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::{Gateway, MixNode, MixNodeCostParams};
|
||||
use contracts_common::signing::{MessageType, SigningPurpose};
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct MixnodeBondingPayload {
|
||||
mix_node: MixNode,
|
||||
cost_params: MixNodeCostParams,
|
||||
}
|
||||
|
||||
impl MixnodeBondingPayload {
|
||||
pub fn new(mix_node: MixNode, cost_params: MixNodeCostParams) -> Self {
|
||||
Self {
|
||||
mix_node,
|
||||
cost_params,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SigningPurpose for MixnodeBondingPayload {
|
||||
fn message_type() -> MessageType {
|
||||
MessageType::new("mixnode-bonding")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct GatewayBondingPayload {
|
||||
gateway: Gateway,
|
||||
}
|
||||
|
||||
impl GatewayBondingPayload {
|
||||
pub fn new(gateway: Gateway) -> Self {
|
||||
Self { gateway }
|
||||
}
|
||||
}
|
||||
|
||||
impl SigningPurpose for GatewayBondingPayload {
|
||||
fn message_type() -> MessageType {
|
||||
MessageType::new("gateway-bonding")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct FamilyCreationSignature {
|
||||
label: String,
|
||||
// TODO: add any extra fields?
|
||||
}
|
||||
|
||||
impl FamilyCreationSignature {
|
||||
pub fn new(label: String) -> Self {
|
||||
Self { label }
|
||||
}
|
||||
}
|
||||
|
||||
impl SigningPurpose for FamilyCreationSignature {
|
||||
fn message_type() -> MessageType {
|
||||
MessageType::new("family-creation")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct FamilyJoinSignature {
|
||||
family_head: String,
|
||||
// TODO: add any extra fields?
|
||||
}
|
||||
|
||||
impl FamilyJoinSignature {
|
||||
pub fn new(family_head: String) -> Self {
|
||||
Self { family_head }
|
||||
}
|
||||
}
|
||||
|
||||
impl SigningPurpose for FamilyJoinSignature {
|
||||
fn message_type() -> MessageType {
|
||||
MessageType::new("family-join")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct FamilyLeaveSignature {
|
||||
family_head: String,
|
||||
// TODO: add any extra fields?
|
||||
}
|
||||
|
||||
impl FamilyLeaveSignature {
|
||||
pub fn new(family_head: String) -> Self {
|
||||
Self { family_head }
|
||||
}
|
||||
}
|
||||
|
||||
impl SigningPurpose for FamilyLeaveSignature {
|
||||
fn message_type() -> MessageType {
|
||||
MessageType::new("family-leave")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct FamilyKickSignature {
|
||||
member: String,
|
||||
// TODO: add any extra fields?
|
||||
}
|
||||
|
||||
impl FamilyKickSignature {
|
||||
pub fn new(member: String) -> Self {
|
||||
Self { member }
|
||||
}
|
||||
}
|
||||
|
||||
impl SigningPurpose for FamilyKickSignature {
|
||||
fn message_type() -> MessageType {
|
||||
MessageType::new("family-member-removal")
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: depending on our threat model, we should perhaps extend it to include all _on_behalf methods
|
||||
@@ -581,6 +581,9 @@ pub fn query(
|
||||
QueryMsg::GetNumberOfPendingEvents {} => to_binary(
|
||||
&crate::interval::queries::query_number_of_pending_events(deps)?,
|
||||
),
|
||||
QueryMsg::GetSigningNonce { address } => to_binary(
|
||||
&crate::signing::queries::query_current_signing_nonce(deps, address)?,
|
||||
),
|
||||
};
|
||||
|
||||
Ok(query_res?)
|
||||
|
||||
@@ -5,7 +5,7 @@ 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> {
|
||||
pub fn query_current_signing_nonce(deps: Deps<'_>, address: String) -> StdResult<Nonce> {
|
||||
let address = deps.api.addr_validate(&address)?;
|
||||
get_signing_nonce(deps.storage, address)
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ use validator_client::nyxd;
|
||||
|
||||
#[derive(Args, Clone)]
|
||||
#[clap(group(ArgGroup::new("sign").required(true).args(&["wallet_address", "text", "contract_msg"])))]
|
||||
pub(crate) struct Sign {
|
||||
pub struct Sign {
|
||||
/// The id of the mixnode you want to sign with
|
||||
#[clap(long)]
|
||||
id: String,
|
||||
|
||||
Generated
+220
-36
@@ -20,7 +20,7 @@ version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"generic-array 0.14.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -32,7 +32,8 @@ dependencies = [
|
||||
"cfg-if",
|
||||
"cipher",
|
||||
"cpufeatures",
|
||||
"opaque-debug",
|
||||
"ctr",
|
||||
"opaque-debug 0.3.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -46,7 +47,7 @@ dependencies = [
|
||||
"cipher",
|
||||
"ctr",
|
||||
"ghash",
|
||||
"subtle",
|
||||
"subtle 2.4.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -97,7 +98,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25df3c03f1040d0069fcd3907e24e36d59f9b6fa07ba49be0eb25a794f036ba7"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
"blake2",
|
||||
"blake2 0.10.6",
|
||||
"password-hash 0.3.2",
|
||||
]
|
||||
|
||||
@@ -108,10 +109,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a27e27b63e4a34caee411ade944981136fdfa535522dc9944d6700196cbd899f"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
"blake2",
|
||||
"blake2 0.10.6",
|
||||
"password-hash 0.4.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arrayref"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
|
||||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.64"
|
||||
@@ -227,7 +234,7 @@ dependencies = [
|
||||
"rand_core 0.6.4",
|
||||
"ripemd160",
|
||||
"sha2 0.9.9",
|
||||
"subtle",
|
||||
"subtle 2.4.1",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
@@ -268,6 +275,18 @@ dependencies = [
|
||||
"wyz",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "blake2"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94cb07b0da6a73955f8fb85d24c466778e70cda767a568229b104f0264089330"
|
||||
dependencies = [
|
||||
"byte-tools",
|
||||
"crypto-mac 0.7.0",
|
||||
"digest 0.8.1",
|
||||
"opaque-debug 0.2.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "blake2"
|
||||
version = "0.10.6"
|
||||
@@ -290,7 +309,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
|
||||
dependencies = [
|
||||
"block-padding",
|
||||
"generic-array",
|
||||
"generic-array 0.14.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -299,7 +318,7 @@ version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"generic-array 0.14.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -318,7 +337,7 @@ dependencies = [
|
||||
"group",
|
||||
"pairing",
|
||||
"rand_core 0.6.4",
|
||||
"subtle",
|
||||
"subtle 2.4.1",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
@@ -368,6 +387,12 @@ version = "3.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
|
||||
|
||||
[[package]]
|
||||
name = "byte-tools"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
|
||||
|
||||
[[package]]
|
||||
name = "bytemuck"
|
||||
version = "1.13.0"
|
||||
@@ -469,13 +494,23 @@ version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "chacha"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ddf3c081b5fba1e5615640aae998e0fbd10c24cbd897ee39ed754a77601a4862"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"keystream",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cipher"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"generic-array 0.14.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -785,9 +820,9 @@ version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "03c6a1d5fa1de37e071642dfa44ec552ca5b299adb128fab16138e24b548fd21"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"generic-array 0.14.6",
|
||||
"rand_core 0.6.4",
|
||||
"subtle",
|
||||
"subtle 2.4.1",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
@@ -797,18 +832,28 @@ version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"generic-array 0.14.6",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-mac"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5"
|
||||
dependencies = [
|
||||
"generic-array 0.12.4",
|
||||
"subtle 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-mac"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"subtle",
|
||||
"generic-array 0.14.6",
|
||||
"subtle 2.4.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -881,7 +926,7 @@ dependencies = [
|
||||
"byteorder",
|
||||
"digest 0.9.0",
|
||||
"rand_core 0.5.1",
|
||||
"subtle",
|
||||
"subtle 2.4.1",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
@@ -1017,13 +1062,22 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
|
||||
dependencies = [
|
||||
"generic-array 0.12.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"generic-array 0.14.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1034,7 +1088,7 @@ checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f"
|
||||
dependencies = [
|
||||
"block-buffer 0.10.3",
|
||||
"crypto-common",
|
||||
"subtle",
|
||||
"subtle 2.4.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1146,6 +1200,8 @@ checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d"
|
||||
dependencies = [
|
||||
"curve25519-dalek",
|
||||
"ed25519",
|
||||
"rand 0.7.3",
|
||||
"serde",
|
||||
"sha2 0.9.9",
|
||||
"zeroize",
|
||||
]
|
||||
@@ -1181,11 +1237,11 @@ dependencies = [
|
||||
"crypto-bigint",
|
||||
"der",
|
||||
"ff",
|
||||
"generic-array",
|
||||
"generic-array 0.14.6",
|
||||
"group",
|
||||
"rand_core 0.6.4",
|
||||
"sec1",
|
||||
"subtle",
|
||||
"subtle 2.4.1",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
@@ -1294,7 +1350,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "131655483be284720a17d74ff97592b8e76576dc25563148601df2d7c9080924"
|
||||
dependencies = [
|
||||
"rand_core 0.6.4",
|
||||
"subtle",
|
||||
"subtle 2.4.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1580,6 +1636,15 @@ dependencies = [
|
||||
"windows 0.39.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.12.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.6"
|
||||
@@ -1597,8 +1662,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
"libc",
|
||||
"wasi 0.9.0+wasi-snapshot-preview1",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1632,7 +1699,7 @@ version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1583cc1656d7839fd3732b80cf4f38850336cdb9b8ded1cd399ca62958de3c99"
|
||||
dependencies = [
|
||||
"opaque-debug",
|
||||
"opaque-debug 0.3.0",
|
||||
"polyval",
|
||||
]
|
||||
|
||||
@@ -1763,7 +1830,7 @@ dependencies = [
|
||||
"byteorder",
|
||||
"ff",
|
||||
"rand_core 0.6.4",
|
||||
"subtle",
|
||||
"subtle 2.4.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1939,13 +2006,23 @@ version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0"
|
||||
|
||||
[[package]]
|
||||
name = "hkdf"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "01706d578d5c281058480e673ae4086a9f4710d8df1ad80a5b03e39ece5f886b"
|
||||
dependencies = [
|
||||
"digest 0.9.0",
|
||||
"hmac",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hmac"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b"
|
||||
dependencies = [
|
||||
"crypto-mac",
|
||||
"crypto-mac 0.11.1",
|
||||
"digest 0.9.0",
|
||||
]
|
||||
|
||||
@@ -2338,6 +2415,12 @@ dependencies = [
|
||||
"cpufeatures",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "keystream"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c33070833c9ee02266356de0c43f723152bd38bd96ddf52c82b3af10c9138b28"
|
||||
|
||||
[[package]]
|
||||
name = "kuchiki"
|
||||
version = "0.8.1"
|
||||
@@ -2374,6 +2457,12 @@ dependencies = [
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libm"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb"
|
||||
|
||||
[[package]]
|
||||
name = "libz-sys"
|
||||
version = "1.1.8"
|
||||
@@ -2401,6 +2490,18 @@ version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
|
||||
|
||||
[[package]]
|
||||
name = "lioness"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ae926706ba42c425c9457121178330d75e273df2e82e28b758faf3de3a9acb9"
|
||||
dependencies = [
|
||||
"arrayref",
|
||||
"blake2 0.8.1",
|
||||
"chacha",
|
||||
"keystream",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.9"
|
||||
@@ -2650,6 +2751,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
|
||||
dependencies = [
|
||||
"autocfg 1.1.0",
|
||||
"libm",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2797,6 +2899,20 @@ dependencies = [
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-crypto"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bs58",
|
||||
"ed25519-dalek",
|
||||
"nym-pemstore",
|
||||
"nym-sphinx-types",
|
||||
"rand 0.7.3",
|
||||
"subtle-encoding",
|
||||
"thiserror",
|
||||
"x25519-dalek",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-execute"
|
||||
version = "0.1.0"
|
||||
@@ -2866,6 +2982,13 @@ dependencies = [
|
||||
"pem",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-sphinx-types"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"sphinx-packet",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-types"
|
||||
version = "1.0.0"
|
||||
@@ -2961,6 +3084,7 @@ version = "1.1.11"
|
||||
dependencies = [
|
||||
"aes-gcm",
|
||||
"argon2 0.3.4",
|
||||
"async-trait",
|
||||
"base64 0.13.1",
|
||||
"bip39",
|
||||
"cfg-if",
|
||||
@@ -2977,6 +3101,8 @@ dependencies = [
|
||||
"log",
|
||||
"nym-coconut-interface",
|
||||
"nym-config",
|
||||
"nym-contracts-common",
|
||||
"nym-crypto",
|
||||
"nym-mixnet-contract-common",
|
||||
"nym-types",
|
||||
"nym-vesting-contract",
|
||||
@@ -2985,6 +3111,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"pretty_env_logger",
|
||||
"rand 0.6.5",
|
||||
"rand_chacha 0.2.2",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -3071,6 +3198,12 @@ version = "1.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
|
||||
|
||||
[[package]]
|
||||
name = "opaque-debug"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
|
||||
|
||||
[[package]]
|
||||
name = "opaque-debug"
|
||||
version = "0.3.0"
|
||||
@@ -3209,7 +3342,7 @@ checksum = "1d791538a6dcc1e7cb7fe6f6b58aca40e7f79403c45b2bc274008b5e647af1d8"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
"rand_core 0.6.4",
|
||||
"subtle",
|
||||
"subtle 2.4.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3220,7 +3353,7 @@ checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
"rand_core 0.6.4",
|
||||
"subtle",
|
||||
"subtle 2.4.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3241,7 +3374,7 @@ version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f05894bce6a1ba4be299d0c5f29563e08af2bc18bb7d48313113bed71e904739"
|
||||
dependencies = [
|
||||
"crypto-mac",
|
||||
"crypto-mac 0.11.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3513,7 +3646,7 @@ checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"opaque-debug",
|
||||
"opaque-debug 0.3.0",
|
||||
"universal-hash",
|
||||
]
|
||||
|
||||
@@ -3764,6 +3897,16 @@ dependencies = [
|
||||
"getrandom 0.2.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_distr"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c9e9532ada3929fb8b2e9dbe28d1e06c9b2cc65813f074fcb6bd5fbefeff9d56"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
"rand 0.7.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_hc"
|
||||
version = "0.1.0"
|
||||
@@ -4012,7 +4155,7 @@ checksum = "2eca4ecc81b7f313189bf73ce724400a07da2a6dac19588b03c8bd76a2dcc251"
|
||||
dependencies = [
|
||||
"block-buffer 0.9.0",
|
||||
"digest 0.9.0",
|
||||
"opaque-debug",
|
||||
"opaque-debug 0.3.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4162,9 +4305,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08da66b8b0965a5555b6bd6639e68ccba85e1e2506f5fbb089e93f8a04e1a2d1"
|
||||
dependencies = [
|
||||
"der",
|
||||
"generic-array",
|
||||
"generic-array 0.14.6",
|
||||
"pkcs8",
|
||||
"subtle",
|
||||
"subtle 2.4.1",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
@@ -4396,7 +4539,7 @@ dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"digest 0.9.0",
|
||||
"opaque-debug",
|
||||
"opaque-debug 0.3.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4419,7 +4562,7 @@ dependencies = [
|
||||
"block-buffer 0.9.0",
|
||||
"digest 0.9.0",
|
||||
"keccak",
|
||||
"opaque-debug",
|
||||
"opaque-debug 0.3.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4518,6 +4661,30 @@ dependencies = [
|
||||
"system-deps 5.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sphinx-packet"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc43eda802856ee82a7555c7b75ceb9e07451741c7a2f5f23d036020e01189d4"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"arrayref",
|
||||
"blake2 0.8.1",
|
||||
"bs58",
|
||||
"byteorder",
|
||||
"chacha",
|
||||
"curve25519-dalek",
|
||||
"digest 0.9.0",
|
||||
"hkdf",
|
||||
"hmac",
|
||||
"lioness",
|
||||
"log",
|
||||
"rand 0.7.3",
|
||||
"rand_distr",
|
||||
"sha2 0.9.9",
|
||||
"subtle 2.4.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.5.2"
|
||||
@@ -4609,6 +4776,12 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee"
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "2.4.1"
|
||||
@@ -4951,7 +5124,7 @@ dependencies = [
|
||||
"serde_repr",
|
||||
"sha2 0.9.9",
|
||||
"signature",
|
||||
"subtle",
|
||||
"subtle 2.4.1",
|
||||
"subtle-encoding",
|
||||
"tendermint-proto",
|
||||
"time",
|
||||
@@ -5369,8 +5542,8 @@ version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"subtle",
|
||||
"generic-array 0.14.6",
|
||||
"subtle 2.4.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6029,6 +6202,17 @@ dependencies = [
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "x25519-dalek"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a0c105152107e3b96f6a00a65e86ce82d9b125230e1c4302940eca58ff71f4f"
|
||||
dependencies = [
|
||||
"curve25519-dalek",
|
||||
"rand_core 0.5.1",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xattr"
|
||||
version = "0.2.3"
|
||||
|
||||
@@ -19,6 +19,7 @@ tauri-codegen = "=1.2.1"
|
||||
tauri-macros = "=1.2.1"
|
||||
|
||||
[dependencies]
|
||||
async-trait = "0.1.64"
|
||||
bip39 = "1.0"
|
||||
cfg-if = "1.0.0"
|
||||
colored = "2.0"
|
||||
@@ -57,6 +58,8 @@ cosmrs = { git = "https://github.com/neacsu/cosmos-rust", branch = "neacsu/feegr
|
||||
validator-client = { path = "../../common/client-libs/validator-client", features = [
|
||||
"nyxd-client",
|
||||
] }
|
||||
nym-crypto = { path = "../../common/crypto", features = ["asymmetric"] }
|
||||
nym-contracts-common = { path = "../../common/cosmwasm-smart-contracts/contracts-common" }
|
||||
nym-mixnet-contract-common = { path = "../../common/cosmwasm-smart-contracts/mixnet-contract" }
|
||||
nym-vesting-contract-common = { path = "../../common/cosmwasm-smart-contracts/vesting-contract" }
|
||||
nym-config = { path = "../../common/config" }
|
||||
@@ -67,6 +70,8 @@ nym-types = { path = "../../common/types" }
|
||||
nym-wallet-types = { path = "../nym-wallet-types" }
|
||||
|
||||
[dev-dependencies]
|
||||
nym-crypto = { path = "../../common/crypto", features = ["rand"] }
|
||||
rand_chacha = "0.2"
|
||||
tempfile = "3.3.0"
|
||||
ts-rs = "6.1.2"
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
use nym_contracts_common::signing::SigningAlgorithm;
|
||||
use nym_crypto::asymmetric::identity;
|
||||
use nym_crypto::asymmetric::identity::{Ed25519RecoveryError, SignatureError};
|
||||
use nym_types::error::TypesError;
|
||||
use nym_wallet_types::network::Network;
|
||||
use serde::{Serialize, Serializer};
|
||||
@@ -122,6 +125,16 @@ pub enum BackendError {
|
||||
#[error("Unable to open a new window")]
|
||||
NewWindowError,
|
||||
|
||||
#[error("received unexpected signing algorithm: {received:?}. Expected to get {expected:?}")]
|
||||
UnexpectedSigningAlgorithm {
|
||||
received: SigningAlgorithm,
|
||||
expected: SigningAlgorithm,
|
||||
},
|
||||
#[error(transparent)]
|
||||
Ed25519Recovery(#[from] Ed25519RecoveryError),
|
||||
#[error(transparent)]
|
||||
Ed25519SignatureError(SignatureError),
|
||||
|
||||
#[error("This command ({name}) has been removed. Please try to use {alternative} instead.")]
|
||||
RemovedCommand { name: String, alternative: String },
|
||||
}
|
||||
|
||||
@@ -0,0 +1,389 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::error::BackendError;
|
||||
use async_trait::async_trait;
|
||||
use cosmrs::AccountId;
|
||||
use cosmwasm_std::Addr;
|
||||
use nym_contracts_common::signing::{
|
||||
ContractMessageContent, MessageSignature, Nonce, SignableMessage, SigningAlgorithm,
|
||||
};
|
||||
use nym_crypto::asymmetric::identity;
|
||||
use nym_mixnet_contract_common::{
|
||||
Gateway, GatewayBondingPayload, MixNode, MixNodeCostParams, MixnodeBondingPayload,
|
||||
};
|
||||
use validator_client::nyxd::error::NyxdError;
|
||||
use validator_client::nyxd::traits::MixnetQueryClient;
|
||||
use validator_client::nyxd::{Coin, SigningNyxdClient};
|
||||
use validator_client::Client;
|
||||
|
||||
type SignableMixNodeBondingMsg = SignableMessage<ContractMessageContent<MixnodeBondingPayload>>;
|
||||
type SignableGatewayBondingMsg = SignableMessage<ContractMessageContent<GatewayBondingPayload>>;
|
||||
|
||||
// define this as a separate trait for mocking purposes
|
||||
#[async_trait]
|
||||
pub(crate) trait AddressAndNonceProvider {
|
||||
async fn get_signing_nonce(&self) -> Result<Nonce, NyxdError>;
|
||||
fn vesting_contract_address(&self) -> &AccountId;
|
||||
fn cw_address(&self) -> Addr;
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl AddressAndNonceProvider for Client<SigningNyxdClient> {
|
||||
async fn get_signing_nonce(&self) -> Result<Nonce, NyxdError> {
|
||||
self.nyxd.get_signing_nonce(self.nyxd.address()).await
|
||||
}
|
||||
|
||||
fn vesting_contract_address(&self) -> &AccountId {
|
||||
self.nyxd.vesting_contract_address()
|
||||
}
|
||||
|
||||
fn cw_address(&self) -> Addr {
|
||||
self.nyxd.cw_address()
|
||||
}
|
||||
}
|
||||
|
||||
fn proxy<P: AddressAndNonceProvider>(client: &P, vesting: bool) -> Option<Addr> {
|
||||
if vesting {
|
||||
// the call to unchecked is fine here as we're converting directly from `AccountId`
|
||||
// which must have been a valid bech32 address
|
||||
Some(Addr::unchecked(client.vesting_contract_address().as_ref()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
// since the message has to go back to the user due to the increasing nonce, we might as well sign the entire payload
|
||||
pub(crate) async fn create_mixnode_bonding_sign_payload<P: AddressAndNonceProvider>(
|
||||
client: &P,
|
||||
mix_node: MixNode,
|
||||
cost_params: MixNodeCostParams,
|
||||
pledge: Coin,
|
||||
vesting: bool,
|
||||
) -> Result<SignableMixNodeBondingMsg, BackendError> {
|
||||
let payload = MixnodeBondingPayload::new(mix_node, cost_params);
|
||||
let signer = client.cw_address();
|
||||
let proxy = proxy(client, vesting);
|
||||
let content = ContractMessageContent::new(signer, proxy, vec![pledge.into()], payload);
|
||||
let nonce = client.get_signing_nonce().await?;
|
||||
|
||||
Ok(SignableMessage::new(nonce, content))
|
||||
}
|
||||
|
||||
pub(crate) async fn verify_mixnode_bonding_sign_payload<P: AddressAndNonceProvider>(
|
||||
client: &P,
|
||||
mix_node: &MixNode,
|
||||
cost_params: &MixNodeCostParams,
|
||||
pledge: &Coin,
|
||||
vesting: bool,
|
||||
msg_signature: &MessageSignature,
|
||||
) -> Result<(), BackendError> {
|
||||
let identity_key = identity::PublicKey::from_base58_string(&mix_node.identity_key)?;
|
||||
let signature = identity::Signature::from_bytes(msg_signature.as_ref())?;
|
||||
|
||||
// recreate the plaintext
|
||||
let msg = create_mixnode_bonding_sign_payload(
|
||||
client,
|
||||
mix_node.clone(),
|
||||
cost_params.clone(),
|
||||
pledge.clone(),
|
||||
vesting,
|
||||
)
|
||||
.await?;
|
||||
let plaintext = msg.to_plaintext()?;
|
||||
|
||||
if !msg.algorithm.is_ed25519() {
|
||||
return Err(BackendError::UnexpectedSigningAlgorithm {
|
||||
received: msg.algorithm,
|
||||
expected: SigningAlgorithm::Ed25519,
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: possibly provide better error message if this check fails
|
||||
identity_key.verify(&plaintext, &signature)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// since the message has to go back to the user due to the increasing nonce, we might as well sign the entire payload
|
||||
pub(crate) async fn create_gateway_bonding_sign_payload<P: AddressAndNonceProvider>(
|
||||
client: &P,
|
||||
gateway: Gateway,
|
||||
pledge: Coin,
|
||||
vesting: bool,
|
||||
) -> Result<SignableGatewayBondingMsg, BackendError> {
|
||||
let payload = GatewayBondingPayload::new(gateway);
|
||||
let signer = client.cw_address();
|
||||
let proxy = proxy(client, vesting);
|
||||
let content = ContractMessageContent::new(signer, proxy, vec![pledge.into()], payload);
|
||||
let nonce = client.get_signing_nonce().await?;
|
||||
|
||||
Ok(SignableMessage::new(nonce, content))
|
||||
}
|
||||
|
||||
pub(crate) async fn verify_gateway_bonding_sign_payload<P: AddressAndNonceProvider>(
|
||||
client: &P,
|
||||
gateway: &Gateway,
|
||||
pledge: &Coin,
|
||||
vesting: bool,
|
||||
msg_signature: &MessageSignature,
|
||||
) -> Result<(), BackendError> {
|
||||
let identity_key = identity::PublicKey::from_base58_string(&gateway.identity_key)?;
|
||||
let signature = identity::Signature::from_bytes(msg_signature.as_ref())?;
|
||||
|
||||
// recreate the plaintext
|
||||
let msg = create_gateway_bonding_sign_payload(client, gateway.clone(), pledge.clone(), vesting)
|
||||
.await?;
|
||||
let plaintext = msg.to_plaintext()?;
|
||||
|
||||
if !msg.algorithm.is_ed25519() {
|
||||
return Err(BackendError::UnexpectedSigningAlgorithm {
|
||||
received: msg.algorithm,
|
||||
expected: SigningAlgorithm::Ed25519,
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: possibly provide better error message if this check fails
|
||||
identity_key.verify(&plaintext, &signature)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use cosmwasm_std::coin;
|
||||
use nym_contracts_common::Percent;
|
||||
use rand_chacha::rand_core::SeedableRng;
|
||||
use rand_chacha::ChaCha20Rng;
|
||||
|
||||
// use rng with constant seed for all tests so that they would be deterministic
|
||||
pub fn test_rng() -> ChaCha20Rng {
|
||||
let dummy_seed = [42u8; 32];
|
||||
rand_chacha::ChaCha20Rng::from_seed(dummy_seed)
|
||||
}
|
||||
|
||||
struct MockClient {
|
||||
address: Addr,
|
||||
vesting_contract: AccountId,
|
||||
signing_nonce: Nonce,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl AddressAndNonceProvider for MockClient {
|
||||
async fn get_signing_nonce(&self) -> Result<Nonce, NyxdError> {
|
||||
Ok(self.signing_nonce)
|
||||
}
|
||||
|
||||
fn vesting_contract_address(&self) -> &AccountId {
|
||||
&self.vesting_contract
|
||||
}
|
||||
|
||||
fn cw_address(&self) -> Addr {
|
||||
self.address.clone()
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn dummy_mix_bonding_signature_verification() {
|
||||
let mut rng = test_rng();
|
||||
let identity_keypair = identity::KeyPair::new(&mut rng);
|
||||
let dummy_mixnode = MixNode {
|
||||
host: "1.2.3.4".to_string(),
|
||||
mix_port: 1234,
|
||||
verloc_port: 2345,
|
||||
http_api_port: 3456,
|
||||
sphinx_key: "totally-legit-sphinx-key".to_string(),
|
||||
identity_key: identity_keypair.public_key().to_base58_string(),
|
||||
version: "v1.2.3".to_string(),
|
||||
};
|
||||
let dummy_cost_params = MixNodeCostParams {
|
||||
profit_margin_percent: Percent::from_percentage_value(42).unwrap(),
|
||||
interval_operating_cost: coin(1111111, "unym"),
|
||||
};
|
||||
let dummy_pledge: Coin = coin(10000000000, "unym").into();
|
||||
|
||||
let dummy_account = Addr::unchecked("n16t2umcd83zjpl5puyuuq6lgmy4p3qedjd8ynn6");
|
||||
let dummy_client = MockClient {
|
||||
address: dummy_account,
|
||||
vesting_contract: "n17tj0a0w6v7r2dc54rnkzfza6s8hxs87rj273a5".parse().unwrap(),
|
||||
signing_nonce: 42,
|
||||
};
|
||||
|
||||
let signing_msg_liquid = create_mixnode_bonding_sign_payload(
|
||||
&dummy_client,
|
||||
dummy_mixnode.clone(),
|
||||
dummy_cost_params.clone(),
|
||||
dummy_pledge.clone(),
|
||||
false,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let plaintext_liquid = signing_msg_liquid.to_plaintext().unwrap();
|
||||
let sig_liquid: MessageSignature = identity_keypair
|
||||
.private_key()
|
||||
.sign(&plaintext_liquid)
|
||||
.to_bytes()
|
||||
.as_ref()
|
||||
.into();
|
||||
|
||||
let signing_msg_vesting = create_mixnode_bonding_sign_payload(
|
||||
&dummy_client,
|
||||
dummy_mixnode.clone(),
|
||||
dummy_cost_params.clone(),
|
||||
dummy_pledge.clone(),
|
||||
true,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let plaintext_vesting = signing_msg_vesting.to_plaintext().unwrap();
|
||||
let sig_vesting: MessageSignature = identity_keypair
|
||||
.private_key()
|
||||
.sign(&plaintext_vesting)
|
||||
.to_bytes()
|
||||
.as_ref()
|
||||
.into();
|
||||
|
||||
let res = verify_mixnode_bonding_sign_payload(
|
||||
&dummy_client,
|
||||
&dummy_mixnode,
|
||||
&dummy_cost_params,
|
||||
&dummy_pledge,
|
||||
false,
|
||||
&sig_liquid,
|
||||
)
|
||||
.await;
|
||||
assert!(res.is_ok());
|
||||
|
||||
let res = verify_mixnode_bonding_sign_payload(
|
||||
&dummy_client,
|
||||
&dummy_mixnode,
|
||||
&dummy_cost_params,
|
||||
&dummy_pledge,
|
||||
true,
|
||||
&sig_vesting,
|
||||
)
|
||||
.await;
|
||||
assert!(res.is_ok());
|
||||
|
||||
let res = verify_mixnode_bonding_sign_payload(
|
||||
&dummy_client,
|
||||
&dummy_mixnode,
|
||||
&dummy_cost_params,
|
||||
&dummy_pledge,
|
||||
false,
|
||||
&sig_vesting,
|
||||
)
|
||||
.await;
|
||||
assert!(res.is_err());
|
||||
|
||||
let res = verify_mixnode_bonding_sign_payload(
|
||||
&dummy_client,
|
||||
&dummy_mixnode,
|
||||
&dummy_cost_params,
|
||||
&dummy_pledge,
|
||||
true,
|
||||
&sig_liquid,
|
||||
)
|
||||
.await;
|
||||
assert!(res.is_err())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn dummy_gateway_bonding_signature_verification() {
|
||||
let mut rng = test_rng();
|
||||
let identity_keypair = identity::KeyPair::new(&mut rng);
|
||||
let dummy_gateway = Gateway {
|
||||
host: "1.2.3.4".to_string(),
|
||||
mix_port: 1234,
|
||||
clients_port: 2345,
|
||||
location: "whatever".to_string(),
|
||||
sphinx_key: "totally-legit-sphinx-key".to_string(),
|
||||
identity_key: identity_keypair.public_key().to_base58_string(),
|
||||
version: "v1.2.3".to_string(),
|
||||
};
|
||||
|
||||
let dummy_pledge: Coin = coin(10000000000, "unym").into();
|
||||
|
||||
let dummy_account = Addr::unchecked("n16t2umcd83zjpl5puyuuq6lgmy4p3qedjd8ynn6");
|
||||
let dummy_client = MockClient {
|
||||
address: dummy_account,
|
||||
vesting_contract: "n17tj0a0w6v7r2dc54rnkzfza6s8hxs87rj273a5".parse().unwrap(),
|
||||
signing_nonce: 42,
|
||||
};
|
||||
|
||||
let signing_msg_liquid = create_gateway_bonding_sign_payload(
|
||||
&dummy_client,
|
||||
dummy_gateway.clone(),
|
||||
dummy_pledge.clone(),
|
||||
false,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let plaintext_liquid = signing_msg_liquid.to_plaintext().unwrap();
|
||||
let sig_liquid: MessageSignature = identity_keypair
|
||||
.private_key()
|
||||
.sign(&plaintext_liquid)
|
||||
.to_bytes()
|
||||
.as_ref()
|
||||
.into();
|
||||
|
||||
let signing_msg_vesting = create_gateway_bonding_sign_payload(
|
||||
&dummy_client,
|
||||
dummy_gateway.clone(),
|
||||
dummy_pledge.clone(),
|
||||
true,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let plaintext_vesting = signing_msg_vesting.to_plaintext().unwrap();
|
||||
let sig_vesting: MessageSignature = identity_keypair
|
||||
.private_key()
|
||||
.sign(&plaintext_vesting)
|
||||
.to_bytes()
|
||||
.as_ref()
|
||||
.into();
|
||||
|
||||
let res = verify_gateway_bonding_sign_payload(
|
||||
&dummy_client,
|
||||
&dummy_gateway,
|
||||
&dummy_pledge,
|
||||
false,
|
||||
&sig_liquid,
|
||||
)
|
||||
.await;
|
||||
assert!(res.is_ok());
|
||||
|
||||
let res = verify_gateway_bonding_sign_payload(
|
||||
&dummy_client,
|
||||
&dummy_gateway,
|
||||
&dummy_pledge,
|
||||
true,
|
||||
&sig_vesting,
|
||||
)
|
||||
.await;
|
||||
assert!(res.is_ok());
|
||||
|
||||
let res = verify_gateway_bonding_sign_payload(
|
||||
&dummy_client,
|
||||
&dummy_gateway,
|
||||
&dummy_pledge,
|
||||
false,
|
||||
&sig_vesting,
|
||||
)
|
||||
.await;
|
||||
assert!(res.is_err());
|
||||
|
||||
let res = verify_gateway_bonding_sign_payload(
|
||||
&dummy_client,
|
||||
&dummy_gateway,
|
||||
&dummy_pledge,
|
||||
true,
|
||||
&sig_liquid,
|
||||
)
|
||||
.await;
|
||||
assert!(res.is_err())
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,10 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::error::BackendError;
|
||||
use crate::operations::helpers::verify_mixnode_bonding_sign_payload;
|
||||
use crate::state::WalletState;
|
||||
use crate::{nyxd_client, Gateway, MixNode};
|
||||
use nym_contracts_common::signing::MessageSignature;
|
||||
use nym_mixnet_contract_common::{MixId, MixNodeConfigUpdate};
|
||||
use nym_types::currency::DecCoin;
|
||||
use nym_types::gateway::GatewayBond;
|
||||
@@ -73,7 +75,7 @@ pub async fn unbond_gateway(
|
||||
pub async fn bond_mixnode(
|
||||
mixnode: MixNode,
|
||||
cost_params: MixNodeCostParams,
|
||||
owner_signature: String,
|
||||
msg_signature: MessageSignature,
|
||||
pledge: DecCoin,
|
||||
fee: Option<Fee>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
@@ -90,10 +92,31 @@ pub async fn bond_mixnode(
|
||||
pledge_base,
|
||||
fee,
|
||||
);
|
||||
let res = guard
|
||||
.current_client()?
|
||||
|
||||
let client = guard.current_client()?;
|
||||
// check the signature to make sure the user copied it correctly
|
||||
if let Err(err) = verify_mixnode_bonding_sign_payload(
|
||||
client,
|
||||
&mixnode,
|
||||
&cost_params,
|
||||
&pledge_base,
|
||||
false,
|
||||
&msg_signature,
|
||||
)
|
||||
.await
|
||||
{
|
||||
todo!()
|
||||
}
|
||||
|
||||
let res = client
|
||||
.nyxd
|
||||
.bond_mixnode(mixnode, cost_params, owner_signature, pledge_base, fee)
|
||||
.bond_mixnode(
|
||||
mixnode,
|
||||
cost_params,
|
||||
msg_signature.as_bs58_string(),
|
||||
pledge_base,
|
||||
fee,
|
||||
)
|
||||
.await?;
|
||||
log::info!("<<< tx hash = {}", res.transaction_hash);
|
||||
log::trace!("<<< {:?}", res);
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
// Copyright 2021-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod help;
|
||||
pub(crate) mod helpers;
|
||||
pub mod mixnet;
|
||||
pub mod nym_api;
|
||||
pub mod signatures;
|
||||
|
||||
Reference in New Issue
Block a user