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

propose: fast lane ipns #66

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
336 changes: 336 additions & 0 deletions proposals/fast-lane-ipns.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,336 @@
# Fast lane IPNS

Authors:
- @gozala

Initial PR: TBD <!-- Reference the PR first proposing this document. Oooh, self-reference! -->
Related to: [Reliable Mutability Primitive][]

[Reliable Mutability Primitive]:https://github.com/protocol/web3-dev-team/pull/19/
<!--
This template is for a proposal/brief/pitch for a significant project to be undertaken by a Web3 Dev project team.
The goal of project proposals is to help us decide which work to take on, which things are more valuable than other things.
-->
<!--
A proposal should contain enough detail for others to understand how this project contributes to our team’s mission of product-market fit
for our unified stack of protocols, what is included in scope of the project, where to get started if a project team were to take this on,
and any other information relevant for prioritizing this project against others.
It does not need to describe the work in much detail. Most technical design and planning would take place after a proposal is adopted.
Good project scope aims for ~3-5 engineers for 1-3 months (though feel free to suggest larger-scoped projects anyway).
Projects do not include regular day-to-day maintenance and improvement work, e.g. on testing, tooling, validation, code clarity, refactors for future capability, etc.
-->
<!--
For ease of discussion in PRs, consider breaking lines after every sentence or long phrase.
-->

## Purpose &amp; impact
#### Background &amp; intent
_Describe the desired state of the world after this project? Why does that matter?_
<!--
Outline the status quo, including any relevant context on the problem you’re seeing that this project should solve. Wherever possible, include pains or problems that you’ve seen users experience to help motivate why solving this problem works towards top-line objectives.
-->

##### Problem statement

Today [IPNS][] fails to provide reliable mutability primitive. There is no implementation that works across go, node and web, which makes it impractical.

| Routing | web | go | nodejs |
| ------- | ---- | ---- | ------ |
| DHT | ❌ | ✅ | ❌ |
| pubsub | ⚠️ | ⚠️ | ⚠️ |

> ❌ - Not available
> ✅ - Available
> ⚠️ - Not out of the box
>
> - ❌ DHT in web nodes is impractical as most nodes will be undialable and so will be a web node.
> - ❌ DHT implementation in nodejs is buggy, untersted and unoptimized ([ipfs/js-ipfs#3469][]).
> - ⚠️ PubSub in web nodes only works in swarms formed around central ICE server that are disjoint from go nodes. In practice creating fragmented networks of ephemeral peers.
> - ⚠️ IPNS over pubsub is disabled in go by default (Can be enabled by running daemon with `--enable-namesys-pubsub`). Pubusb itself is also disabled by default ([protocol/web3-dev-team#53][]).
> - ⚠️ IPNS over pubsub in nodejs still requires DHT to bootstrap overlay network of participating peers. Lack of proper DHT implementation prevents it. Which could be overcome via delegated routing but it does not work out of the box.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be any router, including the Rendezvous. Ideally what I would like to see was nodes to advertise that they are interested in a given topic in all the means they can DHT/Delegate/Rendezvous/... and then other more limited peers can rely on what suits them better.

I would rephrase the DHT to content/peer routing. I proposed some time ago the Discovery API, which would be a simple abstraction that would forward advertises/findPeers to the available routers. Go also has a discovery API concept similar

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That sounds reasonable and possibly worth adding to considered alternatives section. Here I describe current state of things and to my knowledge it does so accurately, isn't it ?


Only DHT based implementation in go works out of the box. But it still fails to meet user expectations because:
1. *Slow* publish and resolution.
2. Requires continues republishing. (see [ipfs/go-ipfs#4435])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So does pubsub.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Conversation with @aschmahmann left me with an impression that pubsub is less problematic as peers query network and anyone can respond with a record, which in practice happens to be a lot more effective.

@Stebalien Anything I should change about above statements or was that just a side note ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's less problematic as long as someone who resolved the record is still around and still subscribed to the record's pubsub channel. So, for popular records yes.

But for unpopular records, no, you'll need to be online and/or republish regardless.


Teams that have tried using IPNS in their products either switched to using [DNSLink][] or opted-into IPNS over pubsub and still find it *(too slow)* for certain updates *(Textile)*.

To meet a market fit for products with changing state requirement _(that is anything interactive)_ IPNS needs to work reliably, fast _(comparable to web2 solutions)_ and across all supported enviroments _(go, web, nodejs)_.

##### Proposition

At the high level this proposal promises an efficienecy of centralized publishing and resolution while retaining resilience of distributed system.

Proposed name resolution system is inspired by Domain Name System (DNS) as it introduces athoritative name resolvers _(from now on referred as)_ **name keeper** nodes. But unlike DNS, **name owners** _(private key holders)_ are in charge of choosing a name keepers and retain ability to change a name keeper in the future.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this actually work? We could add a set of "keepers" to the IPNS record itself, I guess (as long as it's under a signature). I assume that's what you mean, right?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I go into much greater detail below, but general idea is that instead of having to route on every name resolution, we'd do it very infrequently because there will be specific authoritative node you can ask about current record. That way nodes will be able to resolve "name keeper" address once and cache for future name resolutions.

Hypothesis is that while name keeper can change, it will be infrequent enough that we can see huge gains.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, sorry, my question is: how are you specifying these "name keepers"? Where does the list live, how is it published, how is it authenticated, how do I revoke keepers, etc.

Copy link
Author

@Gozala Gozala Mar 22, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you may have meant how name owners choose name keepers. I don't have thought through the specific here, but general idea is that name owner would provide a name keeper with a signed certificate, which it can use to prove to routing nodes that it is indeed the name keeping authority.

That said I'm pretty open to discussing / reconsidering many details of this proposal, mostly I'm pitching a bigger picture, that is lets make name publishing fast point to point operation. And make name resolution as close to that as possible.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it. My thinking is that the keepers should be added as additional fields to the IPNS records. That way, there's no way to "roll back".

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how are you specifying these "name keepers"?

  1. You can create DNSLink record with /ipns/${key} and multiaddrs to name keeper.
  2. You issue a certificate to a name keeper authorizing them as a name keeper. Which they use to let routing nodes know & proof they are the authority for the name. General assumption here is that pinning services will assume "name keeper" role as they are always on, well connected and you tell them what to pin anyway.

Where does the list live

"Initial resolution optimization" attempts to describe it at high level. It assumes that infrastructure nodes can keep a list of "name keepers" and respond to queries from the network. If the name is unknown they can fallback to regular resolution DHT/PubSub and then cache the record forever. Note that here they resolve a "name keeper" not an actual record, and because those likely to change rarely no significant load is expected since there multiple layers of long term caching.

how is it published, how is it authenticated

Name keepers are in charge of publishing to DHT, and over pubsub (possibly rendezvous) announcing themselves as "name keeper" for a name. Again since name keepers are unlikely to change TTLs could be very high.

how do I revoke keepers, etc.

Again have not thought through all the details, but broadly speaking "name owner" would issue new certificate overriding old one to a different "name owner", which will than be responsible for updating the network. I expect pubsub would be an effective way to let routing routing nodes about the name keeper change. That said I'm open to alternative here as well.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realize I'm pretty vague when I talk about certificates, that is because I intentionally have not spend time thinking through all the details until this gets some traction. That said I think UCANs are providing a pretty good and generalized model.


> It is assumed that pinning services would be a natural fit for name keeping as they they already are responsible for keeping the content around and mantain list of user pins.


This promises to provide efficiency and speed of centralized systems as peers can cache *name keeper* address(es) for name _(on first resolution)_ and use it in all future resolutions, without disturbing rest of the network.

Name publishing becomes also efficient as name owner can notify *name keeper* directly without disturbing rest of the network.

> Please note that this enables peers to effectively resolve and/or publish name without having to remain online.

###### Initial resolution optimization

To make a very first name resolution nearly as efficient as subsequent ones it is propsoed to develop a new **name routing** service and deploy it on boostrap nodes. Name routing nodes will maintain `IPNS name → multiaddrs[]` mapping enabling peers to resolve an address of a name keeper on a first name resolution. Under assumbiton that reassigment of *name keepers* is going to be rare, overhead on name routing nodes should be insignificant as:
Gozala marked this conversation as resolved.
Show resolved Hide resolved

1. Name routers could cache addresses for a long time.
2. Resolving peers could cache address locally (and require router only first time).
3. Name routers can deny service to peers resolving name too frequently.
4. Name routers are not involved in publishing.

It is assumed that name routers will be infrastructure nodes, implying that they can be dialed from limited nodes like browsers _*(Have SSL certificates setup, or have a WebRTC address)*_ and can leverage DHT and PubSub so thay they:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wondering if we can reuse rendezvous servers for the exact same purpose?

A rendezvous server is a libp2p node with a database that keeps all the multiaddrs registered for a given namespace. It receives registration requests and discovery requests.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another possible link here if they would be a different piece of infrastructure would be for the name routers to advertise their role via rendezvous + DHT, so that other peers could easily find such nodes in the network

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think rendezvous nodes could be a perfect fit here, I just did not wanted to tie the proposal to any specific not yet available (as in deployed) solution so it is possible to iterate on this without been blocked on other pieces.


1. Can resolve new name on demand by raced query of DHT and PubSub.
2. Can become aware of new names through PubSub messages.
3. Can become aware of name keeper changes through PubSub.

> Note that since name keeper changes are expected to be rare TTL can be really high.

Name routing service does not has to be limited to infrastructure nodes, peer could provide that service and resolve name keeper address from a local cache.


###### DNSLink Optimization

Name owners could include addresses to chosen name keepers in the [DNSLink][] record, which would enable name resolution without resolving an address through name routers first.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How would this interact with IPNS? IPNS doesn't use DNSLink.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just DNSLink optimization, that would allow you to avoid querying routing nodes described in a previous section. When you resolve IPNS name you'd either already have name keeper address or you query routing nodes to obtain one and cache it forever.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IPNS and DNSLink aren't really related. For DNSLink, you just query your local DNS resolver which is almost always very fast.

Copy link
Author

@Gozala Gozala Mar 22, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I think I know what the misunderstand is here. Today most DNSLink records are /ipfs/... while expectation with this done is that they will turn into /ipns/... and will not require DNS provider specific APIs to do updates.

Does this makes more sense ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's the first I've heard of that. What's the motivation?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's the first I've heard of that. What's the motivation?

"What does success look like?" section calls out specifically related goals as success metric. That said motivation specifically is:

  1. Browser nodes can not update name (unless....)
  2. Not all DNS providers provide programatic API to do record updates. And ones that do have their own custom API so there is no general interface to publishing updates.
  3. Usually updating DNS record involves separate authentication, creating yet another hurdle for doing it especially in browsers but also beyond.
  4. We could have subscribe style interface for realtime stuff if domain name is just a human readable alias to /ipns/..., which seems unrealistic otherwise.

If I'm not mistaken originally #42 covered a lot of this before it rescoped.


##### Visual illutrations

###### Name resolution

Diagram illustrates a name resolution flow. Note however that it does not show how name router can discover new names and their keepers from pubsub.

<!--
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

```flow
pubsub=>start: PubSub
peer=>start: 📱 Peer
router=>start: 🖥 Router Node.
keeper=>start: 🖥 Name Keeper
resolve_keeper=>operation: Resolve QmName keeper
resolve_name=>end: Keeper resolved
cid=>end: QmV8
localcached=>condition: Is keeper address cached
routercached=>condition: Check the cache
dht_query=>operation: Query DHT
pubsub_query=>operation: Query PubSub
query=>parallel: Query
cache_router=>inputoutput: Save Keeper Address
cache_local=>inputoutput: Save Keeper Addresss
resolve_cid=>operation: Resolve CID for QmName
resolved_cid=>inputoutput: QmName is QmV17

peer->localcached
localcached(yes)->resolve_cid
localcached(no, right)->resolve_keeper(right)->router

router(right)->routercached
routercached(yes)->resolve_cid
routercached(no, right)->query

query(path1, bottom)->dht_query->cache_router
query(path2, right)->pubsub_query->cache_router
cache_router(left)->resolve_cid

resolve_cid->keeper->resolved_cid
pubsub->peer
```
-->
![name resolution](./fast-lane-ipns/resolution.svg)



###### Name update

Diagram illustrating how name update flow.

<--
```flow
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

owner=>start: 📱 Name Owner
ok=>inputoutput: ✅ QmName is QmV2
error=>inputoutput: ❌ QmV1 is not a head
update=>operation: Update QmName from QmV1 to QmV2
incremental=>condition: QmName is QmV1 ?
keeper=>end: 🖥 Name Keeper


owner->update->keeper->incremental
incremental(yes)->ok
incremental(no)->error
```
-->
![publish](./fast-lane-ipns/publish.svg)


###### Humane readable name resolution

Diagram illustrates name resolution through DNSLink.

<--

```flow
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure where a.com is coming from.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure where a.com is coming from.

As per test above this "Diagram illustrates name resolution through DNSLink", so it is an example when peer is trying to resolve /ipns/a.com/. @Stebalien does this make sense, otherwise could you please clarify a bit what you mean ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

peer=>start: Peer
keeper=>start: Name Keeper
router=>start: Name Router
DNS=>end: DNS
dnslink=>operation: a.com -> QmName
lookup=>operation: lookup a.com
has_keeper=>condition: DNSLink has keepr address
resolve_cid=>operation: Reslove QmName
resolve_keeper=>operation: Reslove Keeper
keeper_resolved=>inputoutput: Resolved address
cid=>inputoutput: QmV321
ttl_name=>condition: a.com in cache?

peer->ttl_name
ttl_name(no, right)->lookup(right)->has_keeper
ttl_name(yes, bottom)->resolve_cid

has_keeper(yes, bottom)->resolve_cid
has_keeper(no)->resolve_keeper(bottom)->router->keeper_resolved(left)->resolve_cid
resolve_cid(bottom)->keeper
keeper->cid
```
-->
![publish](./fast-lane-ipns/dnslink.svg)

#### Assumptions &amp; hypotheses

_What must be true for this project to matter?_
<!--(bullet list)-->

- Applications need canonical address for a current state.
- Should work across all supported environments out of the box.
- To be practical solution, resolution should be reliable (publish / resolve works at least 99.9%).
- To be practical solution, resolution should be really fast (as fast or faster than DNS resolution).
- To be practical solution publishing should be really fast (To be competitive with web2 should be comparable to sending a HTTP request to the server)
- Overhead should be neglegable.

#### User workflow example
_How would a developer or user use this new capability?_
<!--(short paragraph)-->

#### Impact
_How would this directly contribute to web3 dev stack product-market fit?_

<!--
Explain how this addresses known challenges or opportunities.
What awesome potential impact/outcomes/results will we see if we nail this project?
-->

🔥🔥🔥 This would provide mutability primitive that is reliable and fast as DNS, but does not require centralized authority or blockchain style concensus.

Furthermore it would make updating far more convenient than DNS.

#### Leverage
_How much would nailing this project improve our knowledge and ability to execute future projects?_

<!--
Explain the opportunity or leverage point for our subsequent velocity/impact (e.g. by speeding up development, enabling more contributors, etc)
-->

🎯🎯 - This would turn IPFS into an essential building block for web3 applications _(that need to do state updates)_ by removing a need for a custom server-side components to address this limitation.

#### Confidence
_How sure are we that this impact would be realized? Label from [this scale](https://medium.com/@nimay/inside-product-introduction-to-feature-priority-using-ice-impact-confidence-ease-and-gist-5180434e5b15)_.

<!--Explain why this rating-->

3 - As high confidence as we can have without doing actual user studies. We know teams that have tried IPNS but found it unrelaible, ultimately rolling out an alternative solution. We also know teams that have evaluated IPFS but chose alternative due to lack of reliable mutability story.

## Project definition
#### Brief plan of attack

<!--Briefly describe the milestones/steps/work needed for this project-->

- Define fast lane name resolution specification.
- Define name keeper serivce specification.
- Define name routing service specification.
- Implement name routing service in go-ipfs.
- Implement name keeper service in go-ipfs.
- Implement fast lane name resolution across web, go, node ipfs.
- Deploy name routing service to PL operated boostrap nodes.

#### What does done look like?
_What specific deliverables should completed to consider this project done?_

- IPNS records can be published and resolved across all supported environments (web, go, node).
- Publishing takes couple of miliseconds.
- Resolution in all but pathological case goes through fast lane.
- Resolution in fast lane takes just couple of miliseconds.

#### What does success look like?
_Success means impact. How will we know we did the right thing?_

<!--
Provide success criteria. These might include particular metrics, desired changes in the types of bug reports being filed, desired changes in qualitative user feedback (measured via surveys, etc), etc.
-->

- Teams start using IPNS in [DNSLink][] records as opposet to CIDs.
- We see people storing IPNS addresses in ENS to save on blockchain transactions costs
- We see new projects leveraging IPNS (when human readable name is not a concern) instead of working around it with [DNSLink][].
- Most lookups go through fast lane.

#### Counterpoints &amp; pre-mortem
_Why might this project be lower impact than expected? How could this project fail to complete, or fail to be successful?_

#### Alternatives
_How might this project’s intent be realized in other ways (other than this project proposal)? What other potential solutions can address the same need?_

#### Dependencies/prerequisites
<!--List any other projects that are dependencies/prerequisites for this project that is being pitched.-->

#### Future opportunities
<!--What future projects/opportunities could this project enable?-->

## Required resources

#### Effort estimate
<!--T-shirt size rating of the size of the project. If the project might require external collaborators/teams, please note in the roles/skills section below).
For a team of 3-5 people with the appropriate skills:
- Small, 1-2 weeks
- Medium, 3-5 weeks
- Large, 6-10 weeks
- XLarge, >10 weeks
Describe any choices and uncertainty in this scope estimate. (E.g. Uncertainty in the scope until design work is complete, low uncertainty in execution thereafter.)
-->

#### Roles / skills needed
<!--Describe the knowledge/skill-sets and team that are needed for this project (e.g. PM, docs, protocol or library expertise, design expertise, etc.). If this project could be externalized to the community or a team outside PL's direct employment, please note that here.-->

## Appendix

<!-- ### Fast lane name routing

Today IPNS supports two name resolution/publishing schemes. They make different tradeoffs, but both disturbing a network when publishing and/or resolving a name.

- Over DHT
- 💔 Slow to resolve / publish.
- 💔 Has an overhead of needing to republish.
- 💔 Not an option for web peers.
- 💔 Not implemented for node peers.
- 💚 Very resilient
- Over PubSub.
- 💔 Disabled in go peers.
- 💔 Does not work in web (**TODO:** Figure out if we expect it to work).
- 💔 Has a constant overhead (uses resources whether used or not).
- 💔 Initial resolution is slow which makes it slow for non long living peers (mobile devices, web)
- 💚 Super simple and convinient protocol

-->

#### F.A.Q

- Add your question here


[Pinata]:https://pinata.cloud/
[DNSLink]:https://docs.ipfs.io/concepts/dnslink/
[IPNS]:https://docs.ipfs.io/concepts/ipns/
[Pinning Services API]:https://ipfs.github.io/pinning-services-api-spec/
[Petname]:https://en.wikipedia.org/wiki/Petname

[ipfs/js-ipfs#3469]:https://github.com/ipfs/js-ipfs/issues/3469#issuecomment-775944675
[protocol/web3-dev-team#53]:https://github.com/protocol/web3-dev-team/pull/53
[ipfs/go-ipfs#4435]:https://github.com/ipfs/go-ipfs/issues/4435
Loading