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

add nip 23: relays list. #32

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 93 additions & 0 deletions 23.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
NIP-23
======

Relays List
-----------

`draft` `optional` `author:fiatjaf` `author:cameri` `author:monlovesmango` `author:giszmo`

A special event with kind `10001`, meaning "relay list" is defined as having a list of tags, one for each relay the author uses.

The content is not used.

The tags consist of arrays of 3 elements: the first is the relay URL, the second is the _read_ condition, the third is the _write_ condition.

The _read_ condition consists of a string containing a rule that follows a subset of the [runes](https://pypi.org/project/runes/) language. Specifically only the `|`, `&`, `!`, `>`, `<`, `/` and `=` operators are allowed. When the rule is an empty string it evaluates to `true`. All the operators must be tested against all possible values in the case of filter values that consist of lists of values and also in the case of event tags that can have multiple values for the same tag -- in other words, the `=` may be interpreted as a `values.any(v => v == runeValue)` instead of an `values == runeValue` operator; the `<` may be interpreted as a `values.any(v => v < runeValue)` and so on. Event tags are identified just by their tag key (for example, `e` or `p`) without the `#` prefix used in filters.
Copy link
Member

Choose a reason for hiding this comment

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

Why not include starts-with and ends-with from runes? Would make rules more compact with hardly any false positives and using libraries, implementers wouldn't care.

Copy link
Member

Choose a reason for hiding this comment

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

I agree, please add starts with. For Ends with I can't think of a use case right now.

Copy link
Member Author

Choose a reason for hiding this comment

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

Sure.

Copy link
Member

Choose a reason for hiding this comment

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

@cameri endsWith because proof of work in event IDs makes the start less attractive to use as a short identifier.

Copy link
Member

Choose a reason for hiding this comment

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

should we mention here that the underscore _ is an allowed identifier? It's needed for created_at

Copy link
Contributor

Choose a reason for hiding this comment

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

@fiatjaf bumping this


The `read` rule operates on the values of the [NIP-01](01.md) **filter** object, while the `write` rule operates on the values of the **event** object.

When a `read` rule evaluates to `false` for a given **filter** the client SHOULD NOT send that filter in a `REQ` message to that relay.

When a `write` rule evaluates to `false` for a given **event** the client SHOULD NOT send that event in an `EVENT` message to that relay.

When a rule is malformed or the client is unable to parse it for any reason (for example, for not having implemented all the operators) it SHOULD treat it as `true` if it is a _read_ rule and `false` if it is a _write_ rule.
Copy link
Member

Choose a reason for hiding this comment

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

This needs some justification I think.

Copy link
Member Author

Choose a reason for hiding this comment

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

I can't justify it to myself even. It's probably better to just default to false or leave it for the client to decide. I don't know.

Copy link
Member

Choose a reason for hiding this comment

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

Can we delete this phrase then?

Copy link
Member

Choose a reason for hiding this comment

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

I think we should remove this. If a client implements this NIP it must handle rules properly.


### Purposes

This NIP serves two purposes: (1) backup and interoperability of relay lists and relay specific rules between clients; and (2) sharing of relay URLs between users.

The first use case is meant to make it so users can open their client -- or different clients -- in different devices and have their list of relays automatically fetched from a default relay and start using their relays list without having to set everything up again.

For the second purpose, if any client decides to, they can show to the user what relays other users are using, suggest that or automatically add these to the user's relay list, this can take into account the rules or more likely not. The possibility of sharing a list of relays in standardized format is good for spreading information about relays and contributes to the censorship-resistance of the network.

### Use cases

A client can expose to the user a set of premade rule templates (the user doesn't have to see the rules) for common relay policies, for example:
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure what damus would do with these... I should trust my friends to make filtering decisions for me or something?


- "do not use this relay for DMs": sets _write_ to `kind/4`
- "only use this relay for DMs": sets _write_ to `kind=4` and _read_ to `kinds=4`
- "this is Bob's personal relay, only use it to fetch Bob's events": sets _write_ to `!` and _read_ to `authors=<bob-pubkey>`
- "this relay is full of spambots, do not get note replies from this relay": sets _read_ to `kinds=1&e!|kinds/1`
- "this is my personal relay, only store my stuff in it": sets _read_ to `authors=<my-pubkey>` _write_ to `pubkey=<my-pubkey>`

### Examples

(Public keys are shortened to 4 characters for readability.)

- Rule evaluation examples:

- _read_

- for the filter `{"kinds": [0, 1, 2, 3], "authors": ["abcd", "1234"]}`

- `<empty>`: `true`
- `!`: `invalid` -> `true`
- `zjhcxb`: `invalid` -> `true`
- `false`: `invalid` -> `true`
- `true`: `invalid` -> `true`
- `authors=7890`: `false`
- `authors=7890|authors=1234`: `true`
- `authors=7890&authors=1234`: `false`
- `e!`: `true`
- `e=5555`: `false`
- `kinds=1|kinds=4`: `true`
- `kinds<2`: `true`
- `kinds>7`: `false`
- `kinds=1|kinds=7&authors=8543|authors=1234`: `true`

- _write_

- for the event `{"kind": 7, "content": "banana", "tags": ["p", "6677"], "created_at": 123456789, "pubkey": "e3e3"}`

- `<empty>`: `true`
- `!`: `invalid` -> `false`
- `7237237`: `invalid` -> `false`
- `****`: `invalid` -> `false`
- `pubkey=7890`: `false`
- `pubkey=e3e3`: `true`
- `kind=7&p=6677`: `true`
- `created_at>999999999|e=5a5a`: `false`

- Full example of a kind 10001 event:

```json
{
"kind": 10001,
"tags": [
["wss://alicerelay.com/", "", ""],
["wss://bobrelay.com/", "authors=ef87", "!"],
["wss://carolrelay.com/", "", ""],
],
"content": "",
...other fields
```
20 changes: 11 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,21 @@ NIPs stand for **Nostr Implementation Possibilities**. They exist to document wh
- [NIP-14: Subject tag in text events.](14.md)
- [NIP-15: End of Stored Events Notice](15.md)
- [NIP-16: Event Treatment](16.md)
- [NIP-23: Relays List](23.md)
fiatjaf marked this conversation as resolved.
Show resolved Hide resolved
- [NIP-25: Reactions](25.md)

## Event Kinds

| kind | description | NIP |
|------|---------------------------|------|
| 0 | Metadata | 1, 5 |
| 1 | Text | 1 |
| 2 | Recommend Relay | 1 |
| 3 | Contacts | 2 |
| 4 | Encrypted Direct Messages | 4 |
| 5 | Event Deletion | 9 |
| 7 | Reaction | 25 |
| kind | description | NIP |
| ------ | --------------------------- | ------ |
| 0 | Metadata | 1, 5 |
| 1 | Text | 1 |
| 2 | Recommend Relay | 1 |
| 3 | Contacts | 2 |
| 4 | Encrypted Direct Messages | 4 |
| 5 | Event Deletion | 9 |
| 7 | Reaction | 25 |
| 10001 | Relays List | 23 |

Please update this list when proposing NIPs introducing new event kinds.

Expand Down