Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NIP-116: Event paths #1266

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open

NIP-116: Event paths #1266

wants to merge 3 commits into from

Conversation

mmalmi
Copy link

@mmalmi mmalmi commented May 28, 2024

Event kind 30079 denotes an event defined by its event path rather than its event kind. Event paths are a scalable alternative to numeric event kinds, and help make Nostr a true "everything app".

@arthurfranca
Copy link
Contributor

Event kind 30079 denotes an event defined by its event path rather than its event kind.

But if you want interoperability, don't you need to reserve the event path for a specific usage (by merging a NIP or writing a NUD)? If yes, isn't this the same as reserving an event kind number?

@vitorpamplona
Copy link
Collaborator

vitorpamplona commented May 28, 2024

Event paths are a scalable alternative to numeric event kinds

We do not have a scaling problem in numeric kinds. Pretending there is one is not helpful.

But I am not opposed to creating a directory structure on an event kind. It's just not solving what you think it is solving.

Either way, directories are very similar to #784, you can just use n instead of f. With n, you can even cite a directory via nostr:nset1...

Using d-tagged replaceable events for reactions, such as {tags: [["d", "reactions/[eventId]"]], content: "\"👍\"", kind: 30079, ...} would make un-reacting trivial: just publish a new event with the same d tag and an empty content. Toggling a reaction on and off would not cause a flurry of new reaction & delete events that all need to be persisted.

This is dumb. It's just going to create a ton of empty events that client's don't need to download. It's better to have proper deletions than an empty event. See #1263

@mmalmi
Copy link
Author

mmalmi commented May 28, 2024

But if you want interoperability, don't you need to reserve the event path for a specific usage (by merging a NIP or writing a NUD)? If yes, isn't this the same as reserving an event kind number?

Sometimes you want interoperability, sometimes not. When you do, human-readable indexing is still better than numeric. There's much less risk of colliding with a number picked by someone else. You can get an intuition of what the event is for: e.g. user/profile/name with a string in it is pretty self-explanatory unlike some number like 31337.

Scalability

We will run out of unused 30000 <= n < 40000 event kinds before long. Even if we increase the range, it makes more sense to have human readable directory names which we will never run out of.

There's probably a reason why we have filesystems with nested human-readable directory names instead of having to index every file by some random number only.

n tags

We could use "n" tag instead of "f". The events could reside in multiple directories. Why not.

This is dumb. It's just going to create a ton of empty events that client's don't need to download. It's better to have proper deletions than an empty event. See #1263

With the delete event pattern you need to trust that all your relays are up-to-date and supportive of delete events (which will probably not be the case in a decentralized network) or subscribe to delete events on the client side.

The need for "tombstoning" with empty values is unfortunate, but it's the only reliable way to delete a value in a decentralized system. However, it avoids the situation where a user toggles e.g. "like" button on and off, creating lots of "like" and "delete like" events that relays have to store.

@vitorpamplona
Copy link
Collaborator

However, it avoids the situation where a user toggles e.g. "like" button on and off, creating lots of "like" and "delete like" events that relays have to store.

I don't get this. Relays don't have to store these likes and deletions in the same way they don't have to store the history of replaceables (which are also going back and forth on toggles). They can just delete them forever. It's up to them.

@vitorpamplona
Copy link
Collaborator

it makes more sense to have human readable directory names which we will never run out of.

I worked for 3 years with Verifiable Credentials where schemas and types are strings with "infinite" scaling as you said. There is no real interoperability between Verifiable Credentials. Everyone just creates their own names/types and fuck everybody else. There is no effort to reuse names somebody else is already using and/or to standardize what values those names take.

Strings create the false impression of documenting what the type is without having to write it down somewhere else. Nostr's integer kinds require you to explain what you are doing in some other place than the type name itself. And that creates a possibility to explain the entire sematics of what your type is doing. It's just a better "system" for real interoperability.

@AsaiToshiya
Copy link
Collaborator

If the interoperability is not required, I think #995 will help.

@fiatjaf
Copy link
Member

fiatjaf commented May 28, 2024

Yes, that was the entire point of NIP-78.

I had previously done some experimental apps using remoteStorage.io, which uses a "path-like" namespace for storing app data.

The result is that, of the few apps that exist in that ecosystem, most are "note-taking" apps and each of the note-taking uses a different path and is not compatible with each other.

So the thing is really just meant for specific application data, not for interoperability, and all that is written in NIP-78.

@mmalmi
Copy link
Author

mmalmi commented May 28, 2024

However, it avoids the situation where a user toggles e.g. "like" button on and off, creating lots of "like" and "delete like" events that relays have to store.

I don't get this. Relays don't have to store these likes and deletions in the same way they don't have to store the history of replaceables (which are also going back and forth on toggles). They can just delete them forever. It's up to them.

If the deletion events are not stored, the deleted events can reappear from a relay or client that doesn't support deletions or just hasn't received the deletion.

@fiatjaf
Copy link
Member

fiatjaf commented May 28, 2024

#1263

@mmalmi
Copy link
Author

mmalmi commented May 28, 2024

I could use the existing event kind 30078 and possibly n tags instead of f.

Then the only relay side change in this NIP would be this:

Relays should parse the event directory from the event path d tag and index the event by it. Relays should support "directory listing" of kind 30079 events using the #f filter, such as {"#f": ["user/profile"]}.

But it can be done later if this arrangement becomes popular. Avoids a little bit of redundancy.

Replaceable events for lists and reactions is more of a client side suggestion. It could be done parallel to current follow lists and profiles. You could restore your follow list or profile from the replaceable event side even if there's a kind 0 or 3 overwrite.

"Directory names" and numeric kinds are both possible on Nostr, so we can see which one works better, and maybe they have different purposes.

@vitorpamplona
Copy link
Collaborator

Relays should parse the event directory from the event path d tag and index the event by it. Relays should support "directory listing" of kind 30079 events using the #f filter, such as {"#f": ["user/profile"]}.

What does this mean? What do they actually have to do to support it? Is it a filter with startsWith for f-tags?

@mmalmi
Copy link
Author

mmalmi commented May 28, 2024

Relays should parse the event directory from the event path d tag and index the event by it. Relays should support "directory listing" of kind 30079 events using the #f filter, such as {"#f": ["user/profile"]}.

What does this mean? What do they actually have to do to support it? Is it a filter with startsWith for f-tags?

startsWith for d-tags. It would just save the redundancy in tags: instead of tags: [['f', 'user/profile'], ['d', 'user/profile/name']] you could leave out the 'f' tag altogether.

@vitorpamplona
Copy link
Collaborator

vitorpamplona commented May 28, 2024

startsWith for d-tags.

We have been requesting this for months (for geotags), but I don't think it's going to happen :(

@mmalmi
Copy link
Author

mmalmi commented May 28, 2024

Actually not exactly startsWith: "#f": ['user'] should return an event with ["d", "user/profile"] but not ["d", "user/profile/name"]. So it requires a custom index for "f" to be efficient.

We have been requesting this for months (for geotags), but I don't think it's going to happen :(

Link? Sounds like this should be an efficient startsWith lookup if just "d" is indexed on the relay.

@vitorpamplona
Copy link
Collaborator

Link? Sounds like this should be an efficient startsWith lookup if just "d" is indexed on the relay.

It was def in this repo, but I am unable to find it :(

FYI, pubkey prefixes were also removed for the same reason: #703

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants