Tagged IPNS records

Kind : Proposal/Enhancement

Protocol

An IPNS record should have an optional Tag (bytes) field. The Sequence (uint64) field will be used to identify the latest version only in context of the given Tag and record identifier. Records without any Tag field or an empty Tag would be equivalent to the currently implemented IPNS records. For an intuitive understanding, a Tag may be considered a directory or bucket containing IPNS records having that Tag value.

The key corresponding to the list of IPNS records (latest version) with any given Tag value may have the format:

  • /ipns/tag/<Tag_value> , or
  • /ipts/<Tag_value> , IPTS standing for Inter-Planetary Tag System.

Any specific IPNS record with a given Tag may be keyed as:

  • /ipns/tag/<Tag_value>/<signatoryID> or
  • /ipns/<signatoryID>/<Tag_value> or
  • /ipts/<Tag_value>/<signatoryID>

CLI

Include a --tag=<Tag_value> option to the ipfs name subsystem/subcommand.

Implementation atop “IPNS over Pubsub”

In addition to subscribing to the name-specific topics, nodes running with --enable-namesys-pubsub also subscribe to tag-specific topics on first resolution with ipfs name --tag=<Tag_val> resolve .

Security (Optional)

If the tag is a peer ID, then the Value (bytes) field in the IPNS record may be encrypted with the Ed25519 pubkey of the tagged peer ID. This may be activated with an --encrypt option in the ipfs name --tag=<peerID> publish command.

Benefits / Applications

  • Mailing [also see offline message queue ]. Sender publishes mail (file for single mail, directory otherwise) over IPNS with --ipns-base=b58mh and --tag=<receipientID> and --lifetime=72h . On the recipient’s end, after coming online at least once every 3 days, a simple ipfs name --tag=$(ipfs id -f='<id>') resolve would list the peer IDs of the all the senders for the past 3 days. To download the mail sent by a specific sender: ipfs get | cat /ipns/tag/<selfID>/<senderID> | /ipts/<selfID>/<senderID> . To download all mails in a directory: ipfs get|cat /ipts/<selfID> . When the sender goes offline, its mails may be hosted by Pinata. If the mail body is small enough, it may be embedded in the CID (ipfs path) with ipfs add --inline so that Pinata need not be depended on.
  • Search engine for the distributed web . Web-sites/pages hosted with IPFS and published over IPNS with keywords as tags. The search engine simply resolves the keywords given by the user, to get to the resources.
  • Distributed Key-Value Database published & maintained by recognized central authority(s) . Example - distributed public key database. After verifying email id of the submitter, a recognized IPFS node (central authority) publishes the submitted PGP public key tagged with a hash of the verified email. The node renews the published records every few days. Latest pubkey may be accessed with /ipts/<email_hash>/<authorityID> .

Request

@adin @stebalien @vasco-santos @jbenet & the community: please provide thoughts on feasibility, link to similar issues/topics/threads/discussion

I’m not sure I understand your system but would it not be possible to do the same thing with IPNS and IPLD?

IPNS record resolving to IPLD metadata.

Dear @SionoiS,

Thanks a lot for your interest. But, I fail to see how the current IPNS & IPLD would achieve that. For clarity let me try to rephrase my system.

Currently, a node can have only one IPNS record resolvable by say its peer ID, viz. ipfs name resolve /ipns/peerID. With what I am proposing, a node would be able to publish multiple IPNS records - each with a different tag. Such a tagged record would need both the tag and the peerID to be resolved.

Multiple peers can publish with the same tag. Therefore, one would also be able to list all the IPNS records belonging to any given tag (but different publisher peerIDs). For the mail application for example, A and B can publish their respective messages to C with C’s peerID as the tag, such that C can later find A and B’s records by probing that tag.

I am proposing the tagged system mainly for this ability to pool multiple IPNS records published by different peerIDs under a given label or tag or keyword or recipient ID.

On the other hand, if you are interested in the single publisher + multiple tags scenario, then current IPNS+IPLD would indeed suffice. Simply publish a directory with each tag as a subdirectory or so.

Ok I understand the idea and it would be very cool. Do you have ideas on how to realize it, I’m speaking technically?

Maybe you could hash the tag+peerid and get an IPNS name. No sure how to resolve tags though.

BTW a node can have multiple IPNS record not just one.

You mean a node can have multiple IPNS records each with a different key. But I was referring to a single key - such as the self key (viz. the peerID in b58mh form). There, the record is unique - the latest version of it I mean, right?

Sure, that’s what my OP details. To elaborate, if you checkout the IPNS record specs provided here you will see that the record structure contains different fields. I am proposing the addition of a Tag field that would hold the publisher-provided tag. When any node receives this IPNS record from the (re)publisher, it will read this tag and cache the record in a directory/memory-object named after this tag. That way it will build a local pool of all IPNS records belonging to any given tag. When one executes ipfs name resolve --tag=<tag_value> it can simply return IPNS records belonging to this <tag_value> from its cache.

Hashing tag+peerid, i’m afraid, would defeat the purpose. Consider this. Alice sends Bob a mail by publishing her msg with her self key and Bob’s peerID as the tag. Bob doesn’t know Alice’s peerID. In your hash scheme, how would Bob know Alice has sent him something? However, using the above-described tag-pool system, Bob can simply query the network for IPNS records tagged with his peerID and voila - he sees Alice’s msg.

Maybe I’m wrong but my understanding of IPNS is that you query the network with an IPNS name to get the record.

How having a tag IN the records allow you to query that tag?

If your can pull it off it would be fantastic.

Yes, currently you query with a key of the form: /ipns/peerID. But once tags are there, you would have to mention the tag too - like /ipns/tag/TAG/PID, which means give me the record published by the node with peerID=PID under the tag=TAG.

Also, since the nodes have already sorted their locally cached IPNS records according to their tag values, if you query the network with say /ipns/tag/TAG they ought to be able to return all the records (publisher peerIDs) having tag=TAG.

Note that this can be pulled off without disrupting the currently implemented system. /ipns/peerID would simply give the record published by peerID with an empty tag value.

I am also very tempted to draw parallels between a signed pubsub message and the proposed tagged IPNS record.

The signed message struct contains the following fields (see specs here):

Message { data; publisherID; seqNum; topic; signature; signingKey;}

whereas the tagged IPNS record would contain (specs)

Record { data; publisherID; version; tag; signature; signingKey;}

[ignoring validity, validityType and ttl fields].

So, tag in the context of IPNS is the counterpart of topic in the context of pubsub. You would be able to publish IPNS records under any tag string you choose, much like you can publish to any pubsub topic of your choosing.

Just like we can get messages published to a pubsub topic by subscribing to that topic, we can discover/pool IPNS records with a common tag simply by resolving that tag, even if we don’t know the key/peerID of their actual publishers.

Unlike pubsub however, the publisher node might be offline when a peer accesses an IPNS record published by it.

I think it might be better to take a DNS-like approach to tagging. ie. announce a hash and its tags over PubSub, and let different servers archive and index these metadatas to be served to clients later.

I actually wrote how such a spec might work a few years ago, although it’s likely incomplete, and looking back on it there are a lot of faults and naive assumptions. For instance, Clients shouldn’t have to announce to everyone what they’re looking for, and “Categories” could be supplemented.

I think it would be good to have 1:N:M relation between IPNS address - Tag - Value

I am more interested in tags for IPFS nodeId. Then use it for adding network tag and then use tag for choosing preferred networks to connect while fetching content.

Example of such tag is {“NET”:[“AWS-WEST”]}

Being a name system to address mutable content on IPFS, IPNS would always be 1:1 between IPNS address or key - Value. After all, that’s how a key-value database or hash table works.
Any single IPNS record can have only one value in the Tag field. If multiple tags are required, the publisher has to publish separately under each tag. Note that the IPNS key now becomes - /ipns/tag/<tag_value>/<hash_of_signing_key>. So the 1:1 relation is still there. Once you provide a tag value AND the signing key (hash), IPNS points to a unique IPNS record and therefore unique content.

That has nothing to do with IPNS. What you propose might indeed be beneficial, but you gotta have it outside IPNS - i.e. have a separate system altogether as it concerns node or peer IDs only, not content on IPFS or other IPNS links.
For a specific application, you can rather exploit IPNS for this purpose - say by publishing JSON describing your node with ipfs name publish --ipns-base=b58mh ... that can then be resolved at key=/ipns/<nodeID>.