Purge nym-name-service-common

This commit is contained in:
Jon Häggblad
2024-05-20 09:13:17 +02:00
parent 12c4450527
commit 1ae718c345
8 changed files with 0 additions and 640 deletions
@@ -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"]
@@ -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<T, E = NameServiceError> = std::result::Result<T, E>;
@@ -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<NameEventType> 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())
}
@@ -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};
@@ -1,123 +0,0 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// 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<u32>,
start_after: Option<NameId>,
},
#[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,
}
}
}
@@ -1,53 +0,0 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// 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<RegisteredName>,
}
impl NamesListResponse {
pub fn new(names: Vec<RegisteredName>) -> 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<RegisteredName>,
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<NameId>,
}
impl PagedNamesListResponse {
pub fn new(
names: Vec<RegisteredName>,
per_page: usize,
start_next_after: Option<NameId>,
) -> PagedNamesListResponse {
PagedNamesListResponse {
names,
per_page,
start_next_after,
}
}
}
#[cw_serde]
pub struct ConfigResponse {
pub deposit_required: Coin,
}
@@ -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<ContractMessageContent<NameRegister>>;
#[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)
}
@@ -1,252 +0,0 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// 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<Self> {
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<NymAddressInner> {
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<NymName, NymNameError> {
// 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, Self::Err> {
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("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("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());
}
}