---
# System prepended metadata

title: 'Nom - Name Registry DNA ERD, Entry Structures, Validations'
tags: [Technical Specification]

---

# Nom - Name Registry DNA ERD, Entry Structures, Validations

###### tags: `Technical Specification`

### Diagram for Links/Paths/Entries

**Instruction for reading**
- **Solid borders:** DHT Entry 
- **Dashed borders:** Path
- **Solid arrows:** Represent a `Link`s
- **Dashed arrows(only between Entries):** Indicates that the Entry contains the EntryHash of the Entry being pointed to
#### Link Structrure for Rival DNA entries
```mermaid
graph TD
    subgraph Rival DNA Namespace NamespaceProp Nametype Entries
    classDef dash stroke-dasharray: 5 5
        subgraph Entry Links
        subgraph Hardcoded Path
            .("hash_entry('all_namespace')"):::dash %% Hardcoded Path
        end
        subgraph Namespace Entry
            DevHub
            .("hash_entry('all_namespace')")-->DevHub
        end
        subgraph FreeNameAllotment Entry
            DevHub-->|name_type_eh|FreeNameAllotment_1st
            DevHub-->|name_type_eh|FreeNameAllotment_2nd
        end
        subgraph Nametype Entry
                DevHub_Nametype_Nickname_V1
                DevHub_Nametype_Nickname_V2

                DevHub_Nametype_Nickname_V1-->DevHub_Nametype_Nickname_V2
                DevHub_Nametype_Nickname_V1-.->DevHub
                DevHub_Nametype_Nickname_V2-.->DevHub
                
        end
        subgraph Namespace Props Entry
                DevHubNamespaceProps_V1 
                DevHubNamespaceProps_V2
                DevHubNamespaceProps_V3
            
                DevHub -->|"metadata"|DevHubNamespaceProps_V3 
                DevHubNamespaceProps_V1 -->DevHubNamespaceProps_V2
                DevHubNamespaceProps_V2 -->DevHubNamespaceProps_V3
               
        end
        subgraph agents 
            alice-->|maintainer|DevHubNamespaceProps_V1 
        end
                DevHubNamespaceProps_V1 -.-> DevHub_Nametype_Nickname_V1
                DevHubNamespaceProps_V2 -.-> DevHub_Nametype_Nickname_V1
                DevHubNamespaceProps_V3 -.-> DevHub_Nametype_Nickname_V2
    end
end
```
#### Link Structure for Paths for the Name Registration
```mermaid
graph TD
    classDef dash stroke-dasharray: 5 5
    classDef update fill:#8abd00
    subgraph Nom DNA Paths to Name
        subgraph Root Component
            .("hash_entry('Nom')"):::dash
        end
        
        subgraph Global Namespace
            GlobalNamespace:::dash
            Elsa_the_Global:::dash
            Elsa_the_Global
            Agentname:::dash
            
            .("hash_entry('Nom')")-->GlobalNamespace
            GlobalNamespace-->|agent_bound|Agentname
            Agentname-->Elsa_the_Global

        end
        
        subgraph Devhub Namespace
            DevHubInitialDNAHash:::dash
            Charlie_Chaplin:::dash
            Username:::dash
            Orgname:::dash
            
            .("hash_entry('Nom')")-->DevHubInitialDNAHash
            DevHubInitialDNAHash-->|agent_bound|Username
            DevHubInitialDNAHash-->Orgname
            
            Username-->Charlie_Chaplin
            
        end
        
        subgraph Kizuna Namespace
        KizunaInitialDNAHash:::dash
        Bob_the_Magnificent:::dash
        mushroom_farmer_community:::dash
        Nickname:::dash
        Groups:::dash
        
        KizunaInitialDNAHash-->|agent_bound|Nickname
        KizunaInitialDNAHash-->Groups
        .("hash_entry('Nom')")-->KizunaInitialDNAHash
        Nickname-->Bob_the_Magnificent
                Bob_the_Magnificent-->Bob_Name_Registration_V1
                Bob_the_Magnificent-->Bob_BindNameToClientAppAgent_V1
        Groups-->mushroom_farmer_community
        end
        
  end
```

#### Updating Name Registration and Name Binding
```mermaid
graph TD
    subgraph Kizuna Namespace
    classDef dash stroke-dasharray: 5 5
    KizunaInitialDNAHash:::dash
    Bob_the_Magnificent:::dash
    Nickname:::dash

    KizunaInitialDNAHash-->|agent_bound|Nickname
    .("hash_entry('Nom')"):::dash-->KizunaInitialDNAHash
    Nickname-->Bob_the_Magnificent
        Bob_Name_Registration_V1
        Bob_the_Magnificent-->Bob_Name_Registration_V2
        Bob_BindNameToClientAppAgent_V1
        Bob_the_Magnificent-->Bob_BindNameToClientAppAgent_V2
    end
```

### Entries

#### Namespace Entries
```rust=
// Create
// Update is invalid
// Delete is invalid
#[hdk_entry]
struct Namespace {
    origin_dna: HoloHash<Dna>, // immutable. How do we verify that this is actually a dna hash? or at least that it is a hash to prevent junk data being put here which can potentially cause collusion?
    global_name_reg_opt_in: bool, // immutable
    ttl: u8 // time to live. expressed in years
    binding_public_key: String
}

#[hdk_entry]
struct FreeNameAllotment {
    namespace: EntryHash,
    nametype: EntryHash,
    qty: u32 // bundle of free names purchased
}

// Create
// - the origin_dna hash should match the origin_dna hash in Namespace entry 
// - the author of this entry is the same as the author of the previous entry (which is the Namespace)
// - 1 =< organization name string length >= 50
// 1 =< display name >= 50
// - organization email must conform to regex
// - name types and agent name type field cannot be empty

// Update
// - origin_dna (the first item in dna_versions) must be the same compared to the prev entry
// - Updates can only be done by the previous entry's maintainers or creator
// - creator field must be the same with the previous entry
// - the Path (Vec<u8>) in the name types vector should match the path name 
// - get the name type eh found in name types field and make sure that the path in index 0 matches

// Delete is invalid

#[hdk_entry]
struct NamespaceProperties {
// Q: why ActionHash?
    namespace: ActionHash
    display_name: string,
    dna_versions: Vec<HoloHash<Dna>>, // index 0 is the initial DNA hash
    org_detail: Organization,
    // The new NameType entry is the prev_action so 
    // we can get it in validation to see if it exist
    name_types: Vec<(Vec<u8>, EntryHash)>,
    // we separate the names for agents for ease in validation
    agent_name_type: Option<u8>, // index of the agent name type in name types vector
    // list of agents that can create NameType entries within this namespace and modify this property entry
    maintainers: Vec<AgentPubKey>,
    ownership_proof: Option<Signature>, // must be verified using the public binding key to create the first maintainer
}

pub struct Organization {
    name: String,
    email: String,
    country: String,
    province: String,
    city: String,
contact_no: String,
}
```

#### Nametype Entries
```rust=
// For NameType and AgentHandleNameType
// Create
//    - Namespace entry must exist
//    - reg_duration > 0
//    - purchase price >= 100 (minimum 1USD)
// Update
//    - path_name should be constant
//    - Namespace entry should be constant
//    - reserved_names should be constant
//    - regex should be constant
// Delete is invalid
#[hdk_entry]
pub struct NameType {
    path: Path, // immutable
    namespace: EntryHash, // immutable
    reserved_names: Vec<Vec<u8>>, // immutable
    valid_name_structure_regex: ???, // immutable
    // path_component + name allow us to change the name in the UI 
    // (e.g. path: handle -> name: nickname) w/o breaking the pathing
    display_name: string, // name presented in UI
    ttl: u8,
    purchase_price: u32, // payment portal would need to check the current exchange rate of other currencies to accept currencies other than USD. This can be set to 0 which means that the names in this name type is pre-paid by the namespace owner.
    prev_name_type_eh: Option<EntryHash>
}

// #[hdk_entry]
// pub struct AgentHandleNameType {
//     path_component: Component, 
//     name: string, // name presented in UI
//     // path_component + name allow us to change the name in the UI 
//     // (e.g. path: handle -> name: nickname) w/o breaking the pathing
//     namespace: EntryHash,
//     // to check that the author was at some point a maintainer of the namespace (proof of membership)
//     namespace_property: EntryHash,
//     ttl: u8,
//     purchase_price: u32, // min 100 = 1USD; payment portal would need to check the current exchange rate of other currencies to accept currencies other than USD. 
//     reserved_names: Vec<Vec<u8>>,
//     with_roles: bool,
//     regex: ???
//     version: u16
// }

// progenitor (not one of the witnesses) of the DNA must commit this entry in init()
// renewable based on ttl

#[hdk_entry]
pub struct GlobalNameType {
    path_component_name: Component,
    presented_name: string,
    purchase_price: u32,
    regex: ???
}
```

#### Name Registration Entries
```rust=
// Create
//    - payment_proof_sig must be verified with the PubKey from DNA property
//    - `get(namespace_hash)` -> Namespace must exist
//    - `get(nametype_hash)` -> name bytes should not // be in NameType.reserved_names
//    - `get_remote_agent_state` -> iterate through `NameRegistration` entries for at least 4 witnesses (also iterate through `GlobalNameRegistration` if the namespace opted in to global name registry)
//        - couponData's serial_number must not have been used in previous entries
//        - name must not be found in previous NameRegistration entries *or*
//        - name can be found in a previous NameRegistration entry as long as
//            - previous registration must be expired (beyond ttl+grace)

// Update(Renew)
//    - `get(namespace_hash)` -> Namespace must exist
//    - `get(nametype_hash)` -> name bytes should not be in NameType.reserved_names
//    - `get_remote_agent_state` -> iterate through `NameRegistration` entries
//        - couponData's serial_number must not have been used in previous entries
//        - name must be found in a previous NameRegistration entry *and* 
//            - previous registration is not yet expired (beyond ttl+grace) *and*
//                - author of new registration must be the same as the author of the previous registration
// Delete is invalid (??)
#[hdk_entry]
struct NameRegistration {
    namespace: HoloHash<EntryHash>,
    name_type: EntryHash, // NameType spec that is the latest version (display price and ttl)
    name: Vec<u8>,
    binding_public_key: String
}

// Create
//    - payment_proof_sig must be verified with the PubKey from DNA property
//    - `get(nametype_hash)` -> name bytes should not be in NameType.reserved_names
//    - `get_remote_agent_state` -> iterate through `NameRegistration` and `GlobalNameRegistration` entries
//        - couponData's serial_number must not have been used in previous entries
//        - name must not be found in previous NameRegistration entries *or*
//        - name can be found in a previous NameRegistration entry as long as
//            - previous registration must be expired (beyond ttl+grace)
// Update
//    - `get(nametype_hash)` -> name bytes should not be in NameType.reserved_names
//    - `get_local_agent_state` -> iterate through `NameRegistration` and `GlobalNameRegistration` entries
//        - couponData's serial_number must not have been used in previous entries
//        - name must be found in a previous NameRegistration entry *and* 
//            - previous registration is not yet expired (beyond ttl+grace) *and*
//                - author of new registration must be the same as the author of the previous registration
// Delete is invalid (??)

// NOTE: We should build a reclamation mechanism for unused global names that have been unused for a year
#[hdk_entry]
struct GlobalNameRegistration {
    namespace: HoloHash<EntryHash>,
    name_type: EntryHash
    name: Vec<u8>,
    initial_binding_public_key: String
}

#[hdk_entry]
struct GlobalNameTransfer {
    name_registration: EntryHash,
    // denominated in USD
    transfer_price: String,
    // This is the binding key found in the old name 
    // registration entry authorizing the transfer of 
    // global name.
    authorization_by_previous_owner: Signature,
    new_binding_public_key: String
}

#[hdk_entry]
struct BindNameToClientAppAgent {
    name_registration: EntryHash,
    (original?)dna_hash: HoloHash<Dna>,
    agent_pub_key: AgentPubKey,
    expiry_date: Timestamp,
    // Signing of AgentPubKey using the binding private key found in UserCredential (verified using the binding public key found in the NameRegistration)
    ownership_proof: Signature
}

#[hdk_entry] // private entry in registration's node
struct UserCredential {
    email: String,
    binding_public_key: String,
    // encrypted with the user's password hash at the time of account creation.
    encrypted_private_key: String
}

// outstanding issues

// Art mentioned that looping through the source chain of witnesses in the validation will be very slow. However, what other ways do we have to validate the uniqueness of the name if we are not going to look at the source chain of at least 4 witnesses? (Check the mattermost chat)

// ----

// we can create a function to police the payment node 
// from creating conflicting coupons if we are willing 
// to store the coupons as private entries. This gives 
// a person an ability to report binding conflicts.

// What if we get the local time of the witness nodes 
// instead of the local time of the server? This way 
// there is no way for the payment node to cheat on the 
// timestamp. And it is in the interest of witness to protect the integrity of the coupons so they are incentivized to provided the timestamp that is accurate.

// How do we recover lost password?
```
#### Link Validation
##### Namespace -> NamespaceProperties
##### NamespaceProperties -> NameType
##### Rival.Handle -> GlobalNameRegistration
##### Rival.<DNA_Hash>.<Name_Type> -> NameRegistration
- **Create**
    - The author of the path is the reservation node's pubkey
    - Question: Is the Path
    - The same
##### NamePath -> NameRegistrationReceipt
##### NamePath -> GlobalNameRegistrationReceipt


