From 82aafbef39a4a183fc6b1e8488e4a2db81a3fa90 Mon Sep 17 00:00:00 2001 From: Semisol <45574030+Semisol@users.noreply.github.com> Date: Fri, 16 Dec 2022 01:11:08 +0300 Subject: [PATCH 01/87] add nip-41: authentication --- 41.md | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 41.md diff --git a/41.md b/41.md new file mode 100644 index 00000000..56adf3fe --- /dev/null +++ b/41.md @@ -0,0 +1,69 @@ +NIP-41 +====== + +Authentication of clients to relays +----------------------------------- + +`draft` `optional` `author:Semisol` + +This NIP defines a way for clients to authenticate to relays by signing an ephemeral event. + +## Event format + +An event should be signed with `kind: 22241` and `content` being the WebSockets URL of the relay. +The URL MUST: +- Have a trailing slash if the path is `/` +- Not have a port number if protocol is `ws` and port is `80` or protocol is `wss` and port is `443` +- Not include the search/query + +An example event is shown below: +```json +{ + "id": "...", + "pubkey": "...", + "created_at": 1669695536, + "kind": 22223, + "tags": [], + "content": "wss://relay.example.com/", + "sig": "..." +} +``` + +## Commands between the relay and the client + +This NIP defines a new command, `AUTH`, which can be sent by either the relay or the client with different meanings. + +A relay may send `["AUTH", , ]` when it needs authentication (examples: accessing kind 4 events, whitelist only, requiring proof of authorship for `EVENT`). +The human readable reason SHOULD be prefixed with a string in the format `: `. A list of short descriptions is listed below: +- `restricted`: This relay is restricted and requires the pubkey of the client to check if it can access the relay. (requires a whitelist, payment, etc) +- `publish`: The relay requests that the client identify who is sending an `EVENT` command. + This can be used for where only the signer of an event can publish it, or a pay-as-you-go relay allowing for you to publish others' events +- `private`: The client has attempted to access a restricted set of events (example: kind 4 DMs) and should authenticate with the relay to receive them. +- `other`: Any reason not defined here. + +`data object` MUST be a JSON object. It currently has one defined field, but may be extended by amendments to this NIP or other NIPs: +- `subscription_id`: The subscription ID that triggered the `AUTH` request. + +A client may send one of the following to the relay: +- `["AUTH", ]` to indicate it has accepted the request. This may also be sent without an authentication request. +- `["AUTH", null]` to indicate it has rejected the request. + +A relay SHOULD send the [`OK`](https://github.com/nostr-protocol/nips/blob/master/20.md) command after they receive a +non-rejecting authentication response, and use one of the following `message` prefixes if the event sent cannot be verified: +- `too-old:`: The event signed has a too old `created_at` date. +- `invalid-url:`: The URL in `content` is not matching. +- `already-used:`: This event was already used to authenticate to this relay. +- `bad-signature:`: The event has a bad signature. + +Please note that the `OK` message should only be sent as a response to other commands that the client sends instead of the `AUTH` command if the issue is not related to the authentication event being incorrectly signed (example: not on whitelist). + +Relays SHOULD send [`EOSE`](https://github.com/nostr-protocol/nips/blob/master/15.md) when an authentication request is triggered by a `REQ` command, and not send stored events after the `EOSE` when authentication is completed. +Relays SHOULD send `OK` as a response when a command triggers authentication with the reason starting with `auth:`. + +Clients SHOULD retry the action (resending event, resubscribing) after they authenticate if they receive an `AUTH` request. + +## Signed event verification +Relays when processing `AUTH` responses SHOULD verify the following before accepting the response: +- that the `kind` is `22223` +- that the event was recently signed (~10 minutes, by `created_at`) +- that the `content` field matches the relay URL From a04da3f1765a960e5994fad0044f45de1d43e683 Mon Sep 17 00:00:00 2001 From: Semisol <45574030+Semisol@users.noreply.github.com> Date: Sat, 17 Dec 2022 00:02:03 +0300 Subject: [PATCH 02/87] nip-41: fix kind mismatch on example event --- 41.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/41.md b/41.md index 56adf3fe..e2fd15b0 100644 --- a/41.md +++ b/41.md @@ -22,7 +22,7 @@ An example event is shown below: "id": "...", "pubkey": "...", "created_at": 1669695536, - "kind": 22223, + "kind": 22241, "tags": [], "content": "wss://relay.example.com/", "sig": "..." From df2837606441953be553f3b31e80ceae48f63a5e Mon Sep 17 00:00:00 2001 From: Semisol <45574030+Semisol@users.noreply.github.com> Date: Sat, 24 Dec 2022 14:08:34 +0300 Subject: [PATCH 03/87] nip41: fix outdated kind --- 41.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/41.md b/41.md index e2fd15b0..d50096c1 100644 --- a/41.md +++ b/41.md @@ -64,6 +64,6 @@ Clients SHOULD retry the action (resending event, resubscribing) after they auth ## Signed event verification Relays when processing `AUTH` responses SHOULD verify the following before accepting the response: -- that the `kind` is `22223` +- that the `kind` is `22241` - that the event was recently signed (~10 minutes, by `created_at`) - that the `content` field matches the relay URL From b9467cb428489d800e8e2729b0449ee1ceec03a5 Mon Sep 17 00:00:00 2001 From: Semisol <45574030+Semisol@users.noreply.github.com> Date: Sat, 24 Dec 2022 18:42:05 +0300 Subject: [PATCH 04/87] nip41: allow for delegated events --- 41.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/41.md b/41.md index d50096c1..dfa49c31 100644 --- a/41.md +++ b/41.md @@ -16,6 +16,8 @@ The URL MUST: - Not have a port number if protocol is `ws` and port is `80` or protocol is `wss` and port is `443` - Not include the search/query +Relays SHOULD treat authenticaiton events with a valid delegation as if it was the delegator authenticating. + An example event is shown below: ```json { From c80be21cd44aa74efa42ead23a12343bf33ade34 Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Mon, 2 Jan 2023 16:49:37 -0300 Subject: [PATCH 05/87] drastically simplify @semisol's auth NIP. --- 41.md | 71 ------------------------------------------------------- 42.md | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 13 ++++++---- 3 files changed, 76 insertions(+), 76 deletions(-) delete mode 100644 41.md create mode 100644 42.md diff --git a/41.md b/41.md deleted file mode 100644 index dfa49c31..00000000 --- a/41.md +++ /dev/null @@ -1,71 +0,0 @@ -NIP-41 -====== - -Authentication of clients to relays ------------------------------------ - -`draft` `optional` `author:Semisol` - -This NIP defines a way for clients to authenticate to relays by signing an ephemeral event. - -## Event format - -An event should be signed with `kind: 22241` and `content` being the WebSockets URL of the relay. -The URL MUST: -- Have a trailing slash if the path is `/` -- Not have a port number if protocol is `ws` and port is `80` or protocol is `wss` and port is `443` -- Not include the search/query - -Relays SHOULD treat authenticaiton events with a valid delegation as if it was the delegator authenticating. - -An example event is shown below: -```json -{ - "id": "...", - "pubkey": "...", - "created_at": 1669695536, - "kind": 22241, - "tags": [], - "content": "wss://relay.example.com/", - "sig": "..." -} -``` - -## Commands between the relay and the client - -This NIP defines a new command, `AUTH`, which can be sent by either the relay or the client with different meanings. - -A relay may send `["AUTH", , ]` when it needs authentication (examples: accessing kind 4 events, whitelist only, requiring proof of authorship for `EVENT`). -The human readable reason SHOULD be prefixed with a string in the format `: `. A list of short descriptions is listed below: -- `restricted`: This relay is restricted and requires the pubkey of the client to check if it can access the relay. (requires a whitelist, payment, etc) -- `publish`: The relay requests that the client identify who is sending an `EVENT` command. - This can be used for where only the signer of an event can publish it, or a pay-as-you-go relay allowing for you to publish others' events -- `private`: The client has attempted to access a restricted set of events (example: kind 4 DMs) and should authenticate with the relay to receive them. -- `other`: Any reason not defined here. - -`data object` MUST be a JSON object. It currently has one defined field, but may be extended by amendments to this NIP or other NIPs: -- `subscription_id`: The subscription ID that triggered the `AUTH` request. - -A client may send one of the following to the relay: -- `["AUTH", ]` to indicate it has accepted the request. This may also be sent without an authentication request. -- `["AUTH", null]` to indicate it has rejected the request. - -A relay SHOULD send the [`OK`](https://github.com/nostr-protocol/nips/blob/master/20.md) command after they receive a -non-rejecting authentication response, and use one of the following `message` prefixes if the event sent cannot be verified: -- `too-old:`: The event signed has a too old `created_at` date. -- `invalid-url:`: The URL in `content` is not matching. -- `already-used:`: This event was already used to authenticate to this relay. -- `bad-signature:`: The event has a bad signature. - -Please note that the `OK` message should only be sent as a response to other commands that the client sends instead of the `AUTH` command if the issue is not related to the authentication event being incorrectly signed (example: not on whitelist). - -Relays SHOULD send [`EOSE`](https://github.com/nostr-protocol/nips/blob/master/15.md) when an authentication request is triggered by a `REQ` command, and not send stored events after the `EOSE` when authentication is completed. -Relays SHOULD send `OK` as a response when a command triggers authentication with the reason starting with `auth:`. - -Clients SHOULD retry the action (resending event, resubscribing) after they authenticate if they receive an `AUTH` request. - -## Signed event verification -Relays when processing `AUTH` responses SHOULD verify the following before accepting the response: -- that the `kind` is `22241` -- that the event was recently signed (~10 minutes, by `created_at`) -- that the `content` field matches the relay URL diff --git a/42.md b/42.md new file mode 100644 index 00000000..d5122bad --- /dev/null +++ b/42.md @@ -0,0 +1,68 @@ +NIP-42 +====== + +Authentication of clients to relays +----------------------------------- + +`draft` `optional` `author:Semisol` `author:fiatjaf` + +This NIP defines a way for clients to authenticate to relays by signing an ephemeral event. + +## Motivation + +A relay may want to require clients to authenticate to access restricted resources. For example, + + - A relay may request payment or other forms of whitelisting to publish events -- this can naïvely be achieved by limiting publication + to events signed by the whitelisted key, but with this NIP they may choose to accept any events as long as they are published from an + authenticated user; + - A relay may limit access to `kind: 4` DMs to only the parties involved in the chat exchange, and for that it may require authentication + before clients can query for that kind. + - A relay may limit subscriptions of any kind to paying users or users whitelisted through any other means, and require authentication. + +## Protocol flow + +This NIP defines a new message, `AUTH`, which clients can send to relays when they want to authenticate. The message is of the following form: + +``` +["AUTH", ] +``` + +The signed event is an ephemeral event not meant to be published or queried, it must be of `kind: 22242` and content must be set to the +WebSocket URL of the relay. `created_at` should be the current time. Example: + +```json +{ + "id": "...", + "pubkey": "...", + "created_at": 1669695536, + "kind": 22242, + "tags": [], + "content": "wss://relay.example.com/", + "sig": "..." +} +``` + +The client may send an auth message right before performing an action for which it knows authentication will be required -- for example, right +before requesting `kind: 4` chat messages --, or it may do right on connection start or at some other moment it deems best. + +Upon receiving a message from an unauthenticated user it can't fulfill without authentication, a relay may choose to notify the client. For +that it can use a `NOTICE` message with a standard prefix `"restricted: "` that is readable both by humans and machines, for example: + +``` +["NOTICE", "restricted: we can't serve DMs to unauthenticated users, does your client implement NIP-42?"] +``` + +or + +``` +["NOTICE", "restricted: we do not accept events from unauthenticated users, please sign up at https://example.com/"] +``` + +## Signed Event Verification + +To verify `AUTH` messages, relays must ensure: + + - that the `kind` is `22242` + - that the event was recently signed (~10 minutes, by `created_at`) + - that the `content` field matches the relay URL + - URL normalization techniques can be applied. For most cases just checking if the domain name is correct should be enough. diff --git a/README.md b/README.md index cce4166b..f627f4d1 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,7 @@ NIPs stand for **Nostr Implementation Possibilities**. They exist to document wh - [NIP-35: User Discovery](35.md) - [NIP-36: Sensitive Content](36.md) - [NIP-40: Expiration Timestamp](40.md) +- [NIP-42: Authentication of clients to relays](42.md) ## Event Kinds @@ -47,6 +48,7 @@ NIPs stand for **Nostr Implementation Possibilities**. They exist to document wh | 43 | Channel Hide Message | [28](28.md) | | 44 | Channel Mute User | [28](28.md) | | 45-49 | Public Chat Reserved | [28](28.md) | +| 22242 | Client Authentication | [42](42.md) | | 10000-19999 | Replaceable Events Reserved | [16](16.md) | | 20000-29999 | Ephemeral Events Reserved | [16](16.md) | @@ -54,11 +56,12 @@ NIPs stand for **Nostr Implementation Possibilities**. They exist to document wh ## Message types ### Client to Relay -| type | description | NIP | -|-------|-----------------------------------------------------|------------| -| EVENT | used to publish events | [1](01.md) | -| REQ | used to request events and subscribe to new updates | [1](01.md) | -| CLOSE | used to stop previous subscriptions | [1](01.md) | +| type | description | NIP | +|-------|-----------------------------------------------------|-------------| +| EVENT | used to publish events | [1](01.md) | +| REQ | used to request events and subscribe to new updates | [1](01.md) | +| CLOSE | used to stop previous subscriptions | [1](01.md) | +| AUTH | used to send authentication events | [42](42.md) | ### Relay to Client | type | description | NIP | From 4a5202646a86ce63a85a50b560d1a2fbce277df6 Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Mon, 2 Jan 2023 17:26:41 -0300 Subject: [PATCH 06/87] use "OK" message. --- 42.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/42.md b/42.md index d5122bad..b17aa143 100644 --- a/42.md +++ b/42.md @@ -52,10 +52,10 @@ that it can use a `NOTICE` message with a standard prefix `"restricted: "` that ["NOTICE", "restricted: we can't serve DMs to unauthenticated users, does your client implement NIP-42?"] ``` -or +or it can return an `OK` message noting the reason an event was not written using the same prefix: ``` -["NOTICE", "restricted: we do not accept events from unauthenticated users, please sign up at https://example.com/"] +["OK", "b1a649ebe8...", false, "restricted: we do not accept events from unauthenticated users, please sign up at https://example.com/"] ``` ## Signed Event Verification From 50faceef0965042714e7f50a45b102f35c5231ca Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Wed, 4 Jan 2023 10:24:37 -0300 Subject: [PATCH 07/87] clarify `created_at` and auth session duration. --- 42.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/42.md b/42.md index b17aa143..4c884a9a 100644 --- a/42.md +++ b/42.md @@ -43,7 +43,8 @@ WebSocket URL of the relay. `created_at` should be the current time. Example: ``` The client may send an auth message right before performing an action for which it knows authentication will be required -- for example, right -before requesting `kind: 4` chat messages --, or it may do right on connection start or at some other moment it deems best. +before requesting `kind: 4` chat messages --, or it may do right on connection start or at some other moment it deems best. The authentication +is expected to last for the duration of the WebSocket connection. Upon receiving a message from an unauthenticated user it can't fulfill without authentication, a relay may choose to notify the client. For that it can use a `NOTICE` message with a standard prefix `"restricted: "` that is readable both by humans and machines, for example: @@ -62,7 +63,7 @@ or it can return an `OK` message noting the reason an event was not written usin To verify `AUTH` messages, relays must ensure: - - that the `kind` is `22242` - - that the event was recently signed (~10 minutes, by `created_at`) - - that the `content` field matches the relay URL + - that the `kind` is `22242`; + - that the event `created_at` is close (e.g. within ~10 minutes) of the current time; + - that the `content` field matches the relay URL: - URL normalization techniques can be applied. For most cases just checking if the domain name is correct should be enough. From 01a3090c6ab872621e01019c58f8cac38c354c25 Mon Sep 17 00:00:00 2001 From: Luke Childs Date: Fri, 6 Jan 2023 19:37:55 +0700 Subject: [PATCH 08/87] NIP05 Improve CORS header check command --- 05.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/05.md b/05.md index 437c637f..a67f530e 100644 --- a/05.md +++ b/05.md @@ -83,7 +83,7 @@ By adding the `` as a query string instead of as part of the path th JavaScript Nostr apps may be restricted by browser [CORS][] policies that prevent them from accessing `/.well-known/nostr.json` on the user's domain. When CORS prevents JS from loading a resource, the JS program sees it as a network failure identical to the resource not existing, so it is not possible for a pure-JS app to tell the user for certain that the failure was caused by a CORS issue. JS Nostr apps that see network failures requesting `/.well-known/nostr.json` files may want to recommend to users that they check the CORS policy of their servers, e.g.: ```bash -$ curl -sI https://example.com/.well-known/nostr.json?name=bob | grep ^Access-Control +$ curl -sI https://example.com/.well-known/nostr.json?name=bob | grep -i ^Access-Control Access-Control-Allow-Origin: * ``` From 741ac01b970d318fd61406087dd21371eb1a1e55 Mon Sep 17 00:00:00 2001 From: Jeff Thibault Date: Fri, 6 Jan 2023 10:58:30 -0500 Subject: [PATCH 09/87] NIP-22: use nip-20; minor updates --- 22.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/22.md b/22.md index 9ab601d2..fb29e6ac 100644 --- a/22.md +++ b/22.md @@ -8,7 +8,7 @@ Event `created_at` Limits Relays may define both upper and lower limits within which they will consider an event's `created_at` to be acceptable. Both the upper and lower limits MUST be unix timestamps in seconds as defined in [NIP-01](01.md). -If a relay supports this NIP, the relay SHOULD send the client a `NOTICE` message saying the event was not stored for the `created_at` timestamp not being within the permitted limits. +If a relay supports this NIP, the relay SHOULD send the client a [NIP-20](20.md) command result saying the event was not stored for the `created_at` timestamp not being within the permitted limits. Client Behavior --------------- @@ -22,24 +22,24 @@ This NIP formalizes restrictions on event timestamps as accepted by a relay and The event `created_at` field is just a unix timestamp and can be set to a time in the past or future. Relays accept and share events dated to 20 years ago or 50,000 years in the future. This NIP aims to define a way for relays that do not want to store events with *any* timestamp to set their own restrictions. -[Replaceable events](16.md#replaceable-events) can behave rather unexpected if the user wrote them - or tried to write them - with a wrong system clock. Persisting an update with a backdated system now would result in the update not getting persisted without a `NOTICE` and if they did the last update with a forward dated system, they will again fail to do another update with the now correct time. +[Replaceable events](16.md#replaceable-events) can behave rather unexpected if the user wrote them - or tried to write them - with a wrong system clock. Persisting an update with a backdated system now would result in the update not getting persisted without a notification and if they did the last update with a forward dated system, they will again fail to do another update with the now correct time. -A wide adoption of this nip could create a better user experience as it would decrease the amount of events that appear wildly out of order or even from impossible dates in the distant past or future. +A wide adoption of this NIP could create a better user experience as it would decrease the amount of events that appear wildly out of order or even from impossible dates in the distant past or future. Keep in mind that there is a use case where a user migrates their old posts onto a new relay. If a relay rejects events that were not recently created, it cannot serve this use case. -Python Example --------------- +Python (pseudocode) Example +--------------------------- ```python import time -TIME = int(time.now) +TIME = int(time.time()) LOWER_LIMIT = TIME - (60 * 60 * 24) # Define lower limit as 1 day into the past UPPER_LIMIT = TIME + (60 * 15) # Define upper limit as 15 minutes into the future if event.created_at not in range(LOWER_LIMIT, UPPER_LIMIT): - # NOTE: This is one example of a notice message. Relays can change this to notify clients however they like. - ws.send('["NOTICE", "The event created_at field is out of the acceptable range (-24h, +15min) for this relay and was not stored."]') + ws.send('["OK", event.id, False, "invalid: the event created_at field is out of the acceptable range (-24h, +15min) for this relay"]') ``` +Note: These are just example limits, the relay operator can choose whatever limits they want. From 6a70967f0eb6e7b00fc811e34631f8db046d6e1f Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Sat, 7 Jan 2023 19:53:42 -0300 Subject: [PATCH 10/87] add challenge from relay. --- 42.md | 37 +++++++++++++++++++++++++++---------- README.md | 1 + 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/42.md b/42.md index 4c884a9a..93bb3e39 100644 --- a/42.md +++ b/42.md @@ -19,16 +19,23 @@ A relay may want to require clients to authenticate to access restricted resourc before clients can query for that kind. - A relay may limit subscriptions of any kind to paying users or users whitelisted through any other means, and require authentication. -## Protocol flow +## Definitions -This NIP defines a new message, `AUTH`, which clients can send to relays when they want to authenticate. The message is of the following form: +This NIP defines a new message, `AUTH`, which relays can send when they support authentication and clients can send to relays when they want +to authenticate. When sent by relays, the message is of the following form: ``` -["AUTH", ] +["AUTH", ] ``` -The signed event is an ephemeral event not meant to be published or queried, it must be of `kind: 22242` and content must be set to the -WebSocket URL of the relay. `created_at` should be the current time. Example: +And, when sent by clients, of the following form: + +``` +["AUTH", ] +``` + +The signed event is an ephemeral event not meant to be published or queried, it must be of `kind: 22242` and it should have at least two tags, +one for the relay URL and one for the challenge string as received from the relay. `created_at` should be the current time. Example: ```json { @@ -36,18 +43,27 @@ WebSocket URL of the relay. `created_at` should be the current time. Example: "pubkey": "...", "created_at": 1669695536, "kind": 22242, - "tags": [], - "content": "wss://relay.example.com/", + "tags": [ + ["relay", "wss://relay.example.com/"], + ["challenge", "challengestringhere"] + ], + "content": "", "sig": "..." } ``` +## Protocol flow + +At any moment the relay may send an `AUTH` message to the client containing a challenge. After receiving that the client may decide to +authenticate itself or not. The challenge is expected to be valid for the duration of the connection or until a next challenge is sent by +the relay. + The client may send an auth message right before performing an action for which it knows authentication will be required -- for example, right before requesting `kind: 4` chat messages --, or it may do right on connection start or at some other moment it deems best. The authentication is expected to last for the duration of the WebSocket connection. Upon receiving a message from an unauthenticated user it can't fulfill without authentication, a relay may choose to notify the client. For -that it can use a `NOTICE` message with a standard prefix `"restricted: "` that is readable both by humans and machines, for example: +that it can use a `NOTICE` or `OK` message with a standard prefix `"restricted: "` that is readable both by humans and machines, for example: ``` ["NOTICE", "restricted: we can't serve DMs to unauthenticated users, does your client implement NIP-42?"] @@ -56,7 +72,7 @@ that it can use a `NOTICE` message with a standard prefix `"restricted: "` that or it can return an `OK` message noting the reason an event was not written using the same prefix: ``` -["OK", "b1a649ebe8...", false, "restricted: we do not accept events from unauthenticated users, please sign up at https://example.com/"] +["OK", , false, "restricted: we do not accept events from unauthenticated users, please sign up at https://example.com/"] ``` ## Signed Event Verification @@ -65,5 +81,6 @@ To verify `AUTH` messages, relays must ensure: - that the `kind` is `22242`; - that the event `created_at` is close (e.g. within ~10 minutes) of the current time; - - that the `content` field matches the relay URL: + - that the `"challenge"` tag matches the challenge sent before; + - that the `"relay"` tag matches the relay URL: - URL normalization techniques can be applied. For most cases just checking if the domain name is correct should be enough. diff --git a/README.md b/README.md index f627f4d1..05737b19 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,7 @@ NIPs stand for **Nostr Implementation Possibilities**. They exist to document wh | NOTICE | used to send human-readable messages to clients | [1](01.md) | | EOSE | used to notify clients all stored events have been sent | [15](15.md) | | OK | used to notify clients if an EVENT was successuful | [20](20.md) | +| AUTH | used to send authentication challenges | [42](42.md) | Please update these lists when proposing NIPs introducing new event kinds. From e55c86d207e11a29ccceaa0d28554a8eca9440cf Mon Sep 17 00:00:00 2001 From: kdmukai Date: Sat, 7 Jan 2023 17:12:48 -0600 Subject: [PATCH 11/87] NIP-26: Change example condition to expire at a future date (#157) also Regenerate example PKs and improve organization/presentation. --- 26.md | 48 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/26.md b/26.md index 45578753..fc4d6f89 100644 --- a/26.md +++ b/26.md @@ -25,41 +25,59 @@ This NIP introduces a new tag: `delegation` which is formatted as follows: ##### Delegation Token -The **delegation token** should be a 64-bytes schnorr signature of the sha256 hash of the following string: +The **delegation token** should be a 64-byte Schnorr signature of the sha256 hash of the following string: ``` nostr:delegation:: ``` -For example, the token `c33c88ba78ec3c760e49db591ac5f7b129e3887c8af7729795e85a0588007e5ac89b46549232d8f918eefd73e726cb450135314bfda419c030d0b6affe401ec1` is signed by `86f0689bd48dcd19c67a19d994f938ee34f251d8c39976290955ff585f2db42e` and consists of: - -```json -nostr:delegation:62903b1ff41559daf9ee98ef1ae67cc52f301bb5ce26d14baba3052f649c3f49:kind=1&created_at>1640995200 -``` #### Example -Below is an example of an event published by `62903b1ff41559daf9ee98ef1ae67cc52f301bb5ce26d14baba3052f649c3f49`, on behalf of `86f0689bd48dcd19c67a19d994f938ee34f251d8c39976290955ff585f2db42e`. +``` +# Delegator: +privkey: ee35e8bb71131c02c1d7e73231daa48e9953d329a4b701f7133c8f46dd21139c +pubkey: 8e0d3d3eb2881ec137a11debe736a9086715a8c8beeeda615780064d68bc25dd +# Delegatee: +privkey: 777e4f60b4aa87937e13acc84f7abcc3c93cc035cb4c1e9f7a9086dd78fffce1 +pubkey: 477318cfb5427b9cfc66a9fa376150c1ddbc62115ae27cef72417eb959691396 +``` + +Delegation string to grant note publishing authorization to the delegatee (477318cf) for the next 30 days. +```json +nostr:delegation:477318cfb5427b9cfc66a9fa376150c1ddbc62115ae27cef72417eb959691396:kind=1&created_at<1675721885 +``` + +The delegator (8e0d3d3e) then signs the above delegation string, the result of which is the delegation token: +``` +cbc49c65fe04a3181d72fb5a9f1c627e329d5f45d300a2dfed1c3e788b7834dad48a6d27d8e244af39c77381334ede97d4fd15abe80f35fda695fd9bd732aa1e +``` + +The delegatee (477318cf) can now construct an event on behalf of the delegator (8e0d3d3e). The delegatee then signs the event with its own private key and publishes. ```json { - "id": "a080fd288b60ac2225ff2e2d815291bd730911e583e177302cc949a15dc2b2dc", - "pubkey": "62903b1ff41559daf9ee98ef1ae67cc52f301bb5ce26d14baba3052f649c3f49", - "created_at": 1660896109, + "id": "ac4c71e69c39b1bd605de812543ebfaf81d5af365354f061d48981fb61e00b8a", + "pubkey": "477318cfb5427b9cfc66a9fa376150c1ddbc62115ae27cef72417eb959691396", + "created_at": 1673129661, "kind": 1, "tags": [ [ "delegation", - "86f0689bd48dcd19c67a19d994f938ee34f251d8c39976290955ff585f2db42e", - "kind=1&created_at>1640995200", - "c33c88ba78ec3c760e49db591ac5f7b129e3887c8af7729795e85a0588007e5ac89b46549232d8f918eefd73e726cb450135314bfda419c030d0b6affe401ec1" + "8e0d3d3eb2881ec137a11debe736a9086715a8c8beeeda615780064d68bc25dd", + "kind=1&created_at<1675721813", + "cbc49c65fe04a3181d72fb5a9f1c627e329d5f45d300a2dfed1c3e788b7834dad48a6d27d8e244af39c77381334ede97d4fd15abe80f35fda695fd9bd732aa1e" ] ], - "content": "Hello world", - "sig": "cd4a3cd20dc61dcbc98324de561a07fd23b3d9702115920c0814b5fb822cc5b7c5bcdaf3fa326d24ed50c5b9c8214d66c75bae34e3a84c25e4d122afccb66eb6" + "content": "Hello, world!", + "sig": "55ed9a78d6449b8c189b6dbc34bc4bcd34dcc79e6da6c9078268fe3d7c0cbe62b1b907ffb76ba591e83895b1329bf2e6e16f3b0cd5827272e420d419c6f0f0b5" } ``` +The event should be considered a valid delegation if the conditions are satisfied (`kind=1` and `created_at<1675721813` in this example) and, upon validation of the delegation token, are found to be unchanged from the conditions in the original delegation string. + +Clients should display the delegated note as if it was published directly by the delegator (8e0d3d3e). + #### Relay & Client Querying Support From 60741160535de8137fb7a74bd6561adef974b884 Mon Sep 17 00:00:00 2001 From: Leo Wandersleb Date: Wed, 11 Jan 2023 00:05:15 -0300 Subject: [PATCH 12/87] Update 42.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ricardo Arturo Cabral Mejía --- 42.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/42.md b/42.md index 93bb3e39..9b0c45b4 100644 --- a/42.md +++ b/42.md @@ -35,7 +35,9 @@ And, when sent by clients, of the following form: ``` The signed event is an ephemeral event not meant to be published or queried, it must be of `kind: 22242` and it should have at least two tags, -one for the relay URL and one for the challenge string as received from the relay. `created_at` should be the current time. Example: +one for the relay URL and one for the challenge string as received from the relay. +Relays MUST exclude `kind: 22242` events from being broadcasted to any client. +`created_at` should be the current time. Example: ```json { From 0019a206a351fcdb7429b829d08024fd4f565f02 Mon Sep 17 00:00:00 2001 From: benthecarman <15256660+benthecarman@users.noreply.github.com> Date: Wed, 11 Jan 2023 14:26:31 -0600 Subject: [PATCH 13/87] NIP25: allow for emojis to be considered dislikes --- 25.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/25.md b/25.md index 8608ed82..5ab1553c 100644 --- a/25.md +++ b/25.md @@ -18,7 +18,7 @@ downvote or dislike on a post. A client MAY also choose to tally likes against dislikes in a reddit-like system of upvotes and downvotes, or display them as separate tallys. -The `content` MAY be an emoji, in this case it MAY be interpreted as a "like", +The `content` MAY be an emoji, in this case it MAY be interpreted as a "like" or "dislike", or the client MAY display this emoji reaction on the post. Tags From 5355edb9cb1c712bcc8c024416b1e2e25a32317a Mon Sep 17 00:00:00 2001 From: monlovesmango <96307647+monlovesmango@users.noreply.github.com> Date: Sun, 27 Nov 2022 16:02:38 -0600 Subject: [PATCH 14/87] add 'mention' marker I think that adding a mention marker would eliminate ambiguity for clients supporting both the deprecated and preferred conventions. I also think that this would allow for extensibility in adding new types of event mentions (for example if we want to add context for a note). --- 10.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/10.md b/10.md index 8b617f6e..5fff879c 100644 --- a/10.md +++ b/10.md @@ -44,9 +44,9 @@ Where: * `` is the id of the event being referenced. * `` is the URL of a recommended relay associated with the reference. It is NOT optional. - * `` is optional and if present is one of `"reply"` or `"root"` + * `` is optional and if present is one of `"reply"`, `"root"`, or `"mention"` -**The order of marked "e" tags is not relevant.** Those marked with `"reply"` denote the ``. Those marked with `"root"` denote the root id of the reply thread. +**The order of marked "e" tags is not relevant.** Those marked with `"reply"` denote the ``. Those marked with `"root"` denote the root id of the reply thread. Those marked `"mention"` denote id of events that are tagged and are not the `"reply"` nor `"root"`. A direct reply to the root of a thread should have a single marked "e" tag of type "root". From 6f5f9856b970992bd282d9cac2671975556ba05f Mon Sep 17 00:00:00 2001 From: monlovesmango <96307647+monlovesmango@users.noreply.github.com> Date: Tue, 29 Nov 2022 10:27:18 -0600 Subject: [PATCH 15/87] define 'mention' tag --- 10.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/10.md b/10.md index 5fff879c..1d6f8eec 100644 --- a/10.md +++ b/10.md @@ -46,7 +46,7 @@ Where: * `` is the URL of a recommended relay associated with the reference. It is NOT optional. * `` is optional and if present is one of `"reply"`, `"root"`, or `"mention"` -**The order of marked "e" tags is not relevant.** Those marked with `"reply"` denote the ``. Those marked with `"root"` denote the root id of the reply thread. Those marked `"mention"` denote id of events that are tagged and are not the `"reply"` nor `"root"`. +**The order of marked "e" tags is not relevant.** Those marked with `"reply"` denote the ``. Those marked with `"root"` denote the root id of the reply thread. Those marked with `"mention"` denote a quoted or reposted event id. A direct reply to the root of a thread should have a single marked "e" tag of type "root". From f0842438c149be4834010540a30a4bdea7bee81e Mon Sep 17 00:00:00 2001 From: monlovesmango <96307647+monlovesmango@users.noreply.github.com> Date: Mon, 5 Dec 2022 11:22:43 -0600 Subject: [PATCH 16/87] clarify top level reply behavior --- 10.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/10.md b/10.md index 1d6f8eec..c0ef9d19 100644 --- a/10.md +++ b/10.md @@ -46,7 +46,7 @@ Where: * `` is the URL of a recommended relay associated with the reference. It is NOT optional. * `` is optional and if present is one of `"reply"`, `"root"`, or `"mention"` -**The order of marked "e" tags is not relevant.** Those marked with `"reply"` denote the ``. Those marked with `"root"` denote the root id of the reply thread. Those marked with `"mention"` denote a quoted or reposted event id. +**The order of marked "e" tags is not relevant.** Those marked with `"reply"` denote the id of the reply event being responded to. Those marked with `"root"` denote the root id of the reply thread being responded to. For top level replies (those replying directly to the root event), only the `"root"` marker should be used. Those marked with `"mention"` denote a quoted or reposted event id. A direct reply to the root of a thread should have a single marked "e" tag of type "root". From 230f63dd5fb1e0d3465c6962ffafbc7fa29e4983 Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Sun, 15 Jan 2023 15:37:42 -0300 Subject: [PATCH 17/87] nip-07 extensions to also add .id and .pubkey when signing. --- 07.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/07.md b/07.md index 0bd3de67..20c671a7 100644 --- a/07.md +++ b/07.md @@ -12,7 +12,7 @@ That object must define the following methods: ``` async window.nostr.getPublicKey(): string // returns a public key as hex -async window.nostr.signEvent(event: Event): Event // takes an event object and returns it with the `sig` +async window.nostr.signEvent(event: Event): Event // takes an event object, adds `id`, `pubkey` and `sig` and returns it ``` Aside from these two basic above, the following functions can also be implemented optionally: From 132100fd161a3e41547973d50e787177cbc28d6c Mon Sep 17 00:00:00 2001 From: Vasilios Daskalopoulos Date: Sun, 15 Jan 2023 15:38:10 -0500 Subject: [PATCH 18/87] fix minor typo --- 02.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/02.md b/02.md index 624d33f2..ba1ae60e 100644 --- a/02.md +++ b/02.md @@ -38,7 +38,7 @@ A client may rely on the kind-3 event to display a list of followed people by pr ### Relay sharing -A client may publish a full list of contacts with good relays for each of their contacts so other clients may use these to update their internal relay lists if needed, increasing censorship-resistant. +A client may publish a full list of contacts with good relays for each of their contacts so other clients may use these to update their internal relay lists if needed, increasing censorship-resistance. ### Petname scheme From 7d792055372ce1af2205a1451e5e9fa110d73450 Mon Sep 17 00:00:00 2001 From: Vasilios Daskalopoulos Date: Sun, 15 Jan 2023 15:39:55 -0500 Subject: [PATCH 19/87] fix erroneous reference to pubkey --- 09.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/09.md b/09.md index 881eb8a4..b0febc74 100644 --- a/09.md +++ b/09.md @@ -27,13 +27,13 @@ For example: } ``` -Relays SHOULD delete or stop publishing any referenced events that have an identical `pubkey` as the deletion request. Clients SHOULD hide or otherwise indicate a deletion status for referenced events. +Relays SHOULD delete or stop publishing any referenced events that have an identical `id` as the deletion request. Clients SHOULD hide or otherwise indicate a deletion status for referenced events. Relays SHOULD continue to publish/share the deletion events indefinitely, as clients may already have the event that's intended to be deleted. Additionally, clients SHOULD broadcast deletion events to other relays which don't have it. ## Client Usage -Clients MAY choose to fully hide any events that are referenced by valid deletion events. This includes text notes, direct messages, or other yet-to-be defined event kinds. Alternatively, they MAY show the event along with an icon or other indication that the author has "disowned" the event. The `content` field MAY also be used to replace the deleted events own content, although a user interface should clearly indicate that this is a deletion reason, not the original content. +Clients MAY choose to fully hide any events that are referenced by valid deletion events. This includes text notes, direct messages, or other yet-to-be defined event kinds. Alternatively, they MAY show the event along with an icon or other indication that the author has "disowned" the event. The `content` field MAY also be used to replace the deleted event's own content, although a user interface should clearly indicate that this is a deletion reason, not the original content. A client MUST validate that each event `pubkey` referenced in the `e` tag of the deletion request is identical to the deletion request `pubkey`, before hiding or deleting any event. Relays can not, in general, perform this validation and should not be treated as authoritative. From e5ae318984bdc2f28932420be976183c9a0cd3ff Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Sun, 15 Jan 2023 20:05:52 -0300 Subject: [PATCH 20/87] add nos2x-fox to NIP-07 implementations. --- 07.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/07.md b/07.md index 20c671a7..8ebb4d99 100644 --- a/07.md +++ b/07.md @@ -24,6 +24,7 @@ async window.nostr.nip04.decrypt(pubkey, ciphertext): string // takes ciphertext ### Implementation -- [nos2x](https://github.com/fiatjaf/nos2x) is available as a Chromium extension that provides such capabilities. -- [Alby](https://getalby.com) is a Bitcoin extension that also provides a compatible `window.nostr`. +- [nos2x](https://github.com/fiatjaf/nos2x) +- [Alby](https://getalby.com) - [Blockcore](https://www.blockcore.net/wallet) +- [nos2x-fox](https://diegogurpegui.com/nos2x-fox/) From 73496430691befb08c4dd22e4027b86091580e29 Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Mon, 16 Jan 2023 15:58:49 -0300 Subject: [PATCH 21/87] remove NIP-18, it is not really a standard. closes https://github.com/nostr-protocol/nips/issues/173 --- 18.md | 19 ------------------- README.md | 1 - 2 files changed, 20 deletions(-) delete mode 100644 18.md diff --git a/18.md b/18.md deleted file mode 100644 index 365de9c3..00000000 --- a/18.md +++ /dev/null @@ -1,19 +0,0 @@ -NIP-18 -====== - -Reposts -------- - -`draft` `optional` `author:jb55` - -A repost is a `kind 6` note that is used to signal to followers -that another event is worth reading. - -The `content` of a repost event is empty. - -The repost event MUST include an `e` tag with the `id` of the note that is -being reposted. That tag SHOULD include a relay URL as its third entry -to indicate where it can be fetched. - -The repost SHOULD include a `p` tag with the `pubkey` of the event being -reposted. diff --git a/README.md b/README.md index 5dec5f16..ed63973a 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,6 @@ 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-18: Reposts](18.md) - [NIP-19: bech32-encoded entities](19.md) - [NIP-20: Command Results](20.md) - [NIP-22: Event created_at Limits](22.md) From 1840c5cbdf37635fcada6434e91e9a47b0251d91 Mon Sep 17 00:00:00 2001 From: "marc@roosoft.com" Date: Mon, 16 Jan 2023 14:46:13 -0500 Subject: [PATCH 22/87] removed kind 6 since NIP-18 has been removed from the spec --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index ed63973a..1576965a 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,6 @@ NIPs stand for **Nostr Implementation Possibilities**. They exist to document wh | 3 | Contacts | [2](02.md) | | 4 | Encrypted Direct Messages | [4](04.md) | | 5 | Event Deletion | [9](09.md) | -| 6 | Repost | [18](18.md) | | 7 | Reaction | [25](25.md) | | 40 | Channel Creation | [28](28.md) | | 41 | Channel Metadata | [28](28.md) | From 086d224e1d75366ec45d23544159ed9c5610010a Mon Sep 17 00:00:00 2001 From: Artur Brugeman Date: Tue, 17 Jan 2023 18:49:10 +0300 Subject: [PATCH 23/87] NIP-50: Keywords Filter --- 50.md | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 50.md diff --git a/50.md b/50.md new file mode 100644 index 00000000..f0ee8432 --- /dev/null +++ b/50.md @@ -0,0 +1,52 @@ +NIP-50 +====== + +Keywords Filter +--------------- + +`draft` `optional` `author:brugeman` + +## Abstract + +Many Nostr use cases require some form of search by `content` field. The meaning and format of `content` differs +with event kind and use case. Thus, this NIP only establishes a general framework for search over `content`, +and specifies the details for kind `0` and kind `1` events. + +## `keywords` filter field + +A new `keywords` field is introduced for `REQ` messages from clients: +```json +{ + "kinds": + "keywords": +} +``` +A filter with `keywords` field MUST also include `kinds` field. This NIP specifies the behavior for kinds `0` and `1`, +if none of these kinds are provided along with `keywords`, relay SHOULD ignore the filter, and MAY send +a `NOTICE` to inform the client. Future NIPs will specify behavior for other event kinds. + +A filter matches if one of the provided `keywords` matches. Each keyword string may contain several conditions - `words`, +all the words must match for a keyword to match. The meaning of `words` depends on event kind. + +Clients SHOULD query several relays supporting this NIP and specific kind to compensate for potentially different +implementation details between relays (like string sanitization, etc). + +Clients SHOULD verify that events returned by a relay match the specified `keywords` in the way that suits the +client's use case, and MAY stop querying relays that have low precision. + +## Keyword search for kind `0` and kind `1` + +For kind `0` and kind `1`, each keyword is a lowercase string consisting of words separated by spaces (in most languages), punctuation/control +characters are ignored. + +For kind `1`, an event must include all words in it's `content` field for it to match the keyword. + +For kind `0`, an event must include all mentioned words in the json object stored at the `content` field. Recommended +json fields for matching are `about`, `display_name`, `name`, `nip05`, `lud06` and `lud18`. + +A keyword may contain a word starting with prefix `option:` (like `option:no_spam`), such words specify additional +constraints for event matching, and are reserved for the future extensions. Relay SHOULD ignore `option:` words that it does not support. + +Relay MAY support these options for kind `0` and kind `1` events: +- `option:no_spam` - only include events deemed 'high-quality' by whatever internal metric the relay adopts + From 8b18e7818e0c2fcbd8bc82e0660f8b6ba23af50d Mon Sep 17 00:00:00 2001 From: Mike Dilger Date: Sat, 14 Jan 2023 09:59:19 +1300 Subject: [PATCH 24/87] Several NIP examples (3, 11) weren't quoting the field keys (JSON keys must be quoted) --- 03.md | 6 +++--- 11.md | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/03.md b/03.md index 578c3515..3c5d764e 100644 --- a/03.md +++ b/03.md @@ -10,11 +10,11 @@ When there is an OTS available it MAY be included in the existing event body und ``` { - id: ..., - kind: ..., + "id": ..., + "kind": ..., ..., ..., - ots: + "ots": } ``` diff --git a/11.md b/11.md index 2b268239..8cdb85e4 100644 --- a/11.md +++ b/11.md @@ -12,13 +12,13 @@ When a relay receives an HTTP(s) request with an `Accept` header of `application ```json { - name: , - description: , - pubkey: , - contact: , - supported_nips: , - software: , - version: + "name": , + "description": , + "pubkey": , + "contact": , + "supported_nips": , + "software": , + "version": } ``` From 69685588f0d60e73ac0148181472e1ceaea4f767 Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Sat, 21 Jan 2023 07:36:44 -0300 Subject: [PATCH 25/87] specify lowercase on nip01 event hex fields. --- 01.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/01.md b/01.md index d040666c..38ba2904 100644 --- a/01.md +++ b/01.md @@ -16,8 +16,8 @@ The only object type that exists is the `event`, which has the following format ```json { - "id": <32-bytes sha256 of the the serialized event data> - "pubkey": <32-bytes hex-encoded public key of the event creator>, + "id": <32-bytes lowercase hex-encoded sha256 of the the serialized event data> + "pubkey": <32-bytes lowercase hex-encoded public key of the event creator>, "created_at": , "kind": , "tags": [ From b58efb08a0ec2b1ff449422e9a58a09c88420e4e Mon Sep 17 00:00:00 2001 From: thesimplekid Date: Sun, 22 Jan 2023 09:51:36 -0500 Subject: [PATCH 26/87] NIP-28 Add missing comma's in tags --- 28.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/28.md b/28.md index f37299ee..0862e72d 100644 --- a/28.md +++ b/28.md @@ -54,7 +54,7 @@ Clients SHOULD use [NIP-10](10.md) marked "e" tags to recommend a relay. ```json { "content": "{\"name\": \"Updated Demo Channel\", \"about\": \"Updating a test channel.\", \"picture\": \"https://placekitten.com/201/201\"}", - "tags": [["e", ]], + "tags": [["e", , ]], ... } ``` @@ -73,7 +73,7 @@ Root message: ```json { "content": , - "tags": [["e", "root"]], + "tags": [["e", , , "root"]], ... } ``` @@ -84,8 +84,8 @@ Reply to another message: { "content": , "tags": [ - ["e", "reply"], - ["p", ], + ["e", , , "reply"], + ["p", , ], ... ], ... From 9682e43ee03cd50b5994bada0e3a97e3c259b314 Mon Sep 17 00:00:00 2001 From: monlovesmango <96307647+monlovesmango@users.noreply.github.com> Date: Sun, 22 Jan 2023 21:31:27 -0600 Subject: [PATCH 27/87] update Parameterized Replaceable Events range --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 1576965a..df955d32 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,8 @@ NIPs stand for **Nostr Implementation Possibilities**. They exist to document wh | 22242 | Client Authentication | [42](42.md) | | 10000-19999 | Replaceable Events Reserved | [16](16.md) | | 20000-29999 | Ephemeral Events Reserved | [16](16.md) | +| 30000-39999 | Param. Repl. Events Reserved| [33](33.md) | + ## Message types From a5a4f312ccb44a33dd2c685d735a96bf0acb8838 Mon Sep 17 00:00:00 2001 From: Artur Brugeman Date: Tue, 24 Jan 2023 09:03:59 +0300 Subject: [PATCH 28/87] Add mention of supported_nips by mikedilger --- 50.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/50.md b/50.md index f0ee8432..470da1c4 100644 --- a/50.md +++ b/50.md @@ -4,7 +4,7 @@ NIP-50 Keywords Filter --------------- -`draft` `optional` `author:brugeman` +`draft` `optional` `author:brugeman` `author:mikedilger` ## Abstract @@ -28,6 +28,8 @@ a `NOTICE` to inform the client. Future NIPs will specify behavior for other eve A filter matches if one of the provided `keywords` matches. Each keyword string may contain several conditions - `words`, all the words must match for a keyword to match. The meaning of `words` depends on event kind. +Clients SHOULD use the supported_nips field to learn if a relay supports keyword filter queries. + Clients SHOULD query several relays supporting this NIP and specific kind to compensate for potentially different implementation details between relays (like string sanitization, etc). From 54b6c0090dbf3d30c20385bbd4814f3336e29f5f Mon Sep 17 00:00:00 2001 From: Semisol <45574030+Semisol@users.noreply.github.com> Date: Tue, 24 Jan 2023 21:36:15 +0300 Subject: [PATCH 29/87] NIP-33: Add example for more than one value --- 33.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/33.md b/33.md index db572ad2..4ebabc40 100644 --- a/33.md +++ b/33.md @@ -10,10 +10,10 @@ This NIP adds a new event range that allows for replacement of events that have Implementation -------------- -A *parameterized replaceable event* is defined as an event with a kind `30000 <= n < 40000`. +A *parameterized replaceable event* is defined as an event with a kind `30000 <= n < 40000`. Upon a parameterized replaceable event with a newer timestamp than the currently known latest replaceable event with the same kind and first `d` tag value being received, the old event -SHOULD be discarded and replaced with the newer event. +SHOULD be discarded and replaced with the newer event. A missing or a `d` tag with no value should be interpreted equivalent to a `d` tag with the value as an empty string. Events from the same author with any of the following `tags` replace each other: @@ -24,6 +24,7 @@ replace each other: * `"tags":[["d",""],["d","not empty"]]`: only first `d` tag is considered * `"tags":[["d"],["d","some value"]]`: only first `d` tag is considered * `"tags":[["e"]]`: same as no tags +* `"tags":[["d","test","1"]]`: only the value is considered (`test`) Client Behavior --------------- From d179cd9758c0305300757ae6fa7eb9dc6d781223 Mon Sep 17 00:00:00 2001 From: Semisol <45574030+Semisol@users.noreply.github.com> Date: Tue, 24 Jan 2023 21:48:54 +0300 Subject: [PATCH 30/87] NIP-33: `d` tag requirements --- 33.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/33.md b/33.md index 4ebabc40..6b05bd06 100644 --- a/33.md +++ b/33.md @@ -10,6 +10,8 @@ This NIP adds a new event range that allows for replacement of events that have Implementation -------------- +The value of a tag is defined as the first parameter of a tag after the tag name. + A *parameterized replaceable event* is defined as an event with a kind `30000 <= n < 40000`. Upon a parameterized replaceable event with a newer timestamp than the currently known latest replaceable event with the same kind and first `d` tag value being received, the old event @@ -26,6 +28,8 @@ replace each other: * `"tags":[["e"]]`: same as no tags * `"tags":[["d","test","1"]]`: only the value is considered (`test`) +Clients SHOULD NOT use `d` tags with multiple values and SHOULD include the `d` tag even if it has no value to allow querying using the `#d` filter. + Client Behavior --------------- From d534df39c05f26e26d47f1813cbacbb02c9d7718 Mon Sep 17 00:00:00 2001 From: Artur Brugeman Date: Wed, 25 Jan 2023 14:46:28 +0300 Subject: [PATCH 31/87] Add hint about client-side filtering --- 50.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/50.md b/50.md index 470da1c4..b02a3f3a 100644 --- a/50.md +++ b/50.md @@ -28,7 +28,7 @@ a `NOTICE` to inform the client. Future NIPs will specify behavior for other eve A filter matches if one of the provided `keywords` matches. Each keyword string may contain several conditions - `words`, all the words must match for a keyword to match. The meaning of `words` depends on event kind. -Clients SHOULD use the supported_nips field to learn if a relay supports keyword filter queries. +Clients SHOULD use the supported_nips field to learn if a relay supports keyword filter queries. Clients MAY send keyword filter queries to any relay, if they are prepared to filter out extraneous responses from relays that do not support this NIP. Clients SHOULD query several relays supporting this NIP and specific kind to compensate for potentially different implementation details between relays (like string sanitization, etc). From 45649d7b4d40fda4b4db8a02d007e6243a1153c9 Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Tue, 24 Jan 2023 10:23:00 -0300 Subject: [PATCH 32/87] add NIP-21, `nostr:` url scheme. --- 21.md | 20 ++++++++++++++++++++ README.md | 1 + 2 files changed, 21 insertions(+) create mode 100644 21.md diff --git a/21.md b/21.md new file mode 100644 index 00000000..2525bf10 --- /dev/null +++ b/21.md @@ -0,0 +1,20 @@ +NIP-21 +====== + +`nostr:` URL scheme +------------------- + +`draft` `optional` `author:fiatjaf` + +This NIP standardizes the usage of a common URL scheme for maximum interoperability and openness in the network. + +The scheme is `nostr:`. + +The identifiers that come after are expected to be the same as those defined in NIP-19 (except `nsec`). + +## Examples + +- `nostr:npub1sn0wdenkukak0d9dfczzeacvhkrgz92ak56egt7vdgzn8pv2wfqqhrjdv9` +- `nostr:nprofile1qqsrhuxx8l9ex335q7he0f09aej04zpazpl0ne2cgukyawd24mayt8gpp4mhxue69uhhytnc9e3k7mgpz4mhxue69uhkg6nzv9ejuumpv34kytnrdaksjlyr9p` +- `nostr:note1fntxtkcy9pjwucqwa9mddn7v03wwwsu9j330jj350nvhpky2tuaspk6nqc` +- `nostr:nevent1qqstna2yrezu5wghjvswqqculvvwxsrcvu7uc0f78gan4xqhvz49d9spr3mhxue69uhkummnw3ez6un9d3shjtn4de6x2argwghx6egpr4mhxue69uhkummnw3ez6ur4vgh8wetvd3hhyer9wghxuet5nxnepm` diff --git a/README.md b/README.md index df955d32..f8dd7c99 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ NIPs stand for **Nostr Implementation Possibilities**. They exist to document wh - [NIP-16: Event Treatment](16.md) - [NIP-19: bech32-encoded entities](19.md) - [NIP-20: Command Results](20.md) +- [NIP-21: `nostr:` URL scheme](21.md) - [NIP-22: Event created_at Limits](22.md) - [NIP-25: Reactions](25.md) - [NIP-26: Delegated Event Signing](26.md) From d82599bc7f894a175174014d3afc44e428ecb99d Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Wed, 25 Jan 2023 13:20:36 -0300 Subject: [PATCH 33/87] add list of standardized tags. --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index f8dd7c99..1ef0ec80 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,20 @@ Please update these lists when proposing NIPs introducing new event kinds. When experimenting with kinds, keep in mind the classification introduced by [NIP-16](16.md). +## Standardized Tags + +| name | value | other parameters | NIP | +| ---------- | ----------------------- | ----------------- | ------------------------ | +| e | event id (hex) | relay URL, marker | [1](01.md), [10](10.md) | +| p | pubkey (hex) | relay URL | [1](01.md) | +| r | a reference (URL, etc) | | [12](12.md) | +| t | hashtag | | [12](12.md) | +| g | geohash | | [12](12.md) | +| nonce | random | | [13](13.md) | +| subject | subject | | [14](14.md) | +| d | identifier | | [33](33.md) | +| expiration | unix timestamp (string) | | [40](40.md) | + ## Criteria for acceptance of NIPs 1. They should be implemented in at least two clients and one relay -- when applicable. From 8362ff8f79d913ac1dfded9668cd31dcc8c73f22 Mon Sep 17 00:00:00 2001 From: Ben Franks Date: Wed, 25 Jan 2023 17:10:03 +0000 Subject: [PATCH 34/87] Update NIP-01 to clarify since and until filters The since and until filters does not clarify integer format and some relays fail to recognize filters with a float based timestamp. --- 01.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/01.md b/01.md index 38ba2904..e1e94447 100644 --- a/01.md +++ b/01.md @@ -66,8 +66,8 @@ Clients can send 3 types of messages, which must be JSON arrays, according to th "kinds": , "#e": , "#p": , - "since": , - "until": , + "since": , + "until": , "limit": } ``` From f6cf3b6c3c76d15f9b17e42ea05b72deff359183 Mon Sep 17 00:00:00 2001 From: Artur Brugeman Date: Thu, 26 Jan 2023 15:14:44 +0300 Subject: [PATCH 35/87] Fix: change lud18 to lud16 --- 50.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/50.md b/50.md index b02a3f3a..0692fd1d 100644 --- a/50.md +++ b/50.md @@ -44,7 +44,7 @@ characters are ignored. For kind `1`, an event must include all words in it's `content` field for it to match the keyword. For kind `0`, an event must include all mentioned words in the json object stored at the `content` field. Recommended -json fields for matching are `about`, `display_name`, `name`, `nip05`, `lud06` and `lud18`. +json fields for matching are `about`, `display_name`, `name`, `nip05`, `lud06` and `lud16`. A keyword may contain a word starting with prefix `option:` (like `option:no_spam`), such words specify additional constraints for event matching, and are reserved for the future extensions. Relay SHOULD ignore `option:` words that it does not support. From 5901fe0b87f8d7ec56bf91a065111f0c3d3b0405 Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Fri, 27 Jan 2023 07:47:12 -0300 Subject: [PATCH 36/87] add NIP-50 to README. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 1ef0ec80..829e61ba 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ NIPs stand for **Nostr Implementation Possibilities**. They exist to document wh - [NIP-36: Sensitive Content](36.md) - [NIP-40: Expiration Timestamp](40.md) - [NIP-42: Authentication of clients to relays](42.md) +- [NIP-50: Keywords filter](50.md) ## Event Kinds From 95fa5a4a5f15b54a0e98edccf480ca5b03896f99 Mon Sep 17 00:00:00 2001 From: Zack Wynne Date: Fri, 27 Jan 2023 03:11:27 -0800 Subject: [PATCH 37/87] NIP-26: adding section documenting valid fields and operators for conditions string (#194) --- 26.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/26.md b/26.md index fc4d6f89..3eb1856d 100644 --- a/26.md +++ b/26.md @@ -31,6 +31,26 @@ The **delegation token** should be a 64-byte Schnorr signature of the sha256 has nostr:delegation:: ``` +##### Conditions Query String + +The following fields and operators are supported in the above query string: + +*Fields*: +1. `kind` + - *Operators*: + - `=${KIND_NUMBER}` - delegator may only sign events of this kind +2. `created_at` + - *Operators*: + - `<${TIMESTAMP}` - delegator may only sign events created ***before*** the specified timestamp + - `>${TIMESTAMP}` - delegator may only sign events created ***after*** the specified timestamp + +In order to create a single condition, you must use a supported field and operator. Multiple conditions can be used in a single query string, including on the same field. Conditions must be combined with `&`. + +For example, the following condition strings are valid: + +- `kind=1&created_at<1675721813` +- `kind=0&kind=1&created_at>1675721813` +- `kind=1&created_at>1674777689&created_at<1675721813` #### Example From 6708a73bbcd141094c75f739c8b31446620b30e1 Mon Sep 17 00:00:00 2001 From: Artur Brugeman Date: Fri, 27 Jan 2023 15:43:06 +0300 Subject: [PATCH 38/87] Rewrite, keywords renamed to search --- 50.md | 61 +++++++++++++++++++++++++++-------------------------------- 1 file changed, 28 insertions(+), 33 deletions(-) diff --git a/50.md b/50.md index 0692fd1d..230b8e08 100644 --- a/50.md +++ b/50.md @@ -1,54 +1,49 @@ NIP-50 ====== -Keywords Filter ---------------- +Keyword Search +-------------- -`draft` `optional` `author:brugeman` `author:mikedilger` +`draft` `optional` `author:brugeman` `author:mikedilger` `author:fiatjaf` ## Abstract -Many Nostr use cases require some form of search by `content` field. The meaning and format of `content` differs -with event kind and use case. Thus, this NIP only establishes a general framework for search over `content`, -and specifies the details for kind `0` and kind `1` events. +Many Nostr use cases require some form of general search feature, in addition to structured queries by tags or ids. +Specifics of the search algorithms will differ between event kinds, this NIP only describes a general +extensible framework for performing such queries. -## `keywords` filter field +## `search` filter field -A new `keywords` field is introduced for `REQ` messages from clients: +A new `search` field is introduced for `REQ` messages from clients: ```json { - "kinds": - "keywords": + ... + "search": } ``` -A filter with `keywords` field MUST also include `kinds` field. This NIP specifies the behavior for kinds `0` and `1`, -if none of these kinds are provided along with `keywords`, relay SHOULD ignore the filter, and MAY send -a `NOTICE` to inform the client. Future NIPs will specify behavior for other event kinds. +`search` field is a string describing a query in a human-readable form, i.e. "best nostr apps". +Relays SHOULD interpret the query to the best of their ability and return events that match it. +Relays SHOULD perform matching against `content` event field, and MAY perform +matching against other fields if that makes sense in the context of a specific kind. -A filter matches if one of the provided `keywords` matches. Each keyword string may contain several conditions - `words`, -all the words must match for a keyword to match. The meaning of `words` depends on event kind. +A query string may contain `key:value` pairs (two words separated by colon), these are extensions, relays SHOULD ignore +extensions they don't support. -Clients SHOULD use the supported_nips field to learn if a relay supports keyword filter queries. Clients MAY send keyword filter queries to any relay, if they are prepared to filter out extraneous responses from relays that do not support this NIP. +Clients may specify several search filters, i.e. `["REQ", "", [{"search":"orange"},{"search":"purple"}]`. Clients may +include `kinds`, `ids` and other filter field to restrict the search results to particular event kinds. -Clients SHOULD query several relays supporting this NIP and specific kind to compensate for potentially different -implementation details between relays (like string sanitization, etc). +Clients SHOULD use the supported_nips field to learn if a relay supports `search` filter. Clients MAY send `search` +filter queries to any relay, if they are prepared to filter out extraneous responses from relays that do not support this NIP. -Clients SHOULD verify that events returned by a relay match the specified `keywords` in the way that suits the +Clients SHOULD query several relays supporting this NIP to compensate for potentially different +implementation details between relays. + +Clients MAY verify that events returned by a relay match the specified query in a way that suits the client's use case, and MAY stop querying relays that have low precision. -## Keyword search for kind `0` and kind `1` +Relays SHOULD exclude spam from search results by default if they supports some form of spam filtering. -For kind `0` and kind `1`, each keyword is a lowercase string consisting of words separated by spaces (in most languages), punctuation/control -characters are ignored. - -For kind `1`, an event must include all words in it's `content` field for it to match the keyword. - -For kind `0`, an event must include all mentioned words in the json object stored at the `content` field. Recommended -json fields for matching are `about`, `display_name`, `name`, `nip05`, `lud06` and `lud16`. - -A keyword may contain a word starting with prefix `option:` (like `option:no_spam`), such words specify additional -constraints for event matching, and are reserved for the future extensions. Relay SHOULD ignore `option:` words that it does not support. - -Relay MAY support these options for kind `0` and kind `1` events: -- `option:no_spam` - only include events deemed 'high-quality' by whatever internal metric the relay adopts +## Extensions +Relay MAY support these extensions: +- `include:spam` - turn off spam filtering, if it was enabled by default From f89187a2581aceb99c436d5919391622a82b0713 Mon Sep 17 00:00:00 2001 From: Artur Brugeman Date: Fri, 27 Jan 2023 15:44:51 +0300 Subject: [PATCH 39/87] Change name to 'search capability' --- 50.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/50.md b/50.md index 230b8e08..ea9eb5db 100644 --- a/50.md +++ b/50.md @@ -1,8 +1,8 @@ NIP-50 ====== -Keyword Search --------------- +Search Capability +----------------- `draft` `optional` `author:brugeman` `author:mikedilger` `author:fiatjaf` From 524ff9b8052d7e8c0515f63baae218dc40c6f696 Mon Sep 17 00:00:00 2001 From: Semisol <45574030+Semisol@users.noreply.github.com> Date: Fri, 27 Jan 2023 20:49:43 +0300 Subject: [PATCH 40/87] Bech32 encoded relay entities (#196) --- 19.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/19.md b/19.md index 577399c3..e63ca005 100644 --- a/19.md +++ b/19.md @@ -34,6 +34,7 @@ These are the possible bech32 prefixes with `TLV`: - `nprofile`: a nostr profile - `nevent`: a nostr event + - `nrelay`: a nostr relay These possible standardized `TLV` types are indicated here: @@ -41,9 +42,11 @@ These possible standardized `TLV` types are indicated here: - depends on the bech32 prefix: - for `nprofile` it will be the 32 bytes of the profile public key - for `nevent` it will be the 32 bytes of the event id + - for `nrelay`, this is the relay URL. + - for `nprofile`, `nevent` and `nrelay` this may be included only once. - `1`: `relay` - A relay in which the entity (profile or event) is more likely to be found, encoded as UTF-8. This may be included multiple times. - + - not applicable to `nrelay`. ## Examples - `npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsyjh6w6` should decode into the public key hex `3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d` and vice-versa From 3b1cd96798a9c6b6607b01814b31266dc41934f0 Mon Sep 17 00:00:00 2001 From: Zack Wynne Date: Fri, 27 Jan 2023 11:47:54 -0700 Subject: [PATCH 41/87] NIP-26: fixing typo in conditions query string section --- 26.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/26.md b/26.md index 3eb1856d..1299b725 100644 --- a/26.md +++ b/26.md @@ -38,11 +38,11 @@ The following fields and operators are supported in the above query string: *Fields*: 1. `kind` - *Operators*: - - `=${KIND_NUMBER}` - delegator may only sign events of this kind + - `=${KIND_NUMBER}` - delegatee may only sign events of this kind 2. `created_at` - *Operators*: - - `<${TIMESTAMP}` - delegator may only sign events created ***before*** the specified timestamp - - `>${TIMESTAMP}` - delegator may only sign events created ***after*** the specified timestamp + - `<${TIMESTAMP}` - delegatee may only sign events created ***before*** the specified timestamp + - `>${TIMESTAMP}` - delegatee may only sign events created ***after*** the specified timestamp In order to create a single condition, you must use a supported field and operator. Multiple conditions can be used in a single query string, including on the same field. Conditions must be combined with `&`. From 57d758b07fbe7d3bf95558c93abdbd9eef6a9b42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luiz=20Pican=C3=A7o?= Date: Fri, 27 Jan 2023 21:15:00 +0000 Subject: [PATCH 42/87] Fix NIP-50 typo --- 50.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/50.md b/50.md index ea9eb5db..5bda3559 100644 --- a/50.md +++ b/50.md @@ -29,7 +29,7 @@ matching against other fields if that makes sense in the context of a specific k A query string may contain `key:value` pairs (two words separated by colon), these are extensions, relays SHOULD ignore extensions they don't support. -Clients may specify several search filters, i.e. `["REQ", "", [{"search":"orange"},{"search":"purple"}]`. Clients may +Clients may specify several search filters, i.e. `["REQ", "", { "search": "orange" }, { "kinds": [1, 2], "search": "purple" }]`. Clients may include `kinds`, `ids` and other filter field to restrict the search results to particular event kinds. Clients SHOULD use the supported_nips field to learn if a relay supports `search` filter. Clients MAY send `search` From 38074f664301b0bcb65f0b77da533ffba8df46e4 Mon Sep 17 00:00:00 2001 From: Ben Hayward Date: Wed, 1 Feb 2023 12:05:25 +0000 Subject: [PATCH 43/87] NIP-26: Advice on using after operators in conditions query string (#199) Co-authored-by: Ben Hayward --- 26.md | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/26.md b/26.md index 1299b725..955a0430 100644 --- a/26.md +++ b/26.md @@ -19,7 +19,7 @@ This NIP introduces a new tag: `delegation` which is formatted as follows: "delegation", , , - <64-bytes schnorr signature of the sha256 hash of the delegation token> + <64-byte Schnorr signature of the sha256 hash of the delegation token> ] ``` @@ -52,6 +52,8 @@ For example, the following condition strings are valid: - `kind=0&kind=1&created_at>1675721813` - `kind=1&created_at>1674777689&created_at<1675721813` +For the vast majority of use-cases, it is advisable that query strings should include a `created_at` ***after*** condition reflecting the current time, to prevent the delegatee from publishing historic notes on the delegator's behalf. + #### Example ``` @@ -64,41 +66,41 @@ privkey: 777e4f60b4aa87937e13acc84f7abcc3c93cc035cb4c1e9f7a9086dd78fffce1 pubkey: 477318cfb5427b9cfc66a9fa376150c1ddbc62115ae27cef72417eb959691396 ``` -Delegation string to grant note publishing authorization to the delegatee (477318cf) for the next 30 days. +Delegation string to grant note publishing authorization to the delegatee (477318cf) from now, for the next 30 days, given the current timestamp is `1674834236`. ```json -nostr:delegation:477318cfb5427b9cfc66a9fa376150c1ddbc62115ae27cef72417eb959691396:kind=1&created_at<1675721885 +nostr:delegation:477318cfb5427b9cfc66a9fa376150c1ddbc62115ae27cef72417eb959691396:kind=1&created_at>1674834236&created_at<1677426236 ``` -The delegator (8e0d3d3e) then signs the above delegation string, the result of which is the delegation token: +The delegator (8e0d3d3e) then signs a SHA256 hash of the above delegation string, the result of which is the delegation token: ``` -cbc49c65fe04a3181d72fb5a9f1c627e329d5f45d300a2dfed1c3e788b7834dad48a6d27d8e244af39c77381334ede97d4fd15abe80f35fda695fd9bd732aa1e +6f44d7fe4f1c09f3954640fb58bd12bae8bb8ff4120853c4693106c82e920e2b898f1f9ba9bd65449a987c39c0423426ab7b53910c0c6abfb41b30bc16e5f524 ``` The delegatee (477318cf) can now construct an event on behalf of the delegator (8e0d3d3e). The delegatee then signs the event with its own private key and publishes. ```json { - "id": "ac4c71e69c39b1bd605de812543ebfaf81d5af365354f061d48981fb61e00b8a", + "id": "e93c6095c3db1c31d15ac771f8fc5fb672f6e52cd25505099f62cd055523224f", "pubkey": "477318cfb5427b9cfc66a9fa376150c1ddbc62115ae27cef72417eb959691396", - "created_at": 1673129661, + "created_at": 1677426298, "kind": 1, "tags": [ [ "delegation", "8e0d3d3eb2881ec137a11debe736a9086715a8c8beeeda615780064d68bc25dd", - "kind=1&created_at<1675721813", - "cbc49c65fe04a3181d72fb5a9f1c627e329d5f45d300a2dfed1c3e788b7834dad48a6d27d8e244af39c77381334ede97d4fd15abe80f35fda695fd9bd732aa1e" + "kind=1&created_at>1674834236&created_at<1677426236", + "6f44d7fe4f1c09f3954640fb58bd12bae8bb8ff4120853c4693106c82e920e2b898f1f9ba9bd65449a987c39c0423426ab7b53910c0c6abfb41b30bc16e5f524" ] ], "content": "Hello, world!", - "sig": "55ed9a78d6449b8c189b6dbc34bc4bcd34dcc79e6da6c9078268fe3d7c0cbe62b1b907ffb76ba591e83895b1329bf2e6e16f3b0cd5827272e420d419c6f0f0b5" + "sig": "633db60e2e7082c13a47a6b19d663d45b2a2ebdeaf0b4c35ef83be2738030c54fc7fd56d139652937cdca875ee61b51904a1d0d0588a6acd6168d7be2909d693" } ``` -The event should be considered a valid delegation if the conditions are satisfied (`kind=1` and `created_at<1675721813` in this example) and, upon validation of the delegation token, are found to be unchanged from the conditions in the original delegation string. +The event should be considered a valid delegation if the conditions are satisfied (`kind=1`, `created_at>1674834236` and `created_at<1677426236` in this example) and, upon validation of the delegation token, are found to be unchanged from the conditions in the original delegation string. Clients should display the delegated note as if it was published directly by the delegator (8e0d3d3e). #### Relay & Client Querying Support -Relays should answer requests such as `["REQ", "", {"authors": ["A"]}]` by querying both the `pubkey` and delegation tags `[1]` value. +Relays should answer requests such as `["REQ", "", {"authors": ["A"]}]` by querying both the `pubkey` and delegation tags `[1]` value. \ No newline at end of file From 69438fc3445490a7081a09f0de65ff8c6abe723b Mon Sep 17 00:00:00 2001 From: Mike Dilger Date: Fri, 3 Feb 2023 18:52:56 +1300 Subject: [PATCH 44/87] NIP-65 Feed Advertisements --- 65.md | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 1 + 2 files changed, 60 insertions(+) create mode 100644 65.md diff --git a/65.md b/65.md new file mode 100644 index 00000000..1a947ebf --- /dev/null +++ b/65.md @@ -0,0 +1,59 @@ +NIP-65 +====== + +Feed Advertisements +------------------- + +`draft` `optional` `author:mikedilger` + +A special replaceable event meaning "Feed Advertisement" is defined as an event with kind `10002` having a list of `r` tags, one for each relay the author posts their outgoing "feed" to. + +The content is not used. + +A feed consists of events that the author posts and wishes for their followers to "follow". Normally these would be kind-1 Text Note events but is not limited as such. + +Clients SHOULD, as with all replaceable events, use only the most recent kind-10002 event they can find. + +Clients SHOULD presume that if their user has a pubkey in their ContactList (kind 3) that it is because they wish to see this author's "feed" events. But clients MAY presume otherwise. + +Clients SHOULD interpret these Feed Advertisements as being the best relays to source the "feed" events from the author of the feed advertisement. + +### Motivation + +There is a common nostr use case where users wish to follow the content produced by other users. This is evidenced by the implicit meaning of the Contact List in [NIP-02](02.md) + +Because users don't often share the same sets of relays, ad-hoc solutions have arisen to get that content, but these solutions negatively impact scalability and decentralization: + + - Most people are sending their posts to the same most popular relays in order to be more widely seen + - Many people are pulling from a large number of relays (including many duplicate events) in order to get more data + - Events are being copied between relays, oftentimes to many different relays + +### Purposes + +The purpose of this NIP is to help clients find the events of the people they follow, and to help nostr scale better. + +### Suggestions + +It is suggested that people spread their kind-10002 events to many relays, but to post their normal feed notes to a much smaller number of relays. It is suggested that clients offer a way for users to spread their Feed Advertisements to many more relays than they normally post to. + +Authors may post events outside of the feed that they wish their followers to follow by posting them to relays outside of those listed in their "Feed Advertisement". For example, an author may want to reply to someone without all of their followers watching, but in many cases they want all their replies to show up in their "feed". + +It is suggsted that relays allow any user to write their own kind-10002 event (optionally with AUTH to verify it is their own) even if they are not otherwise subscribed to the relay because + + - finding where someone posts is rather important + - these events do not have content that needs management + - relays only need to store one replaceable event per pubkey to offer this service + +### Example + +```json +{ + "kind": 10002, + "tags": [ + ["r", "wss://alicerelay.example.com"], + ["r", "wss://brando-relay.com"], + ["r", "wss://expensive-relay.example2.com"], + ], + "content": "", + ...other fields +``` diff --git a/README.md b/README.md index 829e61ba..9767f0de 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,7 @@ NIPs stand for **Nostr Implementation Possibilities**. They exist to document wh | 43 | Channel Hide Message | [28](28.md) | | 44 | Channel Mute User | [28](28.md) | | 45-49 | Public Chat Reserved | [28](28.md) | +| 10002 | Feed Advertisement | [65](65.md) | | 22242 | Client Authentication | [42](42.md) | | 10000-19999 | Replaceable Events Reserved | [16](16.md) | | 20000-29999 | Ephemeral Events Reserved | [16](16.md) | From 025beb332cfb90e56ce39c27bba909f05b04147d Mon Sep 17 00:00:00 2001 From: Jeff Jing Date: Fri, 3 Feb 2023 13:04:21 +0800 Subject: [PATCH 45/87] fix: typo --- 05.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/05.md b/05.md index a67f530e..992983f7 100644 --- a/05.md +++ b/05.md @@ -50,7 +50,7 @@ or with the **optional** `"relays"` attribute: If the pubkey matches the one given in `"names"` (as in the example above) that means the association is right and the `"nip05"` identifier is valid and can be displayed. -The optional `"relays"` attribute may contain an object with public keys as properties and arrays of relay URLs as values. When present, that can be used to help clients learn in which relays a that user may be found. Web servers which serve `/.well-known/nostr.json` files dynamically based on the query string SHOULD also serve the relays data for any name they serve in the same reply when that is available. +The optional `"relays"` attribute may contain an object with public keys as properties and arrays of relay URLs as values. When present, that can be used to help clients learn in which relays that user may be found. Web servers which serve `/.well-known/nostr.json` files dynamically based on the query string SHOULD also serve the relays data for any name they serve in the same reply when that is available. ## Finding users from their NIP-05 identifier From 7c444e3474167f7dcdcecf28b8679b022996e958 Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Fri, 3 Feb 2023 15:59:07 -0300 Subject: [PATCH 46/87] NIP-23: long-form content. --- 19.md | 11 +++++--- 23.md | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 1 + 3 files changed, 84 insertions(+), 3 deletions(-) create mode 100644 23.md diff --git a/19.md b/19.md index e63ca005..f3dd2b87 100644 --- a/19.md +++ b/19.md @@ -35,6 +35,7 @@ These are the possible bech32 prefixes with `TLV`: - `nprofile`: a nostr profile - `nevent`: a nostr event - `nrelay`: a nostr relay + - `nref`: a nostr parameterized replaceable event coordinate (NIP-33) These possible standardized `TLV` types are indicated here: @@ -42,11 +43,15 @@ These possible standardized `TLV` types are indicated here: - depends on the bech32 prefix: - for `nprofile` it will be the 32 bytes of the profile public key - for `nevent` it will be the 32 bytes of the event id - - for `nrelay`, this is the relay URL. + - for `nrelay`, this is the relay URL + - for `nref`, it is the identifier (the `"d"` tag) of the event being referenced - for `nprofile`, `nevent` and `nrelay` this may be included only once. - `1`: `relay` - - A relay in which the entity (profile or event) is more likely to be found, encoded as UTF-8. This may be included multiple times. - - not applicable to `nrelay`. + - for `nprofile`, `nevent` and `nref`, a relay in which the entity (profile or event) is more likely to be found, encoded as UTF-8. This may be included multiple times +- `2`: `author` + - for `nref`, the 32 bytes of the pubkey of the event + + ## Examples - `npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsyjh6w6` should decode into the public key hex `3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d` and vice-versa diff --git a/23.md b/23.md new file mode 100644 index 00000000..b8b86989 --- /dev/null +++ b/23.md @@ -0,0 +1,75 @@ +NIP-23 +====== + +Long-form Content +----------------- + +`draft` `optional` `author:fiatjaf` + +This NIP defines `kind:30023` (a parameterized replaceable event according to NIP-33) for long-form text content, generally referred to as "articles" or "blog posts". + +"Social" clients that deal primarily with `kind:1` notes should not be expected to implement this NIP. + +### Format + +The `.content` of these events should be a string text in Markdown syntax, including YAML front-matter for other metadata that may be necessary. + +### Metadata + +This NIP defines only `title` as the metadata. For the date of publication the event `.created_at` field should be used, and for "tags"/"hashtags" (i.e. topics about which the event might be of relevance) the `"t"` event tag should be used, as in NIP-12. + +### Editability + +These articles are meant to be editable, so they should make use of the replaceability feature of NIP-33 and include a `"d"` tag with an identifier for the article. Clients should take care to only publish and read these events from relays that implement that. If they don't do that they should also take care to hide old versions of the same article they may receive. + +### Linking + +The article may be linked to using the NIP-19 `nref` code, which should contain both the public key of the author and the article identifier (the `"d"` tag) and some relays. With that information it is possible to locate the article. + +### References + +Writing clients should implement support for parsing pasted NIP-19 `nref` identifiers and adding them automatically to the list of `.tags` of the event, replacing the actual content with a string like `#[tag_index]` in the same way as NIP-08 -- or, if the reference is in the form of a URL (for example, `[click here](nref...)`) then they should be replaced with just the tag number directly (for example, `[click here][0]`). + +Reader clients should parse the Markdown and replace these references with either internal links so the referenced events can be accessed directly, with NIP-21 `nostr:` links or direct links to web clients that will handle these references. + +The idea here is that having these tags is that reader clients can display a list of backreferences at the bottom when one article mentions another. + +### `kind:1` interface + +In case there is the desire for users or clients to share the written article on their "social" clients, a `kind:1` event must be used. + +Since "social" clients aren't expected to understand this NIP, these notes should contain a URL like `nostr:nref1...` specifying the `nref1` code for the article, such that it can be rendered clickable and other users can use a different client than their "social" to read the article -- and also if their client handles both kinds of posts, their client may recognize the URL and handle it internally. + +For clients that want to implement the ability for users to comment on these articles. `kind:1` notes should be used as the comments. They must be made in reply to another `kind:1` as above, such that other people on "social" clients can see the comments and get the context from the note above and load the article being commented on if they so desire. + +## Example of an event + +Article text: + +```markdown +title: Lorem Ipsum +--- + +Lorem [ipsum][4] dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. + +Read more at #[3]. +``` + +Derived event: + +```json +{ + "kind": 30023, + "created_at": 1000000000, + "title": "Lorem Ipsum\\n---\\n\\nLorem [ipsum][4] dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n\nRead more at #[3].", + "tags": [ + ["d", "lorem-ipsum"], + ["t", "lorem"], + ["t", "ipsum"], + ["e", "b3e392b11f5d4f28321cedd09303a748acfd0487aea5a7450b3481c60b6e4f87", "wss://relay.example.com"], + ["e", "a695f6b60119d9521934a691347d9f78e8770b56da16bb255ee286ddf9fda919", "wss://relay.nostr.org"] + ], + "pubkey": "...", + "id": "..." +} +``` diff --git a/README.md b/README.md index 829e61ba..0115e682 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ NIPs stand for **Nostr Implementation Possibilities**. They exist to document wh | 3 | Contacts | [2](02.md) | | 4 | Encrypted Direct Messages | [4](04.md) | | 5 | Event Deletion | [9](09.md) | +| 30023 | Long-form Content | [23](23.md) | | 7 | Reaction | [25](25.md) | | 40 | Channel Creation | [28](28.md) | | 41 | Channel Metadata | [28](28.md) | From 0acfd0e84badd3bc54f680e3617ab045a844919c Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Sat, 4 Feb 2023 07:16:16 -0300 Subject: [PATCH 47/87] declare `nref` on NIP-33. remove need for NIP-01 bridge event. --- 23.md | 16 +++++----------- 33.md | 18 ++++++++++++++++-- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/23.md b/23.md index b8b86989..15597887 100644 --- a/23.md +++ b/23.md @@ -24,23 +24,17 @@ These articles are meant to be editable, so they should make use of the replacea ### Linking -The article may be linked to using the NIP-19 `nref` code, which should contain both the public key of the author and the article identifier (the `"d"` tag) and some relays. With that information it is possible to locate the article. +The article may be linked to using the NIP-19 `nref` code along with the `"f"` tag (see NIP-33 and NIP-19). ### References -Writing clients should implement support for parsing pasted NIP-19 `nref` identifiers and adding them automatically to the list of `.tags` of the event, replacing the actual content with a string like `#[tag_index]` in the same way as NIP-08 -- or, if the reference is in the form of a URL (for example, `[click here](nref...)`) then they should be replaced with just the tag number directly (for example, `[click here][0]`). +Writing clients should implement support for parsing pasted NIP-19 `nref` identifiers and adding them automatically to the list of `.tags` of the event, replacing the actual content with a string like `#[tag_index]` in the same way as NIP-08 -- or, if the reference is in the form of a URL (for example, `[click here](nref1...)`) then they should be replaced with just the tag number directly as if link with that name existed at the bottom of the Markdown (for example, `[click here][0]`). -Reader clients should parse the Markdown and replace these references with either internal links so the referenced events can be accessed directly, with NIP-21 `nostr:` links or direct links to web clients that will handle these references. +Reader clients should parse the Markdown and replace these references with either internal links so the referenced events can be accessed directly, with NIP-21 `nostr:nref1...` links or direct links to web clients that will handle these references. The idea here is that having these tags is that reader clients can display a list of backreferences at the bottom when one article mentions another. -### `kind:1` interface - -In case there is the desire for users or clients to share the written article on their "social" clients, a `kind:1` event must be used. - -Since "social" clients aren't expected to understand this NIP, these notes should contain a URL like `nostr:nref1...` specifying the `nref1` code for the article, such that it can be rendered clickable and other users can use a different client than their "social" to read the article -- and also if their client handles both kinds of posts, their client may recognize the URL and handle it internally. - -For clients that want to implement the ability for users to comment on these articles. `kind:1` notes should be used as the comments. They must be made in reply to another `kind:1` as above, such that other people on "social" clients can see the comments and get the context from the note above and load the article being commented on if they so desire. +The same principles can be applied to `nevent1...`, `note1...`, `nprofile1...` or `npub1...`. ## Example of an event @@ -67,7 +61,7 @@ Derived event: ["t", "lorem"], ["t", "ipsum"], ["e", "b3e392b11f5d4f28321cedd09303a748acfd0487aea5a7450b3481c60b6e4f87", "wss://relay.example.com"], - ["e", "a695f6b60119d9521934a691347d9f78e8770b56da16bb255ee286ddf9fda919", "wss://relay.nostr.org"] + ["f", "a695f6b60119d9521934a691347d9f78e8770b56da16bb255ee286ddf9fda919:ipsum", "wss://relay.nostr.org"] ], "pubkey": "...", "id": "..." diff --git a/33.md b/33.md index 6b05bd06..314cc836 100644 --- a/33.md +++ b/33.md @@ -12,10 +12,10 @@ Implementation -------------- The value of a tag is defined as the first parameter of a tag after the tag name. -A *parameterized replaceable event* is defined as an event with a kind `30000 <= n < 40000`. +A *parameterized replaceable event* is defined as an event with a kind `30000 <= n < 40000`. Upon a parameterized replaceable event with a newer timestamp than the currently known latest replaceable event with the same kind and first `d` tag value being received, the old event -SHOULD be discarded and replaced with the newer event. +SHOULD be discarded and replaced with the newer event. A missing or a `d` tag with no value should be interpreted equivalent to a `d` tag with the value as an empty string. Events from the same author with any of the following `tags` replace each other: @@ -30,6 +30,20 @@ replace each other: Clients SHOULD NOT use `d` tags with multiple values and SHOULD include the `d` tag even if it has no value to allow querying using the `#d` filter. +Referencing and tagging +----------------------- + +Normally (as per NIP-01, NIP-12) the `"p"` tag is used for referencing public keys and the +`"e"` tag for referencing event ids and the `note`, `npub`, `nprofile` or `nevent` are their +equivalents for event tags (i.e. an `nprofile` is generally translated into a tag +`["p", "", ""]`). + +To support linking to parameterized replaceable events, the `nref` code is introduced on +NIP-19. It includes the public key of the event author and the `d` tag (and relays) such that +the referenced combination of public key and `d` tag can be found. + +The equivalent in `tags` to the `nref` code is the tag `"f"`, comprised of `["f", ":", ""]`. + Client Behavior --------------- From 251382552355258f19403c8ddc8bd63a7c74bd19 Mon Sep 17 00:00:00 2001 From: Mike Dilger Date: Sun, 5 Feb 2023 03:50:26 +1300 Subject: [PATCH 48/87] Rename, recognize read relays --- 65.md | 33 ++++++++++++++++++++++----------- README.md | 2 +- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/65.md b/65.md index 1a947ebf..01c2723b 100644 --- a/65.md +++ b/65.md @@ -1,22 +1,28 @@ NIP-65 ====== -Feed Advertisements +Relay List Metadata ------------------- `draft` `optional` `author:mikedilger` -A special replaceable event meaning "Feed Advertisement" is defined as an event with kind `10002` having a list of `r` tags, one for each relay the author posts their outgoing "feed" to. +A special replaceable event meaning "Relay List Metadata" is defined as an event with kind `10002` having a list of `r` tags, one for each relay the author uses to either read or write to. -The content is not used. +The primary purpose of this relay list is to advertise to others, not for configuring one's client. -A feed consists of events that the author posts and wishes for their followers to "follow". Normally these would be kind-1 Text Note events but is not limited as such. +The content is not used and SHOULD be blank. + +The `r` tags can have a second parameter as either `read` or `write`. If it is omitted, it means the author both reads from and writes to that relay. Clients SHOULD, as with all replaceable events, use only the most recent kind-10002 event they can find. -Clients SHOULD presume that if their user has a pubkey in their ContactList (kind 3) that it is because they wish to see this author's "feed" events. But clients MAY presume otherwise. +### The meaning of read and write -Clients SHOULD interpret these Feed Advertisements as being the best relays to source the "feed" events from the author of the feed advertisement. +If an author advertises a write relay in a kind `10002` event, that means that feed-related events created by the author, which the author wants their followers to see, will be posted there. Normally these would be kind-1 Text Note events, but are not limited as such. + +Clients SHOULD presume that if their user has a pubkey in their ContactList (kind 3) that it is because they wish to see that author's feed-related events. But clients MAY presume otherwise. + +If an author advertises a read relay in a kind `10002` event, that means that the author may be subscribed to events that tag them on such relays. Clients SHOULD publish events that tag someone on at least the read relays of the person being tagged. ### Motivation @@ -30,20 +36,24 @@ Because users don't often share the same sets of relays, ad-hoc solutions have a ### Purposes -The purpose of this NIP is to help clients find the events of the people they follow, and to help nostr scale better. +The purpose of this NIP is to help clients find the events of the people they follow, to help tagged events get to the people tagged, and to help nostr scale better. ### Suggestions -It is suggested that people spread their kind-10002 events to many relays, but to post their normal feed notes to a much smaller number of relays. It is suggested that clients offer a way for users to spread their Feed Advertisements to many more relays than they normally post to. +It is suggested that people spread their kind `10002` events to many relays, but write their normal feed-related events to a much smaller number of relays (between 2 to 6 relays). It is suggested that clients offer a way for users to spread their kind `10002` events to many more relays than they normally post to. -Authors may post events outside of the feed that they wish their followers to follow by posting them to relays outside of those listed in their "Feed Advertisement". For example, an author may want to reply to someone without all of their followers watching, but in many cases they want all their replies to show up in their "feed". +Authors may post events outside of the feed that they wish their followers to follow by posting them to relays outside of those listed in their "Relay List Metadata". For example, an author may want to reply to someone without all of their followers watching. -It is suggsted that relays allow any user to write their own kind-10002 event (optionally with AUTH to verify it is their own) even if they are not otherwise subscribed to the relay because +It is suggsted that relays allow any user to write their own kind `10002` event (optionally with AUTH to verify it is their own) even if they are not otherwise subscribed to the relay because - finding where someone posts is rather important - these events do not have content that needs management - relays only need to store one replaceable event per pubkey to offer this service +### Why not in kind `0` Metadata + +Even though this is user related metadata, it is a separate event from kind `0` in order to keep it small (as it should be widely spread) and to not have content that may require moderation by relay operators so that it is more acceptable to relays. + ### Example ```json @@ -52,7 +62,8 @@ It is suggsted that relays allow any user to write their own kind-10002 event (o "tags": [ ["r", "wss://alicerelay.example.com"], ["r", "wss://brando-relay.com"], - ["r", "wss://expensive-relay.example2.com"], + ["r", "wss://expensive-relay.example2.com", "write"], + ["r", "wss://nostr-relay.example.com", "read"], ], "content": "", ...other fields diff --git a/README.md b/README.md index 9767f0de..e7ab5ec1 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ NIPs stand for **Nostr Implementation Possibilities**. They exist to document wh | 43 | Channel Hide Message | [28](28.md) | | 44 | Channel Mute User | [28](28.md) | | 45-49 | Public Chat Reserved | [28](28.md) | -| 10002 | Feed Advertisement | [65](65.md) | +| 10002 | Relay List Metadata | [65](65.md) | | 22242 | Client Authentication | [42](42.md) | | 10000-19999 | Replaceable Events Reserved | [16](16.md) | | 20000-29999 | Ephemeral Events Reserved | [16](16.md) | From 870f96b988697d6ae59ea74223b6d3b549e6af83 Mon Sep 17 00:00:00 2001 From: Mike Dilger Date: Sun, 5 Feb 2023 03:56:07 +1300 Subject: [PATCH 49/87] spelling and wording --- 65.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/65.md b/65.md index 01c2723b..c4fc2461 100644 --- a/65.md +++ b/65.md @@ -22,7 +22,7 @@ If an author advertises a write relay in a kind `10002` event, that means that f Clients SHOULD presume that if their user has a pubkey in their ContactList (kind 3) that it is because they wish to see that author's feed-related events. But clients MAY presume otherwise. -If an author advertises a read relay in a kind `10002` event, that means that the author may be subscribed to events that tag them on such relays. Clients SHOULD publish events that tag someone on at least the read relays of the person being tagged. +If an author advertises a read relay in a kind `10002` event, that means that the author may be subscribed to events that tag them on such relays. Clients SHOULD publish events that tag someone on at least some of the read relays of the person being tagged. ### Motivation @@ -44,7 +44,7 @@ It is suggested that people spread their kind `10002` events to many relays, but Authors may post events outside of the feed that they wish their followers to follow by posting them to relays outside of those listed in their "Relay List Metadata". For example, an author may want to reply to someone without all of their followers watching. -It is suggsted that relays allow any user to write their own kind `10002` event (optionally with AUTH to verify it is their own) even if they are not otherwise subscribed to the relay because +It is suggested that relays allow any user to write their own kind `10002` event (optionally with AUTH to verify it is their own) even if they are not otherwise subscribed to the relay because - finding where someone posts is rather important - these events do not have content that needs management From cf053d2a418db8ea489f6857d017eacc12cc97b5 Mon Sep 17 00:00:00 2001 From: Erik Westra Date: Mon, 6 Feb 2023 10:11:26 +1300 Subject: [PATCH 50/87] Suggested additions to NIP-05 to enhance security Proposing a couple of changes to the NIP-05 protocol to reduce the chance of fraudulent use of "verified" public keys. At present, I could create an account on a well-known verifying server under a random name, and then send DMs pretending to be someone else, and there's no easy way for users to tell who the verifying account actually belongs to. As well as displaying the name of the account on the verifying server, this PR suggests an enhancement to the JSON data being returned so that clients can redirect the user to the user's profile page on the server. This will make it much easier for users to check that someone who claims to have verified their Nostr account is who they claim to be. --- 05.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/05.md b/05.md index 992983f7..d042b301 100644 --- a/05.md +++ b/05.md @@ -35,7 +35,7 @@ It will make a GET request to `https://example.com/.well-known/nostr.json?name=b } ```` -or with the **optional** `"relays"` attribute: +or with the **optional** `"relays"` and/or `"account_uris"` attributes: ```json { @@ -44,6 +44,9 @@ or with the **optional** `"relays"` attribute: }, "relays": { "b0635d6a9851d3aed0cd6c495b282167acf761729078d975fc341b22650b07b9": [ "wss://relay.example.com", "wss://relay2.example.com" ] + }, + "account_uris": { + "b0635d6a9851d3aed0cd6c495b282167acf761729078d975fc341b22650b07b9": "https://bob.com/profile/bob" } } ```` @@ -52,6 +55,8 @@ If the pubkey matches the one given in `"names"` (as in the example above) that The optional `"relays"` attribute may contain an object with public keys as properties and arrays of relay URLs as values. When present, that can be used to help clients learn in which relays that user may be found. Web servers which serve `/.well-known/nostr.json` files dynamically based on the query string SHOULD also serve the relays data for any name they serve in the same reply when that is available. +The optional `"account_uris"` attribute may contain an object with public keys as properties and URIs as values. When present, this allows clients to direct their users to a URI which provides more information about the account on the server which was used to validate the given public key. Clients should ignore any URIs which don't include the server's ``. + ## Finding users from their NIP-05 identifier A client may implement support for finding users' public keys from _internet identifiers_, the flow is the same as above, but reversed: first the client fetches the _well-known_ URL and from there it gets the public key of the user, then it tries to fetch the kind `0` event for that user and check if it has a matching `"nip05"`. @@ -66,6 +71,10 @@ For example, if after finding that `bob@bob.com` has the public key `abc...def`, Keys must be returned in hex format. Keys in NIP-19 `npub` format are are only meant to be used for display in client UIs, not in this NIP. +### Clients should display the name used to verify the public key + +While users can choose their own Nostr username, displaying that username beside the "verified" icon and the name of the verifying server alone is an invitation for abuse. A malicious user could verify their public key using one account name, and then display a different account name within Nostr, misleading users into thinking they are someone else. To prevent this, clients should display the user's account name on the verifying server, rather than (or in addition to) their self-selected username within Nostr. + ### User Discovery implementation suggestion A client can also use this to allow users to search other profiles. If a client has a search box or something like that, a user may be able to type "bob@example.com" there and the client would recognize that and do the proper queries to obtain a pubkey and suggest that to the user. From 16b50a481fa7c373ba8dfbdc92c3b880fecd235a Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Sun, 5 Feb 2023 20:23:59 -0300 Subject: [PATCH 51/87] rename `nref` to `nitem` and use the `i` tag. --- 19.md | 8 ++++---- 23.md | 15 +++++++-------- 33.md | 4 ++-- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/19.md b/19.md index f3dd2b87..caf60f97 100644 --- a/19.md +++ b/19.md @@ -35,7 +35,7 @@ These are the possible bech32 prefixes with `TLV`: - `nprofile`: a nostr profile - `nevent`: a nostr event - `nrelay`: a nostr relay - - `nref`: a nostr parameterized replaceable event coordinate (NIP-33) + - `nitem`: a nostr parameterized replaceable event coordinate (NIP-33) These possible standardized `TLV` types are indicated here: @@ -44,12 +44,12 @@ These possible standardized `TLV` types are indicated here: - for `nprofile` it will be the 32 bytes of the profile public key - for `nevent` it will be the 32 bytes of the event id - for `nrelay`, this is the relay URL - - for `nref`, it is the identifier (the `"d"` tag) of the event being referenced + - for `nitem`, it is the identifier (the `"d"` tag) of the event being referenced - for `nprofile`, `nevent` and `nrelay` this may be included only once. - `1`: `relay` - - for `nprofile`, `nevent` and `nref`, a relay in which the entity (profile or event) is more likely to be found, encoded as UTF-8. This may be included multiple times + - for `nprofile`, `nevent` and `nitem`, a relay in which the entity (profile or event) is more likely to be found, encoded as UTF-8. This may be included multiple times - `2`: `author` - - for `nref`, the 32 bytes of the pubkey of the event + - for `nitem`, the 32 bytes of the pubkey of the event ## Examples diff --git a/23.md b/23.md index 15597887..d1353aff 100644 --- a/23.md +++ b/23.md @@ -24,13 +24,13 @@ These articles are meant to be editable, so they should make use of the replacea ### Linking -The article may be linked to using the NIP-19 `nref` code along with the `"f"` tag (see NIP-33 and NIP-19). +The article may be linked to using the NIP-19 `nitem` code along with the `"i"` tag (see NIP-33 and NIP-19). ### References -Writing clients should implement support for parsing pasted NIP-19 `nref` identifiers and adding them automatically to the list of `.tags` of the event, replacing the actual content with a string like `#[tag_index]` in the same way as NIP-08 -- or, if the reference is in the form of a URL (for example, `[click here](nref1...)`) then they should be replaced with just the tag number directly as if link with that name existed at the bottom of the Markdown (for example, `[click here][0]`). +Writing clients should implement support for parsing pasted NIP-19 `nitem` identifiers and adding them automatically to the list of `.tags` of the event, replacing the actual content with a string like `#[tag_index]` in the same way as NIP-08 -- or, if the reference is in the form of a URL (for example, `[click here](nitem1...)`) then they should be replaced with just the tag number directly as if link with that name existed at the bottom of the Markdown (for example, `[click here][0]`). -Reader clients should parse the Markdown and replace these references with either internal links so the referenced events can be accessed directly, with NIP-21 `nostr:nref1...` links or direct links to web clients that will handle these references. +Reader clients should parse the Markdown and replace these references with either internal links so the referenced events can be accessed directly, with NIP-21 `nostr:nitem1...` links or direct links to web clients that will handle these references. The idea here is that having these tags is that reader clients can display a list of backreferences at the bottom when one article mentions another. @@ -44,9 +44,9 @@ Article text: title: Lorem Ipsum --- -Lorem [ipsum][4] dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. +Lorem [ipsum][3] dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. -Read more at #[3]. +Read more at #[2]. ``` Derived event: @@ -58,10 +58,9 @@ Derived event: "title": "Lorem Ipsum\\n---\\n\\nLorem [ipsum][4] dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n\nRead more at #[3].", "tags": [ ["d", "lorem-ipsum"], - ["t", "lorem"], - ["t", "ipsum"], + ["t", "plceholder"], ["e", "b3e392b11f5d4f28321cedd09303a748acfd0487aea5a7450b3481c60b6e4f87", "wss://relay.example.com"], - ["f", "a695f6b60119d9521934a691347d9f78e8770b56da16bb255ee286ddf9fda919:ipsum", "wss://relay.nostr.org"] + ["i", "30023:a695f6b60119d9521934a691347d9f78e8770b56da16bb255ee286ddf9fda919:ipsum", "wss://relay.nostr.org"] ], "pubkey": "...", "id": "..." diff --git a/33.md b/33.md index 314cc836..5b8ad66c 100644 --- a/33.md +++ b/33.md @@ -38,11 +38,11 @@ Normally (as per NIP-01, NIP-12) the `"p"` tag is used for referencing public ke equivalents for event tags (i.e. an `nprofile` is generally translated into a tag `["p", "", ""]`). -To support linking to parameterized replaceable events, the `nref` code is introduced on +To support linking to parameterized replaceable events, the `nitem` code is introduced on NIP-19. It includes the public key of the event author and the `d` tag (and relays) such that the referenced combination of public key and `d` tag can be found. -The equivalent in `tags` to the `nref` code is the tag `"f"`, comprised of `["f", ":", ""]`. +The equivalent in `tags` to the `nitem` code is the tag `"i"`, comprised of `["i", "::", ""]`. Client Behavior --------------- From ea48646a0f2773c9b55bf8ff851eae98b200b3d3 Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Sun, 5 Feb 2023 21:18:38 -0300 Subject: [PATCH 52/87] get rid of YAML frontmatter. --- 23.md | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/23.md b/23.md index d1353aff..54009661 100644 --- a/23.md +++ b/23.md @@ -12,11 +12,18 @@ This NIP defines `kind:30023` (a parameterized replaceable event according to NI ### Format -The `.content` of these events should be a string text in Markdown syntax, including YAML front-matter for other metadata that may be necessary. +The `.content` of these events should be a string text in Markdown syntax. ### Metadata -This NIP defines only `title` as the metadata. For the date of publication the event `.created_at` field should be used, and for "tags"/"hashtags" (i.e. topics about which the event might be of relevance) the `"t"` event tag should be used, as in NIP-12. +For the date of the last update the `.created_at` field should be used, for "tags"/"hashtags" (i.e. topics about which the event might be of relevance) the `"t"` event tag should be used, as per NIP-12. + +Other metadata fields can be added as tags to the event as necessary. Here we standardize 4 that may be useful, although they remain strictly optional: + +- `"title"`, for the article title +- `"image"`, for an image to be shown along with the title +- `"summary"`, for the article summary +- `"published_at"`, for the timestamp in unix seconds (stringified) of the first time the article was published ### Editability @@ -36,29 +43,18 @@ The idea here is that having these tags is that reader clients can display a lis The same principles can be applied to `nevent1...`, `note1...`, `nprofile1...` or `npub1...`. -## Example of an event - -Article text: - -```markdown -title: Lorem Ipsum ---- - -Lorem [ipsum][3] dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. - -Read more at #[2]. -``` - -Derived event: +## Example Event ```json { "kind": 30023, - "created_at": 1000000000, - "title": "Lorem Ipsum\\n---\\n\\nLorem [ipsum][4] dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n\nRead more at #[3].", + "created_at": 1675642635, + "title": "Lorem [ipsum][4] dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n\nRead more at #[3].", "tags": [ ["d", "lorem-ipsum"], - ["t", "plceholder"], + ["title", "Lorem Ipsum"], + ["published_at", "1296962229"], + ["t", "placeholder"], ["e", "b3e392b11f5d4f28321cedd09303a748acfd0487aea5a7450b3481c60b6e4f87", "wss://relay.example.com"], ["i", "30023:a695f6b60119d9521934a691347d9f78e8770b56da16bb255ee286ddf9fda919:ipsum", "wss://relay.nostr.org"] ], From 5a5ef4a82d4e9f289ee15939deda3caf87ebde73 Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Mon, 6 Feb 2023 08:11:11 -0300 Subject: [PATCH 53/87] encode `kind` into `nitem` --- 19.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/19.md b/19.md index caf60f97..2caf8bd1 100644 --- a/19.md +++ b/19.md @@ -45,11 +45,13 @@ These possible standardized `TLV` types are indicated here: - for `nevent` it will be the 32 bytes of the event id - for `nrelay`, this is the relay URL - for `nitem`, it is the identifier (the `"d"` tag) of the event being referenced - - for `nprofile`, `nevent` and `nrelay` this may be included only once. - `1`: `relay` - - for `nprofile`, `nevent` and `nitem`, a relay in which the entity (profile or event) is more likely to be found, encoded as UTF-8. This may be included multiple times + - for `nprofile`, `nevent` and `nitem`, a relay in which the entity (profile or event) is more likely to be found, encoded as ascii + - this may be included multiple times - `2`: `author` - for `nitem`, the 32 bytes of the pubkey of the event +- `3`: `kind` + - for `nitem`, the 32-bit unsigned integer of the kind, big-endian ## Examples From 6a11f4d4cd0159c517414ffa6cfc646f8c7c9da3 Mon Sep 17 00:00:00 2001 From: kdmukai Date: Mon, 6 Feb 2023 09:21:58 -0600 Subject: [PATCH 54/87] [NIP-26] Fix for multiple `kind`s in delegation conditions (#208) --- 26.md | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/26.md b/26.md index 955a0430..0f8f64a0 100644 --- a/26.md +++ b/26.md @@ -38,20 +38,34 @@ The following fields and operators are supported in the above query string: *Fields*: 1. `kind` - *Operators*: - - `=${KIND_NUMBER}` - delegatee may only sign events of this kind + - `=${KIND_NUMBERS}` - delegatee may only sign events of listed kind(s) (comma-separated) 2. `created_at` - *Operators*: - - `<${TIMESTAMP}` - delegatee may only sign events created ***before*** the specified timestamp - - `>${TIMESTAMP}` - delegatee may only sign events created ***after*** the specified timestamp + - `<${TIMESTAMP}` - delegatee may only sign events whose `created_at` is ***before*** the specified timestamp + - `>${TIMESTAMP}` - delegatee may only sign events whose `created_at` is ***after*** the specified timestamp -In order to create a single condition, you must use a supported field and operator. Multiple conditions can be used in a single query string, including on the same field. Conditions must be combined with `&`. +Multiple conditions can be used in a single query string, including on the same field. Conditions must be combined with `&`. + +Multiple conditions should be treated as `AND` requirements; all conditions must be true for the delegated event to be valid. + +Multiple comma-separated `kind` values should be interpreted as: +``` +# kind=0,1,3000 +... AND (kind == 0 OR kind == 1 OR kind == 3000) AND ... +``` For example, the following condition strings are valid: - +- `kind=1` +- `created_at<1675721813` - `kind=1&created_at<1675721813` -- `kind=0&kind=1&created_at>1675721813` +- `kind=0,1,3000&created_at>1675721813` - `kind=1&created_at>1674777689&created_at<1675721813` +However, specifying multiple _separate_ `kind` conditions is impossible to satisfy: +- `kind=1&kind=5` + +There is no way for an event to satisfy the `AND` requirement of being both `kind`s simultaneously. + For the vast majority of use-cases, it is advisable that query strings should include a `created_at` ***after*** condition reflecting the current time, to prevent the delegatee from publishing historic notes on the delegator's behalf. #### Example From 694f2f056ef2dbee2846e092572168efbd9cc66c Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Mon, 6 Feb 2023 15:09:32 -0300 Subject: [PATCH 55/87] Update 23.md Co-authored-by: mplorentz --- 23.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/23.md b/23.md index 54009661..a3117b8a 100644 --- a/23.md +++ b/23.md @@ -21,7 +21,7 @@ For the date of the last update the `.created_at` field should be used, for "tag Other metadata fields can be added as tags to the event as necessary. Here we standardize 4 that may be useful, although they remain strictly optional: - `"title"`, for the article title -- `"image"`, for an image to be shown along with the title +- `"image"`, for a URL pointing to an image to be shown along with the title - `"summary"`, for the article summary - `"published_at"`, for the timestamp in unix seconds (stringified) of the first time the article was published From e939751f04fdcf9a04113e692493ee3a4ebc7ba5 Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Mon, 6 Feb 2023 15:10:50 -0300 Subject: [PATCH 56/87] Update 23.md Co-authored-by: mplorentz --- 23.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/23.md b/23.md index a3117b8a..cbb726be 100644 --- a/23.md +++ b/23.md @@ -35,7 +35,7 @@ The article may be linked to using the NIP-19 `nitem` code along with the `"i"` ### References -Writing clients should implement support for parsing pasted NIP-19 `nitem` identifiers and adding them automatically to the list of `.tags` of the event, replacing the actual content with a string like `#[tag_index]` in the same way as NIP-08 -- or, if the reference is in the form of a URL (for example, `[click here](nitem1...)`) then they should be replaced with just the tag number directly as if link with that name existed at the bottom of the Markdown (for example, `[click here][0]`). +Clients that support publishing NIP-23 events should implement support for parsing pasted NIP-19 `nitem` identifiers and adding them automatically to the list of `.tags` of the event, replacing the actual content with a string like `#[tag_index]` in the same way as NIP-08 -- or, if the reference is in the form of a URL (for example, `[click here](nitem1...)`) then they should be replaced with just the tag number directly as if link with that name existed at the bottom of the Markdown (for example, `[click here][0]`). Reader clients should parse the Markdown and replace these references with either internal links so the referenced events can be accessed directly, with NIP-21 `nostr:nitem1...` links or direct links to web clients that will handle these references. From 8c031aa710a8f0325620e6ac1d94e30f8a8f212b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lio=E6=9D=8E=E6=AD=90?= Date: Mon, 6 Feb 2023 16:15:08 -0800 Subject: [PATCH 57/87] Update README.md kind table (#226) --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 829e61ba..53f0aaeb 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,7 @@ NIPs stand for **Nostr Implementation Possibilities**. They exist to document wh | 44 | Channel Mute User | [28](28.md) | | 45-49 | Public Chat Reserved | [28](28.md) | | 22242 | Client Authentication | [42](42.md) | +| 1000-9999 | Regular Events Reserved | [16](16.md) | | 10000-19999 | Replaceable Events Reserved | [16](16.md) | | 20000-29999 | Ephemeral Events Reserved | [16](16.md) | | 30000-39999 | Param. Repl. Events Reserved| [33](33.md) | From b99ca748c8227d2723b5f856b004267b3c122c06 Mon Sep 17 00:00:00 2001 From: Mike Dilger Date: Wed, 8 Feb 2023 08:52:35 +1300 Subject: [PATCH 58/87] Put NIP-65 in the readme contents --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 24ade624..f4ed3d25 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ NIPs stand for **Nostr Implementation Possibilities**. They exist to document wh - [NIP-40: Expiration Timestamp](40.md) - [NIP-42: Authentication of clients to relays](42.md) - [NIP-50: Keywords filter](50.md) +- [NIP-65: Relay List Metadata](65.md) ## Event Kinds From f9e38ed00f5b11694ff93c368aacbf47ec21437a Mon Sep 17 00:00:00 2001 From: William Casarin Date: Tue, 7 Feb 2023 13:15:38 -0800 Subject: [PATCH 59/87] NIP-56: Reporting (#205) Co-authored-by: Semisol <45574030+Semisol@users.noreply.github.com> Co-authored-by: Leo Wandersleb --- 56.md | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 2 ++ 2 files changed, 84 insertions(+) create mode 100644 56.md diff --git a/56.md b/56.md new file mode 100644 index 00000000..55ee1a2e --- /dev/null +++ b/56.md @@ -0,0 +1,82 @@ + +NIP-56 +====== + +Reporting +--------- + +`draft` `optional` `author:jb55` + +A report is a `kind 1984` note that is used to report other notes for spam, +illegal and explicit content. + +The content MAY contain additional information submitted by the entity +reporting the content. + +Tags +---- + +The report event MUST include a `p` tag referencing the pubkey of the user you +are reporting. + +If reporting a note, an `e` tag MUST also be included referencing the note id. + +A `report type` string MUST be included as the 3rd entry to the `e` or `p` tag +being reported, which consists of the following report types: + +- `nudity` - depictions of nudity, porn, etc. +- `profanity` - profanity, hateful speech, etc. +- `illegal` - something which may be illegal in some jurisdiction +- `spam` - spam +- `impersonation` - someone pretending to be someone else + +Some report tags only make sense for profile reports, such as `impersonation` + +Example events +-------------- + +```json +{ + "kind": 1984, + "tags": [ + [ "p", , "nudity"] + ], + "content": "", + ... +} + +{ + "kind": 1984, + "tags": [ + [ "e", , "illegal"], + [ "p", ] + ], + "content": "He's insulting the king!", + ... +} + +{ + "kind": 1984, + "tags": [ + [ "p", , "impersonation"], + [ "p", ] + ], + "content": "Profile is imitating #[1]", + ... +} +``` + +Client behavior +--------------- + +Clients can use reports from friends to make moderation decisions if they +choose to. For instance, if 3+ of your friends report a profile as explicit, +clients can have an option to automatically blur photos from said account. + + +Relay behavior +-------------- + +It is not recommended that relays perform automatic moderation using reports, +as they can be easily gamed. Admins could use reports from trusted moderators to +takedown illegal or explicit content if the relay does not allow such things. diff --git a/README.md b/README.md index f4ed3d25..225379b4 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ NIPs stand for **Nostr Implementation Possibilities**. They exist to document wh - [NIP-40: Expiration Timestamp](40.md) - [NIP-42: Authentication of clients to relays](42.md) - [NIP-50: Keywords filter](50.md) +- [NIP-56: Reporting](56.md) - [NIP-65: Relay List Metadata](65.md) ## Event Kinds @@ -49,6 +50,7 @@ NIPs stand for **Nostr Implementation Possibilities**. They exist to document wh | 43 | Channel Hide Message | [28](28.md) | | 44 | Channel Mute User | [28](28.md) | | 45-49 | Public Chat Reserved | [28](28.md) | +| 1984 | Reporting | [56](56.md) | | 10002 | Relay List Metadata | [65](65.md) | | 22242 | Client Authentication | [42](42.md) | | 1000-9999 | Regular Events Reserved | [16](16.md) | From 3f39a241b170a4e11d5c162c03f03da4fedb0756 Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Wed, 8 Feb 2023 08:36:07 -0300 Subject: [PATCH 60/87] Revert "[NIP-26] Fix for multiple `kind`s in delegation conditions (#208)" This reverts commit 6a11f4d4cd0159c517414ffa6cfc646f8c7c9da3. --- 26.md | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/26.md b/26.md index 0f8f64a0..955a0430 100644 --- a/26.md +++ b/26.md @@ -38,34 +38,20 @@ The following fields and operators are supported in the above query string: *Fields*: 1. `kind` - *Operators*: - - `=${KIND_NUMBERS}` - delegatee may only sign events of listed kind(s) (comma-separated) + - `=${KIND_NUMBER}` - delegatee may only sign events of this kind 2. `created_at` - *Operators*: - - `<${TIMESTAMP}` - delegatee may only sign events whose `created_at` is ***before*** the specified timestamp - - `>${TIMESTAMP}` - delegatee may only sign events whose `created_at` is ***after*** the specified timestamp + - `<${TIMESTAMP}` - delegatee may only sign events created ***before*** the specified timestamp + - `>${TIMESTAMP}` - delegatee may only sign events created ***after*** the specified timestamp -Multiple conditions can be used in a single query string, including on the same field. Conditions must be combined with `&`. - -Multiple conditions should be treated as `AND` requirements; all conditions must be true for the delegated event to be valid. - -Multiple comma-separated `kind` values should be interpreted as: -``` -# kind=0,1,3000 -... AND (kind == 0 OR kind == 1 OR kind == 3000) AND ... -``` +In order to create a single condition, you must use a supported field and operator. Multiple conditions can be used in a single query string, including on the same field. Conditions must be combined with `&`. For example, the following condition strings are valid: -- `kind=1` -- `created_at<1675721813` + - `kind=1&created_at<1675721813` -- `kind=0,1,3000&created_at>1675721813` +- `kind=0&kind=1&created_at>1675721813` - `kind=1&created_at>1674777689&created_at<1675721813` -However, specifying multiple _separate_ `kind` conditions is impossible to satisfy: -- `kind=1&kind=5` - -There is no way for an event to satisfy the `AND` requirement of being both `kind`s simultaneously. - For the vast majority of use-cases, it is advisable that query strings should include a `created_at` ***after*** condition reflecting the current time, to prevent the delegatee from publishing historic notes on the delegator's behalf. #### Example From a9dd1ce7710bd801bdc0d09c233d087ca2d3c10d Mon Sep 17 00:00:00 2001 From: Jimmy Song Date: Wed, 8 Feb 2023 23:21:40 +0400 Subject: [PATCH 61/87] Added clarification for signature to be in hex --- 01.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/01.md b/01.md index e1e94447..68efc6fc 100644 --- a/01.md +++ b/01.md @@ -26,7 +26,7 @@ The only object type that exists is the `event`, which has the following format ... // other kinds of tags may be included later ], "content": , - "sig": <64-bytes signature of the sha256 hash of the serialized event data, which is the same as the "id" field> + "sig": <64-bytes hex of the signature of the sha256 hash of the serialized event data, which is the same as the "id" field> } ``` From e91f8f22216a6a7059d5cb8670bb7a93693caa04 Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Thu, 9 Feb 2023 06:59:31 -0300 Subject: [PATCH 62/87] fix title->content typo. --- 23.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/23.md b/23.md index cbb726be..0c9923d9 100644 --- a/23.md +++ b/23.md @@ -49,7 +49,7 @@ The same principles can be applied to `nevent1...`, `note1...`, `nprofile1...` o { "kind": 30023, "created_at": 1675642635, - "title": "Lorem [ipsum][4] dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n\nRead more at #[3].", + "content": "Lorem [ipsum][4] dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n\nRead more at #[3].", "tags": [ ["d", "lorem-ipsum"], ["title", "Lorem Ipsum"], From 643de1b7dac1d00ff8344e887da54ae9edd9ee82 Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Thu, 9 Feb 2023 13:41:54 -0300 Subject: [PATCH 63/87] change kind:1 description on README. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 225379b4..72973c09 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ NIPs stand for **Nostr Implementation Possibilities**. They exist to document wh | kind | description | NIP | |-------------|-----------------------------|------------------------| | 0 | Metadata | [1](01.md), [5](05.md) | -| 1 | Text | [1](01.md) | +| 1 | Short Text Note | [1](01.md) | | 2 | Recommend Relay | [1](01.md) | | 3 | Contacts | [2](02.md) | | 4 | Encrypted Direct Messages | [4](04.md) | From a1a090160b610c69513725ae871efdb346cbd82d Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Thu, 9 Feb 2023 13:43:53 -0300 Subject: [PATCH 64/87] rewrite ranges. --- README.md | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 72973c09..54bb5d44 100644 --- a/README.md +++ b/README.md @@ -35,28 +35,28 @@ NIPs stand for **Nostr Implementation Possibilities**. They exist to document wh ## Event Kinds -| kind | description | NIP | -|-------------|-----------------------------|------------------------| -| 0 | Metadata | [1](01.md), [5](05.md) | -| 1 | Short Text Note | [1](01.md) | -| 2 | Recommend Relay | [1](01.md) | -| 3 | Contacts | [2](02.md) | -| 4 | Encrypted Direct Messages | [4](04.md) | -| 5 | Event Deletion | [9](09.md) | -| 7 | Reaction | [25](25.md) | -| 40 | Channel Creation | [28](28.md) | -| 41 | Channel Metadata | [28](28.md) | -| 42 | Channel Message | [28](28.md) | -| 43 | Channel Hide Message | [28](28.md) | -| 44 | Channel Mute User | [28](28.md) | -| 45-49 | Public Chat Reserved | [28](28.md) | -| 1984 | Reporting | [56](56.md) | -| 10002 | Relay List Metadata | [65](65.md) | -| 22242 | Client Authentication | [42](42.md) | -| 1000-9999 | Regular Events Reserved | [16](16.md) | -| 10000-19999 | Replaceable Events Reserved | [16](16.md) | -| 20000-29999 | Ephemeral Events Reserved | [16](16.md) | -| 30000-39999 | Param. Repl. Events Reserved| [33](33.md) | +| kind | description | NIP | +| ------------- | -------------------------------- | ----------------------- | +| 0 | Metadata | [1](01.md), [5](05.md) | +| 1 | Short Text Note | [1](01.md) | +| 2 | Recommend Relay | [1](01.md) | +| 3 | Contacts | [2](02.md) | +| 4 | Encrypted Direct Messages | [4](04.md) | +| 5 | Event Deletion | [9](09.md) | +| 7 | Reaction | [25](25.md) | +| 40 | Channel Creation | [28](28.md) | +| 41 | Channel Metadata | [28](28.md) | +| 42 | Channel Message | [28](28.md) | +| 43 | Channel Hide Message | [28](28.md) | +| 44 | Channel Mute User | [28](28.md) | +| 45-49 | Public Chat Reserved | [28](28.md) | +| 1984 | Reporting | [56](56.md) | +| 10002 | Relay List Metadata | [65](65.md) | +| 22242 | Client Authentication | [42](42.md) | +| 1000-9999 | Regular Events | [16](16.md) | +| 10000-19999 | Replaceable Events | [16](16.md) | +| 20000-29999 | Ephemeral Events | [16](16.md) | +| 30000-39999 | Parameterized Replaceable Events | [33](33.md) | From d87763781dc1213d7c1b53ab0a4172f8237cbdf3 Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Thu, 9 Feb 2023 17:13:35 -0300 Subject: [PATCH 65/87] clarify and change account account_uris to account_paths. --- 05.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/05.md b/05.md index d042b301..5a5b5f2e 100644 --- a/05.md +++ b/05.md @@ -35,7 +35,7 @@ It will make a GET request to `https://example.com/.well-known/nostr.json?name=b } ```` -or with the **optional** `"relays"` and/or `"account_uris"` attributes: +or with the **optional** `"relays"` and/or `"account_paths"` attributes: ```json { @@ -45,8 +45,8 @@ or with the **optional** `"relays"` and/or `"account_uris"` attributes: "relays": { "b0635d6a9851d3aed0cd6c495b282167acf761729078d975fc341b22650b07b9": [ "wss://relay.example.com", "wss://relay2.example.com" ] }, - "account_uris": { - "b0635d6a9851d3aed0cd6c495b282167acf761729078d975fc341b22650b07b9": "https://bob.com/profile/bob" + "account_paths": { + "b0635d6a9851d3aed0cd6c495b282167acf761729078d975fc341b22650b07b9": "/profile/bob" } } ```` @@ -55,7 +55,7 @@ If the pubkey matches the one given in `"names"` (as in the example above) that The optional `"relays"` attribute may contain an object with public keys as properties and arrays of relay URLs as values. When present, that can be used to help clients learn in which relays that user may be found. Web servers which serve `/.well-known/nostr.json` files dynamically based on the query string SHOULD also serve the relays data for any name they serve in the same reply when that is available. -The optional `"account_uris"` attribute may contain an object with public keys as properties and URIs as values. When present, this allows clients to direct their users to a URI which provides more information about the account on the server which was used to validate the given public key. Clients should ignore any URIs which don't include the server's ``. +The optional `"account_paths"` attribute may contain an object with public keys as properties and URIs as values. When present, this allows clients to direct their users to a URI that provides more information about the account on the same NIP-05 server -- for example, if the address is `"bob@example.com"` and the account_path for Bob's public key is `"/profile/bob"` the client may have a link to `https://example.com/profile/bob` at Bob's NIP-05 address. ## Finding users from their NIP-05 identifier From 9d0b59d381a3d70dcf9947fd6bb194b259b05f9e Mon Sep 17 00:00:00 2001 From: Matthew Lorentz Date: Thu, 9 Feb 2023 16:59:50 -0500 Subject: [PATCH 66/87] Revert "Merge pull request #227 from erikwestra/nip-05-security-proposal" This reverts commit 6d55463c89e6c944bcd49c93f90b16a0ce5fce1e, and d87763781dc1213d7c1b53ab0a4172f8237cbdf3 reversing changes made to a1a090160b610c69513725ae871efdb346cbd82d. --- 05.md | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/05.md b/05.md index 5a5b5f2e..992983f7 100644 --- a/05.md +++ b/05.md @@ -35,7 +35,7 @@ It will make a GET request to `https://example.com/.well-known/nostr.json?name=b } ```` -or with the **optional** `"relays"` and/or `"account_paths"` attributes: +or with the **optional** `"relays"` attribute: ```json { @@ -44,9 +44,6 @@ or with the **optional** `"relays"` and/or `"account_paths"` attributes: }, "relays": { "b0635d6a9851d3aed0cd6c495b282167acf761729078d975fc341b22650b07b9": [ "wss://relay.example.com", "wss://relay2.example.com" ] - }, - "account_paths": { - "b0635d6a9851d3aed0cd6c495b282167acf761729078d975fc341b22650b07b9": "/profile/bob" } } ```` @@ -55,8 +52,6 @@ If the pubkey matches the one given in `"names"` (as in the example above) that The optional `"relays"` attribute may contain an object with public keys as properties and arrays of relay URLs as values. When present, that can be used to help clients learn in which relays that user may be found. Web servers which serve `/.well-known/nostr.json` files dynamically based on the query string SHOULD also serve the relays data for any name they serve in the same reply when that is available. -The optional `"account_paths"` attribute may contain an object with public keys as properties and URIs as values. When present, this allows clients to direct their users to a URI that provides more information about the account on the same NIP-05 server -- for example, if the address is `"bob@example.com"` and the account_path for Bob's public key is `"/profile/bob"` the client may have a link to `https://example.com/profile/bob` at Bob's NIP-05 address. - ## Finding users from their NIP-05 identifier A client may implement support for finding users' public keys from _internet identifiers_, the flow is the same as above, but reversed: first the client fetches the _well-known_ URL and from there it gets the public key of the user, then it tries to fetch the kind `0` event for that user and check if it has a matching `"nip05"`. @@ -71,10 +66,6 @@ For example, if after finding that `bob@bob.com` has the public key `abc...def`, Keys must be returned in hex format. Keys in NIP-19 `npub` format are are only meant to be used for display in client UIs, not in this NIP. -### Clients should display the name used to verify the public key - -While users can choose their own Nostr username, displaying that username beside the "verified" icon and the name of the verifying server alone is an invitation for abuse. A malicious user could verify their public key using one account name, and then display a different account name within Nostr, misleading users into thinking they are someone else. To prevent this, clients should display the user's account name on the verifying server, rather than (or in addition to) their self-selected username within Nostr. - ### User Discovery implementation suggestion A client can also use this to allow users to search other profiles. If a client has a search box or something like that, a user may be able to type "bob@example.com" there and the client would recognize that and do the proper queries to obtain a pubkey and suggest that to the user. From ffe6a49557253a1f6227793787c6fcf58565a980 Mon Sep 17 00:00:00 2001 From: Jeff Thibault Date: Fri, 10 Feb 2023 08:18:40 -0500 Subject: [PATCH 67/87] NIP-04: clarify how shared secret is computed --- 04.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/04.md b/04.md index 723bd708..0ebcddb9 100644 --- a/04.md +++ b/04.md @@ -14,6 +14,8 @@ A special event with kind `4`, meaning "encrypted direct message". It is suppose **`tags`** MAY contain an entry identifying the previous message in a conversation or a message we are explicitly replying to (such that contextual, more organized conversations may happen), in the form `["e", ""]`. +**Note**: By default in the [libsecp256k1](https://github.com/bitcoin-core/secp256k1) ECDH implementation, the secret is the SHA256 hash of the shared point (both X and Y coorinates). In Nostr, only the X coordinate of the shared point is used as the secret and it is NOT hashed. If using libsecp256k1, a custom function that copies the X coordinate must be passed as the `hashfp` argument in `secp256k1_ecdh`. See [here](https://github.com/bitcoin-core/secp256k1/blob/master/src/modules/ecdh/main_impl.h#L29). + Code sample for generating such an event in JavaScript: ```js From 17ffd3ee4efa33c3f6abb4304d1c4dd998efc523 Mon Sep 17 00:00:00 2001 From: William Casarin Date: Mon, 13 Feb 2023 03:36:04 -0800 Subject: [PATCH 68/87] NIP-57: Lightning Zaps (#224) --- 57.md | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 3 ++ 2 files changed, 149 insertions(+) create mode 100644 57.md diff --git a/57.md b/57.md new file mode 100644 index 00000000..78a3fd63 --- /dev/null +++ b/57.md @@ -0,0 +1,146 @@ +NIP-57 +====== + +Lightning Zaps +-------------- + +`draft` `optional` `author:jb55` `author:kieran` + +This NIP defines a new note type called a lightning zap of kind `9735`. These represent paid lightning invoice receipts sent by a lightning node called the `zapper`. We also define another note type of kind `9734` which are `zap request` notes, which will be described in this document. + +Having lightning receipts on nostr allows clients to display lightning payments from entities on the network. These can be used for fun or for spam deterrence. + + +## Definitions + +`zapper` - the lightning node or service that sends zap notes (kind `9735`) + +`zap request` - a note of kind `9734` created by the person zapping + +`zap invoice` - the bolt11 invoice fetched from a custom lnurl endpoint which contains a `zap request` note + + +## Protocol flow + +### Client side + +1. Calculate the lnurl pay request url for a user from the lud06 or lud16 field on their profile + +2. Fetch the lnurl pay request static endpoint (`https://host.com/.well-known/lnurlp/user`) and gather the `allowsNostr` and `nostrPubkey` fields. If `allowsNostr` exists and it is `true`, and if `nostrPubkey` exists and is a valid BIP 340 public key, associate this information with the user. The `nostrPubkey` is the `zapper`'s pubkey, and it is used to authorize zaps sent to that user. + +3. Clients may choose to display a lightning zap button on each post or on the users profile, if the user's lnurl pay request endpoint supports nostr, the client SHOULD generate a `zap invoice` instead of a normal lnurl invoice. + +4. To generate a `zap invoice`, call the `callback` url with `amount` set to the milli-satoshi amount value. A `nostr` querystring value MUST be set as well. It is a uri-encoded `zap request` note signed by the user's key. The `zap request` note contains an `e` tag of the note it is zapping, and a `p` tag of the target user's pubkey. The `e` tag is optional which allows profile tipping. The `zap request` note must also have a `relays` tag, which is gathered from the user's configured relays. The `content` MAY be an additional comment from the user which can be displayed when listing zaps on posts and profiles. + +5. Pay this invoice or pass it to an app that can pay the invoice. Once it's paid, a `zap note` will be created by the `zapper`. + +### LNURL Server side + +The lnurl server will need some additional pieces of information so that clients can know that zap invoices are supported: + +1. Add a `nostrPubkey` to the lnurl-pay static endpoint `/.well-known/lnurlp/user`, where `nostrPubkey` is the nostr pubkey of the `zapper`, the entity that creates zap notes. Clients will use this to authorize zaps. + +2. Add an `allowsNostr` field and set it to true. + +3. In the lnurl-pay callback URL, watch for a `nostr` querystring, where the contents of the note is a uri-encoded `zap request` JSON. + +4. If present, the zap request note must be validated: + + a. It MUST have a valid nostr signature + + b. It MUST have tags + + c. It MUST have at least one p-tag + + d. It MUST have either 0 or 1 e-tag + + e. There should be a `relays` tag with the relays to send the `zap` note to. + +5. If valid, fetch a description hash invoice where the description is this note and this note only. No additional lnurl metadata is included in the description. + +At this point, the lightning node is ready to send the zap note once payment is received. + +## The zap note + +Zap notes are created by a lightning node reacting to paid invoices. Zap notes are only created when the invoice description (committed to the description hash) contains a `zap request` note. + +Example zap note: + +```json +{ + "id": "67b48a14fb66c60c8f9070bdeb37afdfcc3d08ad01989460448e4081eddda446", + "pubkey": "9630f464cca6a5147aa8a35f0bcdd3ce485324e732fd39e09233b1d848238f31", + "created_at": 1674164545, + "kind": 9735, + "tags": [ + [ + "p", + "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245" + ], + [ + "e", + "3624762a1274dd9636e0c552b53086d70bc88c165bc4dc0f9e836a1eaf86c3b8" + ], + [ + "bolt11", + "lnbc10u1p3unwfusp5t9r3yymhpfqculx78u027lxspgxcr2n2987mx2j55nnfs95nxnzqpp5jmrh92pfld78spqs78v9euf2385t83uvpwk9ldrlvf6ch7tpascqhp5zvkrmemgth3tufcvflmzjzfvjt023nazlhljz2n9hattj4f8jq8qxqyjw5qcqpjrzjqtc4fc44feggv7065fqe5m4ytjarg3repr5j9el35xhmtfexc42yczarjuqqfzqqqqqqqqlgqqqqqqgq9q9qxpqysgq079nkq507a5tw7xgttmj4u990j7wfggtrasah5gd4ywfr2pjcn29383tphp4t48gquelz9z78p4cq7ml3nrrphw5w6eckhjwmhezhnqpy6gyf0" + ], + [ + "description", + "{\"pubkey\":\"32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245\",\"content\":\"\",\"id\":\"d9cc14d50fcb8c27539aacf776882942c1a11ea4472f8cdec1dea82fab66279d\",\"created_at\":1674164539,\"sig\":\"77127f636577e9029276be060332ea565deaf89ff215a494ccff16ae3f757065e2bc59b2e8c113dd407917a010b3abd36c8d7ad84c0e3ab7dab3a0b0caa9835d\",\"kind\":9734,\"tags\":[[\"e\",\"3624762a1274dd9636e0c552b53086d70bc88c165bc4dc0f9e836a1eaf86c3b8\"],[\"p\",\"32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245\"],[\"relays\",\"wss://relay.damus.io\",\"wss://nostr-relay.wlvs.space\",\"wss://nostr.fmt.wiz.biz\",\"wss://relay.nostr.bg\",\"wss://nostr.oxtr.dev\",\"wss://nostr.v0l.io\",\"wss://brb.io\",\"wss://nostr.bitcoiner.social\",\"ws://monad.jb55.com:8080\",\"wss://relay.snort.social\"]]}" + ], + [ + "preimage", + "5d006d2cf1e73c7148e7519a4c68adc81642ce0e25a432b2434c99f97344c15f" + ] + ], + "content": "", + "sig": "b0a3c5c984ceb777ac455b2f659505df51585d5fd97a0ec1fdb5f3347d392080d4b420240434a3afd909207195dac1e2f7e3df26ba862a45afd8bfe101c2b1cc" + } +``` + +* The zap note MUST have a `bolt11` tag containing the description hash bolt11 invoice. + +* The zap note MUST contain a `description` tag which is the invoice description. + +* `SHA256(description)` MUST match the description hash in the bolt11 invoice. + +* The zap note MAY contain a `preimage` to match against the payment hash of the bolt11 invoice. This isn't really a payment proof, there is no real way to prove that the invoice is real or has been paid. You are trusting the author of the zap note for the legitimacy of the payment. + +The zap note is not a proof of payment, all it proves is that some nostr user fetched an invoice. The existence of the zap note implies the invoice as paid, but it could be a lie given a rogue implementation. + + +### Creating a zap note + +When receiving a payment, the following steps are executed: + +1. Get the description for the invoice. This needs to be saved somewhere during the generation of the description hash invoice. It is saved automatically for you with CLN, which is the reference implementation used here. + +2. Parse the bolt11 description as a JSON nostr note. You SHOULD check the signature of the parsed note to ensure that it is valid. This is the `zap request` note created by the entity who is zapping. + +4. The note MUST have only one `p` tag + +5. The note MUST have 0 or 1 `e` tag + +6. Create a nostr note of kind `9735` that includes the `p` tag AND optional `e` tag. The content SHOULD be empty. The created_at date SHOULD be set to the invoice paid_at date for idempotency. + +7. Send the note to the `relays` declared in the `zap request` note from the invoice description. + +A reference implementation for the zapper is here: [zapper][zapper] + +[zapper]: https://github.com/jb55/cln-nostr-zapper + + +## Client Behavior + +Clients MAY fetch zap notes on posts and profiles: + +`{"kinds": [9735], "#e": [...]}` + +To authorize these notes, clients MUST fetch the `nostrPubkey` from the users configured lightning address or lnurl and ensure that the zaps to their posts were created by this pubkey. If clients don't do this, anyone could forge unauthorized zaps. + +Once authorized, clients MAY tally zaps on posts, and list them on profiles. If the zap request note contains a non-empty `content`, it may display a zap comment. Generally clients should show users the `zap request` note, and use the `zap note` to show "zap authorized by ..." but this is optional. + +## Future Work + +Zaps can be extended to be more private by encrypting zap request notes to the target user, but for simplicity it has been left out of this initial draft. diff --git a/README.md b/README.md index 54bb5d44..d4e3c047 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ NIPs stand for **Nostr Implementation Possibilities**. They exist to document wh - [NIP-40: Expiration Timestamp](40.md) - [NIP-42: Authentication of clients to relays](42.md) - [NIP-50: Keywords filter](50.md) +- [NIP-57: Lightning Zaps](57.md) - [NIP-56: Reporting](56.md) - [NIP-65: Relay List Metadata](65.md) @@ -51,6 +52,8 @@ NIPs stand for **Nostr Implementation Possibilities**. They exist to document wh | 44 | Channel Mute User | [28](28.md) | | 45-49 | Public Chat Reserved | [28](28.md) | | 1984 | Reporting | [56](56.md) | +| 9734 | Zap Request | [57](57.md) | +| 9735 | Zap | [57](57.md) | | 10002 | Relay List Metadata | [65](65.md) | | 22242 | Client Authentication | [42](42.md) | | 1000-9999 | Regular Events | [16](16.md) | From b4493aa56abdea4b05780651e7af06ea13bbfafa Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Mon, 13 Feb 2023 08:47:23 -0300 Subject: [PATCH 69/87] rename coordinates: nitem->naddr, "i"->"a" --- 19.md | 10 +++++----- 23.md | 8 ++++---- 33.md | 4 ++-- README.md | 1 + 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/19.md b/19.md index 2caf8bd1..ab3b578d 100644 --- a/19.md +++ b/19.md @@ -35,7 +35,7 @@ These are the possible bech32 prefixes with `TLV`: - `nprofile`: a nostr profile - `nevent`: a nostr event - `nrelay`: a nostr relay - - `nitem`: a nostr parameterized replaceable event coordinate (NIP-33) + - `naddr`: a nostr parameterized replaceable event coordinate (NIP-33) These possible standardized `TLV` types are indicated here: @@ -44,14 +44,14 @@ These possible standardized `TLV` types are indicated here: - for `nprofile` it will be the 32 bytes of the profile public key - for `nevent` it will be the 32 bytes of the event id - for `nrelay`, this is the relay URL - - for `nitem`, it is the identifier (the `"d"` tag) of the event being referenced + - for `naddr`, it is the identifier (the `"d"` tag) of the event being referenced - `1`: `relay` - - for `nprofile`, `nevent` and `nitem`, a relay in which the entity (profile or event) is more likely to be found, encoded as ascii + - for `nprofile`, `nevent` and `naddr`, a relay in which the entity (profile or event) is more likely to be found, encoded as ascii - this may be included multiple times - `2`: `author` - - for `nitem`, the 32 bytes of the pubkey of the event + - for `naddr`, the 32 bytes of the pubkey of the event - `3`: `kind` - - for `nitem`, the 32-bit unsigned integer of the kind, big-endian + - for `naddr`, the 32-bit unsigned integer of the kind, big-endian ## Examples diff --git a/23.md b/23.md index 0c9923d9..0648a354 100644 --- a/23.md +++ b/23.md @@ -31,13 +31,13 @@ These articles are meant to be editable, so they should make use of the replacea ### Linking -The article may be linked to using the NIP-19 `nitem` code along with the `"i"` tag (see NIP-33 and NIP-19). +The article may be linked to using the NIP-19 `naddr` code along with the `"a"` tag (see NIP-33 and NIP-19). ### References -Clients that support publishing NIP-23 events should implement support for parsing pasted NIP-19 `nitem` identifiers and adding them automatically to the list of `.tags` of the event, replacing the actual content with a string like `#[tag_index]` in the same way as NIP-08 -- or, if the reference is in the form of a URL (for example, `[click here](nitem1...)`) then they should be replaced with just the tag number directly as if link with that name existed at the bottom of the Markdown (for example, `[click here][0]`). +Clients that support publishing NIP-23 events should implement support for parsing pasted NIP-19 `naddr` identifiers and adding them automatically to the list of `.tags` of the event, replacing the actual content with a string like `#[tag_index]` in the same way as NIP-08 -- or, if the reference is in the form of a URL (for example, `[click here](naddr1...)`) then they should be replaced with just the tag number directly as if link with that name existed at the bottom of the Markdown (for example, `[click here][0]`). -Reader clients should parse the Markdown and replace these references with either internal links so the referenced events can be accessed directly, with NIP-21 `nostr:nitem1...` links or direct links to web clients that will handle these references. +Reader clients should parse the Markdown and replace these references with either internal links so the referenced events can be accessed directly, with NIP-21 `nostr:naddr1...` links or direct links to web clients that will handle these references. The idea here is that having these tags is that reader clients can display a list of backreferences at the bottom when one article mentions another. @@ -56,7 +56,7 @@ The same principles can be applied to `nevent1...`, `note1...`, `nprofile1...` o ["published_at", "1296962229"], ["t", "placeholder"], ["e", "b3e392b11f5d4f28321cedd09303a748acfd0487aea5a7450b3481c60b6e4f87", "wss://relay.example.com"], - ["i", "30023:a695f6b60119d9521934a691347d9f78e8770b56da16bb255ee286ddf9fda919:ipsum", "wss://relay.nostr.org"] + ["a", "30023:a695f6b60119d9521934a691347d9f78e8770b56da16bb255ee286ddf9fda919:ipsum", "wss://relay.nostr.org"] ], "pubkey": "...", "id": "..." diff --git a/33.md b/33.md index 5b8ad66c..409ce4f7 100644 --- a/33.md +++ b/33.md @@ -38,11 +38,11 @@ Normally (as per NIP-01, NIP-12) the `"p"` tag is used for referencing public ke equivalents for event tags (i.e. an `nprofile` is generally translated into a tag `["p", "", ""]`). -To support linking to parameterized replaceable events, the `nitem` code is introduced on +To support linking to parameterized replaceable events, the `naddr` code is introduced on NIP-19. It includes the public key of the event author and the `d` tag (and relays) such that the referenced combination of public key and `d` tag can be found. -The equivalent in `tags` to the `nitem` code is the tag `"i"`, comprised of `["i", "::", ""]`. +The equivalent in `tags` to the `naddr` code is the tag `"a"`, comprised of `["a", "::", ""]`. Client Behavior --------------- diff --git a/README.md b/README.md index 42cbc0c9..c88d9490 100644 --- a/README.md +++ b/README.md @@ -92,6 +92,7 @@ When experimenting with kinds, keep in mind the classification introduced by [NI | ---------- | ----------------------- | ----------------- | ------------------------ | | e | event id (hex) | relay URL, marker | [1](01.md), [10](10.md) | | p | pubkey (hex) | relay URL | [1](01.md) | +| a | coordinates to an event | relay URL | [33](33.md), [23](23.md) | | r | a reference (URL, etc) | | [12](12.md) | | t | hashtag | | [12](12.md) | | g | geohash | | [12](12.md) | From b00888cec79b495f8c01d5abdbf2e1ed373896ab Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Mon, 13 Feb 2023 09:00:09 -0300 Subject: [PATCH 70/87] add nip23 to list. --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c88d9490..7bef8f36 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ NIPs stand for **Nostr Implementation Possibilities**. They exist to document wh - [NIP-07: `window.nostr` capability for web browsers](07.md) - [NIP-08: Handling Mentions](08.md) - [NIP-09: Event Deletion](09.md) -- [NIP-10: Conventions for clients' use of `e` and `p` tags in text events.](10.md) +- [NIP-10: Conventions for clients' use of `e` and `p` tags in text events](10.md) - [NIP-11: Relay Information Document](11.md) - [NIP-12: Generic Tag Queries](12.md) - [NIP-13: Proof of Work](13.md) @@ -21,7 +21,8 @@ NIPs stand for **Nostr Implementation Possibilities**. They exist to document wh - [NIP-19: bech32-encoded entities](19.md) - [NIP-20: Command Results](20.md) - [NIP-21: `nostr:` URL scheme](21.md) -- [NIP-22: Event created_at Limits](22.md) +- [NIP-22: Event `created_at` Limits](22.md) +- [NIP-23: Long-form Content](23.md) - [NIP-25: Reactions](25.md) - [NIP-26: Delegated Event Signing](26.md) - [NIP-28: Public Chat](28.md) From c80cb09e8097c78640756f72d6ba79286a193dee Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Mon, 13 Feb 2023 14:06:21 -0300 Subject: [PATCH 71/87] simplify description. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7bef8f36..8f316561 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # NIPs -NIPs stand for **Nostr Implementation Possibilities**. They exist to document what MUST, what SHOULD and what MAY be implemented by [Nostr](https://github.com/fiatjaf/nostr)-compatible _relay_ and _client_ software. +NIPs stand for **Nostr Implementation Possibilities**. They exist to document what may be implemented by [Nostr](https://github.com/fiatjaf/nostr)-compatible _relay_ and _client_ software. - [NIP-01: Basic protocol flow description](01.md) - [NIP-02: Contact List and Petnames](02.md) From 04e7f0cef80802ab7cd1fac7604170dec309ee8c Mon Sep 17 00:00:00 2001 From: Chemaclass Date: Tue, 14 Feb 2023 14:27:06 +0100 Subject: [PATCH 72/87] Fix readme sorting NIP-56/57 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8f316561..e45c531b 100644 --- a/README.md +++ b/README.md @@ -31,8 +31,8 @@ NIPs stand for **Nostr Implementation Possibilities**. They exist to document wh - [NIP-40: Expiration Timestamp](40.md) - [NIP-42: Authentication of clients to relays](42.md) - [NIP-50: Keywords filter](50.md) -- [NIP-57: Lightning Zaps](57.md) - [NIP-56: Reporting](56.md) +- [NIP-57: Lightning Zaps](57.md) - [NIP-65: Relay List Metadata](65.md) ## Event Kinds From 23b863ad65694f041bbe921168d96cd274b998d3 Mon Sep 17 00:00:00 2001 From: Adam B <13562139+catenocrypt@users.noreply.github.com> Date: Mon, 13 Feb 2023 12:34:12 +0100 Subject: [PATCH 73/87] Minor change to make delegation token/string naming consistent --- 26.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/26.md b/26.md index 955a0430..11468c07 100644 --- a/26.md +++ b/26.md @@ -19,7 +19,7 @@ This NIP introduces a new tag: `delegation` which is formatted as follows: "delegation", , , - <64-byte Schnorr signature of the sha256 hash of the delegation token> + ] ``` From 2a2c665e2719ff2e37e4aadc81a8002ebcc5c1f2 Mon Sep 17 00:00:00 2001 From: SondreB Date: Tue, 14 Feb 2023 23:39:08 +0100 Subject: [PATCH 74/87] Update the key examples with a key pair --- 19.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/19.md b/19.md index ab3b578d..45081b0e 100644 --- a/19.md +++ b/19.md @@ -56,8 +56,8 @@ These possible standardized `TLV` types are indicated here: ## Examples -- `npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsyjh6w6` should decode into the public key hex `3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d` and vice-versa -- `nsec180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsgyumg0` should decode into the private key hex `3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d` and vice-versa +- `npub10elfcs4fr0l0r8af98jlmgdh9c8tcxjvz9qkw038js35mp4dma8qzvjptg` should decode into the public key hex `7e7e9c42a91bfef19fa929e5fda1b72e0ebc1a4c1141673e2794234d86addf4e` and vice-versa +- `nsec1vl029mgpspedva04g90vltkh6fvh240zqtv9k0t9af8935ke9laqsnlfe5` should decode into the private key hex `67dea2ed018072d675f5415ecfaed7d2597555e202d85b3d65ea4e58d2d92ffa` and vice-versa - `nprofile1qqsrhuxx8l9ex335q7he0f09aej04zpazpl0ne2cgukyawd24mayt8gpp4mhxue69uhhytnc9e3k7mgpz4mhxue69uhkg6nzv9ejuumpv34kytnrdaksjlyr9p` should decode into a profile with the following TLV items: - pubkey: `3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d` - relay: `wss://r.x.com` From 6849f3bdf4739c4fe52199504092cea7247fc615 Mon Sep 17 00:00:00 2001 From: Semisol <45574030+Semisol@users.noreply.github.com> Date: Tue, 14 Feb 2023 09:38:19 +0300 Subject: [PATCH 75/87] NIP-57: Add amount tag to zap request --- 57.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/57.md b/57.md index 78a3fd63..f6fa4ccf 100644 --- a/57.md +++ b/57.md @@ -30,7 +30,7 @@ Having lightning receipts on nostr allows clients to display lightning payments 3. Clients may choose to display a lightning zap button on each post or on the users profile, if the user's lnurl pay request endpoint supports nostr, the client SHOULD generate a `zap invoice` instead of a normal lnurl invoice. -4. To generate a `zap invoice`, call the `callback` url with `amount` set to the milli-satoshi amount value. A `nostr` querystring value MUST be set as well. It is a uri-encoded `zap request` note signed by the user's key. The `zap request` note contains an `e` tag of the note it is zapping, and a `p` tag of the target user's pubkey. The `e` tag is optional which allows profile tipping. The `zap request` note must also have a `relays` tag, which is gathered from the user's configured relays. The `content` MAY be an additional comment from the user which can be displayed when listing zaps on posts and profiles. +4. To generate a `zap invoice`, call the `callback` url with `amount` set to the milli-satoshi amount value. A `nostr` querystring value MUST be set as well. It is a uri-encoded `zap request` note signed by the user's key. The `zap request` note contains an `e` tag of the note it is zapping, and a `p` tag of the target user's pubkey. The `e` tag is optional which allows profile tipping. The `zap request` note must also have a `relays` tag, which is gathered from the user's configured relays. The `zap request` note SHOULD contain an `amount` tag, which is the milli-satoshi value of the zap which clients SHOULD verify being equal to the amount of the invoice. The `content` MAY be an additional comment from the user which can be displayed when listing zaps on posts and profiles. 5. Pay this invoice or pass it to an app that can pay the invoice. Once it's paid, a `zap note` will be created by the `zapper`. @@ -56,6 +56,8 @@ The lnurl server will need some additional pieces of information so that clients e. There should be a `relays` tag with the relays to send the `zap` note to. + f. If there is an `amount` tag, it MUST be equal to the `amount` query parameter. + 5. If valid, fetch a description hash invoice where the description is this note and this note only. No additional lnurl metadata is included in the description. At this point, the lightning node is ready to send the zap note once payment is received. From 524caa38563f49fc2aacbbe48b212fde0f24f97e Mon Sep 17 00:00:00 2001 From: Mike Dilger Date: Mon, 20 Feb 2023 09:28:39 +1300 Subject: [PATCH 76/87] More explicit explanation of the meaning of read and write relays --- 65.md | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/65.md b/65.md index c4fc2461..4c7a6a53 100644 --- a/65.md +++ b/65.md @@ -10,20 +10,26 @@ A special replaceable event meaning "Relay List Metadata" is defined as an event The primary purpose of this relay list is to advertise to others, not for configuring one's client. -The content is not used and SHOULD be blank. +The content is not used and SHOULD be an empty string. -The `r` tags can have a second parameter as either `read` or `write`. If it is omitted, it means the author both reads from and writes to that relay. +The `r` tags can have a second parameter as either `read` or `write`. If it is omitted, it means the author uses the relay for both purposes. Clients SHOULD, as with all replaceable events, use only the most recent kind-10002 event they can find. ### The meaning of read and write -If an author advertises a write relay in a kind `10002` event, that means that feed-related events created by the author, which the author wants their followers to see, will be posted there. Normally these would be kind-1 Text Note events, but are not limited as such. +Write relays are for events that are intended for anybody (e.g. your followers). Read relays are for events that address a particular person. + +Clients SHOULD write feed-related events created by their user to their user's write relays. + +Clients SHOULD read feed-related events created by another from at least some of that other person's write relays. Explicitly, they SHOULD NOT expect them to be available at their user's read relays. It SHOULD NOT be presumed that the user's read relays coincide with the write relays of the people the user follows. + +Clients SHOULD read events that tag their user from their user's read relays. + +Clients SHOULD write events that tag a person to at least some of that person's read relays. Explicitly, they SHOULD NOT expect that person will pick them up from their user's write relays. It SHOULD NOT be presumed that the user's write relays coincide with the read relays of the person being tagged. Clients SHOULD presume that if their user has a pubkey in their ContactList (kind 3) that it is because they wish to see that author's feed-related events. But clients MAY presume otherwise. -If an author advertises a read relay in a kind `10002` event, that means that the author may be subscribed to events that tag them on such relays. Clients SHOULD publish events that tag someone on at least some of the read relays of the person being tagged. - ### Motivation There is a common nostr use case where users wish to follow the content produced by other users. This is evidenced by the implicit meaning of the Contact List in [NIP-02](02.md) From b1a5ad355a8b376170471a41817d8722ba7443b1 Mon Sep 17 00:00:00 2001 From: Marco Argentieri <3596602+tiero@users.noreply.github.com> Date: Mon, 20 Feb 2023 20:26:13 +0100 Subject: [PATCH 77/87] =?UTF-8?q?NIP-46:=20Nostr=20Connect=20=F0=9F=94=8C?= =?UTF-8?q?=20connect=20your=20Nostr=20app=20with=20remote=20signing=20dev?= =?UTF-8?q?ices=20(#153)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 46.md | 162 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 2 + 2 files changed, 164 insertions(+) create mode 100644 46.md diff --git a/46.md b/46.md new file mode 100644 index 00000000..a9f37c1b --- /dev/null +++ b/46.md @@ -0,0 +1,162 @@ +NIP-46 +====== + +Nostr Connect +------------------------ + +`draft` `optional` `author:tiero` `author:giowe` `author:vforvalerio87` + +## Rationale + +Private keys should be exposed to as few systems - apps, operating systems, devices - as possible as each system adds to the attack surface. + +Entering private keys can also be annoying and requires exposing them to even more systems such as the operating system's clipboard that might be monitored by malicious apps. + + +## Terms + +* **App**: Nostr app on any platform that *requires* to act on behalf of a nostr account. +* **Signer**: Nostr app that holds the private key of a nostr account and *can sign* on its behalf. + + +## `TL;DR` + + +**App** and **Signer** sends ephemeral encrypted messages to each other using kind `24133`, using a relay of choice. + +App prompts the Signer to do things such as fetching the public key or signing events. + +The `content` field must be an encrypted JSONRPC-ish **request** or **response**. + +## Signer Protocol + +### Messages + +#### Request + +```json +{ + "id": , + "method": , + "params": [, ] +} +``` + +#### Response + +```json +{ + "id": , + "result": , + "error": +} +``` + +### Methods + + +#### Mandatory + +These are mandatory methods the remote signer app MUST implement: + +- **describe** + - params [] + - result `{"get_public_key": { params: [], result: anything }}` +- **get_public_key** + - params [] + - result `pubkey` +- **sign_event** + - params [`event`] + - result `signature` + +#### optional + + +- **connect** + - params [`pubkey`] +- **disconnect** + - params [] +- **delegate** + - params [`pubkey`, `conditions query string`] + - result `nip26 delegation token` +- **get_relays** + - params [] + - result `{ [url: string]: {read: boolean, write: boolean} }` +- **nip04_encrypt** + - params [`pubkey`, `plaintext`] + - result `nip4 ciphertext` +- **nip04_decrypt** + - params [`pubkey`, `nip4 ciphertext`] + - result [`plaintext`] + + +NOTICE: `pubkey` and `signature` are hex-encoded strings. + + +### Nostr Connect URI + +**Signer** discovers **App** by scanning a QR code, clicking on a deep link or copy-pasting an URI. + +The **App** generates a special URI with prefix `nostrconnect://` and base path the hex-encoded `pubkey` with the following querystring parameters **URL encoded** + +- `relay` URL of the relay of choice where the **App** is connected and the **Signer** must send and listen for messages. +- `metadata` metadata JSON of the **App** + - `name` human-readable name of the **App** + - `url` (optional) URL of the website requesting the connection + - `description` (optional) description of the **App** + - `icons` (optional) array of URLs for icons of the **App**. + +#### JavaScript + +```js +const uri = `nostrconnect://?relay=${encodeURIComponent("wss://relay.damus.io")}&metadata=${encodeURIComponent(JSON.stringify({"name": "Example"}))}` +``` + +#### Example +```sh +nostrconnect://b889ff5b1513b641e2a139f661a661364979c5beee91842f8f0ef42ab558e9d4?relay=wss%3A%2F%2Frelay.damus.io&metadata=%7B%22name%22%3A%22Example%22%7D +``` + + + +## Flows + +The `content` field contains encrypted message as specified by [NIP04](https://github.com/nostr-protocol/nips/blob/master/04.md). The `kind` chosen is `24133`. + +### Connect + +1. User clicks on **"Connect"** button on a website or scan it with a QR code +2. It will show an URI to open a "nostr connect" enabled **Signer** +3. In the URI there is a pubkey of the **App** ie. `nostrconnect://&relay=&metadata=` +4. The **Signer** will send a message to ACK the `connect` request, along with his public key + +### Disconnect (from App) + +1. User clicks on **"Disconnect"** button on the **App** +2. The **App** will send a message to the **Signer** with a `disconnect` request +3. The **Signer** will send a message to ACK the `disconnect` request + +### Disconnect (from Signer) + +1. User clicks on **"Disconnect"** button on the **Signer** +2. The **Signer** will send a message to the **App** with a `disconnect` request + + +### Get Public Key + +1. The **App** will send a message to the **Signer** with a `get_public_key` request +3. The **Signer** will send back a message with the public key as a response to the `get_public_key` request + +### Sign Event + +1. The **App** will send a message to the **Signer** with a `sign_event` request along with the **event** to be signed +2. The **Signer** will show a popup to the user to inspect the event and sign it +3. The **Signer** will send back a message with the schnorr `signature` of the event as a response to the `sign_event` request + +### Delegate + +1. The **App** will send a message with metadata to the **Signer** with a `delegate` request along with the **conditions** query string and the **pubkey** of the **App** to be delegated. +2. The **Signer** will show a popup to the user to delegate the **App** to sign on his behalf +3. The **Signer** will send back a message with the signed [NIP-26 delegation token](https://github.com/nostr-protocol/nips/blob/master/26.md) or reject it + + diff --git a/README.md b/README.md index e45c531b..25e5861a 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ NIPs stand for **Nostr Implementation Possibilities**. They exist to document wh - [NIP-36: Sensitive Content](36.md) - [NIP-40: Expiration Timestamp](40.md) - [NIP-42: Authentication of clients to relays](42.md) +- [NIP-46: Nostr Connect](46.md) - [NIP-50: Keywords filter](50.md) - [NIP-56: Reporting](56.md) - [NIP-57: Lightning Zaps](57.md) @@ -56,6 +57,7 @@ NIPs stand for **Nostr Implementation Possibilities**. They exist to document wh | 9735 | Zap | [57](57.md) | | 10002 | Relay List Metadata | [65](65.md) | | 22242 | Client Authentication | [42](42.md) | +| 24133 | Nostr Connect | [46](46.md) | | 30023 | Long-form Content | [23](23.md) | | 1000-9999 | Regular Events | [16](16.md) | | 10000-19999 | Replaceable Events | [16](16.md) | From 050317409d92aaab9007408f4bd5b206cdada1d7 Mon Sep 17 00:00:00 2001 From: Alejandro Gomez Date: Tue, 21 Feb 2023 20:08:46 +0100 Subject: [PATCH 78/87] NIP-57: add optional a tag for tipping nip-33 coordinates --- 57.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/57.md b/57.md index f6fa4ccf..bbeb629d 100644 --- a/57.md +++ b/57.md @@ -30,7 +30,7 @@ Having lightning receipts on nostr allows clients to display lightning payments 3. Clients may choose to display a lightning zap button on each post or on the users profile, if the user's lnurl pay request endpoint supports nostr, the client SHOULD generate a `zap invoice` instead of a normal lnurl invoice. -4. To generate a `zap invoice`, call the `callback` url with `amount` set to the milli-satoshi amount value. A `nostr` querystring value MUST be set as well. It is a uri-encoded `zap request` note signed by the user's key. The `zap request` note contains an `e` tag of the note it is zapping, and a `p` tag of the target user's pubkey. The `e` tag is optional which allows profile tipping. The `zap request` note must also have a `relays` tag, which is gathered from the user's configured relays. The `zap request` note SHOULD contain an `amount` tag, which is the milli-satoshi value of the zap which clients SHOULD verify being equal to the amount of the invoice. The `content` MAY be an additional comment from the user which can be displayed when listing zaps on posts and profiles. +4. To generate a `zap invoice`, call the `callback` url with `amount` set to the milli-satoshi amount value. A `nostr` querystring value MUST be set as well. It is a uri-encoded `zap request` note signed by the user's key. The `zap request` note contains an `e` tag of the note it is zapping, and a `p` tag of the target user's pubkey. The `e` tag is optional which allows profile tipping. An optional `a` tag allows tipping parameterized replaceable events such as NIP-23 long-form notes. The `zap request` note must also have a `relays` tag, which is gathered from the user's configured relays. The `zap request` note SHOULD contain an `amount` tag, which is the milli-satoshi value of the zap which clients SHOULD verify being equal to the amount of the invoice. The `content` MAY be an additional comment from the user which can be displayed when listing zaps on posts and profiles. 5. Pay this invoice or pass it to an app that can pay the invoice. Once it's paid, a `zap note` will be created by the `zapper`. @@ -58,6 +58,8 @@ The lnurl server will need some additional pieces of information so that clients f. If there is an `amount` tag, it MUST be equal to the `amount` query parameter. + g. If there is an `a` tag, it MUST be a valid NIP-33 event coordinate + 5. If valid, fetch a description hash invoice where the description is this note and this note only. No additional lnurl metadata is included in the description. At this point, the lightning node is ready to send the zap note once payment is received. From 2a4c44035e56580fb22929972a69280236663557 Mon Sep 17 00:00:00 2001 From: Brandon Lucas Date: Wed, 22 Feb 2023 19:14:07 -0500 Subject: [PATCH 79/87] Fix minor typo Fix spelling of `coordinates` in Note --- 04.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/04.md b/04.md index 0ebcddb9..bafc5c7e 100644 --- a/04.md +++ b/04.md @@ -14,7 +14,7 @@ A special event with kind `4`, meaning "encrypted direct message". It is suppose **`tags`** MAY contain an entry identifying the previous message in a conversation or a message we are explicitly replying to (such that contextual, more organized conversations may happen), in the form `["e", ""]`. -**Note**: By default in the [libsecp256k1](https://github.com/bitcoin-core/secp256k1) ECDH implementation, the secret is the SHA256 hash of the shared point (both X and Y coorinates). In Nostr, only the X coordinate of the shared point is used as the secret and it is NOT hashed. If using libsecp256k1, a custom function that copies the X coordinate must be passed as the `hashfp` argument in `secp256k1_ecdh`. See [here](https://github.com/bitcoin-core/secp256k1/blob/master/src/modules/ecdh/main_impl.h#L29). +**Note**: By default in the [libsecp256k1](https://github.com/bitcoin-core/secp256k1) ECDH implementation, the secret is the SHA256 hash of the shared point (both X and Y coordinates). In Nostr, only the X coordinate of the shared point is used as the secret and it is NOT hashed. If using libsecp256k1, a custom function that copies the X coordinate must be passed as the `hashfp` argument in `secp256k1_ecdh`. See [here](https://github.com/bitcoin-core/secp256k1/blob/master/src/modules/ecdh/main_impl.h#L29). Code sample for generating such an event in JavaScript: From 405cf480e9f6d419eb5b3516b7acdd1fc5759248 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Arturo=20Cabral=20Mej=C3=ADa?= Date: Wed, 22 Feb 2023 20:11:55 -0500 Subject: [PATCH 80/87] docs: add nip-58 badge event and profile badges (#229) --- 58.md | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 7 +-- 2 files changed, 136 insertions(+), 3 deletions(-) create mode 100644 58.md diff --git a/58.md b/58.md new file mode 100644 index 00000000..2fa44066 --- /dev/null +++ b/58.md @@ -0,0 +1,132 @@ +NIP-58 +====== + +Badges +------ + +`draft` `optional` `author:cameri` + +Three special events are used to define, award and display badges in +user profiles: + +1. A "Badge Definition" event is defined as a parameterized replaceable event +with kind `30009` having a `d` tag with a value that uniquely identifies +the badge (e.g. `bravery`) published by the badge issuer. Badge definitions can +be updated. + +2. A "Badge Award" event is a kind `8` event with a single `a` tag referencing +a "Define Badge" event and one or more `p` tags, one for each pubkey the +badge issuer wishes to award. The value for the `a` tag MUST follow the format +defined in [NIP-33](33.md). Awarded badges are immutable and non-transferrable. + +3. A "Profile Badges" event is defined as a parameterized replaceable event +with kind `30008` with a `d` tag with the value `profile_badges`. +Profile badges contain an ordered list of pairs of `a` and `e` tags referencing a `Badge Definition` and a `Badge Award` for each badge to be displayed. + +### Badge Definition event + +The following tags MUST be present: + +- `d` tag with the unique name of the badge. + +The following tags MAY be present: + +- A `name` tag with a short name for the badge. +- `image` tag whose value is the URL of a high-resolution image representing the badge. The second value optionally specifies the dimensions of the image as `width`x`height` in pixels. Badge recommended dimensions is 1024x1024 pixels. +- A `description` tag whose value MAY contain a textual representation of the +image, the meaning behind the badge, or the reason of it's issuance. +- One or more `thumb` tags whose first value is an URL pointing to a thumbnail version of the image referenced in the `image` tag. The second value optionally specifies the dimensions of the thumbnail as `width`x`height` in pixels. + +### Badge Award event + +The following tags MUST be present: + +- An `a` tag referencing a kind `30009` Badge Definition event. +- One or more `p` tags referencing each pubkey awarded. + +### Profile Badges Event + +The number of badges a pubkey can be awarded is unbounded. The Profile Badge +event allows individual users to accept or reject awarded badges, as well +as choose the display order of badges on their profiles. + +The following tags MUST be present: + +- A `d` tag with the unique identifier `profile_badges` + +The following tags MAY be present: + +- Zero or more ordered consecutive pairs of `a` and `e` tags referencing a kind `30009` Badge Definition and kind `8` Badge Award, respectively. Clients SHOULD +ignore `a` without corresponding `e` tag and viceversa. Badge Awards referenced +by the `e` tags should contain the same `a` tag. + +### Motivation + +Users MAY be awarded badges (but not limited to) in recognition, in gratitude, for participation, or in appreciation of a certain goal, task or cause. + +Users MAY choose to decorate their profiles with badges for fame, notoriety, recognition, support, etc., from badge issuers they deem reputable. + +### Recommendations + +Badge issuers MAY include some Proof of Work as per [NIP-13](13.md) when minting Badge Definitions or Badge Awards to embed them with a combined energy cost, arguably making them more special and valuable for users that wish to collect them. + +Clients MAY whitelist badge issuers (pubkeys) for the purpose of ensuring they retain a valuable/special factor for their users. + +Badge image recommended aspect ratio is 1:1 with a high-res size of 1024x1024 pixels. + +Badge thumbnail image recommended dimensions are: 512x512 (xl), 256x256 (l), 64x64 (m), 32x32 (s) and 16x16 (xs). + +Clients MAY choose to render less badges than those specified by users in the Profile Badges event or replace the badge image and thumbnails with ones that fits the theme of the client. + +Clients SHOULD attempt to render the most appropriate badge thumbnail according to the number of badges chosen by the user and space available. Clients SHOULD attempt render the high-res version on user action (click, tap, hover). + +### Example of a Badge Definition event + +```json +{ + "pubkey": "alice", + "kind": 30009, + "tags": [ + ["d", "bravery"], + ["name", "Medal of Bravery"], + ["description", "Awarded to users demonstrating bravery"], + ["image", "https://nostr.academy/awards/bravery.png", "1024x1024"], + ["thumb", "https://nostr.academy/awards/bravery_256x256.png", "256x256"], + ], + ... +} +``` + +### Example of Badge Award event + +```json +{ + "id": "", + "kind": 8, + "pubkey": "alice", + "tags": [ + ["a", "30009:alice:bravery"], + ["p", "bob", "wss://relay"], + ["p", "charlie", "wss://relay"], + ], + ... +} +``` + +### Example of a Profile Badges event + +Honorable Bob The Brave: +```json +{ + "kind": 30008, + "pubkey": "bob", + "tags": [ + ["d", "profile_badges"], + ["a", "30009:alice:bravery"], + ["e", "", "wss://nostr.academy"], + ["a", "30009:alice:honor"], + ["e", "", "wss://nostr.academy"], + ], + ... +} +``` diff --git a/README.md b/README.md index 25e5861a..24106e1e 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ NIPs stand for **Nostr Implementation Possibilities**. They exist to document wh - [NIP-36: Sensitive Content](36.md) - [NIP-40: Expiration Timestamp](40.md) - [NIP-42: Authentication of clients to relays](42.md) -- [NIP-46: Nostr Connect](46.md) +- [NIP-46: Nostr Connect](46.md) - [NIP-50: Keywords filter](50.md) - [NIP-56: Reporting](56.md) - [NIP-57: Lightning Zaps](57.md) @@ -46,6 +46,7 @@ NIPs stand for **Nostr Implementation Possibilities**. They exist to document wh | 4 | Encrypted Direct Messages | [4](04.md) | | 5 | Event Deletion | [9](09.md) | | 7 | Reaction | [25](25.md) | +| 8 | Badge Award | [58](58.md) | | 40 | Channel Creation | [28](28.md) | | 41 | Channel Metadata | [28](28.md) | | 42 | Channel Message | [28](28.md) | @@ -63,8 +64,8 @@ NIPs stand for **Nostr Implementation Possibilities**. They exist to document wh | 10000-19999 | Replaceable Events | [16](16.md) | | 20000-29999 | Ephemeral Events | [16](16.md) | | 30000-39999 | Parameterized Replaceable Events | [33](33.md) | - - +| 30008 | Profile Badges | [58](58.md) | +| 30009 | Badge Definition | [58](58.md) | ## Message types From 127d5518bfa9a4e4e7510490c0b8d95e342dfa4b Mon Sep 17 00:00:00 2001 From: barkyq <122579762+barkyq@users.noreply.github.com> Date: Thu, 23 Feb 2023 14:20:10 -0500 Subject: [PATCH 81/87] relay hint language update (#291) --- 10.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/10.md b/10.md index c0ef9d19..64947967 100644 --- a/10.md +++ b/10.md @@ -43,8 +43,8 @@ They are citings from this event. `root-id` and `reply-id` are as above. Where: * `` is the id of the event being referenced. - * `` is the URL of a recommended relay associated with the reference. It is NOT optional. - * `` is optional and if present is one of `"reply"`, `"root"`, or `"mention"` + * `` is the URL of a recommended relay associated with the reference. Clients SHOULD add a valid `` field, but may instead leave it as `""`. + * `` is optional and if present is one of `"reply"`, `"root"`, or `"mention"`. **The order of marked "e" tags is not relevant.** Those marked with `"reply"` denote the id of the reply event being responded to. Those marked with `"root"` denote the root id of the reply thread being responded to. For top level replies (those replying directly to the root event), only the `"root"` marker should be used. Those marked with `"mention"` denote a quoted or reposted event id. From 379252f992c2528e287bc4ce7faee5631aa3f73c Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Sat, 25 Feb 2023 13:54:27 -0300 Subject: [PATCH 82/87] explicitly prohibit markdown on kind:1. --- 01.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/01.md b/01.md index 68efc6fc..12b5ba9a 100644 --- a/01.md +++ b/01.md @@ -98,7 +98,7 @@ This NIP defines no rules for how `NOTICE` messages should be sent or treated. ## Basic Event Kinds - `0`: `set_metadata`: the `content` is set to a stringified JSON object `{name: , about: , picture: }` 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). Non-plaintext notes should instead use kind 1000-10000 as described in [NIP-16](16.md). + - `1`: `text_note`: the `content` is set to the plaintext content of a note (anything the user wants to say). Markdown links (`[]()` stuff) are not plaintext. - `2`: `recommend_server`: the `content` is set to the URL (e.g., `wss://somerelay.com`) of a relay the event creator wants to recommend to its followers. A relay may choose to treat different message kinds differently, and it may or may not choose to have a default way to handle kinds it doesn't know about. From ab1f26a3fd8fa0703a4be76091566c92aeadbd4b Mon Sep 17 00:00:00 2001 From: Callum Macdonald Date: Sat, 25 Feb 2023 12:23:46 +0100 Subject: [PATCH 83/87] Add browsers to the extension list --- 07.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/07.md b/07.md index 8ebb4d99..6c9f2b32 100644 --- a/07.md +++ b/07.md @@ -24,7 +24,7 @@ async window.nostr.nip04.decrypt(pubkey, ciphertext): string // takes ciphertext ### Implementation -- [nos2x](https://github.com/fiatjaf/nos2x) -- [Alby](https://getalby.com) -- [Blockcore](https://www.blockcore.net/wallet) -- [nos2x-fox](https://diegogurpegui.com/nos2x-fox/) +- [nos2x](https://github.com/fiatjaf/nos2x) (Chrome and derivatives) +- [Alby](https://getalby.com) (Chrome and derivatives, Firefox, Safari) +- [Blockcore](https://www.blockcore.net/wallet) (Chrome and derivatives) +- [nos2x-fox](https://diegogurpegui.com/nos2x-fox/) (Firefox) From 5a80a906d41a2d756a01addb50f6bead0061fb29 Mon Sep 17 00:00:00 2001 From: Mike O'Bank <111360219+mikeobank@users.noreply.github.com> Date: Sat, 25 Feb 2023 07:02:48 +0100 Subject: [PATCH 84/87] Improve `` specification - "random" is not an accurate description - I've noticed long (sha256 hashes in hex) being rejected by some relays. So there seems a need to specify a max length. - "non empty", cause an empty string could be interpreted as `null` To be decided: - Max length number - Are `subscription_id`s case sensitive? - Will `subscription_id`s be white space trimmed? --- 01.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/01.md b/01.md index 12b5ba9a..d32903b9 100644 --- a/01.md +++ b/01.md @@ -55,7 +55,7 @@ Clients can send 3 types of messages, which must be JSON arrays, according to th * `["REQ", , ...]`, used to request events and subscribe to new updates. * `["CLOSE", ]`, used to stop previous subscriptions. -`` is a random string that should be used to represent a subscription. +`` is an arbitrary, non-empty string of max length 64 chars, that should be used to represent a subscription. `` is a JSON object that determines what events will be sent in that subscription, it can have the following attributes: From 2bf08b34874bc040cc257b46806cc682b56e6b50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Arturo=20Cabral=20Mej=C3=ADa?= Date: Sat, 25 Feb 2023 10:17:33 -0500 Subject: [PATCH 85/87] docs: add nip-58 to readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 24106e1e..77f97c00 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ NIPs stand for **Nostr Implementation Possibilities**. They exist to document wh - [NIP-50: Keywords filter](50.md) - [NIP-56: Reporting](56.md) - [NIP-57: Lightning Zaps](57.md) +- [NIP-58: Badges](58.md) - [NIP-65: Relay List Metadata](65.md) ## Event Kinds From d70959aee6f8e6e2f2bff02898c0281a64c53a8d Mon Sep 17 00:00:00 2001 From: Marco Argentieri <3596602+tiero@users.noreply.github.com> Date: Mon, 27 Feb 2023 18:22:46 +0100 Subject: [PATCH 86/87] Amend nip46 describe and delegate methods (#304) --- 46.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/46.md b/46.md index a9f37c1b..6589fc00 100644 --- a/46.md +++ b/46.md @@ -61,7 +61,7 @@ These are mandatory methods the remote signer app MUST implement: - **describe** - params [] - - result `{"get_public_key": { params: [], result: anything }}` + - result `["describe", "get_public_key", "sign_event", "connect", "disconnect", "delegate", ...]` - **get_public_key** - params [] - result `pubkey` @@ -77,8 +77,8 @@ These are mandatory methods the remote signer app MUST implement: - **disconnect** - params [] - **delegate** - - params [`pubkey`, `conditions query string`] - - result `nip26 delegation token` + - params [`delegatee`, `{ kind: number, since: number, until: number }`] + - result `{ from: string, to: string, cond: string, sig: string }` - **get_relays** - params [] - result `{ [url: string]: {read: boolean, write: boolean} }` From b549a9809f94ca703b3b63b73cdacc5407a2edd0 Mon Sep 17 00:00:00 2001 From: Sepehr Safari Date: Mon, 27 Feb 2023 23:51:22 +0330 Subject: [PATCH 87/87] Update README.md fixed a tiny tipo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 77f97c00..8ee8b858 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,7 @@ NIPs stand for **Nostr Implementation Possibilities**. They exist to document wh | EVENT | used to send events requested to clients | [1](01.md) | | NOTICE | used to send human-readable messages to clients | [1](01.md) | | EOSE | used to notify clients all stored events have been sent | [15](15.md) | -| OK | used to notify clients if an EVENT was successuful | [20](20.md) | +| OK | used to notify clients if an EVENT was successful | [20](20.md) | | AUTH | used to send authentication challenges | [42](42.md) | Please update these lists when proposing NIPs introducing new event kinds.