diff --git a/88.md b/88.md new file mode 100644 index 0000000000..59e8872c10 --- /dev/null +++ b/88.md @@ -0,0 +1,121 @@ +NIP-88 +====== + +Discreet Log Contract Oracles on Nostr +----------------- + +`draft` `optional` + +This NIP describes two event kinds, `88` and `89`, for [Discreet Log Contract (DLC)](https://bitcoinops.org/en/topics/discreet-log-contracts/) oracles to publish their announcements and attestations over Nostr. Clients can consume these signed events to create conditional payment contracts which fulfill differently based on the oracles' attestations. + +## Format + +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. + +## 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": "BA/cNhCpdD25j/MwDaa4F42QIq8NsOGmaW1MxyswZnipGWirwoxPhL1SmoHcp1JuCjYXF...", + "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." + ], + + // optional, if this is a numeric event for an asset pair + ["n", "BTC"], + ["n", "USD"] + ], + "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 UTF-8 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. + +The optional `n` tag is described further down this document. + +Upon receiving an announcement event of kind `88`, clients _should_ validate: +- the base64-encoded announcement data contains a copy of the correct oracle attestation pubkey. The oracle's attestation key may be distinct from the oracle's Nostr key. +- the announcement is signed correctly by the expected oracle attestation pubkey. +- [the event descriptor included in the announcement](https://github.com/discreetlogcontracts/dlcspecs/blob/master/Messaging.md#the-event_descriptor-type) matches the tags in the `kind:88` event. + +### `kind:89` + +```jsonc +{ + "kind": 89, + "content": "w7HSaUaPQn7Fa00PoUwTqkR2+wXHCPjD8Da5f4OcJ0EACsUw6uSdQgUDLLG9o/e9daS...", + "tags": [ + [ + "e", // the Nostr event id of the announcement + "30efed56a035b2549fcaeec0bf2c1595f9a9b3bb4b1a38abaf8ee9041c4b7d93", + ], + + // optional, if this is a numeric attestation for an asset pair + ["n", "BTC"], + ["n", "USD"] + ], + "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: +- the base64-encoded attestation data [contains a copy](https://github.com/discreetlogcontracts/dlcspecs/blob/master/Messaging.md#the-oracle_attestation-type) of the correct oracle attestation pubkey. This should be the same as the pubkey contained in the corresponding announcement event, of `kind:88`. +- the `event_id` field inside the `oracle_attestation` object matches the `event_id` field in the original `oracle_announcement` object, referred to by the `e` tag. +- the attestation signatures are valid under the oracle's attestation key. + +### The `n` Tag + +DLCs are often numeric events, in which the oracle signs the relative price of two assets. In this common case, kind `88` or `89` events may include exactly two `n` tags which indicate the ticker symbols of the assets whose relative value is being signed. + +The order of the tags implies a specific denomination of the price attestation: The attestation's outcome should be **the value of the first symbol in units of the second symbol.** For example, `[... ["n", "BTC"], ["n", "USD"]]` indicates the attestation supposedly signs the price of `BTC` in units of `USD`. + +### Oracle Pubkeys + +Oracles are responsible for choosing how to manage their attestation keypair(s). Oracle announcements and attestations embed their own copies of the oracle's BIP340 attestation public key. Oracles should ideally never change their attestation key pair between events, but they _may_ choose to migrate their attestation key, or use different keys for different types of events if they desire. Clients are responsible for choosing secure policies regarding which oracle attestation keys to trust and use. + +**By default, all clients must accept announcement/attestation signatures issued by the oracle's Nostr key.** This requirement allows oracles to fall back on using their Nostr key pair if managing multiple keys is unnecessary, or if their existing attestation key(s) become unusable. + +### `kind:10088` + +Kind `10088` lists a user's trusted oracles, for the purpose of 3rd party protocols negotating DLCs or DLC-adjacent conditional payment contracts with the user. A kind `10088` event contains one or more `s` tags with a oracle's Nostr pubkey, and one or more relays where that oracle's announcement events (`kind:88`) may be found. + +```jsonc +{ + "kind": 10088, + "tags": [ + ["s", "4fd5e210530e4f6b2cb083795834bfe5108324f1ed9f00ab73b9e8fcfe5f12fe", "wss://bitagent.prices"], + // ... + ], + //... +} +``` diff --git a/README.md b/README.md index 3b36f0bb53..df7c2d8fec 100644 --- a/README.md +++ b/README.md @@ -127,6 +127,8 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos | `43` | Channel Hide Message | [28](28.md) | | `44` | Channel Mute User | [28](28.md) | | `64` | Chess (PGN) | [64](64.md) | +| `88` | DLC Oracle Announcement | [88](88.md) | +| `89` | DLC Oracle Attestation | [88](88.md) | | `818` | Merge Requests | [54](54.md) | | `1021` | Bid | [15](15.md) | | `1022` | Bid confirmation | [15](15.md) | @@ -176,6 +178,7 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos | `10030` | User emoji list | [51](51.md) | | `10050` | Relay list to receive DMs | [51](51.md), [17](17.md) | | `10063` | User server list | [Blossom][blossom] | +| `10088` | Trusted DLC Oracle List | [88](88.md) | | `10096` | File storage server list | [96](96.md) | | `13194` | Wallet Info | [47](47.md) | | `21000` | Lightning Pub RPC | [Lightning.Pub][lnpub] |