A Safe Naming System to support versioned Websites (NRS/DNS)

Comments, critique, questions all welcome.

Safe NRS (DNS)

What follows is an outline design that shows how a Name Resolution System (similar to the web Domain Naming System) might be implemented using Safe Network to provide all three sides of Zooko’s triangle:

  • Human-meaningful: Meaningful and memorable (low-entropy) names are provided to the users.
  • Secure: The amount of damage a malicious entity can inflict on the system should be as low as possible.
  • Decentralized: Names correctly resolve to their respective entities without the use of a central authority or service.

Note: “Zooko Wilcox-O’Hearn conjectured that no single kind of name can achieve more than two.” (Wikipedia)

Example Safe NRS Implementation

An outline design for an NRS that achieves all three sides of Zooko’s triangle, and An outline design follows without support for subdomains or additional services, but implementation of these are considered at the end.

Resolving A Web URL

Resolving a web URL involves two stages:

  1. using the ‘domain+subdomain’ to obtain the address of the structure that holds the content of the website
  2. using the content structure to locate the data referred to by the path (e.g. a file of HTML stored at an xor address)

Step 2 is outside the scope of this topic which focuses on step 1, where a web client such as a browser uses a domain (and possibly subdomain) according to the proposed NRS scheme to retrieve the data necessary for step 2.

A proposal for Step 2 is presented in the topic: Storage of versioned websites for browsing on Safe Network

In more detail, the client uses NRS name to retrieve the NRS register corresponding to the NRS name. From the register it can obtain the address of the latest Website structure (or an earlier version if required). It retrieves this from the network and uses it to resolve the human readable URL to an xor address, and can load that file from the network. Any parameters applied to the URL will be made available to the page through a scripting API compatible with existing web conventions.

Similarly for URLs contained within the HTML files of the website when loading other pages, images, following links etc.

Obtaining the Register for a Domain

In the past a Safe NRS was demonstrated based on using the hash of the domain to obtain the location of data relating to any services (e.g. a website) also stored on Safe Network for that domain. This was done using the hash of the domain name to obtain an effectively random xor location, and then storing the data for the service at that address, in effect claiming the domain by the owner of the data at it’s xor location.

The proposal here is similar, but relies on the ability to create a RegisterCRDT at such an xor address that can be obtained by any client trying to access a service of the domain (and possibly subdomain). I thought the RegisterCRDT API supported this but it appears not, so that would require a change, or some way for clients to work around the limitation in how the RegisterCRDT address is decided.

Using a RegisterCRDT to reference metadata for a domain provides for versioning and concurrent editing of the metadata for services at the domain. So a client can review all previous services published for a domain, and changes can be made concurrently from more than one device but with guaranteed convergence on a single state after all edits are applied from different devices.

Additional Features

Supporting Subdomains and Services

The above doesn’t include support for expected features such as subdomains or additional services.

Both could though be added by using the main domain register to hold references to multiple Website structures for the root and any subdomains, and similarly for additional services (e.g. such as a Wallet or Filesystem).

Alternatively, each Website might have its own register, and those would be referenced by the main domain register in order to maintain separate version histories for each Website.

Related documents

These are I believe the latest relevant documents but I haven’t reviewed them, and I’m not sure how current or applicable they are now.

  • November 2018 - Naming System

    • forum discussion: [RFC 052] Public Name System: Resolution and RDF
    • RFC #052: RDF for the Public Name Resolution System
  • August 2019 - XOR-URL encoding

    • PR #337: Define our own content-id encoding format for XOR-URLs
    • forum post: XOR-URL RFC discussion

I think this would be best, obviously so. Minimise the main NRS system

Sub Names (sub domains in domain system) can then be like individual main entry. IE browsers take the subname and accesses the site NRS just the same as the browser accesses the root name, but in the site’s NRS.

Also the site’s NRS would contain all the previous versions since these structures are append.

Maybe I missed it, but spam will be reduced because it’ll cost to create an NRS entry.

Worth nothing on how name resolution would work (which I don’t see above, forgive me if I missed that?)

Currently registers are addressed by:

  • A random (or specified) xorname
  • A public key.

In my mind, a simple resolution setup would involve:

A PublicKey as a namespace. This is (currently) always added as an owner to the register… Other Permissions can be supplied.

So a known nonsense PK (if one could trust that), would serve as a name space allowing for the xorname to be derived from a hash(String) type function.

That hash function was how previous NRS implementations worked.

So there (in theory) you could have many different namespaces too.

Would we want /need to manage such an eventuality? (Namespaces could be run by any entity perhaps, currently they’d be an owner of any register in that space… I’m not sure on the impacts of that or removing that… :thinking: )

I’m not sure if folk see any drawbacks to that resolution approach?

1 Like

The above scheme is a global name-space where the register address is derived from (hash of) the domain, as the original scheme. You could still have multiple name-spaces by people agreeing on a ‘salt’ for those hashes, but it could be something much easier to share than a public key.

I guess your scheme implies you know already have the public key of any name space you wish to address. How would that work for someone sharing a URL if the URL can’t be resolved without knowing the public key?

What could/would be easier to share?

My scheme is based upon registers at the moment, which address data based upon those two parts. , so without changing the underlying register specs, we’re stuck with that. (Not saying we couldn’t do that, or have a new data type… but there has to be strong reasons).

In the end, IMO, a PK is the same as anything else for namespacing this… Your apps would agree and work within a namespace, hiding all that from the user.

Or, we could have some decentralised list of petnames for namespaces + domains, or something. But that feels like we’re getting inception-y (and who manages that list + why!?)

A single slash should also work:


(see Tim’s Regret).

A word, effectively a top level domain. I explain this. It’s similar to the original scheme where the address of the mutable data (now a Register) is based on the hash of that, and the domain string. So anyone can create the register at the pairing of a tld string and a domain string so long as nobody got there first. So no-one owns the tld part, and no-one owns the domain part, but anyone can register and own the combo tld+domain.

This makes it easy for people to pass human readable domains around as in the current web DNS. I prefer that to having public keys be the first step. What am I going to type into a browser?

Hopefully safe://somedomain.sometld which can have come from some chap I just met in the park and told me to check out this amazing decentralised app he’s building.

Using a pairing of tld and domain creates a massive space. We’ll never run out of useable strings because squatting a tld would mean squatting every likely domain. Someone might try that, but then others start using a different tld of their choice.

It isn’t perfect but I think it is very friendly, and the universality is valuable. It doesn’t preclude other schemes like the one you describe either. Register xor address space is big enough for any number of schemes.

The scheme I describe here, and in the OP is based on the current Register implementation so will work unless you plan changes to the API that would preclude it.

To be clear, I’m not suggesting using any PK and namespacing as a general system.

More like “I will be on madisafe nrs”, which is a baked in PK, and then all the rest of resolution is as normal.

So I suggest in the current system baking the namespacing of the NRS system, essentially, to avoid any of what you are describing (which I agree would be a poor experience).

Exactly this. So the PK is like “choose your scheme”… Not the domain itself.

No it’s not, sadly.

So a PK is required. If you or I store the same string with differing PKs, they are in different locations. So you cannot use that as a namespace without stabilising one of the two variables. (as things stand)

I’ll have to look again thanks. I was under the impression you were able to specify the address of the Register and that use of the public key plus name was optional.

Are you sure you’re not talking about the higher level (e.g. ClientRegister) rather than RegisterCRDT?

No this is how the NetworkAddress::Register is currently formed, I’m afraid.

Eitherway though, if you hash(string) to get your xorname, you’re namespacing is effectively over the hash function. So you have another namespace tool to be sharing somehow.

In prior versions, this was in the spec and baked into apps, so I image the PK could be similarly dealt with. (If we still want to keep it in the addressing).

1 Like

2 posts were merged into an existing topic: Storage of versioned websites for browsing on Safe Network

I have split the OP to separate discussion of the NRS/DNS aspect here, and of the proposed way to store websites in the following topic:

@moderators, with his permission please can you move the two replies immediately above this one (by @Traktion) to the new topic on Storage of versioned websites.

1 Like

I had a play around with registers earlier in the week to try to provide a dynamic URL for IMIM blog.

I created a register of XOR addresses via the CLI and the (longer) hash returned enabled me to change the root config for the blog. This provided the flexibility / performance I needed. However, it’s still a big, long, string which can’t (reasonably) be remembered.

Who would have permission to change the register, should a ‘nonsense PK’ be used? I’m assuming the owner (who has the private key) would usually be the only one who can change a register which doesn’t have public write access?

In the end, IMO, a PK is the same as anything else for namespacing this… Your apps would agree and work within a namespace, hiding all that from the user.

So, in this context, an app which is a ‘autonomi browser’ would share the PK and the developers of said browser would manage all the NRS/DNS registers?

This would seem rather centralising for such a key app.

I’m curious to how this worked in NRS, as IIRC, I could manage (i.e. I’m the only one with write access) while sharing the name with others.

I aim to test the idea that you need a PK to do this but have a bit more to do before I get to that.

The more I look at the APIs the more I think they still need quite a bit of work. Either by developers wanting to use them or ideally Autonomi who have a better overall picture of how they deliver the goals of the network.

NRS is just one potentially very impact-full area where Autonomi’s thinking, goals and plan are unclear to me. I think they don’t have the time yet, but it is so important to get developers going with launch planned for October.

Anyway, for now I’m ploughing on blind and hope that what I work on will be useful. I will at least be able to share my learnings about the APIs, but unless people are using them they won’t be ready and so where will the apps be come October. The coming partner announcements have a lot of work to do!

On the plus side Autonomi’s (and particularly Roland’s) response to the blocker I hit last week was amazing. It would have delayed me for weeks or more because I couldn’t figure out how to get what I needed even by modifying the Autonomi code but they responded fast and it only cost me a few days.

1 Like

I was ponderingnthe PK issue some more too. The following could work:

  1. Create a public writeable ledger against a defined PK and name (e.g. nrs1).
  2. Share address to the ledger with anyone who wants to add NRS addresses.
  3. Users create a private register (e.g. 'my_private_app_register) and add an entry to the XOR address of their app root/file.
  4. Users add an entry to the above register, with a format like ‘name,my_private_app_register’ (or json for flexibility), where name is the ‘host’ (in clear net speak).
  5. The public nrs1 register would be first come, first serve, so duplicates get ignored.
  6. When nrs1 runs out of space, nrs2 is looked up, then nrs3, etc. These could be created ahead of time and/or as needed, all against the original key.
  7. Users update their private register as/when needed to change the destination XOR address.

Ofc, these registers could get spammed and filled. IIRC, thought is going into making thar harder/expensive though.

For revolving URLs:

  1. App searches nrs registers (nrs1, nrs2, etc) for a match against the name (crude/brute force).
  2. Apps could cache nrs into data file (xor addressable, json, etc). Processing could be done by trusted parties, if desired. Local app could provide service/interface if needed.
  3. Apps resolve nrs response to lookup private register, then retrieve data from XOR address.

In terms of what is in the resolved data, that probably comes into the other thread on website paths etc. Something could be standardised though, with file names mapping to XOR addresses. The app could then resolve accordingly (sn_httpd could do the same for clear net infrastructure).

I wasn’t thinking so deeply, more how can I mangle with the APIs but @loziniak has also posted some ideas for handling spam which were interesting - search on this forum (I think).

A post was merged into an existing topic: Register CRDT APIs

5 posts were merged into an existing topic: Register CRDT APIs

I had a go at implementing this as a POC in sn_httpd: sn_httpd/src/main.rs at 4bab513e7b43178e9fd7d16034d7c3e2d927e2e3 · traktion/sn_httpd · GitHub

It’s rudimentary atm and you can only ‘edit’ the DNS registry with the CLI (no append/history exposed yet), but it does work.

Here is an example URL: http://vader:8080/traktion/blog/traktion/article/blogging-with-imim-and-safe-network#article

(some info here - sorry it’s scrappy atm! https://forum.autonomi.community/t/04-19-2024-community-testnet/39641/145?u=traktion)

Note that the base ‘traktion’ is used for the DNS lookup in this context and it could be pushed into the domain name, instead of the root directory in the URL. The latter was just easier to test/experiment with.

Essentially, it sn_httpd is launched with a specific (i.e. ‘dns1’) public register specified. It then does a lookup for the name (‘traktion’) to retrieve an associated private ‘site register’. When there is a change to the site, the ‘site register’ is pointed to the latest XOR for the data map for the site.

The data map is an enhancement of what I was using to define a site in IMIM, but made more generic (but preserving old as an ‘imim’ sub-definition). I’ve added some docs here with an example here.

So, adding an article, changing a file/route, etc, all means a new XOR for the config.json. This XOR is then pushed (appended when possible) to the ‘site register’.

It works pretty well. It’s slower than raw XOR, as caching must be less aggressive and register lookups are also needed, but not unbearable. I’d like to add caching TTLs to the fileMap entries too, as some of those are essentially ‘immutable’ in nature and could be kept forever by the client (e.g. Angular / IMIM source files, in this context).

Note, the file maps are used for direct lookups within sn_httpd, rather than register lookups. It allows ‘friendly’ file names to be resolved to XOR addresses as we discussed within these pages too. I wanted to experiment with that also! :slight_smile:

Anyway, I wanted to share my experimentation. I suspect a similar need will present for an Autonomi browser or any other app that wants to perform lookups.


Sounds really cool. I don’t have time to look in detail for now but :+1: