yet another new nip-01, hopefully this is good now.

pull/17/head
fiatjaf 2021-02-14 21:42:59 -03:00
rodzic 62dfb5f565
commit 33a1a70e6e
1 zmienionych plików z 44 dodań i 20 usunięć

Wyświetl plik

@ -6,9 +6,13 @@ Basic protocol flow description
`draft` `mandatory`
This NIP defines the basic protocol that should be implemented by everybody. New NIPs may add new optional (or mandatory) fields and messages and features to the structures and flows described here.
1. Each user has a keypair. Signatures, public key and encodings are done according to the [Schnorr signatures standard for the curve `secp256k1`](https://bips.xyz/340).
2. The single object type that exists is the `event`, which has the following format on the wire:
### Events and signatures
Each user has a keypair. Signatures, public key and encodings are done according to the [Schnorr signatures standard for the curve `secp256k1`](https://bips.xyz/340).
The single object type that exists is the `event`, which has the following format on the wire:
```
{
id: <32-bytes sha256 of the the serialized event data>
@ -24,7 +28,9 @@ Basic protocol flow description
sig: <64-bytes signature of the sha256 hash of the serialized event data, which is the same as the "id" field>,
}
```
3. To obtain the `event.id`, we `sha256` the serialized event. The serialization is done over the UTF-8 JSON-serialized string (with no indentation or extra spaces) of the following structure:
To obtain the `event.id`, we `sha256` the serialized event. The serialization is done over the UTF-8 JSON-serialized string (with no indentation or extra spaces) of the following structure:
```
[
0,
@ -35,29 +41,47 @@ Basic protocol flow description
<content>, as a string
]
```
4. Users can connect to any compatible relay by opening a WebSocket connection to `<relay_url>/ws`. The WebSocket accepts the following messages (each of them should trigger a different action):
* `sub-key:<pubkey, as a hex string>`, subscribes to events from this key (a client will do this for every key it is "following"). It instructs the relay to send event messages for every new event it sees from this key;
* `unsub-key:<pubkey, as a hex string>`, as above, but unsubscribes ("unfollow"), the opposite of the previous;
* `req-feed:<{limit, offset}, object with these optional parameters>`, requests the latest events from the pubkeys subscribed to above (the basic flow is to open a WebSocket, call `sub-key` many times, then call `req-feed`). Upon receiving this, the relay should gather the latest events from all the keys this WebSocket client has subscribed to with `sub-key` and send them as event messages.
* `req-event:<{id, limit}, object with the event id and optional parameters>`, requests an event specifically and other events related to it ("browse a thread").
* `req-key:<{key, limit, offset}, object with the pubkey and optional parameters>`, requests one pubkey specifically ("browse a user profile").
* `<event, in object format as noted above>`, publishes an event.
5. The WebSocket will emit two types of messages:
* `[<event>, <context>]`, a JSON array containing an event object and the context in which it is being emitted. The `<context>` is a string with a single letter, which can be:
* "p": Used with events the relay has requested with `req-feed`.
* "n": Used when a new event is received by the relay and propagated to the client which has subscribed to it with `sub-key`.
* "r": Used for events sent in response to `req-event` or `req-key`.
* `["notice", <string>]`, a notice from the relay (either an error message or something else the relay wants to communicate).
6. There are three types of events a user can publish (other NIPs may define different types):
### Communication between clients and relays
Relays expose a websocket endpoint at its domain under the `/ws` path (say, `ws(s)://relay.domain/ws`) to which clients can connect.
Clients can send either 3 types of messages, according to the following patterns:
* `EVENT <event JSON as defined above>`, used to publish events.
* `REQ <id> <filter JSON>...`, used to request events and subscribe to new updates.
* `CLOSE <id>`, used to stop previous subscriptions.
`<id>` is a random string that should be used to represent a subscription. The same
`<filters>` is a JSON object that determines what events will be sent in that subscription, it can have the following attributes:
```
{
"id": <the id of an event>,
"author": <the pubkey of an event that identifies its author>,
"#e": <an event id that is referenced in an "e" tag>,
"#p": <a pubkey that is referenced in a "p" tag>,
"since": <a timestamp, events must be newer than this to pass>,
"authors": <a list of pubkeys, the pubkey of an event must be one of these>
}
```
Upon receiving a `REQ` message, the relay MUST query its internal database and return events that match the filter, then store that filter and send again all future events it receives to that same websocket until the websocket is closed, the `CLOSE` event is received withe same `<id>` or a new `REQ` is sent using the same id, in which case it should overwrite the previous subscription.
All conditions of a filter that are specified must be valid for an event for it to pass the filter, i.e., multiple conditions are interpreted as `&&` conditions.
A `REQ` message may contain multiple filters. In this case events that match any of the filters are to be returned, i.e., multiple filters are to be interpreted as `||` conditions.
### Basic Event Kinds
- `0`: `set_metadata`: the `content` is set to a stringified JSON object `{name: <string>, about: <string>, picture: <url, string>}` describing the user who created the event. A relay may delete past `set_metadata` events once it gets a new one for the same pubkey.
- `1`: `text_note`: the `content` is set to the text content of a note (anything the user wants to say).
- `2`: `recommend_server`: the `content` is set to the URL (e.g., `https://somerelay.com`) of a relay the event creator wants to recommend to its followers.
7. A relay may choose to treat different message kinds differently (for example, instead of just returning the newest events for a given profile on `req-key` it can choose to always return the latest `set_metadata` event it has even if that is very old, so the client can always see a name and picture when browsing a profile), or apply any arbitrary filtering criteria it desires to the kinds of events it will accept.
---
### Notes:
### Other Notes:
- Clients should not open more than one websocket to each relay. It also is advised that clients do not open more than 3 subscriptions to the same relay. 3 is enough for most use cases and relays should impose limits to prevent over usage by clients.
- The `tags` array can store any kind of tag the message may be related to. This NIP defines `"p"` — meaning "profile", which points to a pubkey of someone that is referred to in the event —, and `"e"` — meaning "event", which points to the id of an event this event is quoting, replying to or referring to somehow.
- The `<recommended relay URL>` item present on the `"e"` and `"p"` tags is an optional (could be set to `""`) URL of a relay the client could attempt to connect to fetch the tagged event or other events from a tagged profile. It MAY be ignored, but it exists to increase censorship resistance and make the spread of relay addresses more seamless across clients.
- If a message contains an @-prefixed readable name in the body of it — for example, _"hello @bob and @carol"_ — and then 2 or more `"p"` tags, the client MAY replace the text of "@bob" and "@carol" with links to the 2 `"p"` pubkeys, in the order they're found. Or it MAY just show the list of tags somewhere on the side of the note.