This commit is contained in:
Vitor Pamplona 2024-01-03 12:06:12 -05:00
parent c4cc963abc
commit 2c0b534ee1

59
01.md
View File

@ -6,11 +6,11 @@ Nostr Protocol
`draft` `mandatory` `draft` `mandatory`
This NIP defines the complete protocol that MUST be implemented by everybody. New NIPs may add new optional (or mandatory) fields, messages and features to the structures and flows described here. This NIP defines the complete protocol that MUST be implemented by everybody. New NIPs may add new optional (or mandatory) fields, messages, and features to the structures and flows described here.
# Events # Events
Event is only object type available. It is a hashed and signed payload with the following format: Event is the only object type available. It is a hashed and signed payload with the following format:
```json ```json
{ {
@ -43,7 +43,7 @@ To obtain the hash `.id`, we `sha256` the UTF-8 bytearray of a JSON-serialized s
``` ```
The JSON serialization MUST follow this rules: The JSON serialization MUST follow this rules:
- Minified: No whitespace, line breaks or other unnecessary formatting used - Minified: No whitespace, line breaks, or other unnecessary formatting used
- Escape Set: ONLY the following characters MUST be escaped: - Escape Set: ONLY the following characters MUST be escaped:
- line break, `0x0A`, as `\n` - line break, `0x0A`, as `\n`
- double quote, `0x22`, as `\"` - double quote, `0x22`, as `\"`
@ -61,7 +61,7 @@ To verify an event:
The `.kind` property specifies the meaning of an event and its tags. The `.kind` property specifies the meaning of an event and its tags.
Specific ranges define storage behaviours: Specific ranges define storage behaviors:
| Name | Range | SHOULD retain | | Name | Range | SHOULD retain |
| ------------- | --------------------------------- | ------------------------------------------------------ | | ------------- | --------------------------------- | ------------------------------------------------------ |
@ -79,51 +79,38 @@ This NIP defines two kinds:
## Tags ## Tags
Each tag is an array of strings of arbitrary size. Their meaning is determined by the event `.kind` and defined in NIPs in this repository. Tags with the same name might have entirely different meanings in diferent kinds. Each tag is an array of strings of arbitrary size. Their meaning is determined by the event `.kind` and defined in NIPs in this repository. Tags with the same name might have entirely different meanings in different kinds.
```json
{
...,
"tags": [
["e", "5c83da77af1dec6d7289834998ad7aafbd9e2191396d75ec3cc27f5a77226f36", "wss://nostr.example.com"],
["p", "f7234bd4c1394dda46d09f35bd384dd30cc552ad5541990f98844fb06676e9ca"],
["a", "30023:f7234bd4c1394dda46d09f35bd384dd30cc552ad5541990f98844fb06676e9ca:abcd", "wss://nostr.example.com"],
["alt", "a description of this event"],
...
],
...
}
```
The first element of the tag array is referred to as the tag _name_ or _key_ and the second as the tag _value_. All elements after the second do not have a conventional name. The first element of the tag array is referred to as the tag _name_ or _key_ and the second as the tag _value_. All elements after the second do not have a conventional name.
This NIP defines the format of 3 standard tags that can be used across all event kinds: All single-letter (only English alphabet letters: a-z, A-Z) key tags are indexed by relays for faster queries.
- The `e` tag refers to an event: `["e", <32-byte lowercase hex of the id of another event>, <recommended relay URL, optional>]` This NIP defines the format of 3 standard tags: `e`, `p`, and `a`. `e`, `p` can be used to reference events and pubkeys, and `a` references the latest version of a replaceable event, parameterized or not.
- The `p` tag refers to a pubkey: `["p", <32-byte lowercase hex of a pubkey>, <recommended relay URL, optional>]`
- The `a` tag refers to a replaceable event
- for a parameterized replaceable event: `["a", <kind integer>:<32-byte lowercase hex of a pubkey>:<d tag value>, <recommended relay URL, optional>]`
- for a non-parameterized replaceable event: `["a", <kind integer>:<32-byte lowercase hex of a pubkey>:, <recommended relay URL, optional>]`
All single-letter (only english alphabet letters: a-z, A-Z) key tags indexed by relays for faster queries. | Name | Value | Other Params | Description |
| ---- | ---------------------------------------------------------- | ------------------------ | ----------------------------------------- |
| `e` | `<32-byte lowercase hex of an event id>` | `<relay URL, optional>]` | |
| `p` | `<32-byte lowercase hex of a pubkey>` | `<relay URL, optional>]` | |
| `a` | `<kind>:<32-byte lowercase hex of a pubkey>:` | `<relay URL, optional>]` | |
| `a` | `<kind>:<32-byte lowercase hex of a pubkey>:<d-tag value>` | `<relay URL, optional>]` | |
# Relay Protocol # Relay Protocol
Nostr has two main components: Clients & Relays. Users run a client to fetch/subscribe to events from one or more Relays via websockets. Relays are not expected to communicate with one another. It's the Client's responsibility to discover which relay has the event set their user wants to see. Both sides SHOULD verify the hash and the signature of each event upon receipt. Nostr has two main components: Clients & Relays. Users run a client to fetch/subscribe to events from one or more Relays via WebSockets. Relays are not expected to communicate with one another. It's the Client's responsibility to discover which relay has the event set their user wants to see. Both sides SHOULD verify the hash and the signature of each event upon receipt.
Clients SHOULD open a single websocket connection to each relay and use it for all their subscriptions. Relays MAY limit number of connections from specific IP/client/etc. All messages are defined as JSON arrays. Clients SHOULD open a single WebSocket connection to each relay and use it for all their subscriptions. Relays MAY limit the number of connections from specific IP/client/etc. All messages are defined as JSON arrays.
## Subscriptions ## Subscriptions
Clients send a **subscription** message with one or more filters. The Relay MUST query its database, return all events that match the filter and keep applying the filter to all connections, returning new events as they arrive. Subscriptions stay indefinatelly open until either side closes the subscription or the connection. Clients send a **subscription** message with one or more filters. The Relay MUST query its database, return all events that match the filter, and keep applying the filter to all connections, returning new events as they arrive. Subscriptions stay indefinitely open until either side closes the subscription or the connection.
### Subscription Requests ### Subscription Requests
To open, update and close subscriptions, Clients MUST use the following formats: To open, update, and close subscriptions, Clients MUST use the following formats:
* `["REQ", <subscription_id>, <filter1>, <filter2>, ...]`, used to request events and subscribe to new updates. * `["REQ", <subscription_id>, <filter1>, <filter2>, ...]`, used to request events and subscribe to new updates.
* `["CLOSE", <subscription_id>]`, used to stop previous subscriptions. * `["CLOSE", <subscription_id>]`, used to stop previous subscriptions.
`<subscription_id>` is an non-empty string with maximum length of 64 chars. Relays MUST manage `<subscription_id>`s independently for each WebSocket connection. `<subscription_id>`s are not globally unique. A `REQ` message on an existing subscription overwrides the previous subscription. `<subscription_id>` is a non-empty string with a maximum length of 64 chars. Relays MUST manage `<subscription_id>`s independently for each WebSocket connection. `<subscription_id>`s are not globally unique. A `REQ` message on an existing subscription overrides the previous subscription.
`<filterX>` is a JSON object that determines what events will be sent in that subscription, it can have the following attributes: `<filterX>` is a JSON object that determines what events will be sent in that subscription, it can have the following attributes:
@ -143,13 +130,13 @@ A `REQ` message may contain multiple filters which are interpreted as an OR stat
Properties in each filter are a logical AND statement: all present properties must match for the filter to pass. Properties in each filter are a logical AND statement: all present properties must match for the filter to pass.
Array properties (i.e., `ids`, `authors`, `kinds` and tag filters) represent a logical OR statement. At least one of the arrays' values must match the respective field in the event to be considered a match. In the case of tag attributes such as `#e`, for which an event may have multiple values, the event and filter condition values must have at least one item in common. Array properties (i.e., `ids`, `authors`, `kinds`, and tag filters) represent a logical OR statement. At least one of the arrays' values must match the respective field in the event to be considered a match. In the case of tag attributes such as `#e`, for which an event may have multiple values, the event and filter condition values must have at least one item in common.
The `ids`, `authors`, `#e` and `#p` filter lists MUST contain exact 64-character lowercase hex values. The `ids`, `authors`, `#e`, and `#p` filter lists MUST contain exact 64-character lowercase hex values.
The `since` and `until` properties are used to specify the time range of events returned in the subscription. An event matches the filter if `since <= created_at <= until` holds. The `since` and `until` properties are used to specify the time range of events returned in the subscription. An event matches the filter if `since <= created_at <= until` holds.
The `limit` property operates over the stored events and is ignored afterwards. The `limit` property operates over the stored events and is ignored afterward.
### Receiving Events ### Receiving Events
@ -179,7 +166,7 @@ If present, the message MUST be a string formed by a machine-readable single-wor
## Notices ## Notices
Notices are warnings that might help explain or debug the behaviour of a given relay. Notices are warnings that might help explain or debug the behavior of a given relay.
* `["NOTICE", <message>]`, used to send human-readable error messages or other things to clients. * `["NOTICE", <message>]`, used to send human-readable error messages or other things to clients.
@ -193,7 +180,7 @@ Some examples:
* `["OK", "b1a649ebe8...", true, "duplicate: already have this event"]` * `["OK", "b1a649ebe8...", true, "duplicate: already have this event"]`
* `["OK", "b1a649ebe8...", false, "blocked: you are banned from posting here"]` * `["OK", "b1a649ebe8...", false, "blocked: you are banned from posting here"]`
* `["OK", "b1a649ebe8...", false, "blocked: please register your pubkey at https://my-expensive-relay.example.com"]` * `["OK", "b1a649ebe8...", false, "blocked: please register your pubkey at https://my-expensive-relay.example.com"]`
* `["OK", "b1a649ebe8...", false, "rate-limited: slow down there chief"]` * `["OK", "b1a649ebe8...", false, "rate-limited: slow down there, chief"]`
* `["OK", "b1a649ebe8...", false, "invalid: event creation date is too far off from the current time"]` * `["OK", "b1a649ebe8...", false, "invalid: event creation date is too far off from the current time"]`
* `["OK", "b1a649ebe8...", false, "pow: difficulty 26 is less than 30"]` * `["OK", "b1a649ebe8...", false, "pow: difficulty 26 is less than 30"]`
* `["OK", "b1a649ebe8...", false, "error: could not connect to the database"]` * `["OK", "b1a649ebe8...", false, "error: could not connect to the database"]`