Skip to content

ArcTrust Reputation via Social Graph and NIP 32

arkin0x edited this page Jun 21, 2023 · 2 revisions

Purpose

The NIP-32 label events on nostr can be noisy and spammy, but overlaying them onto your social graph can make sense of these ratings in the context of your personal web of trust.

ArcLib will implement features for indexing a user's own social graph in the ArcadeSocial class, querying it for distances between the user and a given pubkey, querying the relay pool for NIP-32 events labeling a given pubkey, and determining the overall reputation of the pubkey for any label (such as trade for scores related to ArcTrade). Implementing this inside of Arcade as a client-side reputation feature will be our first proof of concept. Work on this can be followed here: https://github.com/ArcadeLabsInc/arclib/pull/22

ArcTrust is the next step: a remote API that crawls and indexes the nostr social graph and may be called to retrieve personalized social graph data to easily mark pubkeys in Arcade with reputation scores relative to the user.

If ArcTrust is developed in this way, it could be turned into a monetized API that other apps can pay for. This data enables other apps to provide easy, visual indicators for how trusted a given user is based on their users' personal social graph.

Rating Others

A rater may use a NIP-32 event to rate an evaluee (some pubkey).

{
  id: "..."
  pubkey: "..."
  created_at: ...
  kind: 1985
  tags: [
    ["L","city.arcade"],
    ["l","trade","city.arcade","{\"quality\":0.75}"],
    ["p","<evaluee pubkey>"],
    ["e","<optional trade eventid>"]
  ]
  content: "<optional review>"
}

ArcLib's Social module collects these 1985 events, filtered by nomenclature ["L","city.arcade"] and optionally by label ["l","trade"] to calculate a reputation score.

If the rater would like to change, add to, or remove their ratings for a given pubkey, they may simply publish a new kind 1985. The most recent kind 1985 for a given author should be considered the only valid rating. Instead of using parameterized replaceable events, regular events can be aggregated to visualize a user rating delta and history is not lost.

Arcade City Nomenclature

Ratings can be for anything, but MUST be either a verb (bare infinitive, no "-ing") or noun (singular).

Official nomenclature includes:

  • trade: quality between 0 and 1 representing the evaluee's desirability as a counterparty.

The "L" namespace tag must be city.arcade to specify this nomenclature.

Calculating Reputation

We want to find out the reputation of a given user, our evaluee, represented by a pubkey.

  1. Collect all 1985 rating events for the evaluee pubkey, optionally filtered by nomenclature L and/or label l:
// in this example we are evaluating a user's `trade` rating.
filter: {
  kinds: [1985],
  "#p": ["<evaluee pubkey>"],
  "#L": ["city.arcade"],
  "#l": ["trade"]
}
  1. For each event author, filter only the most recent event by created_at. The following steps only operate on the remaining events.
  2. For each event, parse the quality as a float as score. Discard events with unparseable values or values outside of 0-1 range.
  3. For each event, get the social graph distance between yourself and the event author as distance. If the distance is not known or calculable, the distance is set to 3.
  4. For each event, calculate ( 1 / distance ** 2 ) as weight. If distance is 0 (you to yourself), weight is set to 10_000.
  5. For each event, calculate weight * score as scaledScore.
  6. Calculate the sum of all weights as weightSum
  7. Calculate the sum of all scaledScores as scaledScoreSum
  8. Calculate scaledScoreSum / weightSum as weightedAverageScore.
  9. The weightedAverageScore is the social graph reputation of the rating.

Social Graph Distance

You have 0 distance to yourself.

You have 1 distance from any pubkey you follow ("friends").

You have 2 distance from any pubkey you don't follow but your friends do follow.

You have 3 distance if your friends do not follow. 3 is the maximum distance. If the pubkey is not in the graph, they get a distance of 3 automatically.

Building a social graph to accommodate this only requires a depth of 2 (level 1 is your friends, level 2 is who your friends follow). Building a social graph deeper than 2 levels is unnecessarily expensive for negligible gain.

Todo

  • decide if we should use a city.arcade nomenclature to establish a standard or use something more generalized so that ratings from other apps come across. How likely is it that we all use the same label if we don't adopt a specific nomenclature? 🤔