nostr-protocol / nips

Nostr Implementation Possibilities
2.39k stars 582 forks source link

Trusted Assertions #1534

Open vitorpamplona opened 1 month ago

vitorpamplona commented 1 month ago

Certain calculations in Nostr require access to the entire dataset of events and are impossible to do directly by Clients. This PR offers a simple way for users to declare trust in service providers for those calculations.

Yes, it's similar to DVMs, but without the need to request/response each item. The service just runs constantly and updates events as quickly as it can.

Read here

vitorpamplona commented 1 month ago

@alexgleason I think you already have something like this, using the same kinds @nostrband we can add all of your stats here if you want @nostr-wine I'd love to get some of your services here as well

melvincarvalho commented 1 month ago

Follower count can be easily gamed by automated agents. And this NIP encourages that.

vitorpamplona commented 1 month ago

Follower count can be easily gamed by automated agents. And this NIP encourages that.

Deciding what counts is up to each service provider and user. This NIP just specifies how they declare trust in each other.

nostrband commented 1 month ago

Concept ack, need to try it.

cesardeazevedo commented 1 month ago

It is possible to add event quotes too?

manimejia commented 1 month ago

WoT "scores" are not absolute for any user, but relative from the perspective of an "observer".

So the event sent (from service) SHOULD specify an observer tag as well as the recipient of the score.

In addition ... our service (and prolly other WoT recommendation engines) would prefer to output a list of scores (possibly thousands) for any given observer. So maybe having a "d" tag for the whole event is not the right format?

vitorpamplona commented 1 month ago

WoT "scores" are not absolute for any user, but relative from the perspective of an "observer".

Correct, but for these events, they will have to be absolute. Picture a WOT algorithm that is just a "page rank" for pubkeys.

So the event sent (from service) SHOULD specify an observer tag as well as the recipient of the score.

No, I don't think this would work (too much data - quadratic on the amount of users). DVMs would work better for the personalized score services (which this PR does NOT replace)

staab commented 1 month ago

I would use DVMs to do this. Most people think of them as a request/response flow, but they also easily support zero requests and 0+ responses. A client looking for these events would just query for the DVM response without publishing a request.

vitorpamplona commented 1 month ago

I would use DVMs to do this.

That was my initial conclusion as well. But after months of testing and debates, I think that just overloads the DVM spec with a use case that needs a different tooling from what they use.

It's a similar thing with your recent NIP-29 fork. It initially looks similar, but in the end it's not the same thing.

staab commented 1 month ago

Actually, on a second read of the PR you're right. It's a totally different use case, even if it could be shoe-horned into the same structure. Onward 🫡

manimejia commented 1 month ago

I CAN picture a WoT algorithm that is just a "page rank" for pubkeys. It's called GrapeRank, and there is no such thing as an absolute WoT score.

https://github.com/Pretty-Good-Freedom-Tech/graperank-nodejs

There MAY BE such a thing as an "average observed" score for a pubkey, but this is only useful AFAIKT if the requestor either does not have a pubkey of their own (because directly observed scores ARE more accurate for any user's use case) or if the requestor does not want their "observed network" to be transmitted publicly. In this latter case, we are working on a better solution for transmitting WoT scores privately.

And you may be right about DVMs being a better solution for WoT lists. An API architecture that accommodates a "list of recommendations for a given observer" is MUCH more useful for transmitting WoT "scores" (and other user and content recommendations) than the NiP proposed here.

IMHO, mostly because WoT scores ARE relative, I do not think this proposal actually solves for any real world problem of transmitting WoT recommendations from a remote service.

vitorpamplona commented 1 month ago

There MAY BE such a thing as an "average observed" score for a pubkey, but this is only useful AFAIKT if the requestor either does not have a pubkey of their own

It's not hypothetical, this is one of the main use cases for this PR. Apps don't need high-precision in WoT scores most of the time. We just need some basic reputational scores to.. say.. rank search results when people are trying to @ someone. Things like that.

Sure, personalized and private WoT are better versions of this but the added performance costs sometimes are not acceptable. For instance, I need the WoT to show up while the user scrolls really fast in the app. We wouldn't be able to call a server for each user in time.

Obviously, this doesn't replace the need for personalized and private WoT. It's just solving a different need.

manimejia commented 1 month ago

I appreciate the need for speed when clients make use of WoT recommendations ... but I still don't think "generic" scores are a great solution. Indeed, a cached "wot list" may perform even better than discrete "wot score" requests.

In many ways ... an observer-centric "recommendation list" is a better solution for "wot scores" than this proposal. IMHO

alexgleason commented 1 month ago

Interesting! In Ditto I am using these kind 30382 events with n tags to mark users as verified, suggested, blocked etc (moderation actions, basically) by the Ditto server. But I haven't used it to cache stats about them - for that I'm making use of custom Postgres tables, and exposing that data only through the Mastodon API. I had considered putting those stats in the same kind 30382 event (basically I had the exact same thought as you), but I simply wasn't brave enough to do it, that's my only reason. So, I think it's a good idea. It's a little harder from a performance standpoint than using a Postgres table, so I thought it was only worth doing if there was standardization around it.

It competes slightly with what I'm doing with labels, but not by much. The drawback of using labels in this way is that they store fixed values (not dynamic ones), they're not replaceable events, and when you start labeling a lot of things at once they can have collisions. A good way I'm using labels is for trending posts, but now I'm considering moving my captcha solved label to kind 30382.

vitorpamplona commented 1 month ago

The cool part of moving to 30382 is that you can add ditto's pubkey to the user's trusted providers and then I can display the same info you have on Amethyst.

And maybe one day Ditto can rely on other service providers as well.

alexgleason commented 1 month ago

I think kind 30078 should be extended, to require a third parameter of the d-tag, "p", like this:

["d", "<pubkey>", "p"]

And then a p-tag with a matching pubkey is also required or else validation fails. Same with "e", "r", etc. This way you can also p-tag query them, and it enforces the type of the "d" tag.

I think this should be a general rule for d-tags whose value references another common type of tag.

EDIT: See https://github.com/nostr-protocol/nips/pull/1536

vitorpamplona commented 1 month ago

that's a cheap and subjective calculation that belongs in the client

Are you referring to the follows of follows set of keys that everyone calls web of trust in Nostr? If so yes, that is cheap, but that is not WoT in my mind. My hope for the WoT is to do a full graph analysis of all keys and iteratively assemble a score for each pubkey from a global perspective. I don't think that can be done in the client.

And again, that does not replace any other approach, neither simpler nor more complex, for WoT calculations. It just offers a base layer that will likely be whatever algorithm the provider wants to make. We will have a competition for the best WoT providers out there.

pablof7z commented 1 month ago

that's a cheap and subjective calculation that belongs in the client

My hope for the WoT is to do a full graph analysis of all keys and iteratively assemble a score for each pubkey from a global perspective.

You lost me at global. 😂

I wouldn't call that WoT, the nature of WoT implies that it would be from someone's perspective, I'd say a "global WoT" is an oxymoron.

Anyways, this is beside the point of this PR and I don't want to derail the conversation.

Are you working on implementing one of these services?

vitorpamplona commented 1 month ago

I wouldn't call that WoT, the nature of WoT implies that it would be from someone's perspective, I'd say a "global WoT" is an oxymoron.

Makes sense. We can call it rank or something else.

Are you working on implementing one of these services?

Yes, but I don't really want to. I don't really want to run any services at all. I find these decisions (when the app also runs the service) extremely centralizing in the long run.

If anyone puts a service like this, I will completely shutdown mine.

nostrband commented 1 month ago

Created wss://nip85.nostr.band and uploaded 30382 by "4fd5e210530e4f6b2cb083795834bfe5108324f1ed9f00ab73b9e8fcfe5f12fe" with "rank" scores (instead of "wot"). Let me know if that looks good.

manimejia commented 1 month ago

We DO need a NIP for clients to retrieve 'on-demand' rankings of users and content from trusted sources, but these values will ALSO need to be 'relative' to the pubkey of the client user (the network observer). With a couple tweaks, I believe this NIP could be perfect for publishing Assertion events with such an 'observer' relationship. @nostrband @vitorpamplona @pablof7z

To indicate this 'observer' relationship, a kind 30382 Assertion event COULD optionally include a delegation tag, used in the same manner as NIP 26

The argument is such : If a signed kind 10040 Authorization event specifies that the service provider is "trusted" by an end user to provide calculated content, then (for certain calculations) these kind 30382 Assertion events ARE in effect 'delegated' content that is signed by the service provider on BEHALF of the end user. If a kind 30382 event includes such a tag, then it SHOULD be treated as content having this relationship.

ALSO : To be clear, if an Assertion event is published in this manner, then the value of "d" tag would need to reflect this relationship. So... "d" == "p" as suggested by @alexgleason would NOT always work for kind 30382 events.

mikedilger commented 1 month ago

+1 for this NIP.

The list of names should be open enough to include all of our disparate ideas. We have different ideas about what WoT means... just add multiple names for each different algorithm people are actually implementing. So I don't think fighting over which ones are in that list makes any sense, just add more as we make up more, and deprecate ones that nobody ended up using.

mikedilger commented 1 month ago

We DO need a NIP for clients to retrieve 'on-demand' rankings of users and content from trusted sources, but these values will ALSO need to be 'relative' to the pubkey of the client user (the network observer). With a couple tweaks, I believe this NIP could be perfect for publishing Assertion events with such an 'observer' relationship. @nostrband @vitorpamplona @pablof7z

To indicate this 'observer' relationship, a kind 30382 Assertion event COULD optionally include a delegation tag, used in the same manner as NIP 26

The argument is such : If a signed kind 10040 Authorization event specifies that the service provider is "trusted" by an end user to provide calculated content, then (for certain calculations) these kind 30382 Assertion events ARE in effect 'delegated' content that is signed by the service provider on BEHALF of the end user. If a kind 30382 event includes such a tag, then it SHOULD be treated as content having this relationship.

ALSO : To be clear, if an Assertion event is published in this manner, then the value of "d" tag would need to reflect this relationship. So... "d" == "p" as suggested by @alexgleason would NOT always work for kind 30382 events.

I hard disagree. It means instead the following: "Hey Mr nostr client that I am currently using, please get this data from the service I specified". It doesn't mean the service can sign on your behalf. At all.

mikedilger commented 1 month ago

I would change the name of this PR to something more like "Data Aggregation". The fact that someone publishes an event that says "I accept the values this relay is giving me" is the smaller part of this... the larger part is the data being published.