Skip to content

Commit

Permalink
oracle proposal (#55)
Browse files Browse the repository at this point in the history
  • Loading branch information
Tibo-lg authored Nov 4, 2020
1 parent 0b69c3e commit 3df7166
Show file tree
Hide file tree
Showing 2 changed files with 200 additions and 73 deletions.
76 changes: 3 additions & 73 deletions Messaging.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ Various fundamental types are referred to in the message specifications:
* `u32`: a 4 byte unsigned integer
* `u64`: an 8 byte unsigned integer
* `int32`: a 4 byte signed integer
* `bool`: a boolean value represented as a `byte` which can have only two value, `0x01` to represent `true` and `0x00` to represent false (any other value should be considered invalid).

Inside TLV records which contain a single value, leading zeros in
integers can be omitted:
Expand All @@ -77,7 +78,8 @@ The following convenience types are also defined:
* `spk`: A bitcoin script public key encoded as ASM prefixed with a `u16` value indicating its length.
* `short_contract_id`: an 8 byte value identifying a contract funding transaction on-chain (see [BOLT #7](https://github.com/lightningnetwork/lightning-rfc/blob/master/07-routing-gossip.md#definition-of-short-channel-id))
* `bigsize`: a variable-length, unsigned integer similar to Bitcoin's CompactSize encoding, but big-endian. Described in [BigSize](https://github.com/lightningnetwork/lightning-rfc/blob/master/01-messaging.md#appendix-a-bigsize-test-vectors).
* `string`: a UTF-8 encoded string using [NFC for normalization](https://github.com/discreetlogcontracts/dlcspecs/issues/89)
* `string`: a UTF-8 encoded string using [NFC for normalization](https://github.com/discreetlogcontracts/dlcspecs/issues/89), prefixed by a `bigsize` value indicating its length in bytes.


## DLC Specific Types

Expand Down Expand Up @@ -178,78 +180,6 @@ This type contains signatures of the funding transaction and any necessary infor
`witness` is the data for a witness element in a witness stack. An empty `witness_stack` is an error,
as every input must be Segwit. Witness elements should *not* include their length as part of the witness data.

### The `event_descriptor` Type

This type contains information about the *exact* and fully specified outcomes in an event for which an oracle plans on releasing a signature over.

#### Version 0 `external_event_descriptor`

1. type: 55300 (`external_event_descriptor_v0`)
2. data:
* [`string`:`external_name`]

`external_name` can refer to anything here and it is up to the oracle and user to agree on how to interpret it.

#### Version 0 `enum_event_descriptor`

1. type: 55302 (`enum_event_descriptor_v0`)
2. data:
* [`u16`:`num_outcomes`]
* [`u16`:`outcome_1_len`]
* [`string`:`outcome_1`]
* ...
* [`u16`:`outcome_n_len`]
* [`string`:`outcome_n`]

This type of event descriptor is a simple enumeration where the value `n` is the number of outcomes in the event.

Each `outcome_i` corresponds to the pre-image of a possible outcome that the oracle could sign.

#### Version 0 `range_event_descriptor`

1. type: 55304 (`range_event_descriptor_v0`)
2. data:
* [`int32`:`start`]
* [`int32`:`stop`]
* [`u16`:`step`]

`start` refers to the first possible outcome number

`end` refers to the last possible outcome number

`step` refers to the increment between each outcome

### The `oracle_event` Type

This type contains information about an event for which an oracle plans on releasing a signature over.

#### Version 0 `oracle_event`

1. type: 55330 (`oracle_event_v0`)
2. data:
* [`x_point`:`oracle_public_key`]
* [`x_point`:`oracle_nonce`]
* [`u32`:`event_maturity_epoch`]
* [`event_descriptor`:`event_descriptor`]
* [`string`:`event_uri`]

`event_maturity_epoch` refers to the earliest time this event (UTC) is expected to be signed, in epoch seconds.

`event_uri` is a name and/or categorization of this event given by the oracle.

### The `oracle_announcement` Type

This type contains information about an announcement of an oracle to attest to an event in the future.

#### Version 0 `oracle_announcement`

1. type: 55332 (`oracle_announcement`)
2. data:
* [`signature`:`annoucement_signature`]
* [`oracle_event`:`oracle_event`]

The `annoucement_signature` is a signature of the hash of the serialized `oracle_event` that is valid with respect to `oracle_public_key`. This can be shared with peers that have already verified this oracle's public key.

## Authors

Nadav Kohen <[email protected]>
Expand Down
197 changes: 197 additions & 0 deletions Oracle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
# Oracle specifications

## Introduction

For the purpose of these specifications, an event is a digital representation of a real world fact.
An [oracle](./Introduction.md#Oracle) is an entity that commits to publishing one or more signatures over a (number of) event outcome(s) ahead of time by releasing one or more [R-values](./Introduction.md#R-value) as well as necessary information for two parties to build a set of [CETs](./Introduction.md#Contract-Execution-Transaction-(CET)).
This necessary information is committed to in a so-called [_event descriptor_](#Event-descriptor) that will be further detailed in this document.

## Table of Contents

- [Event descriptor](#event-descriptor)
- [Simple enumeration](#simple-enumeration)
- [Example: Weather tomorrow](#example-weather-tomorrow)
- [Range](#range)
- [Example: tomorrow's temperature](#example-tomorrows-temperature)
- [Digit decomposition](#digit-decomposition)
- [Example: BTC/USD rate](#example-btcusd-rate)
- [Serialization and signing of outcome values](#serialization-and-signing-of-outcome-values)
- [Serialization of event descriptors](#serialization-of-event-descriptors)
- [Version 0 `enum_event_descriptor`](#version-0-enum_event_descriptor)
- [Version 0 `range_event_descriptor`](#version-0-range_event_descriptor)
- [Version 0 `digit_decomposition_event_descriptor`](#version-0-digit_decomposition_event_descriptor)
- [Oracle events](#oracle-events)
- [Version 0 `oracle_event`](#version-0-oracle_event)
- [Oracle announcements](#oracle-announcements)
- [Version 0 `oracle_announcement`](#version-0-oracle_announcement)

## Event descriptor

An event descriptor provides information to clients about an event for which an oracle plans on releasing a signature over its outcome.
The provided information should be sufficient for a client to create a set of adaptors signatures for some CETs that will cover all possible outcomes of the event.

Here we assume that an event outcome can be represented either as a set of strings or numbers.
Three kinds of event outcomes are defined (note that a single event can be composed of several types).

### Simple enumeration

For events that have a narrow range of possible outcomes, the outcomes can simply be enumerated.

#### Example: Weather tomorrow

Tomorrow's weather can be represented as the set of strings `[sunny, cloudy, rainy]`.

### Range

When an event has numerical outcomes that cannot be easily enumerated, they can be represented as a series with:

- start: the first possible outcome number
- count: the number of possible outcomes
- step: the increment
- unit: the unit of the outcome value
- precision: the precision of the outcome representing the base 10 exponent by which to multiply the signed number to obtain the actual outcome value.

#### Example: tomorrow's temperature

```
start: -100
count: 201
step: 1
unit: °C
precision: 0
```

### Digit decomposition

When a range of a numerical outcomes is large or unbounded, the oracle can represent the outcome using digit decomposition.

The event descriptor should include:

- base: a number representing the base in which the outcome value is decomposed and which will indicate the possible range of each digit that will be signed (e.g. 2 for binary, 10 for decimal, 16 for hex-decimal).
- is-signed: a boolean value indicating whether the outcomes can be negative.
- unit: the unit of the outcome value
- precision: the precision of the outcome representing the base exponent by which to multiply the number represented by the composition of the digits to obtain the actual outcome value.
- number of digits: the number of digits that the oracle will sign (if `is-signed` is set to true, the number of R-values for the event will be `number of digits + 1`).

In the case where the number of digits that make up the outcome value exceeds the number of r-values that the oracle committed to, the oracle should sign the maximal possible value that it can attest to.
In the case where the outcome value became negative but the oracle did not provide an extra R-value, it should sign the value 0.
The minimum and maximum values that can be attested to by an oracle should thus be interpreted as `max_value or more` and `min_value or less`.
This enables contracting party to specify payouts for the overflow and underflow cases, and avoid having to use the refund path which in most cases would be unfair.
More complex constructions where considered to handle these, but the simplicity of the currently specified approach is the reason that it was chosen.

The oracle must separately provide an array of R values, one for each of the digit that will be signed, with the first value of the array being used for signing the leftmost digit. If the is-signed value is true, an additional R-value must be provided as the first element in this array, which will be used to sign the string "+" in case of an outcome with a positive value or zero value and the string "-" in case of an outcome with a negative one.
In practice this array is provided as part of the [Oracle events](#Oracle-events) structure.

When the outcome is not the same order of magnitude as the maximum possible outcome, leading zeros must be signed.

#### Example: BTC/USD rate

The following example illustrates how numerical decomposition can help reduce the number of required CETs while covering a large range of possible outcomes.

Alice and Bob wish to enter into a DLC at time `t` when BTC/USD ~= $10000 with a maturity time of `t+1`.
The oracle provides 6 R-values `R0-5`, meaning that it will sign six digits `D0-5`, enabling him to attest to outcomes in the range `[000000,999999]`:

```
base: 10
isSigned: false
RValues: [R0, R1, R2, R3, R4, R5]
unit: dollars
precision: 0
```

Alice and Bob create a DLC with "relevant" outcomes between $10000 and $10999.
Below $10000 Alice gets everything, and above $10999 Bob gets everything.
They use the `R0` and `R1` values to cover the cases where BTC/USD < $10000 using `D0=0` and `D1=0`.
They use `R0`, `R1` and `R2` to cover the cases where BTC/USD > $10999 and <= $19999, using `D1=0`, `D1=1` and `D2 in [0-9]`.
They use `R0` and `R1` to cover the cases where BTC/USD >= $20000 and < $99999, using `D0=0` and `D1 in [2,9]`.
Finally, they use only `D0` to cover the cases where BTC/USD >= $100000 and <= $999999, using `D0 in [1-9]`.

At maturity time, if the BTC/USD rate is less than $999999, the oracle signs each of the digits representing the outcome value using the digits' corresponding R value.
For example, if the rate at maturity time is $20000, the oracle will sign the digits `0`, `2`, `0`, `0`, `0`, `0`.

If the rate is greater than $999999, the oracle signs the digits `9`, `9`, `9`, `9`, `9`, `9`.

### Serialization and signing of outcome values

Every outcome value should be encoded as [a UTF-8 string with NFC normalization](./Messaging.md#Fundamental-types), before being passed to the signing algorithm.
UTF-8 is chosen as being a widely supported and easy to implement encoding format.

For numerical outcomes represented in bases greater than 10, each digit should be converted to base 10 before being encoded (note that base 10 numbers in UTF-8 take values in the 0x0030-0x0039 range).
This helps preventing any confusion about the capitalization of letters or the introduction of non-standard characters.

### Serialization of event descriptors

Event descriptors should be serialized using [TLV format](https://github.com/lightningnetwork/lightning-rfc/blob/master/01-messaging.md#type-length-value-format) as described bellow.

#### Version 0 `enum_event_descriptor`

1. type: 55302 (`enum_event_descriptor_v0`)
2. data:
* [`u16`:`num_outcomes`]
* [`string`:`outcome_1`]
* ...
* [`string`:`outcome_n`]

This type of event descriptor is a simple enumeration where the value `n` is the number of outcomes in the event.

Note that `outcome_i` is the outcome value itself and not its hash that will be signed by the oracle.

#### Version 0 `range_event_descriptor`

1. type: 55304 (`range_event_descriptor_v0`)
2. data:
* [`int32`:`start`]
* [`u32`:`count`]
* [`u16`:`step`]
* [`string`:`unit`]
* [`int32`:`precision`]

#### Version 0 `digit_decomposition_event_descriptor`

1. type: 55306 (`digit_decomposition_event_descriptor_v0`)
2. data:
* [`bigsize`:`base`]
* [`bool`:`is_signed`]
* [`string`:`unit`]
* [`int32`:`precision`]
* [`uint16`:`nb_digits`]

### Oracle events

For users to be able to create DLCs based on a given event, they also need to obtain information about the oracle and the time at which it plans on releasing a signature over the event outcome.
Oracle events contain such information, which includes:
* the nonce(s) that will be used to sign the event outcome(s)
* the earliest time (UTC) at which it plans on releasing a signature over the event outcome, in epoch seconds,
* the event descriptor,
* the event ID which can be a name or categorization associated with the event by the oracle.

The TLV serialization for oracle events is as follow:

#### Version 0 `oracle_event`

1. type: 55330 (`oracle_event_v0`)
2. data:
* [`u16`:`nb_nonces`]
* [`nb_nonces*x_point`:`oracle_nonces`]
* [`u32`:`event_maturity_epoch`]
* [`event_descriptor`:`event_descriptor`]
* [`string`:`event_id`]

## Oracle announcements

In order to make it possible to hold oracles accountable in cases where they do not release a signature for an event outcome, there needs to be a proof that an oracle has committed to a given outcome.
This proof is given in a so-called oracle announcement, which contains an oracle event together with the oracle public key and a signature over its serialization, which must be valid with respect to the specified public key.

This also makes it possible for users to obtain oracle event information from an un-trusted peer while being guaranteed that it originates from a given oracle.

The TLV serialization of oracle announcements is as follow.

#### Version 0 `oracle_announcement`

1. type: 55332 (`oracle_announcement`)
2. data:
* [`signature`:`annoucement_signature`]
* [`x_point`:`oracle_public_key`]
* [`oracle_event`:`oracle_event`]

where `signature` is a Schnorr signature over a sha256 hash of the serialized `oracle_event`.

0 comments on commit 3df7166

Please sign in to comment.