|
| 1 | +# Naam: Naming As Advertisement |
| 2 | + |
| 3 | + |
| 4 | + |
| 5 | +**Author(s)**: |
| 6 | + |
| 7 | +- [Masih Derkani](https://github.com/masih) |
| 8 | + |
| 9 | +**Maintainer(s)**: |
| 10 | + |
| 11 | +- [Masih Derkani](https://github.com/masih) |
| 12 | + |
| 13 | +* * * |
| 14 | + |
| 15 | +**Abstract** |
| 16 | + |
| 17 | +This document defines the **N**aming **A**s **A**dvertise**m**ent (Naam) protocol: a mechanism by |
| 18 | +which [IPNI](IPNI.md) can be used to both publish, and |
| 19 | +resolve [IPNS](https://github.com/ipfs/specs/blob/main/ipns/IPNS.md) records. Naam utilises the |
| 20 | +extensible IPNI [advertisement metadata](IPNI.md#metadata) to encode IPNS records and form an |
| 21 | +advertisement. The resulting advertisements are consumable by indexer nodes, just like any other |
| 22 | +advertisement. Further, to resolve IPNI records, Naam utilises the existing |
| 23 | +IPNI [multihash lookup API](IPNI.md#get-multihashmultihash) to discover IPNI records. |
| 24 | + |
| 25 | +## Table of Contents |
| 26 | + |
| 27 | +* [Introduction](#introduction) |
| 28 | +* [Specification](#specification) |
| 29 | + + [IPNS Record Publication](#ipns-record-publication) |
| 30 | + + [Updating IPNS Records](#updating-ipns-records) |
| 31 | + + [Removing IPNS Records](#removing-ipns-records) |
| 32 | + + [Resolving IPNS Records](#resolving-ipns-records) |
| 33 | +* [Limitations](#limitations) |
| 34 | + + [IPNS Record Size](#ipns-record-size) |
| 35 | + + [Record Validity Duration](#record-validity-duration) |
| 36 | +* [Security](#security) |
| 37 | + + [Advertisement Verifiability](#advertisement-verifiability) |
| 38 | + + [Reputation](#reputation) |
| 39 | +* [Privacy](#privacy) |
| 40 | +* [Implementations](#implementations) |
| 41 | +* [Related Resources](#related-resources) |
| 42 | +* [Copyright](#copyright) |
| 43 | + |
| 44 | +## Introduction |
| 45 | + |
| 46 | +IPNI introduces a set of protocols to discover providers for content-addressable data, along with |
| 47 | +the protocols over which the data can be retrieved. Content providers maintain a chain of |
| 48 | +advertisements that collectively capture the list of multihashes they provide. IPNI network is |
| 49 | +actively being integrated across multiple networks, including IPFS and FileCoin. |
| 50 | + |
| 51 | +As the IPFS network grows, it is desirable to enable alternative content routing mechanisms in order |
| 52 | +to provide the best user experience possible; e.g. fast time-to-first-byte, low latency lookups, |
| 53 | +etc. IPNI already offers a DHT alternative to discover providers for a given CID. However, DHT in |
| 54 | +IPFS provides other functionalities that go beyond provider lookup. One such functionality is IPNS: |
| 55 | +InterPlanetary Naming System. |
| 56 | + |
| 57 | +IPNS compliments the immutability of IPFS by providing a way to create cryptographically |
| 58 | +verifiable, mutable pointers to content-addressed data. It is part of the core IPFS functionality, |
| 59 | +which offers an intuitive way to enable naming service, such as mapping domain names to changing |
| 60 | +CIDs. For IPNI to become a complete content routing system and a viable alternative to the existing |
| 61 | +IPFS DHT it needs to support IPNS. This is where **N**aming **A**s **A**dvertise**m**ent |
| 62 | +(Naam) comes in. |
| 63 | + |
| 64 | +## Specification |
| 65 | + |
| 66 | +Naam is a naming protocol that build on top of the existing IPNI protocol to facilitate a naming |
| 67 | +system. It enables publication and resolution of IPNS records using the IPNI advertisements and |
| 68 | +indexer node find APIs. Naam utilises the extensible advertisement metadata field to embed IPNS |
| 69 | +records and produce advertisements that are consumable by existing indexer nodes without requiring |
| 70 | +any change to the existing ingestion pipeline nor lookup API. |
| 71 | + |
| 72 | +This approach offers two key advantages; it: |
| 73 | + |
| 74 | +1) reuses the existing IPNI network to implement a name service, which takes IPNI closer to offering |
| 75 | + a fully featured DHT alternative for the IPFS network without having to run any additional |
| 76 | + services dedicated to resolving IPNS records , and |
| 77 | +2) preserves an immutable historical catalogue of all IPNS records published by a peer, which can be |
| 78 | + used for reputation analysis and ultimately holding peers responsible for their participation in |
| 79 | + the network. |
| 80 | + |
| 81 | +Naam naming system involves three main components: |
| 82 | + |
| 83 | +1) **Publisher** - which makes a chain of specifically crafted advertisements available for |
| 84 | + ingestion by the network indexers, |
| 85 | +2) **Network Indexer** - which is an IPNI node responsible for ingesting advertisements and exposing |
| 86 | + find APIs, and |
| 87 | +3) **Resolver** - which with the aid of network indexers given an IPNS key resolves its |
| 88 | + corresponding record. |
| 89 | + |
| 90 | +The flow of information between the three components is similar to the indexing ecosystem depicted |
| 91 | +in IPNI spec: publishers create and publish advertisements -> network indexers ingest them -> and |
| 92 | +similar to retrieval clients resolvers use the find API to map a given IPNS key to IPNS record. In |
| 93 | +this flow no changes are needed on network indexers. Therefore, the reminder of this document |
| 94 | +focuses on interactions of Publishers, Resolvers and the data format exchanged between them. For |
| 95 | +more information on how network indexers ingest advertisements and provide lookup APIs, please |
| 96 | +see [IPNI](IPNI.md). |
| 97 | + |
| 98 | +### IPNS Record Publication |
| 99 | + |
| 100 | +Naam publishes IPNS records via Publishers, which create IPNI-compliant advertisements that |
| 101 | +embed IPNS records and are signed by their identity. The produced advertisements consist of: |
| 102 | + |
| 103 | +* **`PreviousID`** - the optional link to the previous Naam advertisement. `nil` indicates no |
| 104 | + previous advertisements. |
| 105 | +* **`Provider`** - the publisher peer ID. |
| 106 | +* **`Addresses`** - the array of multiaddrs over which the publisher can be reached. |
| 107 | +* **`Entries`** - the link to an `EntryChunk` IPLD node, as specified by IPNI, that contains a |
| 108 | + single entry: the multihash of IPNS record key with `nil` as link to `Next`. |
| 109 | +* **`ContextID`** - fixed to UTF-8 bytes encoding of the value `/ipni/naam`. |
| 110 | +* **`Metadata`** - the bytes representation of Naam metadata, consisting of: |
| 111 | + * the varint representation of IPNS multicodec code, i.e. `0xe5`, as bytes, |
| 112 | + * followed by the marshalled IPNS record. |
| 113 | +* **`IsRm`** - the boolean value specifying weather an IPNS entry is being added/updated, |
| 114 | + i.e. `true`, or removed, i.e. `false`. |
| 115 | +* **`Signature`** - the advertisement signature calculated as specified by IPNI specification. |
| 116 | + |
| 117 | +#### `Entries` |
| 118 | + |
| 119 | +`Entires` in a typical advertisement are responsible for capturing the list of multihashes |
| 120 | +corresponding to the content hosted by a provider. Once ingested, the indexer nodes facilitate |
| 121 | +lookup of providers over find APIs via the same multihashes. |
| 122 | + |
| 123 | +Naam repurposes the same advertisement structure by specifically crafting entries of advertisement |
| 124 | +such that the indexer node find API can also be repurposed to lookup IPNS records. Naam forms a |
| 125 | +single `EntryChunk` IPLD node, that contains a single multihash calculated as: |
| 126 | + |
| 127 | +* the SHA-256 of IPNS Record Key, i.e. `/ipns/<peer-ID>`. |
| 128 | + |
| 129 | +This approach allows the resolvers to deterministically calculate the multihash used for lookup when |
| 130 | +interacting with the indexer node find APIs. |
| 131 | + |
| 132 | +#### Context ID |
| 133 | + |
| 134 | +The field `ContextID` in a regular advertisement is used as a way to uniquely identify the metadata |
| 135 | +associated to a list of multihashes. Naam uses a fixed value, `/ipni/naam`, as context ID to assure |
| 136 | +that the metadata associated to the published advertisement for the same IPNI key is singular and |
| 137 | +uniquely identifiable. |
| 138 | + |
| 139 | +Using a fixed value as context ID also enables network indexers to quickly differentiate Naam |
| 140 | +advertisements from a typical content advertisement. This opens up future opportunities for |
| 141 | +optimisation when it comes to ingesting Naam advertisements. For example, indexers can pro-actively |
| 142 | +process IPNS records and offer bespoke APIs that understand IPNS record expiry/validity. |
| 143 | + |
| 144 | +#### Metadata |
| 145 | + |
| 146 | +`Metadata` is typically used to convey the list of protocols over which the advertised content is |
| 147 | +retrievable. Further, this field is designed to be extensible: a valid metadata should start with a |
| 148 | +`varint` signifying _some_ protocol ID followed by arbitrary bytes. There are currently three well |
| 149 | +known protocol IDs. The protocol ID itself need not to be known by the indexer nodes. In fact, |
| 150 | +indexers treat metadata as a black box and carry on processing advertisements. Instead, it is meant |
| 151 | +to be a signal to the consumers of `Metadata`, i.e. retrieval clients, as a hint on how to decode |
| 152 | +the remaining bytes. |
| 153 | + |
| 154 | +Naam utilises this extensibility to directly encode IPNS records as metadata. The Naam advertisement |
| 155 | +metadata consists of: |
| 156 | + |
| 157 | +* `ipns` multicodec code `0xe5` as protocol ID, |
| 158 | +* followed by marshalled IPNS Record. |
| 159 | + |
| 160 | +The use of metadata to capture IPNS records enables Naam to also utilise the built-in IPNI mechanism |
| 161 | +for updating metadata to update IPNS records. Because, context ID nor the multihash in Naam |
| 162 | +advertisements ever change for the same IPNS key. For more information, |
| 163 | +see [Updating IPNS Records](#updating-ipns-records). |
| 164 | + |
| 165 | +Note that the IPNS multicodec code `0xe5` is tagged as "namespace" in the CSV table, which could |
| 166 | +signify an IPNS path, not record. There is currently no multicodec code for IPNS records themselves. |
| 167 | +Alternatively, a new multicodec code can be introduced to the |
| 168 | +[multicodec CSV file](https://github.com/multiformats/multicodec/blob/master/table.csv) to avoid |
| 169 | +potential confusion between the two. The new code can then be used as the Protocol ID of Naam |
| 170 | +Metadata. |
| 171 | + |
| 172 | +### Updating IPNS Records |
| 173 | + |
| 174 | +IPNI offers a built-in mechanism to efficiently update the metadata associated to a list of |
| 175 | +multihashes without having to republish the entries. Indexer nodes uniquely identify the metadata by |
| 176 | +the advertisement `Provider`, and `ContextID`. |
| 177 | + |
| 178 | +Both of these values remain the same in Naam advertisements: the former is the same peer ID that |
| 179 | +forms part of the IPNS key, i.e. `/ipns/<peer-id>`, and the latter is fixed. As a result, to update |
| 180 | +an IPNS record, all that's needed is to publish a new Naam advertisement that: |
| 181 | + |
| 182 | +* links to the previous advertisement in `PrevousID` link as specified by IPNI, |
| 183 | +* uses the same `Provider` and `ContextID` values as before, |
| 184 | +* sets `IsRm` to `false`, and |
| 185 | +* has the updated IPNS record in Naam Metadata format. |
| 186 | + |
| 187 | +Note that there is no need to specify `Entries` when updating an existing record. It is inferred by |
| 188 | +the network indexers since `Provider` and `ContextID` in Naam advertisements never change. |
| 189 | + |
| 190 | +### Removing IPNS Records |
| 191 | + |
| 192 | +IPNS has EOL and TTL features built-in. This means explicit removal of records is not strictly |
| 193 | +required. Instead, records eventually expire. Though not strictly necessary, Naam protocol can |
| 194 | +utilise IPNI to explicitly remove records just like a traditional DNS nameserver. |
| 195 | + |
| 196 | +The process to remove an IPNS record published via Naam protocol is identical to removal |
| 197 | +advertisement specified by IPNI. Similar to a regular advertisement, an IPNS record may be removed |
| 198 | +by publishing an advertisement that: |
| 199 | + |
| 200 | +* links to the previous advertisement in `PrevousID` link as specified by IPNI, |
| 201 | +* uses the same `Provider` and `ContextID` values as before, |
| 202 | +* sets `IsRm` to `true`, and |
| 203 | +* sets `Entries` link to `NoEntries` as specified by IPNI. |
| 204 | + |
| 205 | +Once ingested, indexer nodes will eventually remove the Naam advertisement metadata along with the |
| 206 | +publisher information. |
| 207 | + |
| 208 | +### Resolving IPNS Records |
| 209 | + |
| 210 | +IPNS record resolution involves finding the IPNS record associated to a given IPNS key, i.e. |
| 211 | +`/ipns/<peer-id>`. As eluded to earlier, Naam uses the find API already provided by the network |
| 212 | +indexers to achieve this. To resolve an IPNS record, a resolver: |
| 213 | + |
| 214 | +* calculates the multihash of the given IPNS key as its SHA-256, |
| 215 | +* looks up the provider info for that multihash via the IPNI find API, |
| 216 | +* decodes the metadata from the provider info as IPNS record, |
| 217 | +* validates the record, and |
| 218 | +* if valid returns its value. |
| 219 | + |
| 220 | +## Limitations |
| 221 | + |
| 222 | +### IPNS Record Size |
| 223 | + |
| 224 | +The maximum size of IPNS records supported by Naam is 1 KiB, even though IPNS specification suggests |
| 225 | +a maximum limit of 10 KiB. The 1 KiB limit currently imposed by network indexers on the maximum size |
| 226 | +of advertisement metadata. |
| 227 | + |
| 228 | +Basic tests show that a 1KiB limit is sufficiently large for storing simple IPNS records pointing to |
| 229 | +IPFS paths, specially for records that do not need the peer's public key to be embedded into IPNS |
| 230 | +records. For example, a Ed25519 peer ID also captures the peer's public key. A marshalled IPNS |
| 231 | +record with such key type and empty value constructed |
| 232 | +using [`go-ipns`](https://github.com/ipfs/go-ipns) library comes to `257` bytes, which leaves |
| 233 | +sufficient space for encoding fairly long IPFS paths as the record value. |
| 234 | + |
| 235 | +### Record Validity Duration |
| 236 | + |
| 237 | +The indexers will maintain information from inactive providers for up to a week. This means IPNS |
| 238 | +records published by Naam with EOL of beyond a week should be re-published to remain resolvable. |
| 239 | + |
| 240 | +## Security |
| 241 | + |
| 242 | +### Advertisement Verifiability |
| 243 | + |
| 244 | +Naam advertisements will benefit from all the verifiability features of regular advertisements. They |
| 245 | +are signed by the IPNS record publisher and are verified for validity before being ingested by the |
| 246 | +network indexers. |
| 247 | + |
| 248 | +### Reputation |
| 249 | + |
| 250 | +Similar to the IPNI indexing protocol, the use of immutable advertisement chain by Naam provides a |
| 251 | +verifiable and immutable catalog of IPNS records exposed by a network participant. Access to such |
| 252 | +historical data enables verifiable analysis of participant behaviour, and offers an opportunity to |
| 253 | +design and develop reputation systems, which ultimately can contribute to the health of the network. |
| 254 | +As far as I know, this is something that is not currently offered by the existing implementations of |
| 255 | +IPNS. |
| 256 | + |
| 257 | +Even though, the specification of such reputation system is beyond the scope of this document, it is |
| 258 | +important to point out such potential. Because, as the size of IPFS network grows so will the need |
| 259 | +for reputation systems that enable users to choose from ever increasing "choices" across the |
| 260 | +network. |
| 261 | + |
| 262 | +## Privacy |
| 263 | + |
| 264 | +To be revisited when double-hashing work is finalised. |
| 265 | + |
| 266 | +## Implementations |
| 267 | + |
| 268 | +* [`ipni/go-naam`](https://github.com/ipni/go-naam) - Golang implementtion of IPNI Naam protocol. |
| 269 | + |
| 270 | +## Related Resources |
| 271 | + |
| 272 | +* [IPNS: InterPlanetary Naming System](https://github.com/ipfs/specs/blob/main/ipns/IPNS.md) |
| 273 | +* [IPNS PubSub Router](https://github.com/ipfs/specs/blob/main/ipns/IPNS_PUBSUB.md) |
| 274 | +* [IPNI: InterPlanetary Network Indexer](https://IPNI.md) |
| 275 | + |
| 276 | +## Copyright |
| 277 | + |
| 278 | +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). |
0 commit comments