# 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