upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--01.md2
-rw-r--r--04.md2
-rw-r--r--56.md82
-rw-r--r--57.md146
-rw-r--r--65.md70
-rw-r--r--README.md49
6 files changed, 329 insertions, 22 deletions
diff --git a/01.md b/01.md
index e1e9444..68efc6f 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
26 ... // other kinds of tags may be included later 26 ... // other kinds of tags may be included later
27 ], 27 ],
28 "content": <arbitrary string>, 28 "content": <arbitrary string>,
29 "sig": <64-bytes signature of the sha256 hash of the serialized event data, which is the same as the "id" field> 29 "sig": <64-bytes hex of the signature of the sha256 hash of the serialized event data, which is the same as the "id" field>
30} 30}
31``` 31```
32 32
diff --git a/04.md b/04.md
index 723bd70..0ebcddb 100644
--- a/04.md
+++ b/04.md
@@ -14,6 +14,8 @@ A special event with kind `4`, meaning "encrypted direct message". It is suppose
14 14
15**`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", "<event_id>"]`. 15**`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", "<event_id>"]`.
16 16
17**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).
18
17Code sample for generating such an event in JavaScript: 19Code sample for generating such an event in JavaScript:
18 20
19```js 21```js
diff --git a/56.md b/56.md
new file mode 100644
index 0000000..55ee1a2
--- /dev/null
+++ b/56.md
@@ -0,0 +1,82 @@
1
2NIP-56
3======
4
5Reporting
6---------
7
8`draft` `optional` `author:jb55`
9
10A report is a `kind 1984` note that is used to report other notes for spam,
11illegal and explicit content.
12
13The content MAY contain additional information submitted by the entity
14reporting the content.
15
16Tags
17----
18
19The report event MUST include a `p` tag referencing the pubkey of the user you
20are reporting.
21
22If reporting a note, an `e` tag MUST also be included referencing the note id.
23
24A `report type` string MUST be included as the 3rd entry to the `e` or `p` tag
25being reported, which consists of the following report types:
26
27- `nudity` - depictions of nudity, porn, etc.
28- `profanity` - profanity, hateful speech, etc.
29- `illegal` - something which may be illegal in some jurisdiction
30- `spam` - spam
31- `impersonation` - someone pretending to be someone else
32
33Some report tags only make sense for profile reports, such as `impersonation`
34
35Example events
36--------------
37
38```json
39{
40 "kind": 1984,
41 "tags": [
42 [ "p", <pubkey>, "nudity"]
43 ],
44 "content": "",
45 ...
46}
47
48{
49 "kind": 1984,
50 "tags": [
51 [ "e", <eventId>, "illegal"],
52 [ "p", <pubkey>]
53 ],
54 "content": "He's insulting the king!",
55 ...
56}
57
58{
59 "kind": 1984,
60 "tags": [
61 [ "p", <impersonator pubkey>, "impersonation"],
62 [ "p", <victim pubkey>]
63 ],
64 "content": "Profile is imitating #[1]",
65 ...
66}
67```
68
69Client behavior
70---------------
71
72Clients can use reports from friends to make moderation decisions if they
73choose to. For instance, if 3+ of your friends report a profile as explicit,
74clients can have an option to automatically blur photos from said account.
75
76
77Relay behavior
78--------------
79
80It is not recommended that relays perform automatic moderation using reports,
81as they can be easily gamed. Admins could use reports from trusted moderators to
82takedown illegal or explicit content if the relay does not allow such things.
diff --git a/57.md b/57.md
new file mode 100644
index 0000000..78a3fd6
--- /dev/null
+++ b/57.md
@@ -0,0 +1,146 @@
1NIP-57
2======
3
4Lightning Zaps
5--------------
6
7`draft` `optional` `author:jb55` `author:kieran`
8
9This 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.
10
11Having 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.
12
13
14## Definitions
15
16`zapper` - the lightning node or service that sends zap notes (kind `9735`)
17
18`zap request` - a note of kind `9734` created by the person zapping
19
20`zap invoice` - the bolt11 invoice fetched from a custom lnurl endpoint which contains a `zap request` note
21
22
23## Protocol flow
24
25### Client side
26
271. Calculate the lnurl pay request url for a user from the lud06 or lud16 field on their profile
28
292. 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.
30
313. 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.
32
334. 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.
34
355. 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`.
36
37### LNURL Server side
38
39The lnurl server will need some additional pieces of information so that clients can know that zap invoices are supported:
40
411. 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.
42
432. Add an `allowsNostr` field and set it to true.
44
453. In the lnurl-pay callback URL, watch for a `nostr` querystring, where the contents of the note is a uri-encoded `zap request` JSON.
46
474. If present, the zap request note must be validated:
48
49 a. It MUST have a valid nostr signature
50
51 b. It MUST have tags
52
53 c. It MUST have at least one p-tag
54
55 d. It MUST have either 0 or 1 e-tag
56
57 e. There should be a `relays` tag with the relays to send the `zap` note to.
58
595. 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.
60
61At this point, the lightning node is ready to send the zap note once payment is received.
62
63## The zap note
64
65Zap 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.
66
67Example zap note:
68
69```json
70{
71 "id": "67b48a14fb66c60c8f9070bdeb37afdfcc3d08ad01989460448e4081eddda446",
72 "pubkey": "9630f464cca6a5147aa8a35f0bcdd3ce485324e732fd39e09233b1d848238f31",
73 "created_at": 1674164545,
74 "kind": 9735,
75 "tags": [
76 [
77 "p",
78 "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245"
79 ],
80 [
81 "e",
82 "3624762a1274dd9636e0c552b53086d70bc88c165bc4dc0f9e836a1eaf86c3b8"
83 ],
84 [
85 "bolt11",
86 "lnbc10u1p3unwfusp5t9r3yymhpfqculx78u027lxspgxcr2n2987mx2j55nnfs95nxnzqpp5jmrh92pfld78spqs78v9euf2385t83uvpwk9ldrlvf6ch7tpascqhp5zvkrmemgth3tufcvflmzjzfvjt023nazlhljz2n9hattj4f8jq8qxqyjw5qcqpjrzjqtc4fc44feggv7065fqe5m4ytjarg3repr5j9el35xhmtfexc42yczarjuqqfzqqqqqqqqlgqqqqqqgq9q9qxpqysgq079nkq507a5tw7xgttmj4u990j7wfggtrasah5gd4ywfr2pjcn29383tphp4t48gquelz9z78p4cq7ml3nrrphw5w6eckhjwmhezhnqpy6gyf0"
87 ],
88 [
89 "description",
90 "{\"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\"]]}"
91 ],
92 [
93 "preimage",
94 "5d006d2cf1e73c7148e7519a4c68adc81642ce0e25a432b2434c99f97344c15f"
95 ]
96 ],
97 "content": "",
98 "sig": "b0a3c5c984ceb777ac455b2f659505df51585d5fd97a0ec1fdb5f3347d392080d4b420240434a3afd909207195dac1e2f7e3df26ba862a45afd8bfe101c2b1cc"
99 }
100```
101
102* The zap note MUST have a `bolt11` tag containing the description hash bolt11 invoice.
103
104* The zap note MUST contain a `description` tag which is the invoice description.
105
106* `SHA256(description)` MUST match the description hash in the bolt11 invoice.
107
108* 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.
109
110The 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.
111
112
113### Creating a zap note
114
115When receiving a payment, the following steps are executed:
116
1171. 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.
118
1192. 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.
120
1214. The note MUST have only one `p` tag
122
1235. The note MUST have 0 or 1 `e` tag
124
1256. 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.
126
1277. Send the note to the `relays` declared in the `zap request` note from the invoice description.
128
129A reference implementation for the zapper is here: [zapper][zapper]
130
131[zapper]: https://github.com/jb55/cln-nostr-zapper
132
133
134## Client Behavior
135
136Clients MAY fetch zap notes on posts and profiles:
137
138`{"kinds": [9735], "#e": [...]}`
139
140To 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.
141
142Once 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.
143
144## Future Work
145
146Zaps 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/65.md b/65.md
new file mode 100644
index 0000000..c4fc246
--- /dev/null
+++ b/65.md
@@ -0,0 +1,70 @@
1NIP-65
2======
3
4Relay List Metadata
5-------------------
6
7`draft` `optional` `author:mikedilger`
8
9A 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.
10
11The primary purpose of this relay list is to advertise to others, not for configuring one's client.
12
13The content is not used and SHOULD be blank.
14
15The `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.
16
17Clients SHOULD, as with all replaceable events, use only the most recent kind-10002 event they can find.
18
19### The meaning of read and write
20
21If 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.
22
23Clients 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.
24
25If 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.
26
27### Motivation
28
29There 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)
30
31Because 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:
32
33 - Most people are sending their posts to the same most popular relays in order to be more widely seen
34 - Many people are pulling from a large number of relays (including many duplicate events) in order to get more data
35 - Events are being copied between relays, oftentimes to many different relays
36
37### Purposes
38
39The 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.
40
41### Suggestions
42
43It 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.
44
45Authors 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.
46
47It 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
48
49 - finding where someone posts is rather important
50 - these events do not have content that needs management
51 - relays only need to store one replaceable event per pubkey to offer this service
52
53### Why not in kind `0` Metadata
54
55Even 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.
56
57### Example
58
59```json
60{
61 "kind": 10002,
62 "tags": [
63 ["r", "wss://alicerelay.example.com"],
64 ["r", "wss://brando-relay.com"],
65 ["r", "wss://expensive-relay.example2.com", "write"],
66 ["r", "wss://nostr-relay.example.com", "read"],
67 ],
68 "content": "",
69 ...other fields
70```
diff --git a/README.md b/README.md
index 0115e68..42cbc0c 100644
--- a/README.md
+++ b/README.md
@@ -30,29 +30,36 @@ NIPs stand for **Nostr Implementation Possibilities**. They exist to document wh
30- [NIP-40: Expiration Timestamp](40.md) 30- [NIP-40: Expiration Timestamp](40.md)
31- [NIP-42: Authentication of clients to relays](42.md) 31- [NIP-42: Authentication of clients to relays](42.md)
32- [NIP-50: Keywords filter](50.md) 32- [NIP-50: Keywords filter](50.md)
33- [NIP-57: Lightning Zaps](57.md)
34- [NIP-56: Reporting](56.md)
35- [NIP-65: Relay List Metadata](65.md)
33 36
34## Event Kinds 37## Event Kinds
35 38| kind | description | NIP |
36| kind | description | NIP | 39| ------------- | -------------------------------- | ----------------------- |
37|-------------|-----------------------------|------------------------| 40| 0 | Metadata | [1](01.md), [5](05.md) |
38| 0 | Metadata | [1](01.md), [5](05.md) | 41| 1 | Short Text Note | [1](01.md) |
39| 1 | Text | [1](01.md) | 42| 2 | Recommend Relay | [1](01.md) |
40| 2 | Recommend Relay | [1](01.md) | 43| 3 | Contacts | [2](02.md) |
41| 3 | Contacts | [2](02.md) | 44| 4 | Encrypted Direct Messages | [4](04.md) |
42| 4 | Encrypted Direct Messages | [4](04.md) | 45| 5 | Event Deletion | [9](09.md) |
43| 5 | Event Deletion | [9](09.md) | 46| 7 | Reaction | [25](25.md) |
44| 30023 | Long-form Content | [23](23.md) | 47| 40 | Channel Creation | [28](28.md) |
45| 7 | Reaction | [25](25.md) | 48| 41 | Channel Metadata | [28](28.md) |
46| 40 | Channel Creation | [28](28.md) | 49| 42 | Channel Message | [28](28.md) |
47| 41 | Channel Metadata | [28](28.md) | 50| 43 | Channel Hide Message | [28](28.md) |
48| 42 | Channel Message | [28](28.md) | 51| 44 | Channel Mute User | [28](28.md) |
49| 43 | Channel Hide Message | [28](28.md) | 52| 45-49 | Public Chat Reserved | [28](28.md) |
50| 44 | Channel Mute User | [28](28.md) | 53| 1984 | Reporting | [56](56.md) |
51| 45-49 | Public Chat Reserved | [28](28.md) | 54| 9734 | Zap Request | [57](57.md) |
52| 22242 | Client Authentication | [42](42.md) | 55| 9735 | Zap | [57](57.md) |
53| 10000-19999 | Replaceable Events Reserved | [16](16.md) | 56| 10002 | Relay List Metadata | [65](65.md) |
54| 20000-29999 | Ephemeral Events Reserved | [16](16.md) | 57| 22242 | Client Authentication | [42](42.md) |
55| 30000-39999 | Param. Repl. Events Reserved| [33](33.md) | 58| 30023 | Long-form Content | [23](23.md) |
59| 1000-9999 | Regular Events | [16](16.md) |
60| 10000-19999 | Replaceable Events | [16](16.md) |
61| 20000-29999 | Ephemeral Events | [16](16.md) |
62| 30000-39999 | Parameterized Replaceable Events | [33](33.md) |
56 63
57 64
58 65