From 7b338b45f43dad083143383bd69c983128c22a38 Mon Sep 17 00:00:00 2001 From: Daniel N <2color@users.noreply.github.com> Date: Tue, 23 Aug 2022 13:29:51 +0200 Subject: [PATCH 01/19] wip --- docs/concepts/ipns.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/docs/concepts/ipns.md b/docs/concepts/ipns.md index d660eb33e..2decce608 100644 --- a/docs/concepts/ipns.md +++ b/docs/concepts/ipns.md @@ -5,9 +5,19 @@ description: Learn about the InterPlanetary Name System (IPNS) and how it can be # InterPlanetary Name System (IPNS) -IPFS uses [content-based addressing](content-addressing.md); it creates an address of a file based on data contained within the file. If you were to share an IPFS address such as `/ipfs/QmbezGequPwcsWo8UL4wDF6a8hYwM1hmbzYv2mnKkEWaUp` with someone, you would need to give the person a new link every time you update the content. +## Mutability in IPFS -The InterPlanetary Name System (IPNS) solves this issue by creating an address that can be updated. +[Content addressing](content-addressing.md) in IPFS is by nature *immutable*: when you add a file to IPFS, it creates an address of a file based on data contained within it. Changing a file changes its hash, and consequently its CID which is used as an address. + +Yet, there are many situations where **mutable pointers** are useful as a complement to immutability, for example, when publishing a website that frequently changes, it would be impractical to share a new CID every time you update the website. Using mutable pointers, you can share the address of the pointer, and update the pointer every time you publish a change. + +The InterPlanetary Name System (IPNS) enables the creation of **self-certifying mutable pointers** to a content path. + +Self-certifying means that an IPNS recrod contains all the information necessary to certify its authenticity. IPNS achieves this using public and private key pairs, where the name of the mutable pointer is derived from the public key that can verify the pointer. + +For example, [`](https://cid.ipfs.tech/#k51qzi5uqu5dgy6fu9073kabgj2nuq3qyo4f2rcnn4380z6n8i4v2lvo8dln6l) + +## How IPNS works A _name_ in IPNS is the [hash](hashing.md) of a public key. It is associated with a record containing information about the hash it links to that is signed by the corresponding private key. New records can be signed and published at any time. From 901581e6603b08b229cfeca5eb0a18bd5122affa Mon Sep 17 00:00:00 2001 From: Daniel N <2color@users.noreply.github.com> Date: Wed, 24 Aug 2022 19:04:14 +0200 Subject: [PATCH 02/19] Progress on IPNS docs --- docs/concepts/ipns.md | 46 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/docs/concepts/ipns.md b/docs/concepts/ipns.md index 2decce608..66caaf18f 100644 --- a/docs/concepts/ipns.md +++ b/docs/concepts/ipns.md @@ -7,19 +7,51 @@ description: Learn about the InterPlanetary Name System (IPNS) and how it can be ## Mutability in IPFS -[Content addressing](content-addressing.md) in IPFS is by nature *immutable*: when you add a file to IPFS, it creates an address of a file based on data contained within it. Changing a file changes its hash, and consequently its CID which is used as an address. +[Content addressing](content-addressing.md) in IPFS is by nature _immutable_: when you add a file to IPFS, it creates a hash from the data contained in it. Changing a file changes its hash, and consequently its CID which is used as an address. -Yet, there are many situations where **mutable pointers** are useful as a complement to immutability, for example, when publishing a website that frequently changes, it would be impractical to share a new CID every time you update the website. Using mutable pointers, you can share the address of the pointer, and update the pointer every time you publish a change. +Yet, there are many situations where **mutable pointers** are useful as a complement to immutability, for example, when publishing a website that frequently changes. It would be impractical to share a new CID every time you update the website. With mutable pointers, you can share the address of the pointer once, and update the pointer – to the new CID – every time you publish a change. -The InterPlanetary Name System (IPNS) enables the creation of **self-certifying mutable pointers** to a content path. +The InterPlanetary Name System (IPNS) enables the creation of such mutable pointers to CIDs and are known as **names** or **IPNS names**. IPNS names can be thought of as links that can be updated over time. -Self-certifying means that an IPNS recrod contains all the information necessary to certify its authenticity. IPNS achieves this using public and private key pairs, where the name of the mutable pointer is derived from the public key that can verify the pointer. - -For example, [`](https://cid.ipfs.tech/#k51qzi5uqu5dgy6fu9073kabgj2nuq3qyo4f2rcnn4380z6n8i4v2lvo8dln6l) +> **Note:** Technically, an IPNS name can also point to another IPNS name or DNSLink path. However, it most commonly points to a CID. ## How IPNS works -A _name_ in IPNS is the [hash](hashing.md) of a public key. It is associated with a record containing information about the hash it links to that is signed by the corresponding private key. New records can be signed and published at any time. +### Anatomy of an IPNS name + +A **name** in IPNS is the [hash](hashing.md) of a public key. It is associated with a [**record**](https://github.com/ipfs/specs/blob/main/IPNS.md#ipns-record) containing the CID it links to and other information such as the expiration, the version number, and a cryptographic signature signed by the corresponding private key. New records can be signed and published at any time by the holder of the private key. + +For example, [`k51qzi5uqu5dgy6fu9073kabgj2nuq3qyo4f2rcnn4380z6n8i4v2lvo8dln6l`](https://cid.ipfs.tech/#k51qzi5uqu5dgy6fu9073kabgj2nuq3qyo4f2rcnn4380z6n8i4v2lvo8dln6l) + +The content path that an IPNS name points to, is typically a CID, e.g. `bafybeicklkqcnlvtiscr2hzkubjwnwjinvskffn4xorqeduft3wq7vm` + +### IPNS names are self-certifying + +IPNS names are self-certifying. This means that an IPNS record contains all the information necessary to certify its authenticity. IPNS achieves this using public and private key pairs: + +- Each IPNS name corresponds to a key pair +- The IPNS name is a hash of the public key +- The IPNS record contains the public key and signature, allowing anyone to verify that the name was signed by the key holder. + +This self-certifying nature gives IPNS several benefits not preset in hierarchical and consensus systems such as DNS, and blockchain identifiers. Notably, IPNS records can come from anywhere, not just a particular service/system, and it is very fast and easy to confirm a record is authentic. + +### IPNS is transport agnostic + +Thanks to the self-certifying nature of IPNS records, they are not tied to a specific transport protocol. However, in practice, most IPFS implementations will publish and resolve IPNS records using either the [**DHT**](dht.md) or **PubSub**. + +Due to the ephemeral nature of the DHT, + + + +## IPNS in practice + +### Consistency vs. availability when publishing IPNS records + +### IPNS names can be resolved using IPFS gateways + + +## Example + When looking up an IPNS address, use the `/ipns/` prefix: From 920460d2998975a904a8be532547fc2f6d19a3db Mon Sep 17 00:00:00 2001 From: Daniel N <2color@users.noreply.github.com> Date: Mon, 29 Aug 2022 20:58:20 +0300 Subject: [PATCH 03/19] Transport agnostic --- docs/concepts/ipns.md | 54 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 7 deletions(-) diff --git a/docs/concepts/ipns.md b/docs/concepts/ipns.md index 66caaf18f..5c2110c11 100644 --- a/docs/concepts/ipns.md +++ b/docs/concepts/ipns.md @@ -11,7 +11,7 @@ description: Learn about the InterPlanetary Name System (IPNS) and how it can be Yet, there are many situations where **mutable pointers** are useful as a complement to immutability, for example, when publishing a website that frequently changes. It would be impractical to share a new CID every time you update the website. With mutable pointers, you can share the address of the pointer once, and update the pointer – to the new CID – every time you publish a change. -The InterPlanetary Name System (IPNS) enables the creation of such mutable pointers to CIDs and are known as **names** or **IPNS names**. IPNS names can be thought of as links that can be updated over time. +The InterPlanetary Name System (IPNS) enables the creation of such mutable pointers to CIDs known as **names** or **IPNS names**. IPNS names can be thought of as links that can be updated over time. > **Note:** Technically, an IPNS name can also point to another IPNS name or DNSLink path. However, it most commonly points to a CID. @@ -21,9 +21,11 @@ The InterPlanetary Name System (IPNS) enables the creation of such mutable point A **name** in IPNS is the [hash](hashing.md) of a public key. It is associated with a [**record**](https://github.com/ipfs/specs/blob/main/IPNS.md#ipns-record) containing the CID it links to and other information such as the expiration, the version number, and a cryptographic signature signed by the corresponding private key. New records can be signed and published at any time by the holder of the private key. -For example, [`k51qzi5uqu5dgy6fu9073kabgj2nuq3qyo4f2rcnn4380z6n8i4v2lvo8dln6l`](https://cid.ipfs.tech/#k51qzi5uqu5dgy6fu9073kabgj2nuq3qyo4f2rcnn4380z6n8i4v2lvo8dln6l) +For example, the following is an IPNS name represented by a CIDv1 of public key: [`k51qzi5uqu5dlvj2baxnqndepeb86cbk3ng7n3i46uzyxzyqj2xjonzllnv0v8`](https://cid.ipfs.tech/#k51qzi5uqu5dlvj2baxnqndepeb86cbk3ng7n3i46uzyxzyqj2xjonzllnv0v8). -The content path that an IPNS name points to, is typically a CID, e.g. `bafybeicklkqcnlvtiscr2hzkubjwnwjinvskffn4xorqeduft3wq7vm` +Typically + + ### IPNS names are self-certifying @@ -35,23 +37,61 @@ IPNS names are self-certifying. This means that an IPNS record contains all the This self-certifying nature gives IPNS several benefits not preset in hierarchical and consensus systems such as DNS, and blockchain identifiers. Notably, IPNS records can come from anywhere, not just a particular service/system, and it is very fast and easy to confirm a record is authentic. +### IPNS record validity tradeoffs – consistency vs. availability + +When setting the `validity` (referred to as [`lifetime` by Kubo](https://github.com/ipfs/kubo/blob/master/docs/config.md#ipnsrecordlifetime)) field of an IPNS record, you typically need to choose whether you favor **consistency** (short validity period, e.g. 24 hours) or **availability** (long validity period, e.g. 1 month), due to the inherent trade-off between the two. + +Consistency means ensuring that users resolve to the latest published IPNS record for the name (with the highest sequence number) at the cost of potentially not being able to resolve. + +Availability means resolving to a valid IPNS record, at the cost of potentially resolving to an outdated record. + ### IPNS is transport agnostic -Thanks to the self-certifying nature of IPNS records, they are not tied to a specific transport protocol. However, in practice, most IPFS implementations will publish and resolve IPNS records using either the [**DHT**](dht.md) or **PubSub**. +The self-certifying nature of IPNS records means that they are not tied to a specific transport protocol. In practice, most IPFS implementations rely on the [**DHT**](dht.md) and **PubSub** to publish and resolve IPNS records. + +There are a few nuanced differences between the **DHT** and **PubSub** to be aware of. + +#### IPNS over the DHT + +Due to the ephemeral nature of the DHT, records get dropped after 24 hours. This applies to any record in the DHT, irrespective of the `validity` (also referred to as `lifetime`) field in the IPNS record. + +Therefore, IPNS records need to be regularly published to the DHT. + +By default, Kubo will republish IPNS records to the DHT based on the [`Ipns.RepublishPeriod`] configuration which defaults to 4 hours. Republishing involves two steps: -Due to the ephemeral nature of the DHT, +1. Creating an updated IPNS record with the `sequence` field incremented, the `validity` field set to a timestamp (by default based on `Ipns.RecordLifetime`), and signed with the private key. +2. Publish the [IPNS record to the DHT](https://docs.ipfs.tech/concepts/dht/#ipns-records) +> Note: See the DHT documentation for more information on the lifecycle of GETs and PUTs of IPNS records. +It's worth noting that publishing and resolving IPNS names using the DHT can be slow. This is because multiple records need to be found to ensure the latest version (record with the highest `sequence`), which involves round trips to multiple nodes. + +#### IPNS with PubSub + +PubSub improves both publishing and resolving times of IPNS by relying on interested peers for both operations. + +TODO: more details here about the **publishing lifecycle** with PubSub +TODO: more details here about the **resolution lifecycle** works with PubSub ## IPNS in practice -### Consistency vs. availability when publishing IPNS records +### Common actions with IPNS + +As a user or developer using IPNS for naming, there are three common actions worth understanding: + +- Updating/Creating IPNS records +- Publishing IPNS records +- Resolving IPNS names ### IPNS names can be resolved using IPFS gateways +TODO: + -## Example +### Third-party providing/publishing w3name + +## Example When looking up an IPNS address, use the `/ipns/` prefix: From ec9351bd1ab7eccaa7853a62b0d38f4a0c56f318 Mon Sep 17 00:00:00 2001 From: Daniel Norman <1992255+2color@users.noreply.github.com> Date: Thu, 1 Sep 2022 15:57:27 +0300 Subject: [PATCH 04/19] Update docs/concepts/ipns.md Co-authored-by: Marcin Rataj --- docs/concepts/ipns.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/docs/concepts/ipns.md b/docs/concepts/ipns.md index 5c2110c11..c80bfb4f7 100644 --- a/docs/concepts/ipns.md +++ b/docs/concepts/ipns.md @@ -23,9 +23,6 @@ A **name** in IPNS is the [hash](hashing.md) of a public key. It is associated w For example, the following is an IPNS name represented by a CIDv1 of public key: [`k51qzi5uqu5dlvj2baxnqndepeb86cbk3ng7n3i46uzyxzyqj2xjonzllnv0v8`](https://cid.ipfs.tech/#k51qzi5uqu5dlvj2baxnqndepeb86cbk3ng7n3i46uzyxzyqj2xjonzllnv0v8). -Typically - - ### IPNS names are self-certifying From 3d2a8a7d89b8e88307d1f8d5dba5b4f160657573 Mon Sep 17 00:00:00 2001 From: Daniel Norman <1992255+2color@users.noreply.github.com> Date: Thu, 1 Sep 2022 15:58:00 +0300 Subject: [PATCH 05/19] Update docs/concepts/ipns.md Co-authored-by: Marcin Rataj --- docs/concepts/ipns.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/concepts/ipns.md b/docs/concepts/ipns.md index c80bfb4f7..52f72e951 100644 --- a/docs/concepts/ipns.md +++ b/docs/concepts/ipns.md @@ -19,7 +19,7 @@ The InterPlanetary Name System (IPNS) enables the creation of such mutable point ### Anatomy of an IPNS name -A **name** in IPNS is the [hash](hashing.md) of a public key. It is associated with a [**record**](https://github.com/ipfs/specs/blob/main/IPNS.md#ipns-record) containing the CID it links to and other information such as the expiration, the version number, and a cryptographic signature signed by the corresponding private key. New records can be signed and published at any time by the holder of the private key. +A **name** in IPNS is the [hash](hashing.md) of a public key. It is associated with an [**IPNS record**](https://github.com/ipfs/specs/blob/main/IPNS.md#ipns-record) containing the content path (`/ipfs/CID`) it links to and other information such as the expiration, the version number, and a cryptographic signature signed by the corresponding private key. New records can be signed and published at any time by the holder of the private key. For example, the following is an IPNS name represented by a CIDv1 of public key: [`k51qzi5uqu5dlvj2baxnqndepeb86cbk3ng7n3i46uzyxzyqj2xjonzllnv0v8`](https://cid.ipfs.tech/#k51qzi5uqu5dlvj2baxnqndepeb86cbk3ng7n3i46uzyxzyqj2xjonzllnv0v8). From 548b98b3a77370ab289291645116bbb6acbe6988 Mon Sep 17 00:00:00 2001 From: Daniel N <2color@users.noreply.github.com> Date: Thu, 1 Sep 2022 19:29:01 +0300 Subject: [PATCH 06/19] Refine pubsub section and restructure --- docs/concepts/ipns.md | 78 ++++++++++++++++++++++++++++++------------- 1 file changed, 55 insertions(+), 23 deletions(-) diff --git a/docs/concepts/ipns.md b/docs/concepts/ipns.md index 52f72e951..0bf906c50 100644 --- a/docs/concepts/ipns.md +++ b/docs/concepts/ipns.md @@ -23,6 +23,7 @@ A **name** in IPNS is the [hash](hashing.md) of a public key. It is associated w For example, the following is an IPNS name represented by a CIDv1 of public key: [`k51qzi5uqu5dlvj2baxnqndepeb86cbk3ng7n3i46uzyxzyqj2xjonzllnv0v8`](https://cid.ipfs.tech/#k51qzi5uqu5dlvj2baxnqndepeb86cbk3ng7n3i46uzyxzyqj2xjonzllnv0v8). +> **Note:** Kubo uses the identity private key (used for the PeerID) as the default IPNS name. ### IPNS names are self-certifying @@ -30,63 +31,94 @@ IPNS names are self-certifying. This means that an IPNS record contains all the - Each IPNS name corresponds to a key pair - The IPNS name is a hash of the public key -- The IPNS record contains the public key and signature, allowing anyone to verify that the name was signed by the key holder. +- The IPNS record contains the public key and signature, allowing anyone to verify that the record was signed by the private key holder. This self-certifying nature gives IPNS several benefits not preset in hierarchical and consensus systems such as DNS, and blockchain identifiers. Notably, IPNS records can come from anywhere, not just a particular service/system, and it is very fast and easy to confirm a record is authentic. -### IPNS record validity tradeoffs – consistency vs. availability +### Common IPNS operations -When setting the `validity` (referred to as [`lifetime` by Kubo](https://github.com/ipfs/kubo/blob/master/docs/config.md#ipnsrecordlifetime)) field of an IPNS record, you typically need to choose whether you favor **consistency** (short validity period, e.g. 24 hours) or **availability** (long validity period, e.g. 1 month), due to the inherent trade-off between the two. - -Consistency means ensuring that users resolve to the latest published IPNS record for the name (with the highest sequence number) at the cost of potentially not being able to resolve. +As a user or developer using IPNS for naming, there are three common operations worth understanding: -Availability means resolving to a valid IPNS record, at the cost of potentially resolving to an outdated record. +- **Updating/Creating an IPNS record:** refers to the creation of an IPNS record and signing it with a private key. +- **Publishing an IPNS record:** advertising the IPNS record so that other nodes can resolve it. Details depend on the transport. +- **Resolving an IPNS name:** Resolving an IPNS name to a content path ### IPNS is transport agnostic The self-certifying nature of IPNS records means that they are not tied to a specific transport protocol. In practice, most IPFS implementations rely on the [**DHT**](dht.md) and **PubSub** to publish and resolve IPNS records. -There are a few nuanced differences between the **DHT** and **PubSub** to be aware of. +There are nuanced differences and trade-offs between the **DHT** and **PubSub** to be aware of. + +The main qualitative difference between the two is that IPNS over the DHT publishes and resolves to a global shared state, whereas IPNS over PubSub uses messaging over topics (where each IPNS name has a unique topic) to publish to and resolve from **interested peers**. + +The main implication of this difference is that IPNS operations (publishing and resolving) over the DHT can take longer than over PubSub, while potentially ensuring higher consistency (you resolve to the latest version). + +> **Note:** This trade-off is best explained by [CAP theorem](https://en.wikipedia.org/wiki/CAP_theorem). #### IPNS over the DHT +The DHT is the default transport mechanism for IPNS records in Kubo. + Due to the ephemeral nature of the DHT, records get dropped after 24 hours. This applies to any record in the DHT, irrespective of the `validity` (also referred to as `lifetime`) field in the IPNS record. -Therefore, IPNS records need to be regularly published to the DHT. +Therefore, IPNS records need to be regularly published to the DHT. Moreover, publishing to the DHT at regular intervals ensures that the IPNS name can be resolved even when there's high node churn (nodes coming and going.) -By default, Kubo will republish IPNS records to the DHT based on the [`Ipns.RepublishPeriod`] configuration which defaults to 4 hours. Republishing involves two steps: +By default, Kubo will republish IPNS records to the DHT based on the [`Ipns.RepublishPeriod`] configuration which defaults to 4 hours. [Republishing](https://github.com/ipfs/go-namesys/blob/1bf7d3d9cbe8f988b232b92288b24d25add85a00/republisher/repub.go#L130-L167) involves two steps: -1. Creating an updated IPNS record with the `sequence` field incremented, the `validity` field set to a timestamp (by default based on `Ipns.RecordLifetime`), and signed with the private key. +1. Creating an updated IPNS record with the `validity` timestamp field updated (by default based on `Ipns.RecordLifetime`), and signing it with the private key. The `sequence` number will only be incremented if the content path changes. 2. Publish the [IPNS record to the DHT](https://docs.ipfs.tech/concepts/dht/#ipns-records) -> Note: See the DHT documentation for more information on the lifecycle of GETs and PUTs of IPNS records. +> **Note:** See the [DHT documentation](dht.md#ipns-records) for more information on the lifecycle of GETs and PUTs of IPNS records. It's worth noting that publishing and resolving IPNS names using the DHT can be slow. This is because multiple records need to be found to ensure the latest version (record with the highest `sequence`), which involves round trips to multiple nodes. -#### IPNS with PubSub +#### IPNS over PubSub -PubSub improves both publishing and resolving times of IPNS by relying on interested peers for both operations. +IPNS over PubSub uses the [Libp2p PubSub](https://docs.libp2p.io/concepts/publish-subscribe/) to publish records and resolve names amongst **interested peers**. -TODO: more details here about the **publishing lifecycle** with PubSub -TODO: more details here about the **resolution lifecycle** works with PubSub +This is achieved by deriving the PubSub topic name from the IPNS name so that each IPNS name has a unique topic. -## IPNS in practice +Because PubSub doesn't have the notion of persistence (messages are ephemeral and dropped after propagation), IPNS over PubSub [adds a persistence layer](https://github.com/ipfs/specs/blob/main/naming/pubsub.md#layering-persistence-onto-libp2p-pubsub) to ensure that IPNS records are always available to the network. + +In Kubo, IPNS over PubSub is not enabled by default and can be enabled using the [`Ipns.UsePubsub`](https://github.com/ipfs/kubo/blob/master/docs/config.md#ipnsusepubsub) configuration. + +Initial operations, e.g. resolving or publishing an IPNS name for the first time can take time as they involve a roundtrip to the DHT (to lookup or publish provider records for the topic). After the subscription to the topic is established, PubSub usually improves both publishing and resolving times of IPNS by relying on interested peers for both operations. -### Common actions with IPNS +It should be noted that there's an upper limit to the number of unique IPNS names you can resolve over PubSub, because for each name, a subscription is created which requires several open network connections for the mesh peer. -As a user or developer using IPNS for naming, there are three common actions worth understanding: +##### Publishing IPNS records over PubSub lifecycle -- Updating/Creating IPNS records -- Publishing IPNS records -- Resolving IPNS names +1. Create a record and sign it +2. Calculate PubSub topic name from IPNS name +3. Join the topic by querying the DHT for the topic's provider records +4. Publish the IPNS record to the topic +5. Whenever [a new peer joins the topic](https://github.com/libp2p/go-libp2p-pubsub-router/blob/292d99457d224853706c5e49f8ddc112740a856a/pubsub.go#L538-L560) (specifically your peer mesh), ask them for the record. If they respond with a newer record, update it locally and publish the updated record to the. +6. Periodically (by default every 10 minutes) rebroadcast the IPNS record, + +### Tradeoffs between consistency vs. availability + +The self-certifying nature of IPNS comes with an inherent tradeoff between **consistency** and **availability**. + +Consistency means ensuring that users resolve to the latest published IPNS record for the name (with the highest sequence number) at the cost of potentially not being able to resolve. + +Availability means resolving to a valid IPNS record, at the cost of potentially resolving to an outdated record. + +#### IPNS record validity tradeoffs + +When setting the `validity` (referred to as [`lifetime` by Kubo](https://github.com/ipfs/kubo/blob/master/docs/config.md#ipnsrecordlifetime)) field of an IPNS record, you typically need to choose whether you favor **consistency** (short validity period, e.g. 24 hours) or **availability** (long validity period, e.g. 1 month), due to the inherent trade-off between the two. + +## IPNS in practice ### IPNS names can be resolved using IPFS gateways -TODO: +IPNS names can be resolved by [IPFS gateways](ipfs-gateway.md) in a _trusted_ fashion using both path resolution and subdomain resolution style: +- Path resolution: `https://ipfs.io/ipns/{ipns-name}` +- Subdomain resolution: `https://{ipns-name}.ipns.dweb.link` +> **Note** IPNS resolution via an IPFS gateway is **trusted** which means you delegate IPNS resolution to the gateway without any means to verify the response you get, i.e the content path and signature of the IPNS record. -### Third-party providing/publishing w3name + ## Example From 9c1084a73fb83a95a69816ab2c3cdbe9d68fa6e6 Mon Sep 17 00:00:00 2001 From: Daniel N <2color@users.noreply.github.com> Date: Fri, 2 Sep 2022 13:47:13 +0300 Subject: [PATCH 07/19] Add section about how IPNS names relate to CIDs --- docs/concepts/ipns.md | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/docs/concepts/ipns.md b/docs/concepts/ipns.md index 0bf906c50..e31f32d9c 100644 --- a/docs/concepts/ipns.md +++ b/docs/concepts/ipns.md @@ -23,7 +23,23 @@ A **name** in IPNS is the [hash](hashing.md) of a public key. It is associated w For example, the following is an IPNS name represented by a CIDv1 of public key: [`k51qzi5uqu5dlvj2baxnqndepeb86cbk3ng7n3i46uzyxzyqj2xjonzllnv0v8`](https://cid.ipfs.tech/#k51qzi5uqu5dlvj2baxnqndepeb86cbk3ng7n3i46uzyxzyqj2xjonzllnv0v8). -> **Note:** Kubo uses the identity private key (used for the PeerID) as the default IPNS name. +> **Note:** Kubo uses the identity private key (used for the PeerID) as the default IPNS name. But you can generate multiple keys. + +#### How IPNS names relate to CIDs + +A CIDv1 can be used to represent both: + +- [Immutable content on IPFS](https://cid.ipfs.tech/#bafybeibml5uieyxa5tufngvg7fgwbkwvlsuntwbxgtskoqynbt7wlchmfm) (since the CID contains a multihash) +- [IPNS name](https://cid.ipfs.tech/#k51qzi5uqu5dlvj2baxnqndepeb86cbk3ng7n3i46uzyxzyqj2xjonzllnv0v8) which corresponds to a libp2p public key. + +The following is a useful mental model for understanding the difference between the two: + +``` +IPFS = immutable *Pointer => content +IPNS = **Pointer => content +``` + +IPNS names are essentially pointers (IPNS names) to pointers (IPFS CIDs) whereas IPFS CIDs are immutable (because they're derived from the content) pointers to content. ### IPNS names are self-certifying From 433bd0c40177a0b1d7a34694b6e5c45aa169447c Mon Sep 17 00:00:00 2001 From: Daniel N <2color@users.noreply.github.com> Date: Fri, 2 Sep 2022 13:47:28 +0300 Subject: [PATCH 08/19] Refine and use CIDsV1 --- docs/concepts/ipns.md | 69 ++++++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/docs/concepts/ipns.md b/docs/concepts/ipns.md index e31f32d9c..266b68f31 100644 --- a/docs/concepts/ipns.md +++ b/docs/concepts/ipns.md @@ -98,9 +98,11 @@ Because PubSub doesn't have the notion of persistence (messages are ephemeral an In Kubo, IPNS over PubSub is not enabled by default and can be enabled using the [`Ipns.UsePubsub`](https://github.com/ipfs/kubo/blob/master/docs/config.md#ipnsusepubsub) configuration. -Initial operations, e.g. resolving or publishing an IPNS name for the first time can take time as they involve a roundtrip to the DHT (to lookup or publish provider records for the topic). After the subscription to the topic is established, PubSub usually improves both publishing and resolving times of IPNS by relying on interested peers for both operations. +Initial operations, e.g. resolving or publishing an IPNS name for the first time can take time as they involve a roundtrip to the DHT (to lookup or publish provider records for the topic). -It should be noted that there's an upper limit to the number of unique IPNS names you can resolve over PubSub, because for each name, a subscription is created which requires several open network connections for the mesh peer. +After the subscription to the topic is established, PubSub usually improves both publishing and resolving times of IPNS by relying on interested peers for both operations. + +It should be noted that there's an upper limit to the number of unique IPNS names you can resolve over PubSub, because for each name, a subscription is created which opens several network connections to mesh peers. ##### Publishing IPNS records over PubSub lifecycle @@ -111,6 +113,8 @@ It should be noted that there's an upper limit to the number of unique IPNS name 5. Whenever [a new peer joins the topic](https://github.com/libp2p/go-libp2p-pubsub-router/blob/292d99457d224853706c5e49f8ddc112740a856a/pubsub.go#L538-L560) (specifically your peer mesh), ask them for the record. If they respond with a newer record, update it locally and publish the updated record to the. 6. Periodically (by default every 10 minutes) rebroadcast the IPNS record, +Steps 5 and 6 describe from a high level how IPNS record persistence is layered over PubSub by ensuring continuous propagation of the IPNS record in the face of node churn (nodes dropping in and out of the network). + ### Tradeoffs between consistency vs. availability The self-certifying nature of IPNS comes with an inherent tradeoff between **consistency** and **availability**. @@ -119,32 +123,37 @@ Consistency means ensuring that users resolve to the latest published IPNS recor Availability means resolving to a valid IPNS record, at the cost of potentially resolving to an outdated record. -#### IPNS record validity tradeoffs +#### IPNS record validity When setting the `validity` (referred to as [`lifetime` by Kubo](https://github.com/ipfs/kubo/blob/master/docs/config.md#ipnsrecordlifetime)) field of an IPNS record, you typically need to choose whether you favor **consistency** (short validity period, e.g. 24 hours) or **availability** (long validity period, e.g. 1 month), due to the inherent trade-off between the two. +#### Practical considerations + +One of the most important things to consider with IPNS names is **how frequently you intend on updating the name**. + +Practically, two levers within your control determine where your IPNS name is on the spectrum between consistency and availability: + +- **IPNS record validity:** longer validity will veer towards availability. Moreover, longer validity will reduce the dependence on the keyholder (which for most purposes is stored on a single machine and rare shared) since the record can continue to persist without requiring the private key holder to sign a new record. Another benefit of a longer validity is that the transport can be delegated to other nodes or services (such as [w3name](https://staging.web3.storage/docs/how-tos/w3name/)), without compromising the private key. +- **Transport mechanism:** the DHT veers towards consistency while PubSub veers towards availability. However, with Kubo, IPNS names are always published to the DHT, while PubSub is opt-in. For most purposes, enabling PubSub is a net gain unless you hit the upper limit of connections as a result of too many PubSub subscriptions. + ## IPNS in practice -### IPNS names can be resolved using IPFS gateways +### Resolving IPNS names using IPFS gateways IPNS names can be resolved by [IPFS gateways](ipfs-gateway.md) in a _trusted_ fashion using both path resolution and subdomain resolution style: - Path resolution: `https://ipfs.io/ipns/{ipns-name}` - Subdomain resolution: `https://{ipns-name}.ipns.dweb.link` -> **Note** IPNS resolution via an IPFS gateway is **trusted** which means you delegate IPNS resolution to the gateway without any means to verify the response you get, i.e the content path and signature of the IPNS record. +For example: +- [https://ipfs.io/ipns/k51qzi5uqu5dlvj2baxnqndepeb86cbk3ng7n3i46uzyxzyqj2xjonzllnv0v8](https://ipfs.io/ipns/k51qzi5uqu5dlvj2baxnqndepeb86cbk3ng7n3i46uzyxzyqj2xjonzllnv0v8) - - -## Example +> **Note** IPNS resolution via an IPFS gateway is **trusted** (in the sense of trusting the gateway) which means you delegate IPNS resolution to the gateway without any means to verify the authenticity response you get, i.e the content path and signature of the IPNS record. -When looking up an IPNS address, use the `/ipns/` prefix: + -```shell -/ipns/QmSrPmbaUKA3ZodhzPWZnpFgcPMFWF4QsxXbkWfEptTBJd -``` -## Example IPNS Setup with CLI +## Publishing IPNS names with Kubo 1. Start your IPFS daemon, if it isn't already running: @@ -161,9 +170,9 @@ When looking up an IPNS address, use the `/ipns/` prefix: 1. Add your file to IPFS: ```shell - ipfs add hello.txt + ipfs add --cid-version 1 hello.txt - > added QmUVTKsrYJpaxUT7dr9FpKq6AoKHhEM7eG1ZHGL56haKLG hello.txt + > added bafkreidfdrlkeq4m4xnxuyx6iae76fdm4wgl5d4xzsb77ixhyqwumhz244 hello.txt > 11 B / 11 B [=====================================================] 100.00% ``` @@ -172,7 +181,7 @@ When looking up an IPNS address, use the `/ipns/` prefix: 1. Use `cat` and the CID you just got from IPFS to view the file again: ```shell - ipfs cat QmUVTKsrYJpaxUT7dr9FpKq6AoKHhEM7eG1ZHGL56haKLG + ipfs cat bafkreidfdrlkeq4m4xnxuyx6iae76fdm4wgl5d4xzsb77ixhyqwumhz244 > Hello IPFS ``` @@ -180,17 +189,17 @@ When looking up an IPNS address, use the `/ipns/` prefix: 1. Publish your CID to IPNS: ```shell - ipfs name publish /ipfs/QmUVTKsrYJpaxUT7dr9FpKq6AoKHhEM7eG1ZHGL56haKLG + ipfs name publish /ipfs/bafkreidfdrlkeq4m4xnxuyx6iae76fdm4wgl5d4xzsb77ixhyqwumhz244 - > Published to k51qzi5uqu5dkkciu33khkzbcmxtyhn376i1e83tya8kuy7z9euedzyr5nhoew: /ipfs/QmUVTKsrYJpaxUT7dr9FpKq6AoKHhEM7eG1ZHGL56haKLG + > Published to k51qzi5uqu5dgy6fu9073kabgj2nuq3qyo4f2rcnn4380z6n8i4v2lvo8dln6l: /ipfs/bafkreidfdrlkeq4m4xnxuyx6iae76fdm4wgl5d4xzsb77ixhyqwumhz244 ``` `k51...` is the public key or IPNS name of the IPFS you are running. You can now change the file repeatedly, and, even though the CID changes when you change the file, you can continue to access it with this key. -1. You can view your file by going to `https://gateway.ipfs.io/ipns/k51qzi5uqu5dkkciu33khkzbcmxtyhn376i1e83tya8kuy7z9euedzyr5nhoew`: +1. You can view your file by going to `https://ipfs.io/ipns/k51qzi5uqu5dgy6fu9073kabgj2nuq3qyo4f2rcnn4380z6n8i4v2lvo8dln6l`: ```shell - curl https://gateway.ipfs.io/ipns/k51qzi5uqu5dkkciu33khkzbcmxtyhn376i1e83tya8kuy7z9euedzyr5nhoew + curl https://ipfs.io/ipns/k51qzi5uqu5dgy6fu9073kabgj2nuq3qyo4f2rcnn4380z6n8i4v2lvo8dln6l > Hello IPFS ``` @@ -201,18 +210,18 @@ When looking up an IPNS address, use the `/ipns/` prefix: echo "Hello again IPFS" > hello.txt ipfs add hello.txt - > added QmaVfeg2GM17RLjBs9C4fhpku6uDgrEGUYCTC183VrZaVW hello.txt + > added bafkreidbbor7mvra2xzzl4kmr2sxrtkzaxlzs6rsr5ktgmbtousuzrhlxq hello.txt > 17 B / 17 B [=====================================================] 100.00% - ipfs name publish QmaVfeg2GM17RLjBs9C4fhpku6uDgrEGUYCTC183VrZaVW + ipfs name publish bafkreidbbor7mvra2xzzl4kmr2sxrtkzaxlzs6rsr5ktgmbtousuzrhlxq - > Published to k51qzi5uqu5dkkciu33khkzbcmxtyhn376i1e83tya8kuy7z9euedzyr5nhoew: /ipfs/QmaVfeg2GM17RLjBs9C4fhpku6uDgrEGUYCTC183VrZaVW + > Published to k51qzi5uqu5dgy6fu9073kabgj2nuq3qyo4f2rcnn4380z6n8i4v2lvo8dln6l: /ipfs/bafkreidbbor7mvra2xzzl4kmr2sxrtkzaxlzs6rsr5ktgmbtousuzrhlxq ``` -1. You can now go back to `https://gateway.ipfs.io/ipns/k51qzi5uqu5dkkciu33khkzbcmxtyhn376i1e83tya8kuy7z9euedzyr5nhoew` to view your updated file using the same address: +2. You can now go back to `https://ipfs.io/ipns/k51qzi5uqu5dgy6fu9073kabgj2nuq3qyo4f2rcnn4380z6n8i4v2lvo8dln6l` to view your updated file using the same address: ```shell - curl https://gateway.ipfs.io/ipns/k51qzi5uqu5dkkciu33khkzbcmxtyhn376i1e83tya8kuy7z9euedzyr5nhoew + curl https://ipfs.io/ipns/k51qzi5uqu5dgy6fu9073kabgj2nuq3qyo4f2rcnn4380z6n8i4v2lvo8dln6l > Hello again IPFS ``` @@ -222,7 +231,7 @@ You can view the CID of the file associated with your `k5` key by using `name re ```shell ipfs name resolve -> /ipfs/QmaVfeg2GM17RLjBs9C4fhpku6uDgrEGUYCTC183VrZaVW +> /ipfs/bafkreidbbor7mvra2xzzl4kmr2sxrtkzaxlzs6rsr5ktgmbtousuzrhlxq ``` To use a different `k5` key, first create one using `key gen test`, and use the `--key` flag when calling `name publish`: @@ -232,9 +241,9 @@ ipfs key gen SecondKey > k51qzi5uqu5dh5kbbff1ucw3ksphpy3vxx4en4dbtfh90pvw4mzd8nfm5r5fnl -ipfs name publish --key=SecondKey /ipfs/QmaVfeg2GM17RLjBs9C4fhpku6uDgrEGUYCTC183VrZaVW +ipfs name publish --key=SecondKey /ipfs/bafybeicklkqcnlvtiscr2hzkubjwnwjinvskffn4xorqeduft3wq7vm5u4 -> Published to k51qzi5uqu5dh5kbbff1ucw3ksphpy3vxx4en4dbtfh90pvw4mzd8nfm5r5fnl: /ipfs/QmaVfeg2GM17RLjBs9C4fhpku6uDgrEGUYCTC183VrZaVW +> Published to k51qzi5uqu5dh5kbbff1ucw3ksphpy3vxx4en4dbtfh90pvw4mzd8nfm5r5fnl: /ipfs/bafybeicklkqcnlvtiscr2hzkubjwnwjinvskffn4xorqeduft3wq7vm5u4 ``` ## Example IPNS Setup with JS SDK API @@ -245,13 +254,13 @@ Here's where the Name API comes in handy. With it, you can create a single, stab ```javascript // The address of your files. -const addr = '/ipfs/QmbezGequPwcsWo8UL4wDF6a8hYwM1hmbzYv2mnKkEWaUp' +const addr = '/ipfs/bafkreidbbor7mvra2xzzl4kmr2sxrtkzaxlzs6rsr5ktgmbtousuzrhlxq' ipfs.name.publish(addr).then(function (res) { // You now receive a res which contains two fields: // - name: the name under which the content was published. // - value: the "real" address to which Name points. - console.log(`https://gateway.ipfs.io/ipns/${res.name}`) + console.log(`https://ipfs.io/ipns/${res.name}`) }) ``` From 8cbc5a7fa5dd8d2d03436b1122fb5967b2154152 Mon Sep 17 00:00:00 2001 From: Daniel N <2color@users.noreply.github.com> Date: Fri, 2 Sep 2022 14:01:36 +0300 Subject: [PATCH 09/19] Add TOC --- docs/concepts/ipns.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/docs/concepts/ipns.md b/docs/concepts/ipns.md index 266b68f31..6c5e53bd3 100644 --- a/docs/concepts/ipns.md +++ b/docs/concepts/ipns.md @@ -5,6 +5,28 @@ description: Learn about the InterPlanetary Name System (IPNS) and how it can be # InterPlanetary Name System (IPNS) +- [InterPlanetary Name System (IPNS)](#interplanetary-name-system-ipns) + - [Mutability in IPFS](#mutability-in-ipfs) + - [How IPNS works](#how-ipns-works) + - [Anatomy of an IPNS name](#anatomy-of-an-ipns-name) + - [How IPNS names relate to CIDs](#how-ipns-names-relate-to-cids) + - [IPNS names are self-certifying](#ipns-names-are-self-certifying) + - [Common IPNS operations](#common-ipns-operations) + - [IPNS is transport agnostic](#ipns-is-transport-agnostic) + - [IPNS over the DHT](#ipns-over-the-dht) + - [IPNS over PubSub](#ipns-over-pubsub) + - [Publishing IPNS records over PubSub lifecycle](#publishing-ipns-records-over-pubsub-lifecycle) + - [Tradeoffs between consistency vs. availability](#tradeoffs-between-consistency-vs-availability) + - [IPNS record validity](#ipns-record-validity) + - [Practical considerations](#practical-considerations) + - [IPNS in practice](#ipns-in-practice) + - [Resolving IPNS names using IPFS gateways](#resolving-ipns-names-using-ipfs-gateways) + - [Publishing IPNS names with Kubo](#publishing-ipns-names-with-kubo) + - [Example IPNS Setup with JS SDK API](#example-ipns-setup-with-js-sdk-api) + - [Alternatives to IPNS](#alternatives-to-ipns) + - [Further Resources](#further-resources) + + ## Mutability in IPFS [Content addressing](content-addressing.md) in IPFS is by nature _immutable_: when you add a file to IPFS, it creates a hash from the data contained in it. Changing a file changes its hash, and consequently its CID which is used as an address. From 5a7d91a7088c85075304c71c04c4323b3697f303 Mon Sep 17 00:00:00 2001 From: Daniel N <2color@users.noreply.github.com> Date: Fri, 2 Sep 2022 14:07:19 +0300 Subject: [PATCH 10/19] Consistent periods --- docs/concepts/ipns.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/concepts/ipns.md b/docs/concepts/ipns.md index 6c5e53bd3..8fd974d08 100644 --- a/docs/concepts/ipns.md +++ b/docs/concepts/ipns.md @@ -79,7 +79,7 @@ As a user or developer using IPNS for naming, there are three common operations - **Updating/Creating an IPNS record:** refers to the creation of an IPNS record and signing it with a private key. - **Publishing an IPNS record:** advertising the IPNS record so that other nodes can resolve it. Details depend on the transport. -- **Resolving an IPNS name:** Resolving an IPNS name to a content path +- **Resolving an IPNS name:** Resolving an IPNS name to a content path. ### IPNS is transport agnostic From 0317969b1ffc37d899a62c9ba4310593c0efc8e7 Mon Sep 17 00:00:00 2001 From: Daniel Norman <1992255+2color@users.noreply.github.com> Date: Fri, 2 Sep 2022 18:52:17 +0300 Subject: [PATCH 11/19] Apply suggestions from code review Co-authored-by: Mosh <1306020+mishmosh@users.noreply.github.com> --- docs/concepts/ipns.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/concepts/ipns.md b/docs/concepts/ipns.md index 8fd974d08..05b6fc7a8 100644 --- a/docs/concepts/ipns.md +++ b/docs/concepts/ipns.md @@ -31,9 +31,9 @@ description: Learn about the InterPlanetary Name System (IPNS) and how it can be [Content addressing](content-addressing.md) in IPFS is by nature _immutable_: when you add a file to IPFS, it creates a hash from the data contained in it. Changing a file changes its hash, and consequently its CID which is used as an address. -Yet, there are many situations where **mutable pointers** are useful as a complement to immutability, for example, when publishing a website that frequently changes. It would be impractical to share a new CID every time you update the website. With mutable pointers, you can share the address of the pointer once, and update the pointer – to the new CID – every time you publish a change. +Yet, there are many situations where content-addressed data needs to be regularly updated, for example, when publishing a website that frequently changes. It would be impractical to share a new CID every time you update the website. With **mutable pointers**, you can share the address of the pointer once, and update the pointer – to the new CID – every time you publish a change. -The InterPlanetary Name System (IPNS) enables the creation of such mutable pointers to CIDs known as **names** or **IPNS names**. IPNS names can be thought of as links that can be updated over time. +The InterPlanetary Name System (IPNS) is a system for creating such mutable pointers to CIDs known as **names** or **IPNS names**. IPNS names can be thought of as links that can be updated over time, while retaining the verifiability of content addressing. > **Note:** Technically, an IPNS name can also point to another IPNS name or DNSLink path. However, it most commonly points to a CID. From d05c748da05a125903a814946956327869866f85 Mon Sep 17 00:00:00 2001 From: Daniel Norman <1992255+2color@users.noreply.github.com> Date: Mon, 5 Sep 2022 19:35:23 +0200 Subject: [PATCH 12/19] Apply suggestions from code review Co-authored-by: Marcin Rataj --- docs/concepts/ipns.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/concepts/ipns.md b/docs/concepts/ipns.md index 05b6fc7a8..b244129ed 100644 --- a/docs/concepts/ipns.md +++ b/docs/concepts/ipns.md @@ -45,14 +45,14 @@ A **name** in IPNS is the [hash](hashing.md) of a public key. It is associated w For example, the following is an IPNS name represented by a CIDv1 of public key: [`k51qzi5uqu5dlvj2baxnqndepeb86cbk3ng7n3i46uzyxzyqj2xjonzllnv0v8`](https://cid.ipfs.tech/#k51qzi5uqu5dlvj2baxnqndepeb86cbk3ng7n3i46uzyxzyqj2xjonzllnv0v8). -> **Note:** Kubo uses the identity private key (used for the PeerID) as the default IPNS name. But you can generate multiple keys. +> **Note:** Kubo uses the `self` key (ed25519 private key used for the PeerID) as the default IPNS name. But you can generate multiple keys via [`ipfs key gen`](https://docs.ipfs.tech/reference/kubo/cli/#ipfs-key-gen), and use them for managing multiple IPNS names. -#### How IPNS names relate to CIDs +#### How IPNS names relate to content paths -A CIDv1 can be used to represent both: +IPNS record can point at an immutable or a mutable path. The meaning behind CID used in a path depends on used namespace: -- [Immutable content on IPFS](https://cid.ipfs.tech/#bafybeibml5uieyxa5tufngvg7fgwbkwvlsuntwbxgtskoqynbt7wlchmfm) (since the CID contains a multihash) -- [IPNS name](https://cid.ipfs.tech/#k51qzi5uqu5dlvj2baxnqndepeb86cbk3ng7n3i46uzyxzyqj2xjonzllnv0v8) which corresponds to a libp2p public key. +- `/ipfs/` – an [immutable content on IPFS](https://cid.ipfs.tech/#bafybeibml5uieyxa5tufngvg7fgwbkwvlsuntwbxgtskoqynbt7wlchmfm) (since the CID contains a multihash) +- `/ipns/` – a mutable, cryptographic [IPNS name](https://cid.ipfs.tech/#k51qzi5uqu5dlvj2baxnqndepeb86cbk3ng7n3i46uzyxzyqj2xjonzllnv0v8) which corresponds to a libp2p public key. The following is a useful mental model for understanding the difference between the two: @@ -68,7 +68,7 @@ IPNS names are essentially pointers (IPNS names) to pointers (IPFS CIDs) whereas IPNS names are self-certifying. This means that an IPNS record contains all the information necessary to certify its authenticity. IPNS achieves this using public and private key pairs: - Each IPNS name corresponds to a key pair -- The IPNS name is a hash of the public key +- The IPNS name is a CID with a multihash of the public key - The IPNS record contains the public key and signature, allowing anyone to verify that the record was signed by the private key holder. This self-certifying nature gives IPNS several benefits not preset in hierarchical and consensus systems such as DNS, and blockchain identifiers. Notably, IPNS records can come from anywhere, not just a particular service/system, and it is very fast and easy to confirm a record is authentic. @@ -83,7 +83,7 @@ As a user or developer using IPNS for naming, there are three common operations ### IPNS is transport agnostic -The self-certifying nature of IPNS records means that they are not tied to a specific transport protocol. In practice, most IPFS implementations rely on the [**DHT**](dht.md) and **PubSub** to publish and resolve IPNS records. +The self-certifying nature of IPNS records means that they are not tied to a specific transport protocol. In practice, most IPFS implementations rely on the [**DHT**](dht.md) and [**libp2p PubSub**](https://docs.libp2p.io/concepts/publish-subscribe/) to publish and resolve IPNS records. There are nuanced differences and trade-offs between the **DHT** and **PubSub** to be aware of. @@ -97,13 +97,13 @@ The main implication of this difference is that IPNS operations (publishing and The DHT is the default transport mechanism for IPNS records in Kubo. -Due to the ephemeral nature of the DHT, records get dropped after 24 hours. This applies to any record in the DHT, irrespective of the `validity` (also referred to as `lifetime`) field in the IPNS record. +Due to the ephemeral nature of the DHT, peers forget records after 24 hours. This applies to any record in the DHT, irrespective of the `validity` (also referred to as `lifetime`) field in the IPNS record. -Therefore, IPNS records need to be regularly published to the DHT. Moreover, publishing to the DHT at regular intervals ensures that the IPNS name can be resolved even when there's high node churn (nodes coming and going.) +Therefore, IPNS records need to be regularly (re-)published to the DHT. Moreover, publishing to the DHT at regular intervals ensures that the IPNS name can be resolved even when there's high node churn (nodes coming and going.) -By default, Kubo will republish IPNS records to the DHT based on the [`Ipns.RepublishPeriod`] configuration which defaults to 4 hours. [Republishing](https://github.com/ipfs/go-namesys/blob/1bf7d3d9cbe8f988b232b92288b24d25add85a00/republisher/repub.go#L130-L167) involves two steps: +By default, Kubo will republish IPNS records to the DHT based on the [`Ipns.RepublishPeriod`](https://github.com/ipfs/kubo/blob/master/docs/config.md#ipnsrepublishperiod) configuration which defaults to 4 hours. [Republishing](https://github.com/ipfs/go-namesys/blob/1bf7d3d9cbe8f988b232b92288b24d25add85a00/republisher/repub.go#L130-L167) involves two steps: -1. Creating an updated IPNS record with the `validity` timestamp field updated (by default based on `Ipns.RecordLifetime`), and signing it with the private key. The `sequence` number will only be incremented if the content path changes. +1. Creating an updated IPNS record with the `validity` timestamp field updated (by default based on [`Ipns.RecordLifetime`](https://github.com/ipfs/kubo/blob/master/docs/config.md#ipnsrecordlifetime)), and signing it with the private key. The `sequence` number will only be incremented if the content path changes. 2. Publish the [IPNS record to the DHT](https://docs.ipfs.tech/concepts/dht/#ipns-records) > **Note:** See the [DHT documentation](dht.md#ipns-records) for more information on the lifecycle of GETs and PUTs of IPNS records. From 1db8465b478cdcd58b4702454441d3e87b0f17e9 Mon Sep 17 00:00:00 2001 From: Daniel N <2color@users.noreply.github.com> Date: Mon, 5 Sep 2022 17:58:14 +0200 Subject: [PATCH 13/19] refine conection between cid and hash --- docs/concepts/ipns.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/concepts/ipns.md b/docs/concepts/ipns.md index b244129ed..d54c8f42c 100644 --- a/docs/concepts/ipns.md +++ b/docs/concepts/ipns.md @@ -26,10 +26,9 @@ description: Learn about the InterPlanetary Name System (IPNS) and how it can be - [Alternatives to IPNS](#alternatives-to-ipns) - [Further Resources](#further-resources) - ## Mutability in IPFS -[Content addressing](content-addressing.md) in IPFS is by nature _immutable_: when you add a file to IPFS, it creates a hash from the data contained in it. Changing a file changes its hash, and consequently its CID which is used as an address. +[Content addressing](content-addressing.md) in IPFS is by nature _immutable_: when you add a file to IPFS, it creates a hash from the data, with which the CID is constructed. Changing a file changes its hash, and consequently its CID which is used as an address. Yet, there are many situations where content-addressed data needs to be regularly updated, for example, when publishing a website that frequently changes. It would be impractical to share a new CID every time you update the website. With **mutable pointers**, you can share the address of the pointer once, and update the pointer – to the new CID – every time you publish a change. @@ -168,13 +167,13 @@ IPNS names can be resolved by [IPFS gateways](ipfs-gateway.md) in a _trusted_ fa - Subdomain resolution: `https://{ipns-name}.ipns.dweb.link` For example: + - [https://ipfs.io/ipns/k51qzi5uqu5dlvj2baxnqndepeb86cbk3ng7n3i46uzyxzyqj2xjonzllnv0v8](https://ipfs.io/ipns/k51qzi5uqu5dlvj2baxnqndepeb86cbk3ng7n3i46uzyxzyqj2xjonzllnv0v8) > **Note** IPNS resolution via an IPFS gateway is **trusted** (in the sense of trusting the gateway) which means you delegate IPNS resolution to the gateway without any means to verify the authenticity response you get, i.e the content path and signature of the IPNS record. - ## Publishing IPNS names with Kubo 1. Start your IPFS daemon, if it isn't already running: From 5cd3f56f03b6be758644b435d2d55511747ca172 Mon Sep 17 00:00:00 2001 From: Daniel N <2color@users.noreply.github.com> Date: Mon, 5 Sep 2022 19:20:39 +0200 Subject: [PATCH 14/19] Address feedback about arbitrary content paths --- docs/concepts/ipns.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/concepts/ipns.md b/docs/concepts/ipns.md index d54c8f42c..cf6386937 100644 --- a/docs/concepts/ipns.md +++ b/docs/concepts/ipns.md @@ -34,7 +34,7 @@ Yet, there are many situations where content-addressed data needs to be regularl The InterPlanetary Name System (IPNS) is a system for creating such mutable pointers to CIDs known as **names** or **IPNS names**. IPNS names can be thought of as links that can be updated over time, while retaining the verifiability of content addressing. -> **Note:** Technically, an IPNS name can also point to another IPNS name or DNSLink path. However, it most commonly points to a CID. +> **Note:** Technically, an IPNS name can point to an arbitrary content path (`/ipfs/` or `/ipns/`), including another IPNS name or DNSLink path. However, it most commonly points to a fully resolved and immutable path, i.e. `/ipfs/[CID]`. ## How IPNS works From fc1a180f8d23065cfd1be5f9dffd4c1224046839 Mon Sep 17 00:00:00 2001 From: Daniel N <2color@users.noreply.github.com> Date: Mon, 5 Sep 2022 19:21:04 +0200 Subject: [PATCH 15/19] Address feedback --- docs/concepts/ipns.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/concepts/ipns.md b/docs/concepts/ipns.md index cf6386937..37a8e8e07 100644 --- a/docs/concepts/ipns.md +++ b/docs/concepts/ipns.md @@ -94,7 +94,7 @@ The main implication of this difference is that IPNS operations (publishing and #### IPNS over the DHT -The DHT is the default transport mechanism for IPNS records in Kubo. +The DHT is the default transport mechanism for IPNS records in most IPFS implementations, e.g. Kubo, and js-ipfs. Due to the ephemeral nature of the DHT, peers forget records after 24 hours. This applies to any record in the DHT, irrespective of the `validity` (also referred to as `lifetime`) field in the IPNS record. @@ -123,7 +123,7 @@ Initial operations, e.g. resolving or publishing an IPNS name for the first time After the subscription to the topic is established, PubSub usually improves both publishing and resolving times of IPNS by relying on interested peers for both operations. -It should be noted that there's an upper limit to the number of unique IPNS names you can resolve over PubSub, because for each name, a subscription is created which opens several network connections to mesh peers. +It should be noted that there's an upper limit to the number of unique IPNS names you can resolve over PubSub, because for each name, a subscription is created which opens several (by default 6) network connections to mesh members. ##### Publishing IPNS records over PubSub lifecycle @@ -131,7 +131,7 @@ It should be noted that there's an upper limit to the number of unique IPNS name 2. Calculate PubSub topic name from IPNS name 3. Join the topic by querying the DHT for the topic's provider records 4. Publish the IPNS record to the topic -5. Whenever [a new peer joins the topic](https://github.com/libp2p/go-libp2p-pubsub-router/blob/292d99457d224853706c5e49f8ddc112740a856a/pubsub.go#L538-L560) (specifically your peer mesh), ask them for the record. If they respond with a newer record, update it locally and publish the updated record to the. +5. Whenever [a new peer joins the topic](https://github.com/libp2p/go-libp2p-pubsub-router/blob/292d99457d224853706c5e49f8ddc112740a856a/pubsub.go#L538-L560) (specifically your mesh), ask them for the record. If they respond with a newer record, update it locally and publish the updated record to the. 6. Periodically (by default every 10 minutes) rebroadcast the IPNS record, Steps 5 and 6 describe from a high level how IPNS record persistence is layered over PubSub by ensuring continuous propagation of the IPNS record in the face of node churn (nodes dropping in and out of the network). From 224022659f8e2fa2434f43b4fb059a620df59335 Mon Sep 17 00:00:00 2001 From: Daniel N <2color@users.noreply.github.com> Date: Mon, 5 Sep 2022 19:36:02 +0200 Subject: [PATCH 16/19] Add mention of the spec --- docs/concepts/ipns.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/concepts/ipns.md b/docs/concepts/ipns.md index 37a8e8e07..cdef7de6a 100644 --- a/docs/concepts/ipns.md +++ b/docs/concepts/ipns.md @@ -136,6 +136,8 @@ It should be noted that there's an upper limit to the number of unique IPNS name Steps 5 and 6 describe from a high level how IPNS record persistence is layered over PubSub by ensuring continuous propagation of the IPNS record in the face of node churn (nodes dropping in and out of the network). +> Further details about the IPNS over PubSub protocol can be found in the [IPNS over PubSub Spec](https://github.com/ipfs/specs/blob/main/naming/pubsub.md#protocol) + ### Tradeoffs between consistency vs. availability The self-certifying nature of IPNS comes with an inherent tradeoff between **consistency** and **availability**. From dbe2740e457d58183ec4293fe76df2b4c799ae00 Mon Sep 17 00:00:00 2001 From: Daniel N <2color@users.noreply.github.com> Date: Wed, 7 Sep 2022 13:28:07 +0200 Subject: [PATCH 17/19] Move guides into how to --- docs/concepts/ipns.md | 158 ++++++------------------------------------ 1 file changed, 23 insertions(+), 135 deletions(-) diff --git a/docs/concepts/ipns.md b/docs/concepts/ipns.md index cdef7de6a..75267f339 100644 --- a/docs/concepts/ipns.md +++ b/docs/concepts/ipns.md @@ -1,30 +1,27 @@ --- title: IPNS -description: Learn about the InterPlanetary Name System (IPNS) and how it can be used in conjunction with IPFS. +description: Learn about the mutability in IPFS, InterPlanetary Name System (IPNS), and how it can be used in conjunction with IPFS. --- # InterPlanetary Name System (IPNS) -- [InterPlanetary Name System (IPNS)](#interplanetary-name-system-ipns) - - [Mutability in IPFS](#mutability-in-ipfs) - - [How IPNS works](#how-ipns-works) - - [Anatomy of an IPNS name](#anatomy-of-an-ipns-name) - - [How IPNS names relate to CIDs](#how-ipns-names-relate-to-cids) - - [IPNS names are self-certifying](#ipns-names-are-self-certifying) - - [Common IPNS operations](#common-ipns-operations) - - [IPNS is transport agnostic](#ipns-is-transport-agnostic) - - [IPNS over the DHT](#ipns-over-the-dht) - - [IPNS over PubSub](#ipns-over-pubsub) - - [Publishing IPNS records over PubSub lifecycle](#publishing-ipns-records-over-pubsub-lifecycle) - - [Tradeoffs between consistency vs. availability](#tradeoffs-between-consistency-vs-availability) - - [IPNS record validity](#ipns-record-validity) - - [Practical considerations](#practical-considerations) - - [IPNS in practice](#ipns-in-practice) - - [Resolving IPNS names using IPFS gateways](#resolving-ipns-names-using-ipfs-gateways) - - [Publishing IPNS names with Kubo](#publishing-ipns-names-with-kubo) - - [Example IPNS Setup with JS SDK API](#example-ipns-setup-with-js-sdk-api) - - [Alternatives to IPNS](#alternatives-to-ipns) - - [Further Resources](#further-resources) +- [Mutability in IPFS](#mutability-in-ipfs) +- [How IPNS works](#how-ipns-works) + - [Anatomy of an IPNS name](#anatomy-of-an-ipns-name) + - [How IPNS names relate to content paths](#how-ipns-names-relate-to-content-paths) + - [IPNS names are self-certifying](#ipns-names-are-self-certifying) + - [Common IPNS operations](#common-ipns-operations) + - [IPNS is transport agnostic](#ipns-is-transport-agnostic) + - [IPNS over the DHT](#ipns-over-the-dht) + - [IPNS over PubSub](#ipns-over-pubsub) + - [Tradeoffs between consistency vs. availability](#tradeoffs-between-consistency-vs-availability) + - [IPNS record validity](#ipns-record-validity) + - [Practical considerations](#practical-considerations) +- [IPNS in practice](#ipns-in-practice) + - [Resolving IPNS names using IPFS gateways](#resolving-ipns-names-using-ipfs-gateways) + - [Publishing IPNS names](#publishing-ipns-names) +- [Alternatives to IPNS](#alternatives-to-ipns) +- [Further Resources](#further-resources) ## Mutability in IPFS @@ -44,13 +41,13 @@ A **name** in IPNS is the [hash](hashing.md) of a public key. It is associated w For example, the following is an IPNS name represented by a CIDv1 of public key: [`k51qzi5uqu5dlvj2baxnqndepeb86cbk3ng7n3i46uzyxzyqj2xjonzllnv0v8`](https://cid.ipfs.tech/#k51qzi5uqu5dlvj2baxnqndepeb86cbk3ng7n3i46uzyxzyqj2xjonzllnv0v8). -> **Note:** Kubo uses the `self` key (ed25519 private key used for the PeerID) as the default IPNS name. But you can generate multiple keys via [`ipfs key gen`](https://docs.ipfs.tech/reference/kubo/cli/#ipfs-key-gen), and use them for managing multiple IPNS names. +> **Note:** Kubo uses the `self` key (ed25519 private key used for the PeerID) as the default IPNS name. But you can generate multiple keys via [`ipfs key gen`](https://docs.ipfs.tech/reference/kubo/cli/#ipfs-key-gen), and use them for managing multiple IPNS names. #### How IPNS names relate to content paths -IPNS record can point at an immutable or a mutable path. The meaning behind CID used in a path depends on used namespace: +IPNS record can point at an immutable or a mutable path. The meaning behind CID used in a path depends on used namespace: -- `/ipfs/` – an [immutable content on IPFS](https://cid.ipfs.tech/#bafybeibml5uieyxa5tufngvg7fgwbkwvlsuntwbxgtskoqynbt7wlchmfm) (since the CID contains a multihash) +- `/ipfs/` – an [immutable content on IPFS](https://cid.ipfs.tech/#bafybeibml5uieyxa5tufngvg7fgwbkwvlsuntwbxgtskoqynbt7wlchmfm) (since the CID contains a multihash) - `/ipns/` – a mutable, cryptographic [IPNS name](https://cid.ipfs.tech/#k51qzi5uqu5dlvj2baxnqndepeb86cbk3ng7n3i46uzyxzyqj2xjonzllnv0v8) which corresponds to a libp2p public key. The following is a useful mental model for understanding the difference between the two: @@ -176,118 +173,9 @@ For example: -## Publishing IPNS names with Kubo +### Publishing IPNS names -1. Start your IPFS daemon, if it isn't already running: - - ```shell - ipfs daemon - ``` - -1. Open another command line window and create the file that you want to set up with IPNS. For the tutorial, we're just going to create a simple _hello world_ file: - - ```shell - echo "Hello IPFS" > hello.txt - ``` - -1. Add your file to IPFS: - - ```shell - ipfs add --cid-version 1 hello.txt - - > added bafkreidfdrlkeq4m4xnxuyx6iae76fdm4wgl5d4xzsb77ixhyqwumhz244 hello.txt - > 11 B / 11 B [=====================================================] 100.00% - ``` - - Take note of the CID output by IPFS. - -1. Use `cat` and the CID you just got from IPFS to view the file again: - - ```shell - ipfs cat bafkreidfdrlkeq4m4xnxuyx6iae76fdm4wgl5d4xzsb77ixhyqwumhz244 - - > Hello IPFS - ``` - -1. Publish your CID to IPNS: - - ```shell - ipfs name publish /ipfs/bafkreidfdrlkeq4m4xnxuyx6iae76fdm4wgl5d4xzsb77ixhyqwumhz244 - - > Published to k51qzi5uqu5dgy6fu9073kabgj2nuq3qyo4f2rcnn4380z6n8i4v2lvo8dln6l: /ipfs/bafkreidfdrlkeq4m4xnxuyx6iae76fdm4wgl5d4xzsb77ixhyqwumhz244 - ``` - - `k51...` is the public key or IPNS name of the IPFS you are running. You can now change the file repeatedly, and, even though the CID changes when you change the file, you can continue to access it with this key. - -1. You can view your file by going to `https://ipfs.io/ipns/k51qzi5uqu5dgy6fu9073kabgj2nuq3qyo4f2rcnn4380z6n8i4v2lvo8dln6l`: - - ```shell - curl https://ipfs.io/ipns/k51qzi5uqu5dgy6fu9073kabgj2nuq3qyo4f2rcnn4380z6n8i4v2lvo8dln6l - - > Hello IPFS - ``` - -1. Make a change to your file, add it to IPFS, and update your IPNS: - - ```shell - echo "Hello again IPFS" > hello.txt - ipfs add hello.txt - - > added bafkreidbbor7mvra2xzzl4kmr2sxrtkzaxlzs6rsr5ktgmbtousuzrhlxq hello.txt - > 17 B / 17 B [=====================================================] 100.00% - - ipfs name publish bafkreidbbor7mvra2xzzl4kmr2sxrtkzaxlzs6rsr5ktgmbtousuzrhlxq - - > Published to k51qzi5uqu5dgy6fu9073kabgj2nuq3qyo4f2rcnn4380z6n8i4v2lvo8dln6l: /ipfs/bafkreidbbor7mvra2xzzl4kmr2sxrtkzaxlzs6rsr5ktgmbtousuzrhlxq - ``` - -2. You can now go back to `https://ipfs.io/ipns/k51qzi5uqu5dgy6fu9073kabgj2nuq3qyo4f2rcnn4380z6n8i4v2lvo8dln6l` to view your updated file using the same address: - - ```shell - curl https://ipfs.io/ipns/k51qzi5uqu5dgy6fu9073kabgj2nuq3qyo4f2rcnn4380z6n8i4v2lvo8dln6l - - > Hello again IPFS - ``` - -You can view the CID of the file associated with your `k5` key by using `name resolve`: - -```shell -ipfs name resolve - -> /ipfs/bafkreidbbor7mvra2xzzl4kmr2sxrtkzaxlzs6rsr5ktgmbtousuzrhlxq -``` - -To use a different `k5` key, first create one using `key gen test`, and use the `--key` flag when calling `name publish`: - -```shell -ipfs key gen SecondKey - -> k51qzi5uqu5dh5kbbff1ucw3ksphpy3vxx4en4dbtfh90pvw4mzd8nfm5r5fnl - -ipfs name publish --key=SecondKey /ipfs/bafybeicklkqcnlvtiscr2hzkubjwnwjinvskffn4xorqeduft3wq7vm5u4 - -> Published to k51qzi5uqu5dh5kbbff1ucw3ksphpy3vxx4en4dbtfh90pvw4mzd8nfm5r5fnl: /ipfs/bafybeicklkqcnlvtiscr2hzkubjwnwjinvskffn4xorqeduft3wq7vm5u4 -``` - -## Example IPNS Setup with JS SDK API - -Imagine you want to publish your website under IPFS. You can use the [Files API](file-systems.md#mutable-file-system-mfs) to publish your static website, and then you'll get a CID you can link to. But when you need to make a change, a problem arises: you get a new CID because you now have different content. And it is not possible for you to be always giving others a new address. - -Here's where the Name API comes in handy. With it, you can create a single, stable IPNS address that points to the CID for the latest version of your website. - -```javascript -// The address of your files. -const addr = '/ipfs/bafkreidbbor7mvra2xzzl4kmr2sxrtkzaxlzs6rsr5ktgmbtousuzrhlxq' - -ipfs.name.publish(addr).then(function (res) { - // You now receive a res which contains two fields: - // - name: the name under which the content was published. - // - value: the "real" address to which Name points. - console.log(`https://ipfs.io/ipns/${res.name}`) -}) -``` - -In the same way, you can republish a new version of your website under the same address. By default, `ipfs.name.publish` will use the Peer ID. +See the following guide on [publishing IPNS names with Kubo and js-ipfs](../how-to/publish-ipns.md). ## Alternatives to IPNS From b219b4e3c7cd461766e199492d6d3cc2ff8d82fa Mon Sep 17 00:00:00 2001 From: Daniel N <2color@users.noreply.github.com> Date: Wed, 7 Sep 2022 13:46:37 +0200 Subject: [PATCH 18/19] Move publishing guide to how-to --- docs/.vuepress/config.js | 8 +++ docs/how-to/publish-ipns.md | 130 ++++++++++++++++++++++++++++++++++++ 2 files changed, 138 insertions(+) create mode 100644 docs/how-to/publish-ipns.md diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index 59c4b88b8..b547d4de0 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -237,6 +237,14 @@ module.exports = { '/how-to/browser-tools-frameworks' ] }, + { + title: 'IPNS and mutability', + sidebarDepth: 1, + collapsable: false, + children: [ + '/how-to/publish-ipns' + ] + }, { title: 'IPFS Companion', sidebarDepth: 1, diff --git a/docs/how-to/publish-ipns.md b/docs/how-to/publish-ipns.md new file mode 100644 index 000000000..298dbf76c --- /dev/null +++ b/docs/how-to/publish-ipns.md @@ -0,0 +1,130 @@ +--- +title: Publishing IPNS names +description: Learn how to publish IPNS names with Kubo and js-ipfs +--- + +# Publishing IPNS names + +IPNS names can be published from both the command line and programmatically. + +- [Publishing IPNS names with Kubo](#publishing-ipns-names-with-kubo) +- [Publishing IPNS names programmatically with JS-IPFS](#publishing-ipns-names-programmatically-with-js-ipfs) + +## Publishing IPNS names with Kubo + +1. Start your IPFS daemon, if it isn't already running: + + ```shell + ipfs daemon + ``` + +1. Open another command line window and create the file that you want to set up with IPNS. For the tutorial, we're just going to create a simple _hello world_ file: + + ```shell + echo "Hello IPFS" > hello.txt + ``` + +1. Add your file to IPFS: + + ```shell + ipfs add --cid-version 1 hello.txt + + > added bafkreidfdrlkeq4m4xnxuyx6iae76fdm4wgl5d4xzsb77ixhyqwumhz244 hello.txt + > 11 B / 11 B [=====================================================] 100.00% + ``` + + Take note of the CID output by IPFS. + +1. Use `cat` and the CID you just got from IPFS to view the file again: + + ```shell + ipfs cat bafkreidfdrlkeq4m4xnxuyx6iae76fdm4wgl5d4xzsb77ixhyqwumhz244 + + > Hello IPFS + ``` + +1. Publish your CID to IPNS: + + ```shell + ipfs name publish /ipfs/bafkreidfdrlkeq4m4xnxuyx6iae76fdm4wgl5d4xzsb77ixhyqwumhz244 + + > Published to k51qzi5uqu5dgy6fu9073kabgj2nuq3qyo4f2rcnn4380z6n8i4v2lvo8dln6l: /ipfs/bafkreidfdrlkeq4m4xnxuyx6iae76fdm4wgl5d4xzsb77ixhyqwumhz244 + ``` + + `k51...` is the public key or IPNS name of the IPFS you are running. You can now change the file repeatedly, and, even though the CID changes when you change the file, you can continue to access it with this key. + +1. You can view your file by going to `https://ipfs.io/ipns/k51qzi5uqu5dgy6fu9073kabgj2nuq3qyo4f2rcnn4380z6n8i4v2lvo8dln6l`: + + ```shell + curl https://ipfs.io/ipns/k51qzi5uqu5dgy6fu9073kabgj2nuq3qyo4f2rcnn4380z6n8i4v2lvo8dln6l + + > Hello IPFS + ``` + +1. Make a change to your file, add it to IPFS, and update your IPNS: + + ```shell + echo "Hello again IPFS" > hello.txt + ipfs add hello.txt + + > added bafkreidbbor7mvra2xzzl4kmr2sxrtkzaxlzs6rsr5ktgmbtousuzrhlxq hello.txt + > 17 B / 17 B [=====================================================] 100.00% + + ipfs name publish bafkreidbbor7mvra2xzzl4kmr2sxrtkzaxlzs6rsr5ktgmbtousuzrhlxq + + > Published to k51qzi5uqu5dgy6fu9073kabgj2nuq3qyo4f2rcnn4380z6n8i4v2lvo8dln6l: /ipfs/bafkreidbbor7mvra2xzzl4kmr2sxrtkzaxlzs6rsr5ktgmbtousuzrhlxq + ``` + +1. You can now go back to `https://ipfs.io/ipns/k51qzi5uqu5dgy6fu9073kabgj2nuq3qyo4f2rcnn4380z6n8i4v2lvo8dln6l` to view your updated file using the same address: + + ```shell + curl https://ipfs.io/ipns/k51qzi5uqu5dgy6fu9073kabgj2nuq3qyo4f2rcnn4380z6n8i4v2lvo8dln6l + + > Hello again IPFS + ``` + +You can view the CID of the file associated with your `k5` key by using `name resolve`: + +```shell +ipfs name resolve + +> /ipfs/bafkreidbbor7mvra2xzzl4kmr2sxrtkzaxlzs6rsr5ktgmbtousuzrhlxq +``` + +To use a different `k5` key, first create one using `key gen test`, and use the `--key` flag when calling `name publish`: + +```shell +ipfs key gen SecondKey + +> k51qzi5uqu5dh5kbbff1ucw3ksphpy3vxx4en4dbtfh90pvw4mzd8nfm5r5fnl + +ipfs name publish --key=SecondKey /ipfs/bafybeicklkqcnlvtiscr2hzkubjwnwjinvskffn4xorqeduft3wq7vm5u4 + +> Published to k51qzi5uqu5dh5kbbff1ucw3ksphpy3vxx4en4dbtfh90pvw4mzd8nfm5r5fnl: /ipfs/bafybeicklkqcnlvtiscr2hzkubjwnwjinvskffn4xorqeduft3wq7vm5u4 +``` + +## Publishing IPNS names programmatically with JS-IPFS + +With [ipfs-core](https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-core#readme) (a full IPNS node in JavaScript) you can you can publish an IPNS name as follows: + +```javascript +import * as IPFS from 'ipfs-core' + +const ipfs = await IPFS.create() + +// The address of your files. +const addr = '/ipfs/bafkreidbbor7mvra2xzzl4kmr2sxrtkzaxlzs6rsr5ktgmbtousuzrhlxq' + +ipfs.name.publish(addr, options).then(function (res) { + // You now receive a res which contains two fields: + // - name: the name under which the content was published. + // - value: the "real" address to which Name points. + console.log(`https://ipfs.io/ipns/${res.name}`) +}) +``` + +By default, `ipfs.name.publish` will use the Peer ID and set the lifetime to 24 hours. To learn more about the full API, check out the [API docs](https://github.com/ipfs/js-ipfs/blob/master/docs/core-api/NAME.md#ipfsnamepublishvalue-options). + +:::warning +Note that when using `ipfs-core`, you're instantiating a full IPFS node. For your IPNS record to propagate through the network, it needs to be connected to other peers. Typically this is not a problem, however, if you're running `ipfs-core` in the browser, you may want to connect it to a long-running IPFS node to ensure it successfully propagates due to [browser connectivity limitations.](https://github.com/ipfs/js-ipfs/blob/master/docs/BROWSERS.md#limitations-of-the-browser-context) +::: From 8f1022a9d94b4c13e70ba17a4c976f4554394418 Mon Sep 17 00:00:00 2001 From: Daniel N <2color@users.noreply.github.com> Date: Fri, 16 Sep 2022 19:38:27 +0200 Subject: [PATCH 19/19] chore: refine ipns howto --- docs/how-to/publish-ipns.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/how-to/publish-ipns.md b/docs/how-to/publish-ipns.md index 298dbf76c..99f60bd8c 100644 --- a/docs/how-to/publish-ipns.md +++ b/docs/how-to/publish-ipns.md @@ -105,7 +105,7 @@ ipfs name publish --key=SecondKey /ipfs/bafybeicklkqcnlvtiscr2hzkubjwnwjinvskffn ## Publishing IPNS names programmatically with JS-IPFS -With [ipfs-core](https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-core#readme) (a full IPNS node in JavaScript) you can you can publish an IPNS name as follows: +With [ipfs-core](https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-core#readme) (a full IPNS node in JavaScript) you can publish an IPNS name as follows: ```javascript import * as IPFS from 'ipfs-core' @@ -118,13 +118,13 @@ const addr = '/ipfs/bafkreidbbor7mvra2xzzl4kmr2sxrtkzaxlzs6rsr5ktgmbtousuzrhlxq' ipfs.name.publish(addr, options).then(function (res) { // You now receive a res which contains two fields: // - name: the name under which the content was published. - // - value: the "real" address to which Name points. - console.log(`https://ipfs.io/ipns/${res.name}`) + // - value: the IPFS path to which the IPNS name points. + console.log(`IPNS name: ${res.name}\n value: ${res.value}`) }) ``` By default, `ipfs.name.publish` will use the Peer ID and set the lifetime to 24 hours. To learn more about the full API, check out the [API docs](https://github.com/ipfs/js-ipfs/blob/master/docs/core-api/NAME.md#ipfsnamepublishvalue-options). :::warning -Note that when using `ipfs-core`, you're instantiating a full IPFS node. For your IPNS record to propagate through the network, it needs to be connected to other peers. Typically this is not a problem, however, if you're running `ipfs-core` in the browser, you may want to connect it to a long-running IPFS node to ensure it successfully propagates due to [browser connectivity limitations.](https://github.com/ipfs/js-ipfs/blob/master/docs/BROWSERS.md#limitations-of-the-browser-context) +Note that when using `ipfs-core`, you're instantiating a full IPFS node. For your IPNS record to propagate through the network, it needs to be connected to other peers. If you're running `ipfs-core` in the browser, you may want to connect it to a long-running IPFS node to ensure it successfully propagates due to [browser connectivity limitations.](https://github.com/ipfs/js-ipfs/blob/master/docs/BROWSERS.md#limitations-of-the-browser-context). :::