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 26 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 algo
  • 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.

@papiche
Copy link
Author

papiche commented Jan 31, 2025

@wds4,

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

You're absolutely right. In a peer-to-peer information system, each user operates from their own relative "point of view." This is a fundamental aspect of decentralization, where no single entity controls the narrative or the data.

P2Pmesh

Your idea of interpretation as a way to bridge the gap between "class 1" (perfectly formatted data) and "class 2" (messy, real-world data) is particularly insightful. This concept resonates with what we might call N1 (friends) and N2 (friends of friends) informational social polyhedrons. These layers of trust and interaction allow users to navigate the network based on their own relationships and preferences.

As you noted, achieving consensus on Web of Trust (WoT) systems is inherently challenging. The most notable historical example is PGP, which struggled to maintain consistency beyond 100,000 members. This is largely due to the CAP Theorem (Consistency, Availability, Partition Tolerance), which highlights the trade-offs in distributed systems. In a decentralized network like Nostr, we must accept that fragmentation and differing perspectives are natural outcomes of a permissionless, P2P architecture.

People aren't gonna generate data in a particular format just bc I want them to.

This is a crucial point. NIP-101 is designed to provide a base layer for establishing relative trust between users and messages through categories. However, its success depends on client adoption and the generation of Kind 33 events. To address this, I’ve started prototyping a strfry plugin that intercepts regular client events and translates them into Kind 33 trust events. For example:

  • A follow (Kind 3) could generate a Kind 33 event with a +100 rating, tagged with ["category", "social"].
  • A mute (Kind 10000) could generate a Kind 33 event with a -100 rating, tagged with ["category", "social"].
  • A reply (Kind 1) or zap event (Kind 9735) could generate a +10 trust signal, tagged with ["category", "interaction"].

By automatically generating trust signals based on user actions, clients can use these events to calculate a relative trust horizon for each user. This allows clients to apply their own formulas and algorithms to provide personalized trust metrics, tailored to individual choices.

In parallel, we are exploring the correlation of this scoring system with the Ğ1 token, a decentralized cryptocurrency built on the Duniter protocol. The Ğ1 token leverages a Proof of Humanity (PoH) mechanism, which uses a Web of Trust to certify unique human identities. This system ensures that each certified human creates the same amount of tokens daily, promoting fairness and reducing the risk of noisy or manipulative behavior.

@wds4
Copy link

wds4 commented Jan 31, 2025

I’ve started prototyping a strfry plugin that intercepts regular client events and translates them into Kind 33 trust events. For example:

  • A follow (Kind 3) could generate a Kind 33 event with a +100 rating, tagged with ["category", "social"].
  • A mute (Kind 10000) could generate a Kind 33 event with a -100 rating, tagged with ["category", "social"].
  • A reply (Kind 1) or zap event (Kind 9735) could generate a +10 trust signal, tagged with ["category", "interaction"].

By automatically generating trust signals based on user actions, clients can use these events to calculate a relative trust horizon for each user. This allows clients to apply their own formulas and algorithms to provide personalized trust metrics, tailored to individual choices.

Cool! My app, which you can try out here, currently translates follows and mutes into a GrapeRank "rating" where a follow is a score of 1 carrying a relative weight ("confidence") of 3, and a mute is a score of 0 carrying a relative weight of 50. In both cases, the rating context is "real nostr user." These ratings are then fed into the GrapeRank algorithm to produce a score between 1 (verified "real nostr user") and 0 (not verified).

Now, we could get into a long and tiresome debate leading nowhere over whether the score should range from 0 to 1 (my preference) or from -100 to + 100 (your preference). But the notion of interpretation saves us from that debate. It allows us to acknowledge that there is no one-size-fits-all interpretation. We can do both: we can interpret using my method when we want to use the GrapeRank algo, and interpret using your method when using a different algo. We can play around with the interpretation and optimize it along with our algos at the same time. Meanwhile, the nostr ecosystem continues to churn out follows and mutes, formatted according to NIPs that can be optimized to good UX, unrestricted by our ever-changing ideas about what we're going to do with the data.

And of course we're not limited to follows and mutes. Interpretation allows us to use whatever data is available to us: Reports, replies, reactions, zaps, badges, labels, the list is endless.

@wds4
Copy link

wds4 commented Jan 31, 2025

I’ve started prototyping a strfry plugin

Nice. One of my upcoming projects is going to be to pair strfry with neo4j, probably the most mature FOSS graph database, and build a personalized WoT relay. It will use interpretation to ingest whatever data is available and best suited for calculation of various WoT scores and will use those scores to manage strfry filters and plugins. In this way, you will have exquisite control over which events you request (filters) and which you discard (plugins). If NIP-101 data is available, GrapeRank will have the ability to make use of it.

In parallel, we are exploring the correlation of this scoring system with the Ğ1 token, a decentralized cryptocurrency built on the Duniter protocol.

You probably already know this: talk about new cryptos will be seen as a red flag by many. But the great thing about nostr is that you don't need anyone's permission to build what you want!

@papiche
Copy link
Author

papiche commented Feb 1, 2025

@wds4,
Your app is fantastic! It’s clear that GrapeRank’s approach to translating follows and mutes into trust scores is both elegant and effective. The message “downloading data from the Brainstorm server (big file; may take up to a minute)” suggests that the app is fetching a large dataset of Nostr relationships to perform its calculations. This highlights the computational challenges of handling complex trust calculations in a decentralized network.

GrapeRank’s binary approach (real vs. not real) is excellent for spam prevention and identity verification, while NIP-101’s Kind 33 events enable nuanced, context-specific trust metrics (e.g., social trust vs. expertise in a topic).

As you’ve pointed out, our “score range expressions” are compatible:

  • (1/0) in GrapeRank is analogous to (+/-) in NIP-101.
  • Relative weight in GrapeRank is similar to rating in NIP-101.

The key difference lies in how these scores are interpreted and used:

  • GrapeRank focuses on binary verification (real vs. not real).
  • NIP-101 focuses on nuanced, context-specific trust metrics.

This flexibility allows clients to choose the method—or a hybrid of methods—that best suits their needs.

The Role of Ğ1 Proof of Humanity (PoH)

By linking Nostr pubkeys to Ğ1 smith keys, we introduce verified identities that can serve as a foundation for trust. The Ğ1 system rewards each verified user with a fixed amount of tokens daily, creating an economic incentive for meaningful participation and reducing noisy behavior.

Those Verified identities allow us to rely less on computationally intensive WoT algorithms like GrapeRank. Ğ1’s PoH enhances the reliability of Kind 33 ratings, making them more effective for content filtering and trust-based interactions (limited to N1/N2)


N1/N2 Visual Exploration App

A visual, intuitive interface could makes it easier for users to navigate their social connections.

I imagine an interface that places you at the center of his social universe. With cards arranged like constellations. The goal is to offer a clear and personal view where user is the explorer.

Each person you follow or who follows you is represented by a unique card, a little portrait of who they are, what they talk about. The border colors—green, blue can indicate the type of relationship you have with them.

  • Green: P2P (Follow + Followed)
  • Blue: 12P (Follow + Unfollowed)
  • Yellow: P21 (Unfollow + Followed)

Clicking on one of these faces opens another level, exploring a circle of friends of friends. The data you see is categorized to help you navigate easily, with categories and trust scores, a bit like a compass that guides you through this social labyrinth.


By combining GrapeRank’s binary verification, Ğ1’s proof-of-humanity, and NIP-101’s nuanced trust metrics, I think we can create a comprehensive trust system that enhances the Nostr ecosystem.

Let’s continue collaborating to make this vision a reality!

Copy link
Collaborator

@Semisol Semisol left a comment

Choose a reason for hiding this comment

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

Why does this feel AI generated?

@wds4
Copy link

wds4 commented Feb 7, 2025

Why does this feel AI generated?

I agree it does. Good question.

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.

9 participants