AntNS: Concept for DNS on Autonomi

I’ve put together an idea for a DNS system for Autonomi and I’d like to get some feedback, concerns if I’ve missed something.

The two main features:

  1. Name registry on the Autonomi network itself
  2. A DNS server for the local machine to resolve names system wide without having to tinker with your browser

So the idea is to use a shared registry that anyone can lookup.

When you register mydomain.ant, a register is created using a shared DNS key that everyone knows.

The first person to create an entry on that register puts a new public key as the first value, which only they will have the private key for.

This means anyone can find it at the same address, and anyone can write to it - but only signed entries from the domain owner are considered valid.

Example Register for mydomain.ant:

Register: mydomain.ant (deterministic address via shared key)
├─ Entry 1: { "publicKey": "98daa2aba6513e5c..." } ← Owner document
├─ Entry 2: { "records": [...], "signature": "valid_sig_abc" } ✅ Valid
├─ Entry 3: { "records": [...], "signature": "spam_sig_xyz" } ❌ Invalid (ignored)
└─ Entry 4: { "records": [...], "signature": "valid_sig_def" } ✅ Valid

Lookup behavior:

  1. Download entry 1 to get the owner’s public key

  2. Process entries 2+ in order

  3. Verify each signature against the owner’s public key

  4. Skip invalid signatures (spam)

  5. Return the last valid entry

Codebase:

From my repo you can clone and build it if you know/have rust:

1) Register a domain:

antns names register mydomain.ant

2) Add a record to the domain:

antns records --name mydomain.ant add ANT . 189ee88668

3) Run the DNS server:

sudo antns server start

4) Browse the site
Choose your favourite browser and goto:

http://mydomain.ant

Explainer:

Git repo:

17 Likes

Does this work cross browser and cross platform?

I’m a bit rusty on how I ended up with the solution implemented in Dweb, but I did begin with a working version using a local DNS. IIRC that required addresses to use an existing tld to work in some browsers. So I used .au (Australia) short for Autonomi, and minimised clashes by mandating use of dweb.au (or similar) to avoid blocking real sites on .au tld.

It worked very well, allowing human readable names, including versioned websites with a ‘vX’ subdomain and the code is still in git of course.

I switched away from that to avoid users needing to install and run a local DNS server which is tricky on different OS and I didn’t want to write one myself.

So in the end I ended up with a route towards sharing user defined name-address mappings rather than a single ‘main’ DNS register. I didn’t get to implement sharing. It wouldn’t be hard in principle but would need to have a well thought out UX.

If you have it all working cross platform and browser that sounds great. :clap:

Unfortunately I don’t have time to dig into it or even try it out, but will watch with interest.

8 Likes

Thanks @happybeing. Yeah it should work on all Chromium browsers, Firefox and Safari. Also should work on Linux and MacOS. Claude helped with the Windows script but I have no idea if it just made up a bunch of lies.

Yeah the dns can be annoying. I’ve just added antns.net as a real domain then they .ant domains can also resolve using that. So either .antns.net or .ant should work

It should be cross platform. I know nothing about Windows but I tried to compile the binary anway. Linux should work fine, but I don’t have a machine right now. I know the concept of the resolver works pretty much the same way.

Maybe someone will create a browser, or an extension that means we can do an actual protocol lookup instead of hacking real name resolution via dns. Like safe://mywebsite instead of http://mywebsite.antorsomething.

On Chain Name Resolution

BUT, what I’d really love your and everyone elses feedback on is the actual name registration and record management concept.

So essentially using the registry, but instead of a private key, having a shared key that anyone can read/write to, but making the first entry a public key to which only the owner has the private key.

RFC: antns/RFC-ANT-DNS.md at main · markwylde/antns · GitHub

Register: mydomain.ant (deterministic address via shared key)
├─ Entry 1: { "publicKey": "98daa2aba6513e5c..." } ← Owner document
├─ Entry 2: { "records": [...], "signature": "valid_sig_abc" } ✅ Valid
├─ Entry 3: { "records": [...], "signature": "spam_sig_xyz" } ❌ Invalid (ignored)
└─ Entry 4: { "records": [...], "signature": "valid_sig_def" } ✅ Valid

It would mean anyone could write an entry to the name record, but any resolver would ignore any entry that was not signed by the first certificate.

6 Likes

Thanks for responding. I have too little time to read and think but can offer a caution about the protocol option: I’m not sure it’s feasible, unless you can get the protocol adopted officially (as with ipfs). Otherwise it’s a no go. The only way to achieve this (cross platform) is I believe with a custom browser.

I’d like confirmation that this works cross platform and cross browser because I think there were issues with your approach that I came up against, but don’t remember well enough to be sure. So just a caution.

3 Likes

This post may be of interest: AntTP - Serving Autonomi data over HTTP - #336 by Traktion

Locally, I’m experimenting with extending it further to resolve first to a JSON record, which is a bit like a zone file.

I haven’t integrated it into a traditional DNS resolver, but AntTP can use it to resolve a name to something else.

There is a shared key for creating pointers from a name to an address. The latter would usually be a private key based pointer, which can then resolve to somewhere of the private key holder’s choosing.

By using max count, the shared key pointer can be made immutable and fixes to point at a user’s private key pointer. This can then be updated, only by the owner, when necessary.

I’m not sure how similar your design is, but will take a read later.

EDIT: Just looked now:

This is a similar approach to what I was experimenting with AntTP, but I have been using pointers with max counter instead, then chaining pointers where necessary.

My documentation isn’t nearly as detailed as yours, but using the same format as above, it would be a bit like:

Pointer: mydomain.ant (deterministic address via shared key)
└─ Content: "98daa2aba6513e5c..." with counter = MAX
    └─ Owners Pointer ("98daa2aba6513e5c...")
         └─ Content: <XOR address>

Or what I’m playing with atm:

Pointer: mydomain.ant (deterministic address via shared key)
└─ Content: "98daa2aba6513e5c..." with counter = MAX
    └─ Owners Pointer ("98daa2aba6513e5c...")
         └─ Content: { "antns": [{ "name": "<subdomain>", "type": "A", "ttl": "3600"}] } 

Or chained:

Pointer: mydomain.ant (deterministic address via shared key)
└─ Content: "98daa2aba6513e5c..." with counter = MAX
    └─ Owners Pointer 1 ("98daa2aba6513e5c...")
         └─ Content: "123aa2aba6513e5c..." with counter = MAX
              └─ Owners Pointer 2 ("123aa2aba6513e5c...")
                  └─ Content: { "antns": [{ "name": "<subdomain>", "type": "A", "ttl": "3600"}] }

etc, to transfer domains.

I wanted to just experiment and see how well it worked before documenting thoroughly. It sounds like the goals are pretty similar though.

7 Likes

Also, it’s worth noting that SOCKS proxies can access the host name of a URL and then resolve it, rather than having to use DNS.

Obviously that’s only useful for browsers using proxies, but it’s a handy win if you only need to resolve within a browser.

2 Likes

Hi, if the register is publicly exposed how would you stop someone writing something that isn’t a valid register entry to the end of it so that no new entries can be added?

I had been playing with something similar regarding publicly appendable data structures and to avoid the above issue have instead made a custom type out of graph entries that is similar to a register but where every possible location on the chain could be derived from information in the initial graph entry…then like you ignoring any invalid entries…but maybe this wasn’t necessary?

2 Likes

Thanks guys for all the feedback. Can’t believe you guys took so much time to offer great advice/info!

And I think my approach is similar to what you’ve tried already, just without relying on the max counter idea.

So looking at the autonomi project the src/client/high_level/register/mod.rs file:

There doesn’t seem to be a limit on register updates. The history is stored as a linked list so when it runs register_update it:

  1. Creates a new GraphEntry (which costs tokens, although not a lot)
  2. Updates the head Pointer (doesn’t cost anthing)
  3. Appends to an unbounded history chain

@traktion I’m not too sure about the counter max limit. Do you know if it will always be this number? It feels arbitary, but I don’t know what I’m talking about.

The keypair approach, makes me feel like no matter what changes only the owner of the private key can change the target of the name entry.

But maybe setting that max counter will be forever?

It’s a shame there is no public register baked into Autonomi/Maidsafe.

Was it ever brought up during the design phase?

Only owner can update, and yes, once set to max you can’t change it because only larger values are accepted and the max is that largest value.

Earlier designs were more flexible, but there’s been no real discussion outside the team about these kind of issues for some time now. Even less than two years ago the register design was broken (limited updates) and then changed completely with the switch to graph entries. No discussion at all about that.

In response to some issues raised they created ScratchPads and this fed into Vaults. There wasn’t much discussion but they did attempt to address some issues raised, while creating others that might well lead to further API/data type changes in future. We don’t know and I don’t think Autonomi can know either, though we all hope not!

You might also be interested in the Dweb History type which I based on the Register implementation. It’s behaviour is very similar but makes it easier to implement storage of arbitrary data types. I use it to store Autonomi Archives for versioned websites.

4 Likes