Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Subdomains!!!: Addressability!!! Addressable Contracts!!! And Excited by Nothing!!!!!!! #29

Closed
the-frey opened this issue Dec 16, 2021 · 23 comments
Labels
help wanted Extra attention is needed question Further information is requested
Milestone

Comments

@the-frey
Copy link
Contributor

How to implement this? Relates to #1

Spiking has been done already, and the base impl is probably as simple as tokens having a parent:

base (no parent) -> token (parent) -> token (parent)

where only the owner of base can mint subtokens

then there's a lookup path for

base <- token.parent <- token.parent 

Screenshot 2021-12-16 at 13 19 49

@the-frey
Copy link
Contributor Author

the-frey commented Dec 16, 2021

It might be worth adding a field for parent into the MVP metadata so that we are forward-compatible with such an approach for tokens minted during the MVP phase.

EDIT: this is #30

@the-frey
Copy link
Contributor Author

cc @elsehow for this discussion

@elsehow
Copy link
Contributor

elsehow commented Dec 16, 2021

my concept is something i've been thinking of as "RAD" (recursive, agnostic, decentralized) DNS.

while the idea is a smart contract running on the Juno testnet, it's best introduced by its client-side logic.

here's some psuedocode for the client:

def resolve (path: Vec<str>) -> Any:
  return_data: Any, remaining_path: Vec<str> = query(path)
  if not remaining_path.is_empty():
    address: Addr = reutrn_data.unwrap_as_address()
    return resolve(address, remaining_path)
  return return_data

imagine the client wants to query the nested path: elsehow/meta/juno/validator

they'd first query the root DNS (our contract) for elsehow. the root DNS would return the name of the address elsehow's token owner set in the root DNS, along with meta/juno/validator - the part of the route it didn't query.

now, you may think: won't that cause lots of lookups - one for each step in the heirarchy?

not necessarily! it depends how the elsehow token holder decides to structure their domain.

for example, given the route elsehow/meta/juno/validator above, i might choose for my DNS contract to parse /meta/juno/valdiator/ all in one contract, rather than nesting actual DNS's beneath it. (in fact, the only reason i'd want to nest DNS's is to enable governance with the domain - more on that below). so, the steps of the elsehow/meta/juno/validator resolution would be:

  1. client does resolve(rootDNSAddr, "elsehow/meta/juno/validator")
  2. root DNS (our contract) returns childDNSAddr, meta/juno/validator
  3. client does resolve(childDNSAddr, meta/juno/validator)
  4. subdomain returns some data and Vec()
  5. client looks at Vec(), and infers we must be done here - there's no further address left to query. it passes whatever data it returned back to the application.

that's only two queries to the chain!

this DNS is recursive because you can nest resolves inside one another.

it's agnostic because our "root TLD" (and indeed, any TLD beneath it) only cares about the head of the list. it doesn't care
how child DNS contracts handle routes, or what data they return. when we mint an NFT for the root domain, for example, we only check that the person updating the route owns the NFT for the head. after that, the root DNS passes queries down to name systems that can work in any arbitrary way. the only thing that makes this a coherent "naming system" is a single, coherent client-side logic.

this DNS is decentralized in that the root DNS - and every child DNS - can be governable by the NFT holders. that governance can do things like revoke routes, grant names, describe what names are legal, etc... it's a more flexible and equitable system than the traditional root DNS model, which relies on ICANN etc etc etc... and owners of TLDs (like .net) have no say over the governance of those domains.

cc @ezekiiel

@the-frey
Copy link
Contributor Author

Right, except that the token_id is necessarily a string, so at an implementation level it ends up as string parsing, unless you make the tokens fully independent and resolve it as a UI problem

i.e. elsehow/meta/juno/validator would actually just be the token validator and we'd need to look up the three additional jumps. Queries to a smart contract are free, so other than the network overhead (which is cacheable) as a first pass at it it also means you can more easily break chains by selling or transferring parts of the tree.

Although, as I type this, I realise the transferring issue is somewhat intractable, because either you have the token id as the full path, which contains the meta in it, i.e. elsehow/meta/juno/validator or you have a problem where the space of avaialable names is too small i.e. validator is already taken, so you can't have it (as it's a PK).

HMMMMMM 🤔

@elsehow
Copy link
Contributor

elsehow commented Dec 16, 2021

i.e. elsehow/meta/juno/validator would actually just be the token validator

in this example, there doesn't need to be any token other than elsehow.

let's stick with the elsehow/meta/juno/validator example.

  1. you, root DNS, grant me the elsehow domain.
  2. i update the root DNS. i hold the elsehow token, so you let me set elsehow to whatever address i want. i set it to a smart contract that exposes resolve(path).
  3. I tweet, "find me on RAD DNS! elsehow/meta/juno/validator".
  4. user goes to their RAD DNS client and does resolve(elsehow/meta/juno/validator).
  5. root DNS gives them my contract, my contract gives them my validator's metadata.

there is no token for elsehow/meta/juno/validator. there is no token for validator. the only token is elsehow, in the root DNS, which at its most minimal has no rules for names except that they cannot include /.

do you see?

@the-frey
Copy link
Contributor Author

Right, so the domain ownership is a token, and there's just a 1-to-many relationship to sub paths that use the token as the root?

@the-frey
Copy link
Contributor Author

I think that would literally only require an indexed map and a single query handler on this contract to implement if so

@elsehow
Copy link
Contributor

elsehow commented Dec 16, 2021

so the domain ownership is a token, and there's just a 1-to-many relationship to sub paths that use the token as the root?

effectively.

I think that would literally only require an indexed map and a single query handler on this contract to implement if so

exactly.

PS - in practice, we would imagine that some subpaths could be their own root. i imagine that top-level domains will be most likely to be roots. for example, i might register dao at the top-level, and run it as a DNS. people can register dao/juno, dao/dao, etc.

@elsehow
Copy link
Contributor

elsehow commented Dec 16, 2021

also, to the issue: "couldn't some people run their TLD in a sketchy way?" yes. of course. that happens already. the goal is to make each TLD maximally self-governing and autonomous.

@the-frey
Copy link
Contributor Author

the-frey commented Dec 16, 2021

Okay, but subpaths-as-tokens feels like a complexity that maybe we can sidestep for now.

Propose then that v1 of this (probably won't be ready for MVP, as I need to test hella stuff atm and wire it into the UI) is:

  • TLDs (i.e. token_id) can have a one-to-many relationship to a path in storage
  • Paths can be looked up by a resolver QueryMsg on the contract*

Resolver

This could be something like

QueryMsg::Resolve { 
    path: "elsehow/meta/juno/validator",
}

which would return something like:

PathInfo<T> {
    root_token_id: String, // i.e "elsehow",
    root_meta: Option<Metadata>, // i.e. root meta rather than root nft_info
    payload: T, // the type of data found at the leaf (serialised JSON)†
}

probably
* I think this is compatible with either approach:

  • subdomains as NFTs
  • subdomains as paths

@the-frey
Copy link
Contributor Author

Incidentally, the

each TLD maximally self-governing and autonomous

is almost solved by default. Since the TLDs are NFTs, they can just be purchased by a multisig or DAO.

@elsehow
Copy link
Contributor

elsehow commented Dec 16, 2021

yep, exactly!

Okay, but subpaths-as-tokens feels like a complexity that maybe we can sidestep for now.

we don't have to think about it - we never have to think about it. it's a feature that can emerge naturally from the design.

@the-frey
Copy link
Contributor Author

Thoughts on #29 (comment)?

@elsehow
Copy link
Contributor

elsehow commented Dec 16, 2021

I think that looks good. @ezekiiel ?

@0xekez
Copy link
Contributor

0xekez commented Dec 16, 2021

I think this is great. This reminds me of an iterative DNS query as opposed to a recursive one.

@the-frey: some subpaths could be their own root

Any particular advantage to even having root and non-root level tokens? From the way that this is being suggested I'd imagine that this change could literally be:

  1. Don't allow names to be registered with '/' characters in them.
  2. Add a field in the token metadata which is the address of a contract which can be queried for subdomain information.

All responses then become:

Response {
  metadata: Metadata,
  unresolved: option<string>
}

This saves the hastle too of needing to provide an upgrade process for upgrading a non-root token to a root-token.

@0xekez
Copy link
Contributor

0xekez commented Dec 16, 2021

@elsehow something re: moderation / subdomain independence to consider:

Should the TLD be able to revoke specific subdomains as well? For example: in the RIR system a RIR can currently revoke part of an issued ip block without revoking the whole thing. Ex: issue 1.2.0.0/16 to comcast and then revoke 1.2.3.0/24. This current design makes that possible as the root resolver sees the entire requested path.

If we want to prevent that we'd need to make this look a little more like a DNS query where the querier needs to split the query and then ask each TLD iteratively for its respective section.

@0xekez
Copy link
Contributor

0xekez commented Dec 16, 2021

This current design makes that possible as the root resolver sees the entire requested

of course with this design a client could always lie and find it anyhow 🤷‍♂️ something else to consider.

@the-frey
Copy link
Contributor Author

the-frey commented Dec 17, 2021

It's funny that you say:

Add a field in the token metadata which is the address of a contract which can be queried for subdomain information.

I hadn't read that, but slept on this, woke up and went "hang on, isn't the general case for this entire shebang simply that you can have NFTs that result in a tree (that is a set of subdomains... and the only missing part is that all (de)NS NFTs need to have a meta field saying if they're a contract or not?"

So I think we're circling around the same idea, that addressing contracts is worth figuring out (see also #33 and the IBC stuff)

Default it to false -> & if it's true, then the NFT represents an addressable entity. Gives you total flexibility of behaviour including whatever hooks you feel like (i.e. non trivial logic and whatnot) at all parts of the tree.

Imagine most people will simply want a root (de)NS NFT that maps onto a single contract but you could envisage a scenario:

the-frey's address owns two tokens:

the-frey a root record with some web of trust metadata (coming v2)
needlecast a root record with a validator address that has info for the validators run by the root address

needlecast::validators a subdomain token id (outstanding q, see #33 ) that maps to a custom smart contract with a query method that returns live validator metrics for that validator (I think this is possible from an SC, don't see why not)

if I list the tokens owned by that address, I get:

the-frey (NFT w/meta contract: false)
needlecast (NFT w/meta contract: false)
needlecast::validators (NFT w/meta, contract: true resolves to contract)

@the-frey
Copy link
Contributor Author

I think there may be a fundamental primitive we're missing here, in the sense that a smart contract isn't quite a lambda.

That said, by at least making SCs referenceable like any other entity in the system, we can create arbitrarily composable behaviour via deref/redirect in a way we couldn't if we enforced a specific interface for the leaf smart contracts and made them tie into a request/reply cycle.

That complects together the name service (data) and the contracts (functions) and that's generally not the most flexible approach.

@the-frey
Copy link
Contributor Author

Changed the title of this issue to be higher energy as well, cos it's nearly the solstice and I was listening to this.

@the-frey the-frey changed the title Subdomains? Subdomains!!!: Addressability!!! Addressable Contracts!!! And Excited by Nothing!!!!!!! Dec 17, 2021
@the-frey the-frey added help wanted Extra attention is needed question Further information is requested labels Dec 17, 2021
@the-frey the-frey added this to the MVP milestone Dec 17, 2021
@the-frey
Copy link
Contributor Author

Actually, a boolean for if something is a contract doesn't make sense. It should be Option<Addr> because impllicitly the boolean state is covered by None or Some(addr)

@the-frey the-frey modified the milestones: MVP, v0.5.0 Dec 21, 2021
@the-frey
Copy link
Contributor Author

the-frey commented Dec 22, 2021

Interesting to see the approach of the Terra Name Service https://agora.terra.money/t/tip-terra-name-service-spec/193

Lots of time spent on auction mechanics, very little on ergonomics or addressability.

This was referenced Jan 4, 2022
the-frey added a commit that referenced this issue Jan 12, 2022
* Basic functionality, querying, cycle detection, and validation for #29

* Add path query again for basic #25 implementation

* Update README, add a test to confirm NotFound behaviour for a parent
@the-frey
Copy link
Contributor Author

Closed by #60 but suspect the saga continues

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants