Merge branch 'nostr-protocol:master' into ethkeygen

This commit is contained in:
0xc0de4c0ffee 2023-02-17 16:43:46 +05:45 committed by GitHub
commit 7d80aecff5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 251 additions and 13 deletions

19
19.md
View File

@ -35,6 +35,7 @@ These are the possible bech32 prefixes with `TLV`:
- `nprofile`: a nostr profile - `nprofile`: a nostr profile
- `nevent`: a nostr event - `nevent`: a nostr event
- `nrelay`: a nostr relay - `nrelay`: a nostr relay
- `naddr`: a nostr parameterized replaceable event coordinate (NIP-33)
These possible standardized `TLV` types are indicated here: These possible standardized `TLV` types are indicated here:
@ -42,15 +43,21 @@ These possible standardized `TLV` types are indicated here:
- depends on the bech32 prefix: - depends on the bech32 prefix:
- for `nprofile` it will be the 32 bytes of the profile public key - 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 `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 `nprofile`, `nevent` and `nrelay` this may be included only once. - for `naddr`, it is the identifier (the `"d"` tag) of the event being referenced
- `1`: `relay` - `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. - for `nprofile`, `nevent` and `naddr`, a relay in which the entity (profile or event) is more likely to be found, encoded as ascii
- not applicable to `nrelay`. - this may be included multiple times
- `2`: `author`
- for `naddr`, the 32 bytes of the pubkey of the event
- `3`: `kind`
- for `naddr`, the 32-bit unsigned integer of the kind, big-endian
## Examples ## Examples
- `npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsyjh6w6` should decode into the public key hex `3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d` and vice-versa - `npub10elfcs4fr0l0r8af98jlmgdh9c8tcxjvz9qkw038js35mp4dma8qzvjptg` should decode into the public key hex `7e7e9c42a91bfef19fa929e5fda1b72e0ebc1a4c1141673e2794234d86addf4e` and vice-versa
- `nsec180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsgyumg0` should decode into the private key hex `3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d` 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: - `nprofile1qqsrhuxx8l9ex335q7he0f09aej04zpazpl0ne2cgukyawd24mayt8gpp4mhxue69uhhytnc9e3k7mgpz4mhxue69uhkg6nzv9ejuumpv34kytnrdaksjlyr9p` should decode into a profile with the following TLV items:
- pubkey: `3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d` - pubkey: `3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d`
- relay: `wss://r.x.com` - relay: `wss://r.x.com`

64
23.md Normal file
View File

@ -0,0 +1,64 @@
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.
### Metadata
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 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
### 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 `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 `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: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.
The same principles can be applied to `nevent1...`, `note1...`, `nprofile1...` or `npub1...`.
## Example Event
```json
{
"kind": 30023,
"created_at": 1675642635,
"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"],
["published_at", "1296962229"],
["t", "placeholder"],
["e", "b3e392b11f5d4f28321cedd09303a748acfd0487aea5a7450b3481c60b6e4f87", "wss://relay.example.com"],
["a", "30023:a695f6b60119d9521934a691347d9f78e8770b56da16bb255ee286ddf9fda919:ipsum", "wss://relay.nostr.org"]
],
"pubkey": "...",
"id": "..."
}
```

2
26.md
View File

@ -19,7 +19,7 @@ This NIP introduces a new tag: `delegation` which is formatted as follows:
"delegation", "delegation",
<pubkey of the delegator>, <pubkey of the delegator>,
<conditions query string>, <conditions query string>,
<64-byte Schnorr signature of the sha256 hash of the delegation token> <delegation token: 64-byte Schnorr signature of the sha256 hash of the delegation string>
] ]
``` ```

18
33.md
View File

@ -12,10 +12,10 @@ Implementation
-------------- --------------
The value of a tag is defined as the first parameter of a tag after the tag name. 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 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 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 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` value as an empty string. Events from the same author with any of the following `tags`
replace each other: 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. 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", "<event hex id>", "<relay url>"]`).
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 `naddr` code is the tag `"a"`, comprised of `["a", "<kind>:<pubkey>:<d-identifier>", "<relay url>"]`.
Client Behavior Client Behavior
--------------- ---------------

148
57.md Normal file
View File

@ -0,0 +1,148 @@
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 `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`.
### 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.
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.
## 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.

View File

@ -1,6 +1,6 @@
# NIPs # 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-01: Basic protocol flow description](01.md)
- [NIP-02: Contact List and Petnames](02.md) - [NIP-02: Contact List and Petnames](02.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-07: `window.nostr` capability for web browsers](07.md)
- [NIP-08: Handling Mentions](08.md) - [NIP-08: Handling Mentions](08.md)
- [NIP-09: Event Deletion](09.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-11: Relay Information Document](11.md)
- [NIP-12: Generic Tag Queries](12.md) - [NIP-12: Generic Tag Queries](12.md)
- [NIP-13: Proof of Work](13.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-19: bech32-encoded entities](19.md)
- [NIP-20: Command Results](20.md) - [NIP-20: Command Results](20.md)
- [NIP-21: `nostr:` URL scheme](21.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-25: Reactions](25.md)
- [NIP-26: Delegated Event Signing](26.md) - [NIP-26: Delegated Event Signing](26.md)
- [NIP-28: Public Chat](28.md) - [NIP-28: Public Chat](28.md)
@ -31,10 +32,10 @@ NIPs stand for **Nostr Implementation Possibilities**. They exist to document wh
- [NIP-42: Authentication of clients to relays](42.md) - [NIP-42: Authentication of clients to relays](42.md)
- [NIP-50: Keywords filter](50.md) - [NIP-50: Keywords filter](50.md)
- [NIP-56: Reporting](56.md) - [NIP-56: Reporting](56.md)
- [NIP-57: Lightning Zaps](57.md)
- [NIP-65: Relay List Metadata](65.md) - [NIP-65: Relay List Metadata](65.md)
## Event Kinds ## Event Kinds
| kind | description | NIP | | kind | description | NIP |
| ------------- | -------------------------------- | ----------------------- | | ------------- | -------------------------------- | ----------------------- |
| 0 | Metadata | [1](01.md), [5](05.md) | | 0 | Metadata | [1](01.md), [5](05.md) |
@ -51,8 +52,11 @@ NIPs stand for **Nostr Implementation Possibilities**. They exist to document wh
| 44 | Channel Mute User | [28](28.md) | | 44 | Channel Mute User | [28](28.md) |
| 45-49 | Public Chat Reserved | [28](28.md) | | 45-49 | Public Chat Reserved | [28](28.md) |
| 1984 | Reporting | [56](56.md) | | 1984 | Reporting | [56](56.md) |
| 9734 | Zap Request | [57](57.md) |
| 9735 | Zap | [57](57.md) |
| 10002 | Relay List Metadata | [65](65.md) | | 10002 | Relay List Metadata | [65](65.md) |
| 22242 | Client Authentication | [42](42.md) | | 22242 | Client Authentication | [42](42.md) |
| 30023 | Long-form Content | [23](23.md) |
| 1000-9999 | Regular Events | [16](16.md) | | 1000-9999 | Regular Events | [16](16.md) |
| 10000-19999 | Replaceable Events | [16](16.md) | | 10000-19999 | Replaceable Events | [16](16.md) |
| 20000-29999 | Ephemeral Events | [16](16.md) | | 20000-29999 | Ephemeral Events | [16](16.md) |
@ -89,6 +93,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) | | e | event id (hex) | relay URL, marker | [1](01.md), [10](10.md) |
| p | pubkey (hex) | relay URL | [1](01.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) | | r | a reference (URL, etc) | | [12](12.md) |
| t | hashtag | | [12](12.md) | | t | hashtag | | [12](12.md) |
| g | geohash | | [12](12.md) | | g | geohash | | [12](12.md) |