diff --git a/common/cosmwasm-smart-contracts/name-service/Cargo.toml b/common/cosmwasm-smart-contracts/name-service/Cargo.toml deleted file mode 100644 index 5e3a3081bd..0000000000 --- a/common/cosmwasm-smart-contracts/name-service/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "nym-name-service-common" -version = "0.1.0" -edition = "2021" -license.workspace = true - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -cosmwasm-schema = { workspace = true } -cosmwasm-std = { workspace = true } -cw2 = { workspace = true, optional = true } -cw-controllers = { workspace = true } -cw-utils = { workspace = true } -nym-contracts-common = { path = "../contracts-common", version = "0.5.0" } -serde = { workspace = true, features = ["derive"] } -thiserror = { workspace = true } - -[features] -schema = ["cw2"] diff --git a/common/cosmwasm-smart-contracts/name-service/src/error.rs b/common/cosmwasm-smart-contracts/name-service/src/error.rs deleted file mode 100644 index 24d62c23cf..0000000000 --- a/common/cosmwasm-smart-contracts/name-service/src/error.rs +++ /dev/null @@ -1,83 +0,0 @@ -use cosmwasm_std::{Addr, StdError}; -use cw_controllers::AdminError; -use nym_contracts_common::signing::verifier::ApiVerifierError; -use thiserror::Error; - -use crate::{Address, NameId, NymName}; - -#[derive(Error, Debug, PartialEq)] -pub enum NameServiceError { - #[error("{0}")] - Std(#[from] StdError), - - #[error("{0}")] - AdminError(#[from] AdminError), - - #[error("name id entry not found: {name_id}")] - NotFound { name_id: NameId }, - - #[error("name entry not found: {name}")] - NameNotFound { name: NymName }, - - #[error("{sender} is not registrator of name")] - Unauthorized { sender: Addr }, - - #[error("deposit required to register a name")] - DepositRequired { source: cw_utils::PaymentError }, - - #[error("insufficiant deposit: {funds}, required: {deposit_required}")] - InsufficientDeposit { - funds: cosmwasm_std::Uint128, - deposit_required: cosmwasm_std::Uint128, - }, - - #[error("deposit too large: {funds}, required: {deposit_required}")] - TooLargeDeposit { - funds: cosmwasm_std::Uint128, - deposit_required: cosmwasm_std::Uint128, - }, - - #[error("reached the max number of names ({max_names}) for owner {owner}")] - ReachedMaxNamesForOwner { max_names: u32, owner: Addr }, - - #[error("reached the max number of names ({max_names}) for address {0}", address.to_string())] - ReachedMaxNamesForAddress { max_names: u32, address: Address }, - - #[error("failed to parse {value} into a valid SemVer version: {error_message}")] - SemVerFailure { - value: String, - error_message: String, - }, - - #[error("failed to recover ed25519 public key from its base58 representation: {0}")] - MalformedEd25519IdentityKey(String), - - #[error("failed to recover ed25519 signature from its base58 representation: {0}")] - MalformedEd25519Signature(String), - - #[error("provided ed25519 signature did not verify correctly")] - InvalidEd25519Signature, - - #[error("failed to verify message signature: {source}")] - SignatureVerificationFailure { - #[from] - source: ApiVerifierError, - }, - - #[error("duplicate entries detected for name: {name}")] - DuplicateNames { name: NymName }, - - #[error("name already registered: {name}")] - NameAlreadyRegistered { name: NymName }, - - #[error("invalid nym address format: {0}")] - InvalidNymAddress(String), - - #[error("client identity in nym address does not match the provided identity key")] - IdentityKeyMismatch { - address: Address, - identity_key: String, - }, -} - -pub type Result = std::result::Result; diff --git a/common/cosmwasm-smart-contracts/name-service/src/events.rs b/common/cosmwasm-smart-contracts/name-service/src/events.rs deleted file mode 100644 index 5bf65e606d..0000000000 --- a/common/cosmwasm-smart-contracts/name-service/src/events.rs +++ /dev/null @@ -1,66 +0,0 @@ -use cosmwasm_std::{Coin, Event}; - -use crate::RegisteredName; - -pub enum NameEventType { - Register, - DeleteId, - DeleteName, - UpdateDepositRequired, -} - -impl std::fmt::Display for NameEventType { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - NameEventType::Register => write!(f, "register"), - NameEventType::DeleteId => write!(f, "delete_id"), - NameEventType::DeleteName => write!(f, "delete_name"), - NameEventType::UpdateDepositRequired => write!(f, "update_deposit_required"), - } - } -} - -impl From for String { - fn from(event_type: NameEventType) -> Self { - event_type.to_string() - } -} - -pub const ACTION: &str = "action"; - -pub const NAME_ID: &str = "name_id"; -pub const NAME: &str = "name"; -pub const OWNER: &str = "owner"; - -pub const DEPOSIT_REQUIRED: &str = "deposit_required"; - -pub fn new_register_event(name: RegisteredName) -> Event { - Event::new(NameEventType::Register) - .add_attribute(ACTION, NameEventType::Register) - .add_attribute(NAME_ID, name.id.to_string()) - .add_attribute(NAME, name.name.name.to_string()) - .add_attribute(name.name.address.event_tag(), name.name.address.to_string()) - .add_attribute(OWNER, name.owner.to_string()) -} - -pub fn new_delete_id_event(name: RegisteredName) -> Event { - Event::new(NameEventType::DeleteId) - .add_attribute(ACTION, NameEventType::DeleteId) - .add_attribute(NAME_ID, name.id.to_string()) - .add_attribute(NAME, name.name.name.to_string()) - .add_attribute(name.name.address.event_tag(), name.name.address.to_string()) -} - -pub fn new_delete_name_event(name: RegisteredName) -> Event { - Event::new(NameEventType::DeleteId) - .add_attribute(ACTION, NameEventType::DeleteName) - .add_attribute(NAME_ID, name.id.to_string()) - .add_attribute(NAME, name.name.name.to_string()) - .add_attribute(name.name.address.event_tag(), name.name.address.to_string()) -} - -pub fn new_update_deposit_required_event(deposit_required: Coin) -> Event { - Event::new(NameEventType::UpdateDepositRequired) - .add_attribute(ACTION, NameEventType::UpdateDepositRequired) - .add_attribute(DEPOSIT_REQUIRED, deposit_required.to_string()) -} diff --git a/common/cosmwasm-smart-contracts/name-service/src/lib.rs b/common/cosmwasm-smart-contracts/name-service/src/lib.rs deleted file mode 100644 index 71a702b7c1..0000000000 --- a/common/cosmwasm-smart-contracts/name-service/src/lib.rs +++ /dev/null @@ -1,11 +0,0 @@ -pub mod error; -pub mod events; -pub mod msg; -pub mod response; -pub mod signing_types; -pub mod types; - -// Re-export all types at the top-level -pub use types::*; - -pub use cosmwasm_std::{Addr, Coin, Decimal, Fraction}; diff --git a/common/cosmwasm-smart-contracts/name-service/src/msg.rs b/common/cosmwasm-smart-contracts/name-service/src/msg.rs deleted file mode 100644 index cdac95c215..0000000000 --- a/common/cosmwasm-smart-contracts/name-service/src/msg.rs +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright 2023 - Nym Technologies SA -// SPDX-License-Identifier: Apache-2.0 - -use crate::{Address, NameDetails, NameId, NymName}; -use cosmwasm_schema::cw_serde; -use cosmwasm_std::Coin; -use nym_contracts_common::signing::MessageSignature; - -#[cfg(feature = "schema")] -use crate::{ - response::{ConfigResponse, NamesListResponse, PagedNamesListResponse}, - types::RegisteredName, -}; -#[cfg(feature = "schema")] -use cosmwasm_schema::QueryResponses; -#[cfg(feature = "schema")] -use nym_contracts_common::{signing::Nonce, ContractBuildInformation}; - -#[cw_serde] -pub struct InstantiateMsg { - pub deposit_required: Coin, -} - -impl InstantiateMsg { - pub fn new(deposit_required: Coin) -> Self { - Self { deposit_required } - } -} - -#[cw_serde] -pub struct MigrateMsg {} - -#[cw_serde] -pub enum ExecuteMsg { - /// Announcing a name pointing to a nym-address - Register { - name: NameDetails, - owner_signature: MessageSignature, - }, - - /// Delete a name entry by id - DeleteId { name_id: NameId }, - - /// Delete a name entry by name - DeleteName { name: NymName }, - - /// Change the deposit required for announcing a name - UpdateDepositRequired { deposit_required: Coin }, -} - -impl ExecuteMsg { - pub fn delete_id(name_id: NameId) -> Self { - ExecuteMsg::DeleteId { name_id } - } - - pub fn default_memo(&self) -> String { - match self { - ExecuteMsg::Register { - name, - owner_signature: _, - } => { - format!("registering {} as name: {}", name.address, name.name) - } - ExecuteMsg::DeleteId { name_id } => { - format!("deleting name with id {name_id}") - } - ExecuteMsg::DeleteName { name } => { - format!("deleting name: {name}") - } - ExecuteMsg::UpdateDepositRequired { deposit_required } => { - format!("updating the deposit required to {deposit_required}") - } - } - } -} - -#[cw_serde] -#[cfg_attr(feature = "schema", derive(QueryResponses))] -pub enum QueryMsg { - /// Query the name by it's assigned id - #[cfg_attr(feature = "schema", returns(RegisteredName))] - NameId { name_id: NameId }, - - /// Query the names by the registrator - #[cfg_attr(feature = "schema", returns(NamesListResponse))] - ByOwner { owner: String }, - - #[cfg_attr(feature = "schema", returns(RegisteredName))] - ByName { name: NymName }, - - #[cfg_attr(feature = "schema", returns(NamesListResponse))] - ByAddress { address: Address }, - - #[cfg_attr(feature = "schema", returns(PagedNamesListResponse))] - All { - limit: Option, - start_after: Option, - }, - - #[cfg_attr(feature = "schema", returns(Nonce))] - SigningNonce { address: String }, - - #[cfg_attr(feature = "schema", returns(ConfigResponse))] - Config {}, - - /// Gets build information of this contract, such as the commit hash used for the build or rustc version. - #[cfg_attr(feature = "schema", returns(ContractBuildInformation))] - GetContractVersion {}, - - /// Gets the stored contract version information that's required by the CW2 spec interface for migrations. - #[serde(rename = "get_cw2_contract_version")] - #[cfg_attr(feature = "schema", returns(cw2::ContractVersion))] - GetCW2ContractVersion {}, -} - -impl QueryMsg { - pub fn all() -> QueryMsg { - QueryMsg::All { - limit: None, - start_after: None, - } - } -} diff --git a/common/cosmwasm-smart-contracts/name-service/src/response.rs b/common/cosmwasm-smart-contracts/name-service/src/response.rs deleted file mode 100644 index 162021d7c7..0000000000 --- a/common/cosmwasm-smart-contracts/name-service/src/response.rs +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2023 - Nym Technologies SA -// SPDX-License-Identifier: Apache-2.0 - -use crate::{NameId, RegisteredName}; -use cosmwasm_schema::cw_serde; -use cosmwasm_std::Coin; - -#[cw_serde] -pub struct NamesListResponse { - pub names: Vec, -} - -impl NamesListResponse { - pub fn new(names: Vec) -> NamesListResponse { - NamesListResponse { names } - } -} - -impl From<&[RegisteredName]> for NamesListResponse { - fn from(names: &[RegisteredName]) -> Self { - NamesListResponse { - names: names.to_vec(), - } - } -} - -#[cw_serde] -pub struct PagedNamesListResponse { - pub names: Vec, - pub per_page: usize, - - /// Field indicating paging information for the following queries if the caller wishes to get further entries. - pub start_next_after: Option, -} - -impl PagedNamesListResponse { - pub fn new( - names: Vec, - per_page: usize, - start_next_after: Option, - ) -> PagedNamesListResponse { - PagedNamesListResponse { - names, - per_page, - start_next_after, - } - } -} - -#[cw_serde] -pub struct ConfigResponse { - pub deposit_required: Coin, -} diff --git a/common/cosmwasm-smart-contracts/name-service/src/signing_types.rs b/common/cosmwasm-smart-contracts/name-service/src/signing_types.rs deleted file mode 100644 index 80a19a7e3d..0000000000 --- a/common/cosmwasm-smart-contracts/name-service/src/signing_types.rs +++ /dev/null @@ -1,32 +0,0 @@ -use cosmwasm_std::{Addr, Coin}; -use nym_contracts_common::signing::{ - ContractMessageContent, MessageType, Nonce, SignableMessage, SigningPurpose, -}; -use serde::Serialize; - -use crate::NameDetails; - -pub type SignableNameRegisterMsg = SignableMessage>; - -#[derive(Serialize)] -pub struct NameRegister { - name: NameDetails, -} - -impl SigningPurpose for NameRegister { - fn message_type() -> MessageType { - MessageType::new("name-register") - } -} - -pub fn construct_name_register_sign_payload( - nonce: Nonce, - sender: Addr, - deposit: Coin, - name: NameDetails, -) -> SignableNameRegisterMsg { - let payload = NameRegister { name }; - let proxy = None; - let content = ContractMessageContent::new(sender, proxy, vec![deposit], payload); - SignableMessage::new(nonce, content) -} diff --git a/common/cosmwasm-smart-contracts/name-service/src/types.rs b/common/cosmwasm-smart-contracts/name-service/src/types.rs deleted file mode 100644 index 58746576a6..0000000000 --- a/common/cosmwasm-smart-contracts/name-service/src/types.rs +++ /dev/null @@ -1,252 +0,0 @@ -// Copyright 2023 - Nym Technologies SA -// SPDX-License-Identifier: Apache-2.0 - -use cosmwasm_schema::cw_serde; -use cosmwasm_std::{Addr, Coin}; -use nym_contracts_common::IdentityKey; -use std::{ - fmt::{Display, Formatter}, - str::FromStr, -}; -use thiserror::Error; - -use crate::error::{NameServiceError, Result}; - -/// The directory of names are indexed by [`NameId`]. -pub type NameId = u32; - -#[cw_serde] -pub struct RegisteredName { - /// Unique id assigned to the registerd name. - pub id: NameId, - - /// The registerd name details. - pub name: NameDetails, - - /// name owner. - pub owner: Addr, - - /// Block height at which the name was added. - pub block_height: u64, - - /// The deposit used to announce the name. - pub deposit: Coin, -} - -impl RegisteredName { - // Shortcut for getting the actual name - pub fn entry(&self) -> &NymName { - &self.name.name - } -} - -#[cw_serde] -pub struct NameDetails { - /// The name pointing to the nym address - pub name: NymName, - - /// The address of the name alias. - pub address: Address, - - /// The identity key of the registered name. - pub identity_key: IdentityKey, -} - -/// String representation of a nym address, which is of the form -/// client_id.client_enc@gateway_id. -/// NOTE: entirely unvalidated. -#[cw_serde] -pub enum Address { - NymAddress(NymAddressInner), - // Possible extension: - //Gateway(String) -} - -#[cw_serde] -pub struct NymAddressInner { - client_id: String, - client_enc: String, - gateway_id: String, -} - -// ADDRESS . ENCRYPTION @ GATEWAY_ID -impl std::fmt::Display for NymAddressInner { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!( - f, - "{}.{}@{}", - self.client_id, self.client_enc, self.gateway_id - ) - } -} - -impl Address { - /// Create a new nym address. - pub fn new(address: &str) -> Result { - parse_nym_address(address) - .map(Self::NymAddress) - .ok_or_else(|| NameServiceError::InvalidNymAddress(address.to_string())) - } - - pub fn client_id(&self) -> &str { - match self { - Address::NymAddress(address) => &address.client_id, - } - } - - pub fn client_enc(&self) -> &str { - match self { - Address::NymAddress(address) => &address.client_enc, - } - } - - pub fn gateway_id(&self) -> &str { - match self { - Address::NymAddress(address) => &address.gateway_id, - } - } - - pub fn event_tag(&self) -> &str { - match self { - Address::NymAddress(_) => "nym_address", - //Address::Gateway(_) => "gatway_address", - } - } -} - -impl Display for Address { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - match self { - Address::NymAddress(address) => write!(f, "{}", address), - } - } -} - -// A valid nym address is of the form client_id.client_enc@gateway_id -fn parse_nym_address(address: &str) -> Option { - let parts: Vec<&str> = address.split('@').collect(); - if parts.len() != 2 { - return None; - } - - let client_part = parts[0]; - let gateway_part = parts[1]; - - // The client part consists of two parts separated by a dot - let client_parts: Vec<&str> = client_part.split('.').collect(); - if client_parts.len() != 2 { - return None; - } - - // Check that the gateway part does not contain any dots - if gateway_part.contains('.') { - return None; - } - - Some(NymAddressInner { - client_id: client_parts[0].to_string(), - client_enc: client_parts[1].to_string(), - gateway_id: gateway_part.to_string(), - }) -} - -/// Name stored and pointing a to a nym-address -#[cw_serde] -pub struct NymName(String); - -#[derive(Debug, Error)] -pub enum NymNameError { - #[error("invalid name")] - InvalidName, -} - -/// Defines what names are allowed -fn is_valid_name_char(c: char) -> bool { - // Normal lowercase letters - (c.is_alphabetic() && c.is_lowercase()) - // or numbers - || c.is_numeric() - // special case hyphen or underscore - || c == '-' || c == '_' -} - -impl NymName { - pub fn new(name: &str) -> Result { - // We are a bit restrictive in which names we allow, to start out with. Consider relaxing - // this in the future. - if !name.chars().all(is_valid_name_char) { - return Err(NymNameError::InvalidName); - } - Ok(Self(name.to_string())) - } - - pub fn as_str(&self) -> &str { - &self.0 - } -} - -impl FromStr for NymName { - type Err = NymNameError; - - fn from_str(s: &str) -> Result { - Self::new(s) - } -} - -impl Display for NymName { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.0) - } -} - -#[cfg(test)] -mod tests { - use super::NymName; - - #[test] - fn parse_nym_name() { - // Test some valid cases - assert!(NymName::new("foo").is_ok()); - assert!(NymName::new("foo-bar").is_ok()); - assert!(NymName::new("foo-bar-123").is_ok()); - assert!(NymName::new("foo_bar").is_ok()); - assert!(NymName::new("foo_bar_123").is_ok()); - - // And now test all some invalid ones - assert!(NymName::new("Foo").is_err()); - assert!(NymName::new("foo bar").is_err()); - assert!(NymName::new("foo!bar").is_err()); - assert!(NymName::new("foo#bar").is_err()); - assert!(NymName::new("foo$bar").is_err()); - assert!(NymName::new("foo%bar").is_err()); - assert!(NymName::new("foo&bar").is_err()); - assert!(NymName::new("foo'bar").is_err()); - assert!(NymName::new("foo(bar").is_err()); - assert!(NymName::new("foo)bar").is_err()); - assert!(NymName::new("foo*bar").is_err()); - assert!(NymName::new("foo+bar").is_err()); - assert!(NymName::new("foo,bar").is_err()); - assert!(NymName::new("foo.bar").is_err()); - assert!(NymName::new("foo.bar").is_err()); - assert!(NymName::new("foo/bar").is_err()); - assert!(NymName::new("foo/bar").is_err()); - assert!(NymName::new("foo:bar").is_err()); - assert!(NymName::new("foo;bar").is_err()); - assert!(NymName::new("foobar").is_err()); - assert!(NymName::new("foo?bar").is_err()); - assert!(NymName::new("foo@bar").is_err()); - assert!(NymName::new("fooBar").is_err()); - assert!(NymName::new("foo[bar").is_err()); - assert!(NymName::new("foo\"bar").is_err()); - assert!(NymName::new("foo\\bar").is_err()); - assert!(NymName::new("foo]bar").is_err()); - assert!(NymName::new("foo^bar").is_err()); - assert!(NymName::new("foo`bar").is_err()); - assert!(NymName::new("foo{bar").is_err()); - assert!(NymName::new("foo|bar").is_err()); - assert!(NymName::new("foo}bar").is_err()); - assert!(NymName::new("foo~bar").is_err()); - } -}