diff --git a/common/commands/src/validator/mixnet/operators/gateway/gateway_bonding_sign_payload.rs b/common/commands/src/validator/mixnet/operators/gateway/gateway_bonding_sign_payload.rs index ba19f618674..0747dcac3c7 100644 --- a/common/commands/src/validator/mixnet/operators/gateway/gateway_bonding_sign_payload.rs +++ b/common/commands/src/validator/mixnet/operators/gateway/gateway_bonding_sign_payload.rs @@ -6,7 +6,7 @@ use crate::utils::{account_id_to_cw_addr, DataWrapper}; use clap::Parser; use cosmwasm_std::Coin; use nym_bin_common::output_format::OutputFormat; -use nym_mixnet_contract_common::construct_gateway_bonding_sign_payload; +use nym_mixnet_contract_common::construct_legacy_gateway_bonding_sign_payload; use nym_network_defaults::{DEFAULT_CLIENT_LISTENING_PORT, DEFAULT_MIX_LISTENING_PORT}; use nym_validator_client::nyxd::contract_traits::MixnetQueryClient; @@ -71,7 +71,7 @@ pub async fn create_payload(args: Args, client: SigningClient) { let address = account_id_to_cw_addr(&client.address()); - let payload = construct_gateway_bonding_sign_payload(nonce, address, coin, gateway); + let payload = construct_legacy_gateway_bonding_sign_payload(nonce, address, coin, gateway); let wrapper = DataWrapper::new(payload.to_base58_string().unwrap()); println!("{}", args.output.format(&wrapper)) } diff --git a/common/commands/src/validator/mixnet/operators/mixnode/mixnode_bonding_sign_payload.rs b/common/commands/src/validator/mixnet/operators/mixnode/mixnode_bonding_sign_payload.rs index a492b3a0b6d..3eda67a2e9a 100644 --- a/common/commands/src/validator/mixnet/operators/mixnode/mixnode_bonding_sign_payload.rs +++ b/common/commands/src/validator/mixnet/operators/mixnode/mixnode_bonding_sign_payload.rs @@ -7,7 +7,9 @@ use clap::Parser; use cosmwasm_std::{Coin, Uint128}; use nym_bin_common::output_format::OutputFormat; use nym_contracts_common::Percent; -use nym_mixnet_contract_common::{construct_mixnode_bonding_sign_payload, MixNodeCostParams}; +use nym_mixnet_contract_common::{ + construct_legacy_mixnode_bonding_sign_payload, MixNodeCostParams, +}; use nym_network_defaults::{ DEFAULT_HTTP_API_LISTENING_PORT, DEFAULT_MIX_LISTENING_PORT, DEFAULT_VERLOC_LISTENING_PORT, }; @@ -98,7 +100,7 @@ pub async fn create_payload(args: Args, client: SigningClient) { let address = account_id_to_cw_addr(&client.address()); let payload = - construct_mixnode_bonding_sign_payload(nonce, address, coin, mixnode, cost_params); + construct_legacy_mixnode_bonding_sign_payload(nonce, address, coin, mixnode, cost_params); let wrapper = DataWrapper::new(payload.to_base58_string().unwrap()); println!("{}", args.output.format(&wrapper)) } diff --git a/common/cosmwasm-smart-contracts/contracts-common/src/signing/mod.rs b/common/cosmwasm-smart-contracts/contracts-common/src/signing/mod.rs index d2722b2f597..228e188b844 100644 --- a/common/cosmwasm-smart-contracts/contracts-common/src/signing/mod.rs +++ b/common/cosmwasm-smart-contracts/contracts-common/src/signing/mod.rs @@ -248,3 +248,31 @@ impl ContractMessageContent { } } } + +impl From> for LegacyContractMessageContent { + fn from(value: ContractMessageContent) -> Self { + LegacyContractMessageContent { + sender: value.sender, + proxy: None, + funds: value.funds, + data: value.data, + } + } +} + +#[derive(Serialize)] +pub struct LegacyContractMessageContent { + pub sender: Addr, + pub proxy: Option, + pub funds: Vec, + pub data: T, +} + +impl SigningPurpose for LegacyContractMessageContent +where + T: SigningPurpose, +{ + fn message_type() -> MessageType { + T::message_type() + } +} diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/src/signing_types.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/signing_types.rs index 84c9b8b4aaf..261fa99ff05 100644 --- a/common/cosmwasm-smart-contracts/mixnet-contract/src/signing_types.rs +++ b/common/cosmwasm-smart-contracts/mixnet-contract/src/signing_types.rs @@ -4,13 +4,18 @@ use crate::families::FamilyHead; use crate::{Gateway, IdentityKey, MixNode, MixNodeCostParams}; use contracts_common::signing::{ - ContractMessageContent, MessageType, Nonce, SignableMessage, SigningPurpose, + ContractMessageContent, LegacyContractMessageContent, MessageType, Nonce, SignableMessage, + SigningPurpose, }; use cosmwasm_std::{Addr, Coin}; use serde::Serialize; pub type SignableMixNodeBondingMsg = SignableMessage>; pub type SignableGatewayBondingMsg = SignableMessage>; +pub type SignableLegacyMixNodeBondingMsg = + SignableMessage>; +pub type SignableLegacyGatewayBondingMsg = + SignableMessage>; pub type SignableFamilyJoinPermitMsg = SignableMessage; #[derive(Serialize)] @@ -47,6 +52,20 @@ pub fn construct_mixnode_bonding_sign_payload( SignableMessage::new(nonce, content) } +pub fn construct_legacy_mixnode_bonding_sign_payload( + nonce: Nonce, + sender: Addr, + pledge: Coin, + mix_node: MixNode, + cost_params: MixNodeCostParams, +) -> SignableLegacyMixNodeBondingMsg { + let payload = MixnodeBondingPayload::new(mix_node, cost_params); + let content: LegacyContractMessageContent<_> = + ContractMessageContent::new(sender, vec![pledge], payload).into(); + + SignableMessage::new(nonce, content) +} + #[derive(Serialize)] pub struct GatewayBondingPayload { gateway: Gateway, @@ -76,6 +95,19 @@ pub fn construct_gateway_bonding_sign_payload( SignableMessage::new(nonce, content) } +pub fn construct_legacy_gateway_bonding_sign_payload( + nonce: Nonce, + sender: Addr, + pledge: Coin, + gateway: Gateway, +) -> SignableLegacyGatewayBondingMsg { + let payload = GatewayBondingPayload::new(gateway); + let content: LegacyContractMessageContent<_> = + ContractMessageContent::new(sender, vec![pledge], payload).into(); + + SignableMessage::new(nonce, content) +} + #[derive(Serialize)] pub struct FamilyJoinPermit { // the granter of this permit diff --git a/contracts/mixnet/src/gateways/signature_helpers.rs b/contracts/mixnet/src/gateways/signature_helpers.rs index 46d37c60731..6f9b7125543 100644 --- a/contracts/mixnet/src/gateways/signature_helpers.rs +++ b/contracts/mixnet/src/gateways/signature_helpers.rs @@ -5,7 +5,9 @@ use crate::signing::storage as signing_storage; use crate::support::helpers::decode_ed25519_identity_key; use cosmwasm_std::{Addr, Coin, Deps}; use mixnet_contract_common::error::MixnetContractError; -use mixnet_contract_common::{construct_gateway_bonding_sign_payload, Gateway}; +use mixnet_contract_common::{ + construct_gateway_bonding_sign_payload, construct_legacy_gateway_bonding_sign_payload, Gateway, +}; use nym_contracts_common::signing::MessageSignature; use nym_contracts_common::signing::Verifier; @@ -19,13 +21,31 @@ pub(crate) fn verify_gateway_bonding_signature( // recover the public key let public_key = decode_ed25519_identity_key(&gateway.identity_key)?; - // reconstruct the payload + // reconstruct the payload, first try the current format, then attempt legacy let nonce = signing_storage::get_signing_nonce(deps.storage, sender.clone())?; - let msg = construct_gateway_bonding_sign_payload(nonce, sender, pledge, gateway); + let msg = construct_gateway_bonding_sign_payload( + nonce, + sender.clone(), + pledge.clone(), + gateway.clone(), + ); - if deps.api.verify_message(msg, signature, &public_key)? { + if deps + .api + .verify_message(msg, signature.clone(), &public_key)? + { Ok(()) } else { - Err(MixnetContractError::InvalidEd25519Signature) + // attempt to use legacy + let msg_legacy = + construct_legacy_gateway_bonding_sign_payload(nonce, sender, pledge, gateway); + if deps + .api + .verify_message(msg_legacy, signature, &public_key)? + { + Ok(()) + } else { + Err(MixnetContractError::InvalidEd25519Signature) + } } } diff --git a/contracts/mixnet/src/mixnodes/signature_helpers.rs b/contracts/mixnet/src/mixnodes/signature_helpers.rs index 975bb556693..04942aaff5e 100644 --- a/contracts/mixnet/src/mixnodes/signature_helpers.rs +++ b/contracts/mixnet/src/mixnodes/signature_helpers.rs @@ -5,7 +5,10 @@ use crate::signing::storage as signing_storage; use crate::support::helpers::decode_ed25519_identity_key; use cosmwasm_std::{Addr, Coin, Deps}; use mixnet_contract_common::error::MixnetContractError; -use mixnet_contract_common::{construct_mixnode_bonding_sign_payload, MixNode, MixNodeCostParams}; +use mixnet_contract_common::{ + construct_legacy_mixnode_bonding_sign_payload, construct_mixnode_bonding_sign_payload, MixNode, + MixNodeCostParams, +}; use nym_contracts_common::signing::MessageSignature; use nym_contracts_common::signing::Verifier; @@ -20,13 +23,37 @@ pub(crate) fn verify_mixnode_bonding_signature( // recover the public key let public_key = decode_ed25519_identity_key(&mixnode.identity_key)?; - // reconstruct the payload + // reconstruct the payload, first try the current format, then attempt legacy let nonce = signing_storage::get_signing_nonce(deps.storage, sender.clone())?; - let msg = construct_mixnode_bonding_sign_payload(nonce, sender, pledge, mixnode, cost_params); + let msg = construct_mixnode_bonding_sign_payload( + nonce, + sender.clone(), + pledge.clone(), + mixnode.clone(), + cost_params.clone(), + ); - if deps.api.verify_message(msg, signature, &public_key)? { + if deps + .api + .verify_message(msg, signature.clone(), &public_key)? + { Ok(()) } else { - Err(MixnetContractError::InvalidEd25519Signature) + // attempt to use legacy + let msg_legacy = construct_legacy_mixnode_bonding_sign_payload( + nonce, + sender, + pledge, + mixnode, + cost_params, + ); + if deps + .api + .verify_message(msg_legacy, signature, &public_key)? + { + Ok(()) + } else { + Err(MixnetContractError::InvalidEd25519Signature) + } } } diff --git a/nym-wallet/src-tauri/src/operations/helpers.rs b/nym-wallet/src-tauri/src/operations/helpers.rs index 2b5631eb580..da0093e2938 100644 --- a/nym-wallet/src-tauri/src/operations/helpers.rs +++ b/nym-wallet/src-tauri/src/operations/helpers.rs @@ -9,8 +9,8 @@ use nym_contracts_common::signing::{ }; use nym_crypto::asymmetric::identity; use nym_mixnet_contract_common::{ - construct_mixnode_bonding_sign_payload, Gateway, GatewayBondingPayload, MixNode, - MixNodeCostParams, SignableGatewayBondingMsg, SignableMixNodeBondingMsg, + construct_legacy_mixnode_bonding_sign_payload, Gateway, GatewayBondingPayload, MixNode, + MixNodeCostParams, SignableGatewayBondingMsg, SignableLegacyMixNodeBondingMsg, }; use nym_validator_client::nyxd::contract_traits::MixnetQueryClient; use nym_validator_client::nyxd::error::NyxdError; @@ -42,14 +42,14 @@ pub(crate) async fn create_mixnode_bonding_sign_payload Result { +) -> Result { if vesting { return Err(BackendError::UnsupportedVestingOperation); } let sender = client.cw_address(); let nonce = client.get_signing_nonce().await?; - Ok(construct_mixnode_bonding_sign_payload( + Ok(construct_legacy_mixnode_bonding_sign_payload( nonce, sender, pledge.into(),