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-101 - Decentralized Trust System for Nostr #1718

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

Conversation

papiche
Copy link

@papiche papiche commented Jan 28, 2025

NIP-101 - Decentralized Trust System for Nostr

This merge request introduces NIP-101: Decentralized Trust System for Nostr, a proposal designed to improve content filtering and moderation on the Nostr network through a decentralized and user-driven trust model.

The key highlights of this proposal include:

  • New Event Kind (Kind 33): Allows users to rate others with trust scores ranging from -100 to 100, enabling dynamic trust-based filtering.
  • Client-Side Trust Calculations: Uses direct and indirect trust ratings to calculate trust scores, mimicking real-world relationships.
  • Configurable Feed Filtering: Users can set trust thresholds to hide or display content based on their preferences.
  • Transparency and Decentralization: Ratings are public, verifiable, and entirely user-controlled, avoiding reliance on central authorities.

We believe this NIP will enhance the overall quality of conversations on Nostr, reduce spam and misinformation, and provide users with greater control over their experience.

Why this matters:
The proposed system aligns with Nostr’s core principles of decentralization and openness, offering a scalable, flexible, and community-driven moderation alternative.

We encourage the community to review, provide feedback, and test this implementation to help refine and integrate it into Nostr clients and infrastructure.

Let’s work together to make the Nostr ecosystem more dynamic, user-centric, and trust-driven!

@vitorpamplona
Copy link
Collaborator

Please get rid of the json object inside the .contents and move those properties to the tag array as usual.

101.md Outdated
```json
{
"kind": 33,
"content": {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it must be a stringified json. also, its better to use tags instead of a json on content.

Copy link
Contributor

@kehiy kehiy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isn't that a same thing as web of trust?

@papiche
Copy link
Author

papiche commented Jan 28, 2025

{
   "kind": 33,
   "content": "", // Content remains empty
   "tags": [
      ["target", "public key of the user being rated"],
      ["rating", "numerical value between -100 and 100"],
      ["related_event", "id of triggering event (optional)"],
      ["category", "trust category (optional)"]
   ],
   "pubkey": "public key of the rater",
   "sig": "signature of the rater"
}

better like this ?

@kehiy
Copy link
Contributor

kehiy commented Jan 28, 2025

{
   "kind": 33,
   "content": "", // Content remains empty
   "tags": [
      ["target", "public key of the user being rated"],
      ["rating", "numerical value between -100 and 100"],
      ["related_event", "id of triggering event (optional)"],
      ["category", "trust category (optional)"]
   ],
   "pubkey": "public key of the rater",
   "sig": "signature of the rater"
}

better like this ?

target -> p.
related_event -> e.

@papiche
Copy link
Author

papiche commented Jan 28, 2025

isn't that a same thing as web of trust?

Yes, it is quite similar to a Web of Trust (WoT) conceptually. Both systems rely on decentralized trust relationships between individuals to establish credibility, reduce spam, and curate meaningful interactions. However, there are some nuanced differences that distinguish this NIP from traditional Web of Trust implementations:

Similarities:

  1. Decentralization: Both systems avoid centralized control and depend on users' trust relationships.
  2. Trust Propagation: Trustworthiness is propagated through the network (e.g., "I trust A, and A trusts B, so I might trust B").
  3. Transparency: Both systems rely on publicly shared trust ratings or endorsements.
  4. User-Defined: Trust decisions are subjective and tailored to individual preferences.

Differences:

  1. Focus on Content Filtering:

    • Traditional Web of Trust systems are often used for verifying identities (e.g., PGP key signing) or establishing broad credibility.
    • The NIP-101 system is focused specifically on social feed curation for Nostr, allowing users to filter events and interactions based on trust thresholds.
  2. Granularity:

    • NIP-101 introduces categories of trust, allowing for different trust contexts (e.g., "trust as a content creator" vs. "trust for political insights"). Traditional WoT systems usually treat trust as a binary or singular value.
  3. Algorithm:

    • NIP-101’s trust calculation involves averaging and square-root-based weighting for indirect trust, specifically designed for performance in a social network setting. Web of Trust systems often rely on simpler or static models of endorsement.
  4. Dynamic Nature:

    • In NIP-101, trust scores can evolve dynamically based on user activity and relationships, while traditional Web of Trust systems are typically more static and certificate-based.
  5. Use Case Scope:

    • The primary goal of NIP-101 is content curation and improving social interactions on Nostr. Web of Trust is more about identity verification or building long-term, verifiable reputations.

Why Not Just Call It Web of Trust?

While NIP-101 shares foundational principles with a Web of Trust, its focus, mechanisms, and application to social content filtering make it a specialized adaptation for Nostr. Referring to it simply as "Web of Trust" might imply it’s a direct replica of older systems, which could lead to confusion about its purpose.

This proposal is essentially a modernized, use-case-specific Web of Trust, optimized for decentralized social networking. Would you like to incorporate this clarification into the proposal?

@kehiy
Copy link
Contributor

kehiy commented Jan 28, 2025

@papiche

  1. please avoid sending ai-generated stuff, they are annoying.
  2. what if we include existing report events to mute/follow lists in calculating the wot rate?

@papiche
Copy link
Author

papiche commented Jan 28, 2025

1. please avoid sending ai-generated stuff, they are annoying.

I agree with you. sorry about that but it helps me a lot to transform this idea https://web.archive.org/web/20230324134924/https://adecentralizedworld.com/2020/06/a-trust-and-moderation-system-for-the-decentralized-web/ into a NIP (i got only one valid arm for typing)

2. what if we include existing report events to mute/follow lists in calculating the wot rate?

Algorithm simulation has pretty nice performance.

Mute/Follow action could send normalized "rating" event to initiate dataset
Each report event could be translated into a small negative or positive rating (-10/+10 : configurable by the client)
Users could choose how much weight to assign to mute lists from their friends (e.g., "If I trust Alice, I’ll automatically trust her mutes").

@papiche
Copy link
Author

papiche commented Jan 28, 2025

target -> p.
related_event -> e.

applyed in last commit

101.md Outdated
Comment on lines 124 to 141
import math

def calculate_trust(user, friend_ratings, all_ratings):
trust_score = 0.0
num_raters = 0
for friend, direct_rating in friend_ratings.items():
if friend in all_ratings and user in all_ratings[friend]:
mutual_rating = all_ratings[friend][user]
if mutual_rating > 0:
trust_score += direct_rating * mutual_rating
num_raters += 1
return math.sqrt(trust_score / num_raters) if num_raters > 0 else 0.0

# Example:
all_ratings = {"A": {"B": 50, "C": 20}, "B": {"D": 100}, "C": {"D": 40}}
user = "D"
friend_ratings = {"B": 80, "C": 60}
print(calculate_trust(user, friend_ratings, all_ratings))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this python code is invalid and unreadable

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for noticing. been fixed in latest version

@fiatjaf
Copy link
Member

fiatjaf commented Jan 28, 2025

I had a proposal years ago that was basically exactly this, but I don't think it will work anymore, it's too complex and most people won't bother. I don't know what is the solution.

@kehiy
Copy link
Contributor

kehiy commented Jan 28, 2025

I had a proposal years ago that was basically exactly this, but I don't think it will work anymore, it's too complex and most people won't bother. I don't know what is the solution.

@fiatjaf best option is to keep it unstandard and let clients/relays do the web of trust rating using their custom model based on user config or any other approach. making it an standard would limit them. we have data over nostr, relay or client can use them in any ways to check trust rate and more.

@staab
Copy link
Member

staab commented Jan 28, 2025

I think @wds4 and @pippellia-btc are already working on this problem, you should consider looking at their work.

@pippellia-btc
Copy link

pippellia-btc commented Jan 28, 2025

Hey @papiche, first of all let me say that this proposal has the benefit of being simple.
However there are imo some shortcomings:

  • It prescribe the algorithm to use. Depending on the context and situation, different algos should be used (e.g. personalized feed, recommended follows, verifying reputation of signer of an application on zapstore...). The choice of the algorithm should ideally be made by the user and/or by the client, and not part of the NIP.
    About the algorithm, it's simple so that's good, but it takes arbitrary decisions, for example the fact that "Negative ratings are ignored for indirect calculations", which is only motivated as far as I understand because of the choice of using the square root. Are there other reasons?

  • It neglects that "trust" is contextual. I may trust someone to recommend a film, but not to take care of my child. You could add a context field, but then we go to the next point.

  • It's a difficult UX for users. I don't believe users will start rating each others on a scale from -100 to +100 in a given context (what context? and who decides the list of all contexts?), especially since those ratings are public! It's just an awkward thing to do for a person. Some might do it for a product (still the minority), but that's an entirely different thing.

For what is worth, very soon @franzaps and I are going to share our approach to solve, not trust (which is vague), but "spamminess" and its opposite, relevance.

@papiche
Copy link
Author

papiche commented Jan 29, 2025

Hi @pippellia-btc thank you for the feedback!

You're absolutely right—prescribing a specific algorithm might overly constrain experimentation.

The proposed formula is expecting users to rate others on a scale of -100 to +100 that coud be awkward.
We can decouple the data structure from the algorithm. As kind 33 events can be related to specific user and publication more calculation models (filtered by categories or relative publisher trust) can be applied.

Concerning UX, clients could associate "trust signal" to actual user actions expressing mood level on a "Hate ↔ Love" scale. For example :

Mood Level Meaning Trust Value (Internal)
❤️ Love Fully trust & endorse +100
😊 Positive Positive opinion +50
👍 Like Good opinion +25
😐 Distrust Cautious, minor distrust -25
😠 Dislike Strong distrust -50
🤬 Hate Fully untrusted, block -100

It could also be associated with other "signals"
Follows → positive trust signal (+100)
Reports/Mutes → negative trust signal (-100)
Replies, zaps, or reposts → lightweight positive trust signals ...

The score is user categorized and capped between - 100 and +100 as the maximum value
then different formula could be applied by client to provide "trust estimated informations" to the user.

@papiche
Copy link
Author

papiche commented Jan 30, 2025

Trying to make a NIP-101 nostr client basic implementation
https://ipfs.copylaradio.com/ipfs/QmbWNu6oaHs1CWXoi99Fi7n7FTW444TgqC7Vah6FokhsUF/

code repo : https://github.com/papiche/NIP-101

@franzaps
Copy link
Contributor

@papiche Have you read previous discussion on WoT systems here in the NIPs repo? What are your thoughts on those?

@papiche
Copy link
Author

papiche commented Jan 30, 2025

@papiche Have you read previous discussion on WoT systems here in the NIPs repo? What are your thoughts on those?

No i don't, do you have some discussion to spot to me ?
But WoT is a central point in my work... I am actually working to introduce PGP and Duniter as "Proof Of Humanity" into nostr trafic ;) NIP-101 results as a need our community identified to produce a relative Human/Message (and Computer) trust meshing. Do you know https://duniter.org/libre-money/ ?

@staab
Copy link
Member

staab commented Jan 30, 2025

@papiche here's a relevant couple of episodes from my podcast that you might enjoy:

https://fountain.fm/episode/SJJKS7tr2WI9R4gaVXxO
https://fountain.fm/episode/aD6Jp6wGxOOitdqeaBii

@franzaps
Copy link
Contributor

@papiche Have you read previous discussion on WoT systems here in the NIPs repo? What are your thoughts on those?

No i don't, do you have some discussion to spot to me ? But WoT is a central point in my work... I am actually working to introduce PGP and Duniter as "Proof Of Humanity" into nostr trafic ;) NIP-101 results as a need our community identified to produce a relative Human/Message (and Computer) trust meshing. Do you know https://duniter.org/libre-money/ ?

This one for example: #1208

Nostr is permissionless, so you can build anything you want on it. It looks like you put quite some effort and your NIP looks interesting. I don't know how familiar you are with the process, or how new to nostr you are, but we have been debating web of trust for a long time. Just that don't expect this NIP to reach consensus soon, especially if you haven't yet considered other stakeholders' points of view.

I personally have a hard time seeing how these love/hate input signals get implemented and meaningful enough to derive any result from. With @pippellia-btc we're building Vertex, a service offering different trust metrics between nostr pubkeys.

@wds4
Copy link

wds4 commented Jan 30, 2025

I had a proposal years ago that was basically exactly this, but I don't think it will work anymore, it's too complex and most people won't bother. I don't know what is the solution.

Proposed WoT solutions virtually always get more and more complex until they collapse under their own weight, before even leaving the drawing board. Like a math problem that diverges to infinity every time we try to solve it. We gotta figure out how to normalize it to make the infinities go away, like Richard Feynman and colleagues back in the day.

One of the techniques that I propose as a way to solve our own infinities is what I call interpretation. I really need to write it up as a long form nostr post. But the down and dirty is this. Suppose you get an idea in your head of The Perfect WoT Algorithm. Algos need raw data, right? And the data needs to be in a format ready for digestion by the algo, right? So now we have two classes of data:

  • class 1 data: data that is perfectly formatted and ready for digestion by our also
  • class 2 data: all the data in the world that it accessible to us and maybe relevant to the problem we are trying to address, but unfortunately it is NOT in the desired format

In the fiat world, where all platforms are centralized, the platform devs have the luxury to impose class 1 = class 2.

But in the real world, the decentralized world where data is messy and not under our control, no one has (or should have) the power to set class 1 = class 2. The problem is that we haven't as a community figured that out yet, so we have solution after solution where we try to do the impossible, which is to set two things equal that simply cannot ever be equal. Which is why our solutions always blow up in our faces as draft NIPs before they even leave the drawing boards.

And so I propose that the only solution is to INTEPRET: we accept that class 1 data and class 2 data are NOT EQUAL and will NEVER BE EQUAL. Which means we write scripts to translate, i.e. interpret, whatever data we can find into a usable format. We write scripts that ingest class 2 data, spit out class 1 data, and feed class 1 data into our algos.

The best thing is that Alice and Bob are free to interpret the world in accordance with their own individual preferences, beliefs, and values.

That's it. That's the idea.

@wds4
Copy link

wds4 commented Jan 30, 2025

This one for example: #1208

I still love NIP-77! Why? because the format of NIP-77 was convenient for My Favorite WoT Algorithm: GrapeRank.

But as discussed above: by advocating for NIP-77, I was attempting to do the impossible: get all of nostr to generate data in a format convenient to me. But I was quickly convinced by many in the nostr space that it ain't gonna happen. People aren't gonna generate data in a particular format just bc I want them to. But they WILL generate LOTS of data in a myriad range of other formats. Data that is imperfect to my purposes because it's maybe only tangentially on topic, and it's often highly ambiguous. But we gotta learn to make do with what we got. Hence, the need to interpret.

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.

8 participants