nostr-protocol / nips

Nostr Implementation Possibilities
2.34k stars 567 forks source link

Standardized Tag for Expirable (ephemeral and replaceable) Events #863

Open manimejia opened 11 months ago

manimejia commented 11 months ago

NIP-1 outlines a convention for defining replaceable, ephemeral, and parameterized replaceable events based on the value of the event kind numeric identifier.

a convention for kind ranges that allow for easier experimentation and flexibility of relay implementation:

… defines an event’s lifecycle based on the value of it’s kind numeric identifier …

These are just conventions and relay implementations may differ.

The Problem

This convention “forces” events to adopt a kind number from a limited a range simply as a means to differentiate it’s “lifecycle” from other events. Event lifecycle DOES need to be easily identified in an indexed metadata, but this convention is brittle and bound to break or constrain the development of nostr protocol in the future. For example:

The Solution

While the “lifecycle” of an event needs to be easily identified in an event’s indexed metadata, there is already a better way to accomplish this. Standardized (single letter indexable) tags, as prescribed in the protocol (NIP-1), are perfectly suited for this need.

Using a single letter tag (like “x”), the nostr protocol can describe how an event should “expire”.

I propose removing the clause in NIP-1 that outlines this convention, and replacing it with either a new clause or a (separately implementable) NIP that describes a more formalized “standardized tag” based approach.

Here is an example that MIGHT work:

Regular “permanent” event : no x tag

{ “tags” : [<no ‘x tag’>] }

Ephemeral event : x=0

{ “tags” : [
[“x”,”0”]
]}

Replaceable event : x=1

{ “tags” : [
 [“x”,”1”],
 ["a", <kind integer>:<32-bytes lowercase hex of a pubkey>:, <recommended relay URL, optional>]
 ]}

Parameterized Replaceable event : x = (not 0 or 1)

{ “tags” : [
 [“x”,”<‘d tag’ identifier>”],
 ["a", <kind integer>:<32-bytes lowercase hex of a pubkey>:<‘d tag’ identifier, optional>, <recommended relay URL, optional>]
 ]}
fiatjaf commented 11 months ago

The more flexibility you add the harder you make for software to be implemented. The idea here is not new, it has been proposed before.

I think it does sound very reasonable and good at first glance, but after careful review having hardcoded conventious is healthier for the simplicity and openness of the protocol.

manimejia commented 11 months ago

These are just conventions and relay implementations may differ.

I'm confused. How are "hard coded conventions" good for openness and simplicity? At what point in the growth of an open protocol does this practice backfire?

Arbitrary inflexibility is also called "brittle". If you (and we all do) want both openness and simplicity for this protocol, the inflexible parts need to be cared for and protected. They need a safe place to rest, not hanging out exposed in a way that causes friction for implementors.

Refactoring for growth is the name of the game. It will be iterative, maybe painful, and hopefully rewarding. We are big enough to handle this.

PS I am a nobody, not an expert. Don't take my word, I don't have solutions. But I do know pain points when I see them.

Thank you for considering.

vitorpamplona commented 11 months ago

@manimejia the way Nostr works is that you have to give these ideas to clients and relays to implement. Once they do implement, you can send a PR to this repo to document the new system.

As a Client developer, I don't see this idea solving anything. But maybe others have the "pain points" you talk about. If they do, and they code your solution, we can have a good debate in a PR.

manimejia commented 11 months ago

Thank you @vitorpamplona. This is why I opened an issue, rather than a PR. To discuss informally and openly with implementors who might (or not) see the same pain points.

staab commented 11 months ago

Arbitrary inflexibility is also called "brittle".

Brittleness only matters if something must bend. With expiration policies attached to kind, that never needs to change, and so it won't ultimately break.

manimejia commented 11 months ago

Brittleness only matters if something must bend. With expiration policies attached to kind, that never needs to change, and so it won't ultimately break.

Fair. An event kind that does not expire will "prolly" never need to "sometimes" expire.

Unless it does.

For the case of reducing NIP bloat, I have proposed one scenario #864 (of many possible scenarios) whereby different event "kinds" (as "content types") would use a single kind number. Sounds ridiculous, but the benefit being that these "content types" can have their own formal (non "kind") protocol for being created, tested, published, and mass adopted "Ad hoc" by implementors without ever needing a nip to be approved.

In this way... maybe a single kind might need different lifecycle parameters available to it.

Maybe I'm off my rocker... but that was my first motivation for this issue. Reducing implementor friction.