Compare commits

..

54 Commits

Author SHA1 Message Date
fiatjaf
65c8a3cdc0 nip-37: remote signing helpers. 2022-12-02 13:20:21 -03:00
Fernando López Guevara
27c6652e0e NIP-36 - sensitive content / content-warning (#82) 2022-12-01 20:41:15 -03:00
fiatjaf
bbc931d02d refine NIP rules. 2022-11-29 11:41:46 -03:00
monlovesmango
0dcf11df80 add nip-26 to readme 2022-11-28 14:31:50 -06:00
fiatjaf
9302c35573 add alby to NIP-07. 2022-11-27 12:03:46 -03:00
Jon Staab
cf5eaf6360 Amend NIP 11 to require CORS support 2022-11-25 13:03:03 -03:00
fiatjaf
743e43a8d4 finalize some NIPs we will not going to change anymore. 2022-11-22 14:52:34 -03:00
Michael Dilger
631e9760bf NIP-35 User Discovery (#73)
* Draft NIP for user discovery

* Renumber to NIP-35

* spelling fix

* Add to README

* fix quote

* and colon
2022-11-19 11:28:47 -08:00
Mike Dilger
c274c65856 Reword NIP-01 to clarify no line breaks. Existing language of "indentation" implies line breaks. 2022-11-15 17:36:13 -03:00
khimaros
a0852a7cbe stronger wording for relay deletion behavior
- change "MAY" to "SHOULD" for removing referenced events
- suggest indefinite retention for deletion events on relays
- include recommendation for clients to rebroadcast deletion events to relays
2022-11-14 14:52:29 -03:00
fiatjaf
30f1e64e01 Merge pull request #62 from jb55/command-results 2022-11-11 11:00:40 -03:00
alex
f09362695d nip16: clarify about the signers of replaceable events
A newer replaceable event must be signed by the same key.
2022-11-11 07:56:24 -03:00
William Casarin
c510e646d0 NIP-20: server errors happen! 2022-11-10 13:14:23 -08:00
William Casarin
ff26b959f8 NIP-20: More clarity around malformed vs invalid events 2022-11-10 12:55:44 -08:00
William Casarin
7569773ad6 NIP-20: add a note about client handling 2022-11-10 12:20:32 -08:00
William Casarin
e7f74d21c4 NIP-20: pow suggestion 2022-11-10 12:02:14 -08:00
William Casarin
a0b0a021a8 NIP-20: add "invalid" message suggestion 2022-11-10 11:57:52 -08:00
William Casarin
15514283f3 NIP-20: Command Results
When submitting events to relays, clients currently have no way to know
if an event was successfully committed to the database. This NIP
introduces the concept of command results which are like NOTICE's except
provide more information about if an event was accepted or rejected.
2022-11-10 10:29:11 -08:00
Blake Jakopovic
27683d3441 Update 10.md
Fixed typo
2022-11-08 16:45:40 -03:00
w3irdrobot
79bb56c2f4 Fix regex for SetMetadata in NIP1
It appears the regex given in NIP1 for setting the username in the setmetadata event was slightly off. I think the fix here is what was intended. Though I think what was meant here was pretty obvious, to make it easier on future developers, I updated the regex to something that should work with just copying and pasting.
2022-11-04 16:33:57 -03:00
William Casarin
b8b5e3aa40 nip25: fix code example
content should not be blank
2022-10-30 08:34:14 -07:00
DZ
6ba2fc3338 Update README.md 2022-10-26 09:54:23 -07:00
DZ
3c0c3ca0f3 Update README.md
add message-type tables
2022-10-26 09:54:23 -07:00
DZ
6d86133118 Update 01.md
fix indentation
2022-10-26 09:54:23 -07:00
Ricardo Arturo Cabral Mejía
147cd0a2ea Merge pull request #53 from Semisol/patch-1
nip16: small fix
2022-10-17 14:24:06 -04:00
Semisol
497d5d9ddf nip16: small fix 2022-10-16 20:24:21 +03:00
DZ
c8a95a0968 Update 01.md
fix typo
2022-10-07 17:17:34 -03:00
fiatjaf
b62aa418de Merge pull request #28 from Minds/minds-nip-26 2022-09-23 13:43:01 -03:00
Greg Heartsfield
fdbf817961 add kinds reserved by NIP-28 2022-09-11 08:23:02 -03:00
Greg Heartsfield
fadbcc0aee add NIP-28 link in README 2022-09-11 08:23:02 -03:00
Christopher David
3423a6dfbc NIP-28: Public Chat (#38) 2022-09-10 14:28:08 -03:00
Leo Wandersleb
3e0e6ca2d6 separate array elements with , 2022-09-02 18:47:42 -03:00
Mark Harding
78522b50a1 Changes based on feedback 2022-08-24 13:24:50 +01:00
William Casarin
7af2540c6e reactions: we should be able to react to any note
Signed-off-by: William Casarin <jb55@jb55.com>
2022-08-19 15:50:39 -07:00
Ricardo Arturo Cabral Mejía
533d316170 Remove NIP-27 2022-08-16 22:59:02 -04:00
Ricardo Arturo Cabral Mejía
ef059e0fde NIP-27 Multicasting 2022-08-16 22:57:22 -04:00
William Casarin
f6346b6e22 Merge pull request #22 from jeffthibault/nip22-unacceptable-event-time
NIP-22: event created_at limits
2022-08-15 13:09:53 -07:00
Jeff Thibault
903cc0992e add Giszmo, add comment in code example 2022-08-14 11:26:39 -04:00
Jeff Thibault
e8a501c08f Merge pull request #1 from Giszmo/nip22
reworded nip-22
2022-08-14 11:18:43 -04:00
Leo Wandersleb
68300c5990 reword nip22, mention replaceable events 2022-08-13 21:50:38 -04:00
Jeff Thibault
6ee98c1bfb spelling nit 2022-08-13 14:08:14 -04:00
Jeff Thibault
f5852fda83 add nip link to readme 2022-08-13 13:54:28 -04:00
Jeff Thibault
ef0f8a1186 rename and rewrite to be more generic 2022-08-13 13:52:14 -04:00
Jeff Thibault
a902083bac Merge branch 'nostr-protocol:master' into nip22-unacceptable-event-time 2022-08-13 10:03:37 -04:00
Mark Harding
e13f6d39b9 First draft of Delegated Event Signing 2022-08-04 09:33:38 +01:00
fiatjaf
7fe572ec5a Merge pull request #26 from jb55/reactions 2022-08-01 08:22:23 -03:00
William Casarin
6903ff5b2c nip25: make generic like an explicit +
Signed-off-by: William Casarin <jb55@jb55.com>
2022-07-31 12:44:40 -07:00
William Casarin
89bb08ba86 nip25: include dislikes/downvotes
Signed-off-by: William Casarin <jb55@jb55.com>
2022-07-30 10:09:33 -07:00
William Casarin
dcbd504639 NIP-25: Reactions
Signed-off-by: William Casarin <jb55@jb55.com>
2022-07-30 09:50:26 -07:00
William Casarin
f2cc7bd86f Merge pull request #23 from Semisol/master
nip16: small fix
2022-07-25 19:02:01 -07:00
Semisol
1b94488742 nip16: small fix 2022-07-26 04:33:33 +03:00
Jeff Thibault
d1b6bdb18e add relay logic 2022-07-22 12:53:54 -04:00
Jeff Thibault
8bef0e9d79 add that events from future are unacceptable 2022-07-22 12:45:14 -04:00
Jeff Thibault
f51ce9dc0e add nip22: unacceptable event created_at field 2022-07-22 11:50:07 -04:00
20 changed files with 585 additions and 70 deletions

6
01.md
View File

@@ -30,7 +30,7 @@ The only object type that exists is the `event`, which has the following format
}
```
To obtain the `event.id`, we `sha256` the serialized event. The serialization is done over the UTF-8 JSON-serialized string (with no indentation or extra spaces) of the following structure:
To obtain the `event.id`, we `sha256` the serialized event. The serialization is done over the UTF-8 JSON-serialized string (with no white space or line breaks) of the following structure:
```json
[
@@ -98,8 +98,8 @@ 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: <username>, about: <string>, picture: <url, string>}` describing the user who created the event. A relay may delete past `set_metadata` events once it gets a new one for the same pubkey.
* Where `<username>` is a string that matches the pattern: `[\w+\-]` (java regular epression). Or, in other words, a sequence of the following
characters: `[a-zA-Z_\-0-9]`. <br>
* Where `<username>` is a string that matches the pattern: `\w[\w\-]+\w` (java regular expression). Or, in other words, a sequence of the following
characters: `[a-zA-Z_0-9][a-zA-Z_\-0-9]+[a-zA-Z_0-9]`. <br>
Thus `George-Washington-1776` is a valid `<username>`, but `George Washington` is not. Clients may reject metadata that does not comply.
- `1`: `text_note`: the `content` is set to the text content of a note (anything the user wants to say).
- `2`: `recommend_server`: the `content` is set to the URL (e.g., `https://somerelay.com`) of a relay the event creator wants to recommend to its followers.

2
02.md
View File

@@ -4,7 +4,7 @@ NIP-02
Contact List and Petnames
-------------------------
`draft` `optional` `author:fiatjaf` `author:arcbtc`
`final` `optional` `author:fiatjaf` `author:arcbtc`
A special event with kind `3`, meaning "contact list" is defined as having a list of `p` tags, one for each of the followed/known profiles one is following.

2
04.md
View File

@@ -4,7 +4,7 @@ NIP-04
Encrypted Direct Message
------------------------
`draft` `optional` `author:arcbtc`
`final` `optional` `author:arcbtc`
A special event with kind `4`, meaning "encrypted direct message". It is supposed to have the following attributes:

2
05.md
View File

@@ -4,7 +4,7 @@ NIP-05
Mapping Nostr keys to DNS-based internet identifiers
----------------------------------------------------
`draft` `optional` `author:fiatjaf`
`final` `optional` `author:fiatjaf`
On events of type `0` (`set_metadata`) one can specify the key `"nip05"` with an [internet identifier](https://datatracker.ietf.org/doc/html/rfc5322#section-3.4.1) (an email-like address) as the value. Although there is a link to a very liberal "internet identifier" specification above, NIP-05 assumes the `<local-part>` part will be restricted to the characters `a-z0-9-_.`, case insensitive.

5
07.md
View File

@@ -15,6 +15,7 @@ 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`
```
### Implementation example
### Implementation
- [nos2x](https://github.com/fiatjaf/nos2x) is available as a Chromium (and partially Firefox) extension that provides such capabilities.
- [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`.

2
08.md
View File

@@ -4,7 +4,7 @@ NIP-08
Handling Mentions
-----------------
`draft` `optional` `author:fiatjaf` `author:scsibug`
`final` `optional` `author:fiatjaf` `author:scsibug`
This document standardizes the treatment given by clients of inline mentions of other events and pubkeys inside the content of `text_note`s.

4
09.md
View File

@@ -27,7 +27,9 @@ For example:
}
```
Relays MAY delete or stop publishing any referenced events that have an identical `pubkey` as the deletion request. Clients may hide or otherwise indicate a deletion status for referenced events.
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 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

14
10.md
View File

@@ -13,7 +13,7 @@ This NIP describes how to use "e" and "p" tags in text events, especially those
## Positional "e" tags (DEPRECATED)
>This scheme is in common use; but should be considered deprecated.
`["e", <event-id> <relay-url>]` as per NIP-01.
`["e", <event-id>, <relay-url>]` as per NIP-01.
Where:
@@ -26,19 +26,19 @@ Where:
This event is not a reply to, nor does it refer to, any other event.
* One "e" tag: <br>
`["e",<id>]`: The id of the event to which this event is a reply.
`["e", <id>]`: The id of the event to which this event is a reply.
* Two "e" tags: `["e",<root-id>]`, `["e",<reply-id>]` <br>
* Two "e" tags: `["e", <root-id>]`, `["e", <reply-id>]` <br>
`<root-id>` is the id of the event at the root of the reply chain. `<reply-id>` is the id of the article to which this event is a reply.
* Many "e" tags: `["e",<root-id>]` `["e",<mention-id>]`, ..., `["e",<reply-id>]`<br>
* Many "e" tags: `["e", <root-id>]` `["e", <mention-id>]`, ..., `["e", <reply-id>]`<br>
There may be any number of `<mention-ids>`. These are the ids of events which may, or may not be in the reply chain.
They are citings from this event. `root-id` and `reply-id` are as above.
>This scheme is deprecated because it creates ambiguities that are difficult, or impossible to resolve when an event references another but is not a reply.
## Marked "e" tags (PREFERRED)
`["e", <event-id> <relay-url> <marker>]`
`["e", <event-id>, <relay-url>, <marker>]`
Where:
@@ -48,13 +48,13 @@ Where:
**The order of marked "e" tags is not relevant.** Those marked with `"reply"` denote the `<reply-id>`. Those marked with `"root"` denote the root id of the reply thread.
>This scheme is preferred because it allows events to mention others without confusing them with `<relay-id>` or `<root-id>`.
>This scheme is preferred because it allows events to mention others without confusing them with `<reply-id>` or `<root-id>`.
## The "p" tag
Used in a text event contains a list of pubkeys used to record who is involved in a reply thread.
When replying to a text event E the reply event's "p" tags should contain all of E's "p" tags as well as the `"pubkey"` of the of the event being replied to.
When replying to a text event E the reply event's "p" tags should contain all of E's "p" tags as well as the `"pubkey"` of the event being replied to.
Example: Given a text event authored by `a1` with "p" tags [`p1`, `p2`, `p3`] then the "p" tags of the reply should be [`a1`, `p1`, `p2`, `p3`]
in no particular order.

2
11.md
View File

@@ -22,7 +22,7 @@ When a relay receives an HTTP(s) request with an `Accept` header of `application
}
```
Any field may be omitted, and clients MUST ignore any additional fields they do not understand.
Any field may be omitted, and clients MUST ignore any additional fields they do not understand. Relays MUST accept CORS requests by sending `Access-Control-Allow-Origin`, `Access-Control-Allow-Headers`, and `Access-Control-Allow-Methods` headers.
Field Descriptions
-----------------

2
15.md
View File

@@ -4,7 +4,7 @@ NIP-15
End of Stored Events Notice
---------------------------
`draft` `optional` `author:Semisol`
`final` `optional` `author:Semisol`
Relays may support notifying clients when all stored events have been sent.

4
16.md
View File

@@ -11,7 +11,7 @@ Relays may decide to allow replaceable and/or ephemeral events.
Replaceable Events
------------------
A *replaceable event* is defined as an event with a kind `10000 <= n < 20000`.
Upon a replaceable event with a newer timestamp than the currently known latest replaceable event with the same kind, the old event SHOULD be discarded and replaced with the newer event.
Upon a replaceable event with a newer timestamp than the currently known latest replaceable event with the same kind being received, and signed by the same key, the old event SHOULD be discarded and replaced with the newer event.
Ephemeral Events
----------------
@@ -21,7 +21,7 @@ Upon an ephemeral event being received, the relay SHOULD send it to all clients
Client Behavior
---------------
Clients SHOULD use the `supported_nips` field to learn if a relay supports generic tag queries. Clients SHOULD NOT send ephemeral events to relays that do not support this NIP; they will most likely be persisted. Clients MAY send replaceable events to relays that may not support this NIP, and clients querying SHOULD be prepared for the relay to send multiple events and should use the latest one.
Clients SHOULD use the `supported_nips` field to learn if a relay supports this NIP. Clients SHOULD NOT send ephemeral events to relays that do not support this NIP; they will most likely be persisted. Clients MAY send replaceable events to relays that may not support this NIP, and clients querying SHOULD be prepared for the relay to send multiple events and should use the latest one.
Suggested Use Cases
-------------------

119
20.md
View File

@@ -1,50 +1,93 @@
NIP-20
======
Web Comments
------------
`draft` `optional` `author:fiatjaf`
Command Results
---------------
A special event with kind `34` is defined, meaning "web comment".
`draft` `optional` `author:jb55`
Events of this kind should have at least one `r` tag with the value set to the normalized URL of the webpage they're commenting in.
When submitting events to relays, clients currently have no way to know if an event was successfully committed to the database. This NIP introduces the concept of command results which are like NOTICE's except provide more information about if an event was accepted or rejected.
The content should be the plaintext of the comment.
A command result is a JSON object with the following structure that is returned when an event is successfully saved to the database or rejected:
For example:
["OK", <event_id>, <true|false>, <message>]
```json
{
"kind": 34,
"tags": [
["r", "https://random.blog/article"]
],
"content": "I didn't like this article.",
...other fields
```
Relays MUST return `true` when the event is a duplicate and has already been saved. The `message` SHOULD start with `duplicate:` in this case.
URL Normalization
Relays MUST return `false` when the event was rejected and not saved.
The `message` SHOULD provide additional information as to why the command succeeded or failed.
The `message` SHOULD start with `blocked:` if the pubkey or network address has been blocked, banned or is not on a whitelist.
The `message` SHOULD start with `invalid:` if the event is invalid or doesn't meet some specific criteria (created_at is too far off, id is wrong, signature is wrong, etc)
The `message` SHOULD start with `pow:` if the event doesn't meet some proof-of-work difficulty. The client MAY consult the relay metadata at this point to retrieve the required posting difficulty.
The `message` SHOULD start with `rate-limited:` if the event was rejected due to rate limiting techniques.
The `message` SHOULD start with `error:` if the event failed to save due to a server issue.
Ephemeral events are not acknowledged with OK responses, unless there is a failure.
If the event or `EVENT` command is malformed and could not be parsed, a NOTICE message SHOULD be used instead of a command result. This NIP only applies to non-malformed EVENT commands.
Examples
--------
Event successfully written to the database:
["OK", "b1a649ebe8b435ec71d3784793f3bbf4b93e64e17568a741aecd4c7ddeafce30", true, ""]
Event successfully written to the database because of a reason:
["OK", "b1a649ebe8b435ec71d3784793f3bbf4b93e64e17568a741aecd4c7ddeafce30", true, "pow: difficulty 25>=24"]
Event blocked due to ip filter
["OK", "b1a649ebe8...", false, "blocked: tor exit nodes not allowed"]
Event blocked due to pubkey ban
["OK", "b1a649ebe8...", false, "blocked: you are banned from posting here"]
Event blocked, pubkey not registered
["OK", "b1a649ebe8...", false, "blocked: please register your pubkey at https://my-expensive-relay.example.com"]
Event rejected, rate limited
["OK", "b1a649ebe8...", false, "rate-limited: slow down there chief"]
Event rejected, `created_at` too far off
["OK", "b1a649ebe8...", false, "invalid: event creation date is too far off from the current time. Is your system clock in sync?"]
Event rejected, insufficient proof-of-work difficulty
["OK", "b1a649ebe8...", false, "pow: difficulty 26 is less than 30"]
Event failed to save,
["OK", "b1a649ebe8...", false, "error: could not connect to the database"]
Client Handling
---------------
`messages` are meant for humans, with `reason:` prefixes so that clients can be slightly more intelligent with what to do with them. For example, with a `rate-limited:` reason the client may not show anything and simply try again with a longer timeout.
For the `pow:` prefix it may query relay metadata to get the updated difficulty requirement and try again in the background.
For the `invalid:` and `blocked`: prefix the client may wish to show these as styled error popups.
The prefixes include a colon so that the message can be cleanly separated from the prefix by taking everything after `:` and trimming it.
Future Extensions
-----------------
Early prototypes have been using the following naïve URL normalization algorithm:
```js
export function normalizeURL(raw) {
let url = new URL(raw)
return (
url.origin
.replace('://m.', '://') // remove known 'mobile' subdomains
.replace('://mobile.', '://')
.replace('http://', 'https://') // default everything to https (maybe a terrible idea)
.replace( /:\d+/, port => (port === ':443' || port === ':80' ? '' : port)) + // remove 443 and 80 ports
url.pathname
.replace(/\/+/g, '/') // remove duplicated slashes in the middle of the path
.replace(/\/*$/, '') // remove slashes from the end of path
// notice that only origin ("https://random.blog") and pathname ("/article") are used, all the rest is thrown away
)
}
```
This is open for improvement, of course.
This proposal SHOULD be extended to support futher commands in the future, such as REQ and AUTH. They are left out of this initial version to keep things simpler.

42
22.md Normal file
View File

@@ -0,0 +1,42 @@
NIP-22
======
Event `created_at` Limits
---------------------------
`draft` `optional` `author:jeffthibault` `author:Giszmo`
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.
Client Behavior
---------------
Clients SHOULD use the [NIP-11](11.md) `supported_nips` field to learn if a relay uses event `created_at` time limits as defined by this NIP.
Motivation
----------
This NIP formalizes restrictions on event timestamps as accepted by a relay and allows clients to be aware of relays that have these restrictions.
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.
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.
Python Example
--------------
```python
import time
TIME = int(time.now)
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."]')
```

49
25.md Normal file
View File

@@ -0,0 +1,49 @@
NIP-25
======
Reactions
---------
`draft` `optional` `author:jb55`
A reaction is a `kind 7` note that is used to react to other notes.
The generic reaction, represented by the `content` set to a `+` string, SHOULD
be interpreted as a "like" or "upvote".
A reaction with `content` set to `-` SHOULD be interepreted as a "dislike" or
"downvote". It SHOULD NOT be counted as a "like", and MAY be displayed as a
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",
or the client MAY display this emoji reaction on the post.
Tags
----
The reaction event SHOULD include `e` and `p` tags from the note the user is
reacting to. This allows users to be notified of reactions to posts they were
mentioned in. Including the `e` tags enables clients to pull all the reactions
associated with individual posts or all the posts in a thread.
The last `e` tag MUST be the `id` of the note that is being reacted to.
The last `p` tag MUST be the `pubkey` of the event being reacted to.
Example code
```swift
func make_like_event(pubkey: String, privkey: String, liked: NostrEvent) -> NostrEvent {
var tags: [[String]] = liked.tags.filter {
tag in tag.count >= 2 && (tag[0] == "e" || tag[0] == "p")
}
tags.append(["e", liked.id])
tags.append(["p", liked.pubkey])
let ev = NostrEvent(content: "+", pubkey: pubkey, kind: 7, tags: tags)
ev.calculate_id()
ev.sign(privkey: privkey)
return ev
}

66
26.md Normal file
View File

@@ -0,0 +1,66 @@
NIP: 26
=======
Delegated Event Signing
-----
`draft` `optional` `author:markharding` `author:minds`
This NIP defines how events can be delegated so that they can be signed by other keypairs.
Another application of this proposal is to abstract away the use of the 'root' keypairs when interacting with clients. For example, a user could generate new keypairs for each client they wish to use and authorize those keypairs to generate events on behalf of their root pubkey, where the root keypair is stored in cold storage.
#### Introducing the 'delegation' tag
This NIP introduces a new tag: `delegation` which is formatted as follows:
```json
[
"delegation",
<pubkey of the delegator>,
<conditions query string>,
<64-bytes schnorr signature of the sha256 hash of the delegation token>
]
```
##### Delegation Token
The **delegation token** should be a 64-bytes schnorr signature of the sha256 hash of the following string:
```
nostr:delegation:<pubkey of publisher (delegatee)>:<conditions query string>
```
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`.
```json
{
"id": "a080fd288b60ac2225ff2e2d815291bd730911e583e177302cc949a15dc2b2dc",
"pubkey": "62903b1ff41559daf9ee98ef1ae67cc52f301bb5ce26d14baba3052f649c3f49",
"created_at": 1660896109,
"kind": 1,
"tags": [
[
"delegation",
"86f0689bd48dcd19c67a19d994f938ee34f251d8c39976290955ff585f2db42e",
"kind=1&created_at>1640995200",
"c33c88ba78ec3c760e49db591ac5f7b129e3887c8af7729795e85a0588007e5ac89b46549232d8f918eefd73e726cb450135314bfda419c030d0b6affe401ec1"
]
],
"content": "Hello world",
"sig": "cd4a3cd20dc61dcbc98324de561a07fd23b3d9702115920c0814b5fb822cc5b7c5bcdaf3fa326d24ed50c5b9c8214d66c75bae34e3a84c25e4d122afccb66eb6"
}
```
#### Relay & Client Querying Support
Relays should answer requests such as `["REQ", "", {"authors": ["A"]}]` by querying both the `pubkey` and delegation tags `[1]` value.

158
28.md Normal file
View File

@@ -0,0 +1,158 @@
NIP-28
======
Public Chat
-----------
`draft` `optional` `author:ChristopherDavid` `author:fiatjaf` `author:jb55` `author:Cameri`
This NIP defines new event kinds for public chat channels, channel messages, and basic client-side moderation.
It reserves five event kinds (40-44) for immediate use and five event kinds (45-49) for future use.
- `40 - channel create`
- `41 - channel metadata`
- `42 - channel message`
- `43 - hide message`
- `44 - mute user`
Client-centric moderation gives client developers discretion over what types of content they want included in their apps, while imposing no additional requirements on relays.
## Kind 40: Create channel
Create a public chat channel.
In the channel creation `content` field, Client SHOULD include basic channel metadata (`name`, `about`, `picture` as specified in kind 41).
```json
{
"content": "{\"name\": \"Demo Channel\", \"about\": \"A test channel.\", \"picture\": \"https://placekitten.com/200/200\"}",
...
}
```
## Kind 41: Set channel metadata
Update a channel's public metadata.
Clients and relays SHOULD handle kind 41 events similar to kind 0 `metadata` events.
Clients SHOULD ignore kind 41s from pubkeys other than the kind 40 pubkey.
Clients SHOULD support basic metadata fields:
- `name` - string - Channel name
- `about` - string - Channel description
- `picture` - string - URL of channel picture
Clients MAY add additional metadata fields.
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", <channel_create_event_id> <relay-url>]],
...
}
```
## Kind 42: Create channel message
Send a text message to a channel.
Clients SHOULD use [NIP-10](10.md) marked "e" tags to recommend a relay and specify whether it is a reply or root message.
Clients SHOULD append [NIP-10](10.md) "p" tags to replies.
Root message:
```json
{
"content": <string>,
"tags": [["e", <kind_40_event_id> <relay-url> "root"]],
...
}
```
Reply to another message:
```json
{
"content": <string>,
"tags": [
["e", <kind_42_event_id> <relay-url> "reply"],
["p", <pubkey> <relay-url>],
...
],
...
}
```
## Kind 43: Hide message
User no longer wants to see a certain message.
The `content` may optionally include metadata such as a `reason`.
Clients SHOULD hide event 42s shown to a given user, if there is an event 43 from that user matching the event 42 `id`.
Clients MAY hide event 42s for other users other than the user who sent the event 43.
(For example, if three users 'hide' an event giving a reason that includes the word 'pornography', a Nostr client that is an iOS app may choose to hide that message for all iOS clients.)
```json
{
"content": "{\"reason\": \"Dick pic\"}",
"tags": [["e", <kind_42_event_id>]],
...
}
```
## Kind 44: Mute user
User no longer wants to see messages from another user.
The `content` may optionally include metadata such as a `reason`.
Clients SHOULD hide event 42s shown to a given user, if there is an event 44 from that user matching the event 42 `pubkey`.
Clients MAY hide event 42s for users other than the user who sent the event 44.
```json
{
"content": "{\"reason\": \"Posting dick pics\"}",
"tags": [["p", <pubkey>]],
...
}
```
## NIP-10 relay recommendations
For [NIP-10](10.md) relay recommendations, clients generally SHOULD use the relay URL of the original (oldest) kind 40 event.
Clients MAY recommend any relay URL. For example, if a relay hosting the original kind 40 event for a channel goes offline, clients could instead fetch channel data from a backup relay, or a relay that clients trust more than the original relay.
Future extensibility
--------------------
We reserve event kinds 45-49 for other events related to chat, to potentially include new types of media (photo/video), moderation, or support of private or group messaging.
Motivation
----------
If we're solving censorship-resistant communication for social media, we may as well solve it also for Telegram-style messaging.
We can bring the global conversation out from walled gardens into a true public square open to all.
Additional info
---------------
- [Chat demo PR with fiatjaf+jb55 comments](https://github.com/ArcadeCity/arcade/pull/28)
- [Conversation about NIP16](https://t.me/nostr_protocol/29566)

41
35.md Normal file
View File

@@ -0,0 +1,41 @@
NIP-35
======
User Discovery
--------------
`draft` `optional` `author:mikedilger`
This NIP extends NIP-05 to facilitate a mechanism of user discovery that provides both public key information and relay information.
This NIP does not modify any data or events within the nostr protocol. It only extends the contents of `https://<domain>/.well-known/nostr.json?name=<local-part>` return values with additional relay information.
With this NIP implemented, clients may then attempt to discover users via email-like addresses (see NIP-05) and potentially find what relays they post to along with their public key.
### nostr.json contents
NIP-05 specifies a `nostr.json` file with contents like this (refer to NIP-05):
```json
{
"names": {
"bob": "b0635d6a9851d3aed0cd6c495b282167acf761729078d975fc341b22650b07b9"
}
}
```
This NIP proposes an optional additional key like this:
````
{
"names": {
"bob": "b0635d6a9851d3aed0cd6c495b282167acf761729078d975fc341b22650b07b9"
},
"relays": {
"b0635d6a9851d3aed0cd6c495b282167acf761729078d975fc341b22650b07b9": [ "wss://relay.example.com", "wss://relay2.example.com" ]
},
}
````
The `relays` key contains an object with public keys as properties and arrays of relays as values.

34
36.md Normal file
View File

@@ -0,0 +1,34 @@
NIP-36
======
Sensitive Content / Content Warning
-----------------------------------
`draft` `optional` `author:fernandolguevara`
The `content-warning` tag enables users to specify if the event's content needs to be approved by readers to be shown.
Clients can hide the content until the user acts on it.
#### Spec
```
tag: content-warning
options:
- [reason]: optional
```
#### Example
```json
{
"pubkey": "<pub-key>",
"created_at": 1000000000,
"kind": 1,
"tags": [
["t", "hastag"],
["content-warning", "reason"] /* reason is optional */
],
"content": "sensitive content with #hastag\n",
"id": "<event-id>"
}
```

41
37.md Normal file
View File

@@ -0,0 +1,41 @@
NIP-37
======
Remote signing of events
------------------------
`draft` `optional` `author:fiatjaf`
## Long, unnecessary rambling introduction
There could be a myriad of other Nostr apps, mainly web apps, that a Nostr user wants to use for different purposes (not as their daily social-networking driver, but for other, small, low or one-time uses), for example, there could be a micro webapp dedicated only to changing profile metadata.
It is a bad experience for these small single-purpose apps to request the user's private key. It is easier for the developer and safer for the user if they could just prepare events and ask the user to sign them. [NIP-07](07.md) exists for this exact purpose, but it's probably reasonable to expect that most users won't install a browser extension and give it their private keys, specially the group of the most paranoid users (who would be using hardware wallets for their Nostr keys) and the less tech-savvy users (who won't even know what a browser extension is).
## Solution
Suppose a Nostr user Ulysses has its main key on an app a Nostr Android Application called ANA. Now to change its profile name, Ulysses visits a webapp called CPN.
After typing his profile name, Ulysses presses the button and that triggers CPN to open a connection to a relay R (chosen by CPN through any means it deems best) and fire a message `UNSIGNED` containing the new event `set_metadata` event without a signature:
```
["UNSIGNED", {"id": "ad68ae903460554de77e397230e54343c6e1247c0c3c0bd21bb5ee968b3ec50f", "pubkey": "11bd73a4b8dfe3434b83baaab1bd5cd3d4c4f63879cc35d28f1cfbaf843f7d3c", "created_at": 1669995181, "kind": 0, "tags": [], "content": "{\"name\": \"ulysses\"}"}]
```
After that, CPN shows a QR code containing the bech32-encoded event id (as bytes) followed by the relay URL (as UTF-8 encoded bytes) and the bech32 prefix `nrs`: `NRS14452AYP5VP25MEM789ERPE2RG0RWZFRUPS7QH5SMKHHFDZE7C58HWUMN8GHJ7UN9D3SHJTNWDAEHGU3WVDHK6W609C5` (along with a clickable link `nostr:nrs14452ayp5vp25mem789erpe2rg0rwzfrups7qh5smkhhfdze7c58hwumn8ghj7un9d3shjtnwdaehgu3wvdhk6w609c5`):
![QR Code](https://user-images.githubusercontent.com/1653275/205337809-a7a8a5ab-e4b5-445c-a2ec-25fcd23d00d1.png)
Ulysses scans that with his phone camera and opens the scanned code on ANA. Upon seeing the `nrs1` prefix, ANA will decode it, open a connection to relay R and fire a message:
```
["UNSIGNED", "ad68ae903460554de77e397230e54343c6e1247c0c3c0bd21bb5ee968b3ec50f"]
```
The relay R will have stored the unsigned for some short time period, like 5 minutes, before discarding it, so when it gets the `UNSIGNED` message it knows to return that unsigned event to the caller.
```
["UNSIGNED", {"id": "ad68ae903460554de77e397230e54343c6e1247c0c3c0bd21bb5ee968b3ec50f", "pubkey": "11bd73a4b8dfe3434b83baaab1bd5cd3d4c4f63879cc35d28f1cfbaf843f7d3c", "created_at": 1669995181, "kind": 0, "tags": [], "content": "{\"name\": \"ulysses\"}"}]
```
Upon getting the unsigned event, ANA can display it to the user before submitting it again to the same relay or to other relays it decides to using a normal `EVENT` message. It is recommended to submit it back at least to the same relay R just in case CPN wants to learn that the event was properly signed and published and wants to do something in its UI after that.

View File

@@ -18,27 +18,65 @@ 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-20: Command Results](20.md)
- [NIP-22: Event created_at Limits](22.md)
- [NIP-25: Reactions](25.md)
- [NIP-26: Delegated Event Signing](26.md)
- [NIP-28: Public Chat](28.md)
- [NIP-35: User Discovery](35.md)
- [NIP-36: Sensitive Content](36.md)
- [NIP-37: Remote Signing of Events](37.md)
## Event Kinds
| kind | description | NIP |
|------|---------------------------|------|
| 0 | Metadata | 1, 5 |
| 1 | Text | 1 |
| 2 | Recommend Relay | 1 |
| 3 | Contacts | 2 |
| 4 | Encrypted Direct Messages | 4 |
| 5 | Event Deletion | 9 |
| kind | description | NIP |
|-------------|-----------------------------|------------------------|
| 0 | Metadata | [1](01.md), [5](05.md) |
| 1 | Text | [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) |
| 10000-19999 | Replaceable Events Reserved | [16](16.md) |
| 20000-29999 | Ephemeral Events Reserved | [16](16.md) |
Please update this list when proposing NIPs introducing new event kinds.
## 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) |
| UNSIGNED | used to send and request unsigned events | [37](37.md) |
### Relay to Client
| type | description | NIP |
| -------- | --------------------------------------------------------- | ------------- |
| 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) |
| UNSIGNED | used to send unsigned events | [37](37.md) |
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).
## Criteria for acceptance of NIPs
1. They should be implemented somewhere at least as a prototype somewhere.
1. They should be implemented in at least one client and one relay -- when applicable.
2. They should make sense.
3. Other rules will be made up when necessary.
3. They should be optional and backwards-compatible: care must be taken such that clients and relays that choose to not implement them do not stop working when interacting with the ones that choose to.
4. Other rules will be made up when necessary.
## License