Note A NIP PR has been open here, the conversation should move to the PR
Ratings give the reputation for a person, service or product. They are important for creating an open and free-market. It helps participants make decisions based on what their peers previously experienced with that person, services or product.
Having a rating system in an open and decentralized system (like nostr
) is hard because anyone can join and give ratings.
Thus bots will be created to overtake the honest human's votes.
Some solutions have been proposed for this problem, but none of them is satisfactory (see first comment).
In order to avoid spam, each rating must have associated with it the proof that a tiny fee has been paid. The fee should not be paid to a centralized service that can cheat (see first comment), but to an impartial, decentralized system (like the bitcoin blockchain).
A user can register its public key
in a Merkle tree and the root of the tree is then persisted (by a specialized service) on the bitcoin blockchain using the OP_RETURN
operator (thus paying a fee). Similarly with what open-timestamps does.
If the public key
is registered as the root of the tree then the rating mass
is 1
, if it is registered on the second level then the rating mass
is 1/2
(there can be two leaves). The lower one goes in the tree, the more leaves it can register, but also the less each leaf is worth (rating mass
is 1/2
n
where n
is the depth - starting at 0
).
The properties of the tree are:
- Each leaf is of the form:
[<tree-level>, <leaf-index>, <public-key>]
. - Leaves can exist at any level. The closer to the tree root a leaf is, the more valuable it is.
Highlighted in the image is the path to leaf [4, 0, a728...]
which is composed of 4
elements: [hash([4,1,a728...]), H2, H7, H9]
. This path has a rating mass
of 1/4
.
For the above example (image), the public key a728...
(yellow rectangles) has purchased 9 rating options
with a total mass of 0.8125
(2 * 1/2
2
+ 2 * 1/2
4
+ 4 * 1/2
5
), whereas public key 1acf...
(purple rectangles) has purchased 3 rating options
with a mass of 0.1875
(3 * 1/2
4
). The total mass of the tree will always be 1
(eg: 0.8125 + 0.1875
), because everybody knows that 1+2+4+⋯+2
𝑛
= 2
𝑛+1
- 1
.
The rating value
can be an integer between 1 and 5
, or it can be a float between 0 and 1
(see this NIP-32 PR), or any other rating system.
The rating mass
represents the importance or intensity that a user gives to a particular rating. It also guarantees that the rating is not spam.
For example I might dislike a film and give it a rating value
of 2 stars
and a rating mass
of 0.03125
(consume a leaf on level 5
of the tree: 1/2
5
). Or I might dislike that the Uber driver just dropped me off in a bad neighborhood and give it a rating value
of 2 stars
, but a rating mass
of 0.5
(consume a leaf on level 1
of the tree: 1/2
1
, more intense).
Ratings in nostr
can be achieved by publishing a particular event (see this NIP-32 PR to get an idea of how the event could look like) and attaching a rating mass
to the event.
This rating event should be a Parameterized Replaceable Events (NIP-33) and have these additional tags representing the rating mass
:
{
"kind": 30030,
"pubkey": <public key of the event creator>,
"tags": [
["tx-id", <id of the transaction where the `OP_RETURN` was included>],
["output-index", <index of the `OP_RETURN` output>],
["leaf", <tree-level>, <leaf-index>, <public-key of the event creator>],
["leaf-path", <hash1>, <hash2>, ...],
["d", <hash(tx-id, output-index, <tree-level>, <leaf-index>, <public-key>, <hash1>, <hash2>, ...)>],
...
],
"content": "...",
...
}
The d
tag is the most important one because it aggregates all the other values and because it is the one used to replace the NIP-33 event. This means that the same leaf
cannot be used in two different rating events. Trying to reuse the leaf
will simply replace the previous rating event. On the other hand, if I have "consumed" one of my ratings for liking a song that I later discover it was plagiarised then I can take that rating back and reuse it one something else.
Note The
public key
in theleaf
must be the same as thepublic key
of the event creator.
Note Rating events without a
rating mass
or which have a very long path (are almost free) should not be taken into consideration
-
detailed doc for the tree structures
-
create a services that allows users to buy
rating mass
- the user selects the levels it wants to register it public key at
- the services computes the cost
- the user pays the invoice and receives the full tree
-
create a service that computes ratings based on the
rating mass
assigned to each rating event- this can be part of the relay, or a standalone service
-
integrate with social media clients, market clients, etc
Other suggested solutions for ratings (and their limitations):
Use proof-of-work
nostr
network (relays) would have to do difficulty adjustment as devices get more powerfulImport reputation
Importing reputation from a centralized system (like Twitter) has some problems:
nostr
.Dedicated centralized reputation servers
Micropayments
A user can make a small lightning payment to show its appreciation. Unfortunately the system can be gamed and the reciever can just pay itself with almost no cost (except routing fees)