mirror of
https://github.com/nostr-protocol/nips.git
synced 2024-12-12 18:36:24 +00:00
Merge eb4f4083b8
into a1ca7a194b
This commit is contained in:
commit
23b564a2d2
181
88.md
Normal file
181
88.md
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
NIP-88
|
||||||
|
======
|
||||||
|
|
||||||
|
Discreet Log Contracts over nostr
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
`draft` `optional`
|
||||||
|
|
||||||
|
This NIP describes a way to use Discreet Log Contracts (DLCs) over Nostr. This comes in four main
|
||||||
|
components: `kind:8_888` for sending DLC messages between wallets. `kind:30088` for posting DLC offers to the global
|
||||||
|
market. `kind:88` and `kind:89` for publishing DLC oracle announcements and attestations. And `kind:90` for a DLC
|
||||||
|
"receipt" that can publish the result of a DLC for social interaction.
|
||||||
|
|
||||||
|
## DLC Messages
|
||||||
|
|
||||||
|
DLCs typically use [BOLT 8](https://github.com/lightning/bolts/blob/master/08-transport.md) for sending messages but
|
||||||
|
this has various problems: it requires the ability to accept incoming connections and an always-on node. Nostr provides
|
||||||
|
a unique opportunity to use a different transport layer for DLCs. This NIP proposes a new `kind:8_888` message that
|
||||||
|
acts like a mailbox for DLC messages. The DLC messages are sent over nostr and available for the user the next time
|
||||||
|
they open their wallet. This allows for a more mobile-friendly DLC experience.
|
||||||
|
|
||||||
|
DLC protocol messages are binary-serialized messages described concretely in
|
||||||
|
[this document](https://github.com/discreetlogcontracts/dlcspecs/blob/master/Messaging.md).
|
||||||
|
Whenever embedding DLC messages inside Nostr events (which are encoded as JSON), we serialize those DLC messages in base64.
|
||||||
|
|
||||||
|
### `kind:8_888`
|
||||||
|
|
||||||
|
Kind 8_888 is a simple message that contains a [NIP04](04.md) encrypted DLC message and is tagged with the recipient's
|
||||||
|
public key with a `p` tag and if it is in reply to another event, that event should be tagged with an `e` tag. The DLC
|
||||||
|
message is first serialized in binary, and then encrypted with [NIP04](04.md).
|
||||||
|
|
||||||
|
A DLC wallet should only process messages that are tagged with their public key and that are in reply to a message they
|
||||||
|
sent unless it is an offer. This is to prevent spam and to prevent a malicious actor from sending a message to a user
|
||||||
|
that looks like it is from a different user.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"kind": 8888,
|
||||||
|
"content": "TJob1dQrf2ndsmdbeGU+05HT5GMnBSx3fx8QdDY/g3NvCa7klfzgaQCmRZuo1d3WQjHDOjzSY1+MgTK5WjewFFumCcOZniWtOMSga9tJk1ky00tLoUUzyLnb1v9x95h/iT/KpkICJyAwUZ+LoJBUzLrK52wNTMt8M5jSLvCkRx8C0BmEwA/00pjOp4eRndy19H4WUUehhjfV2/VV/k4hMAjJ7Bb5Hp9xdmzmCLX9+64+MyeIQQjQAHPj8dkSsRahP7KS3MgMpjaF8nL48Bg5suZMxJayXGVp3BLtgRZx5z5nOk9xyrYk+71e2tnP9IDvSMkiSe76BcMct+m7kGVrRcavDI4n62goNNh25IpghT+a1OjjkpXt9me5wmaL7fxffV1pchdm+A7KJKIUU3kLC7QbUifF22EucRA9xiEyxETusNludBXN24O3llTbOy4vYFsq35BeZl4v1Cse7n2htZicVkItMz3wjzj1q1I1VqbnorNXFgllkRZn4/YXfTG/RMnoK/bDogRapOV+XToZ+IvsN0BqwKSUDx+ydKpci6htDRF2WDRkU+VQMqwM0CoLzy2H6A2cqyMMMD9SLRRzBg==?iv=S3rFeFr1gsYqmQA7bNnNTQ==",
|
||||||
|
"tags": [
|
||||||
|
[
|
||||||
|
"p",
|
||||||
|
"04c915daefee38317fa734444acee390a8269fe5810b2241e5e6dd343dfbecc9"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"e",
|
||||||
|
"9ae37aa68f48645127299e9453eb5d908a0cbb6058ff340d528ed4d37c8994fb"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"pubkey": "97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322",
|
||||||
|
"created_at": 1679673265,
|
||||||
|
"id": "30efed56a035b2549fcaeec0bf2c1595f9a9b3bb4b1a38abaf8ee9041c4b7d93",
|
||||||
|
"sig": "f2cb581a84ed10e4dc84937bd98e27acac71ab057255f6aa8dfa561808c981fe8870f4a03c1e3666784d82a9c802d3704e174371aa13d63e2aeaf24ff5374d9d"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## DLC Offers
|
||||||
|
|
||||||
|
DLCs are done between two parties and Nostr provides a unique opportunity to create a global market for DLCs. This
|
||||||
|
market can be constructed with a simple list of DLC offers that can be filtered by the user's wallet. The user can then
|
||||||
|
select an offer and send a message to the offerer to begin the DLC process. `kind:30088` is an event that contains a DLC
|
||||||
|
offer.
|
||||||
|
|
||||||
|
A parameterized replaceable event is used to allow the offerer to update the offer or remove it from the market. The `d`
|
||||||
|
tag should be the Offer's id to allow replacement of the offer. If the user wishes to remove the offer from the market,
|
||||||
|
they can replace the event with an `expires` tag that is in the past. The `relays` tag indicates the relays on which to
|
||||||
|
contact the offerer.
|
||||||
|
|
||||||
|
The `content` field must be the base64-encoding of a binary-serialized
|
||||||
|
[`contract_info` object](https://github.com/discreetlogcontracts/dlcspecs/blob/master/Messaging.md#the-contract_info-type).
|
||||||
|
|
||||||
|
### `kind:30_088`
|
||||||
|
|
||||||
|
```jsonc
|
||||||
|
{
|
||||||
|
"kind": 30088,
|
||||||
|
"content": "base64 contract_info",
|
||||||
|
"tags": [
|
||||||
|
[
|
||||||
|
"relays",
|
||||||
|
"wss://nostr.mutinywallet.com",
|
||||||
|
"wss://relay.damus.io"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"expires",
|
||||||
|
"1695327657"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"d",
|
||||||
|
"6423394a32f37a4f0590e74f9308f5aee06e59e14f50c4cd6d59365caed13cb7"
|
||||||
|
],
|
||||||
|
],
|
||||||
|
"pubkey": "97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322",
|
||||||
|
"created_at": 1679673265,
|
||||||
|
"id": "30efed56a035b2549fcaeec0bf2c1595f9a9b3bb4b1a38abaf8ee9041c4b7d93",
|
||||||
|
"sig": "f2cb581a84ed10e4dc84937bd98e27acac71ab057255f6aa8dfa561808c981fe8870f4a03c1e3666784d82a9c802d3704e174371aa13d63e2aeaf24ff5374d9d"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## DLC Oracle Gossip
|
||||||
|
|
||||||
|
DLCs require an oracle to attest to the outcome of real world events. This is done by the oracle signing a message
|
||||||
|
containing the outcome of the event. Before they attest to the outcome, they must create an announcement where they
|
||||||
|
publish the intent to sign the future event. This announcement is then used by the DLC participants to create the
|
||||||
|
contract. Here we define two events, `kind:88` and `kind:89` that are used to publish the oracle's announcement and
|
||||||
|
attestations respectively.
|
||||||
|
|
||||||
|
### `kind:88`
|
||||||
|
|
||||||
|
```jsonc
|
||||||
|
{
|
||||||
|
"kind": 88,
|
||||||
|
"content": "base64 oracle_annoucement",
|
||||||
|
"tags": [
|
||||||
|
[
|
||||||
|
"relays", // the relays the oracle will publish attestations to
|
||||||
|
"wss://nostr.mutinywallet.com",
|
||||||
|
"wss://relay.damus.io"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"title",
|
||||||
|
"Optional Event Title"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"description",
|
||||||
|
"An optional human-readable description of the event which the oracle will attest to, in plain text."
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"pubkey": "97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322",
|
||||||
|
"created_at": 1679673265,
|
||||||
|
"id": "30efed56a035b2549fcaeec0bf2c1595f9a9b3bb4b1a38abaf8ee9041c4b7d93",
|
||||||
|
"sig": "f2cb581a84ed10e4dc84937bd98e27acac71ab057255f6aa8dfa561808c981fe8870f4a03c1e3666784d82a9c802d3704e174371aa13d63e2aeaf24ff5374d9d"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `content` field must be the base64-encoding of a binary-serialized
|
||||||
|
[`oracle_annoucement` object](https://github.com/discreetlogcontracts/dlcspecs/blob/master/Messaging.md#the-oracle_annoucement-type).
|
||||||
|
|
||||||
|
The optional `title` tag gives observers a short human-readable title with which to display the announcement in cards, hyperlinks, etc. It _should_ be at most 100 characters of UTF8 text. Clients _should_ ignore or truncate titles longer than 100 characters. This tag must NOT be parsed as markdown or HTML.
|
||||||
|
|
||||||
|
The optional `description` tag provides a human-readable summary of the real-world event which this announcement is for. The `description` should give observers context, so that they know how the real-world event in question will be reflected in the oracle's final attestation. This tag must NOT be parsed as markdown or HTML.
|
||||||
|
|
||||||
|
### `kind:89`
|
||||||
|
|
||||||
|
```jsonc
|
||||||
|
{
|
||||||
|
"kind": 89,
|
||||||
|
"content": "base64 oracle_attestation",
|
||||||
|
"tags": [
|
||||||
|
[
|
||||||
|
"e", // the Nostr event id of the announcement
|
||||||
|
"30efed56a035b2549fcaeec0bf2c1595f9a9b3bb4b1a38abaf8ee9041c4b7d93",
|
||||||
|
],
|
||||||
|
],
|
||||||
|
"pubkey": "97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322",
|
||||||
|
"created_at": 1679673265,
|
||||||
|
"id": "30efed56a035b2549fcaeec0bf2c1595f9a9b3bb4b1a38abaf8ee9041c4b7d93",
|
||||||
|
"sig": "f2cb581a84ed10e4dc84937bd98e27acac71ab057255f6aa8dfa561808c981fe8870f4a03c1e3666784d82a9c802d3704e174371aa13d63e2aeaf24ff5374d9d"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `content` field must be the base64-encoding of a binary-serialized
|
||||||
|
[`oracle_attestation` object](https://github.com/discreetlogcontracts/dlcspecs/blob/master/Messaging.md#the-oracle_attestation-type).
|
||||||
|
|
||||||
|
Note that the `e` tag is the _Nostr event identifier_ for the `kind:88` announcement event, which is distinct from the identifier
|
||||||
|
embedded [in the announcement](https://github.com/discreetlogcontracts/dlcspecs/blob/master/Messaging.md#oracle_event) or
|
||||||
|
[in the attestation itself](https://github.com/discreetlogcontracts/dlcspecs/blob/master/Messaging.md#oracle_attestation). The `e`
|
||||||
|
tag is intended to be used to look up the corresponding announcement event.
|
||||||
|
|
||||||
|
Upon receiving an attestation, clients _should_ validate that the `event_id` field inside the `oracle_announcement` object matches
|
||||||
|
the `event_id` field in the `oracle_attestation` object.
|
||||||
|
|
||||||
|
## DLC Receipts
|
||||||
|
|
||||||
|
DLCs can be fun, social events. This NIP proposes a `kind:90` event that can be used to publish the result of a DLC
|
||||||
|
contract. This event can be used to show off the result of a DLC to the user's followers, similar [Zaps](57.md) but for
|
||||||
|
DLC bets.
|
||||||
|
|
||||||
|
### `kind:90`
|
||||||
|
|
||||||
|
todo I still need to think about this one
|
Loading…
Reference in New Issue
Block a user