From 6e3c362602e237bd84d4fad533ea1dbf5563c6d9 Mon Sep 17 00:00:00 2001 From: nkohen Date: Tue, 29 Dec 2020 14:25:27 -0600 Subject: [PATCH 01/17] Initial outline for multi-oracle doc --- MultiOracle.md | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 MultiOracle.md diff --git a/MultiOracle.md b/MultiOracle.md new file mode 100644 index 0000000..c6299e6 --- /dev/null +++ b/MultiOracle.md @@ -0,0 +1,49 @@ +# Multiple Oracle Support + +## Introduction + +todo + +## Table of Contents + +todo + +## Multiple Oracles for Enumerated Outcome Events + +todo + +### n-of-n Oracles + +todo + +### t-of-n Oracles + +todo + +## Multiple Oracles for Numeric Outcome Events + +todo + +### 2-of-2 Oracles with Bounded Error + +todo + +### n-of-n Oracles with Bounded Error + +todo + +### t-of-n Oracles with Bounded Error + +todo + +## Reference Implementations + +* bitcoin-s + +## Authors + +Nadav Kohen + +![Creative Commons License](https://i.creativecommons.org/l/by/4.0/88x31.png "License CC-BY") +
+This work is licensed under a [Creative Commons Attribution 4.0 International License](http://creativecommons.org/licenses/by/4.0/). \ No newline at end of file From ac2c9e74a593f7a07ec9af8cde35627b153a68c8 Mon Sep 17 00:00:00 2001 From: nkohen Date: Tue, 29 Dec 2020 16:58:10 -0600 Subject: [PATCH 02/17] Finished specifying the small CET cases --- MultiOracle.md | 175 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 172 insertions(+), 3 deletions(-) diff --git a/MultiOracle.md b/MultiOracle.md index c6299e6..81798ac 100644 --- a/MultiOracle.md +++ b/MultiOracle.md @@ -14,11 +14,77 @@ todo ### n-of-n Oracles -todo +In much the same way as we create [adaptor points for oracles publishing multiple signatures](CETCompression.md#adaptor-points-with-multiple-signatures), we +can similarly compute aggregate adaptor points for multiple oracles' signatures by simply using +`s(1..n) * G = (s1 + s2 + ... + sn) * G = s1 * G + s2 * G + ... + sn * G` where +`si` is the `i`th oracle's signature scalar. +When the oracles then broadcast their `n` signatures, the corresponding adaptor secret +`s(1..n) = s1 + s2 + ... + sn` can be used to broadcast the CET. + +Thus, enumerated outcome DLCs constructed for some n-of-n oracles can be constructed +just as it would be for a single oracle, but replacing that single oracle's adaptor points +with aggregate ones. + +For a more detailed rationale for this approach see [this section](CETCompression.md#adaptor-points-with-multiple-signatures)'s rationale. ### t-of-n Oracles -todo +To construct a DLC for an enumerated outcome event using some threshold t-of-n oracles, +we construct CETs for all outcomes for all possible combinations of t-of-t oracles. + +For example, say there are three oracles, Olivia, Oren, and Ollivander, who will be attesting +two one of two outcomes, A or B. +If we wish to construct a 2-of-3 DLC over these outcomes using these oracles, we will construct +and adaptor sign a total of 6 CETs: + +* Olivia and Oren sign A. +* Olivia and Ollivander sign A. +* Oren and Ollivander sign A. +* Olivia and Oren sign B. +* Olivia and Ollivander sign B. +* Oren and Ollivander sign B. + +In general, the resulting DLC will have as many CETs as it did in the single oracle case, +with a multiplier of `n C t`. + +#### Example Algorithm + +```scala +def combinations( + oracles: Vector[ECPublicKey], + threshold: Int): Vector[Vector[ECPublicKey]] = { + if (oracles.length == threshold) { + Vector(oracles) + } else if (threshold == 1) { + oracles.map(Vector(_)) + } else { + combinations(oracles.tail, threshold - 1).map(_.prepended(oracles.head)) ++ + combinations(oracles.tail, threshold) + } +} +``` + +#### Rationale + +There are many approaches that were considered for threshold oracle support. +The above was chosen primarily for the sake of its simplicity as well as other scheme's +failure to be extended to numeric outcome events where some bounded disagreement +between oracles is expected and must be supported. + +Other schemes considered included: + +* Using a t-of-n OP_CMS on-chain in conjunction with a 2p-ECDSA scheme (or in the + future, 2p-Schnorr) where all n on-chain keys are aggregate ones. + * This is too complicated and doesn't extend to numeric outcomes. +* Let `O` be the set of oracles (of size `n`), and let `O_t` be the set of all subsets of `O` of size `t`. + For each outcome, generate a scalar and point pair and verifiably encrypt the scalar using an + aggregate signature for each element of `O_t`. + Provide counter-party with an adaptor signature using the point generated, + along with all encryptions of its scalar. + * This requires verifiable encryption, such as is available with the infrastructure from MuSig-DN, + and also doesn't extend to numeric outcomes. +* Using an OP_CMSV and an OP_CMS on t-of-n keys from each of the two parties. + * Huge on-chain footprint and doesn't extend to numeric outcomes. ## Multiple Oracles for Numeric Outcome Events @@ -26,7 +92,110 @@ todo ### 2-of-2 Oracles with Bounded Error -todo +In the two oracle case, mark one oracle as primary and the other as secondary. +First, generate all adaptor points for the primary oracle as is done in the single-oracle +case for [numeric outcome DLCs](NumericOutcome.md). +Then we shall construct a list of 1-3 secondary points with which to combine each primary point. +This scheme can be thought of as computing a set of 1-3 CETs for the secondary oracle to cover +at least the minimum range and at most the maximum range of outcomes allowed given the each +primary oracle's CET. + +The maximum possible support range is parameterized by a maximum error exponent, `maxErrorExp`, +where all difference more than `maxError = 2^maxErrorExp` are guaranteed **not** to be supported. + +The minimum supported range is parameterized by a minimum failure exponent, `minFailExp`, where +all differences of up to `minFail = 2^minFailExp` are guaranteed to be supported. +It is required that `minFailExp` be strictly less than `maxErrorExp` because this gap is key to the +existence of the following algorithm. + +If the two oracles sign outcomes that are between `minFail` and `maxError` apart, then this procedure +can provide only probabilistic guarantees. +That said, DLC participants can decide in advance whether they wish to maximize the probability of +failure or of success in these cases. + +With these parameters in mind, we shall now detail the algorithm for computing the secondary oracle's +adaptor points given those of the first. + +#### Algorithm + +First, let us define some subprocedures. + +* `computeCETIntervalBinary` takes as input a list of digits corresponding to a CET, and the total + number of binary digits to be signed by an oracle, and returns an interval `[start, end]` + which that CET covers. +* `numToVec` takes as input an integer representing the left endpoint of a CET's range, the number + of binary digits to be signed by the oracle, and a number of digits to ignore, and returns + the binary digits corresponding to that CET. + +We take as input the number of digits to be signed by the oracle, `numDigits`, the binary digits of the primary +oracle's CET which we wish to cover with the secondary oracle, `cetDigits`, `maxErrorExp`, `minFailExp`, +and a boolean flag `maximizeCoverage` which signals whether to maximize the probability of success for +outcomes differing by less than `maxError` and more than `minFail` or not (in which case failure is maximized). + +Let `[start, end] = computeCETIntervalBinary(cetDigits, numDigits)`, +let `halfMaxError = 2^(maxErrorExp - 1)`, +and let `maxNum = (2^numDigits) - 1`. + +We then split into cases: + +* **Case** Small CET (`end - start + 1 < maxError`) + * In this case we consider the primary oracle's CET's range as it relates to the `maxError`-sized + interval, beginning at some multiple of `maxError`, which contains the CET in question. + * Note that the CET cannot be part of two such `maxError`-sized intervals as this would + imply that there are fewer `cetDigits` than `numDigits - maxErrorExp` which would + result in a large CET, but we are in the small CET case. + * Definitions + * Let `leftErrorCET` be the first multiple of `maxError` to the left of `start`. + * Let `rightErrorCET` be the first multiple of `maxError` to the right of `end`. + * Let `errorCET = numToVec(leftErrorCET, numDigits, maxErrorExp)`. + * We now split into cases again depending on whether or not the small CET is near either boundary + of its containing interval `[leftErrorCET, rightErrorCET]`. + * **Case** Middle CET (`start >= leftErrorCET + minFail` and `end <= rightErrorCET - minFail`) + * In this case, only a single secondary CET is needed to cover all cases in which it agrees with + the input primary CET! + * If `maximizeCoverage` is `true`, then `errorCET` is to be used. + * Otherwise, use the smallest CET which contains `[start - minFail, end + minFail]`. + * This can be computed as the common prefix between the binary digits of those two endpoints. + * **Case** Left CET (`start < leftErrorCET + minFail`) + * In this case, two secondary CETs are needed: `leftCET` and `rightCET`, one on each side + of `leftErrorCET`. + * **Special Case** Leftmost CET (`leftErrorCET == 0`) + * In this case only `rightCET` needs to be computed and used + * If `maximizeCoverage` is `true`, then `rightCET = errorCET`. + * Otherwise, `rightCET` is the CET resulting from repeatedly deleting the right half of + `errorCET` until any more deletions would no longer result in a right endpoint greater + than `end + minFail`. + * This can be computed as taking the first `(numDigits - maxErrorExp)` binary digits of + `end + minFail` followed by any additional `0` digits after that. + * If `maximizeCoverage` is `true`, then + `leftCET = numToVec(leftErrorCET - halfMaxError, numDigits, maxErrorExp - 1)`. + * This is the CET of width `halfMaxError` covering the interval + `[leftErrorCET - halfMaxError, leftErrorCET - 1]`. + * Otherwise, `leftCET` is the CET of minimum width containing + `[leftErrorCET - minFail, leftErrorCET - 1]`. + * This can be computed as the first `(numDigits - maxErrorExp)` binary digits of + `start - minFail` followed by any additional `1` digits after that. + * **Case** Right CET (`end > rightErrorCET - minFail`) + * In this case, two secondary CETs are needed: `leftCET` and `rightCET`, one on each side + of `rightErrorCET`. + * **Special Case** Rightmost CET (`rightErrorCET == maxNum`) + * In this case only `leftCET` needs to be computed and used + * If `maximizeCoverage` is `true`, then `leftCET = errorCET`. + * Otherwise, `leftCET` is the CET resulting from repeatedly deleting the left half of + `errorCET` until any more deletions would no longer result in a left endpoint greater + than `start - minFail`. + * This can be computed as taking the first `(numDigits - maxErrorExp)` binary digits of + `start - minFail` followed by any additional `1` digits. + * If `maximizeCoverage` is `true` then + `rightCET = numToVec(rightErrorCET + 1, numDigits, maxErrorExp - 1)`. + * This is the CET of width `halfMaxError` covering the interval + `[rightErrorCET + 1, rightErrorCET + halfMaxError]`. + * Otherwise, `rightCET` is the CET of minimum width containing + `[rightErrorCET + 1, end + minFail]`. + * This can be computed as the first `(numDigits - maxErrorExp)` binary digits of + `end + minFail` followed by any additional `0` digits. +* **Case** Large CET (`end - start + 1 >= maxError`) + * ### n-of-n Oracles with Bounded Error From cf877aa42d9eaf3bc3a37c3f493786af1a9b18ae Mon Sep 17 00:00:00 2001 From: nkohen Date: Tue, 29 Dec 2020 18:10:46 -0600 Subject: [PATCH 03/17] Finished specifying the 2-of-2 with differences case --- MultiOracle.md | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/MultiOracle.md b/MultiOracle.md index 81798ac..3126def 100644 --- a/MultiOracle.md +++ b/MultiOracle.md @@ -138,6 +138,8 @@ and let `maxNum = (2^numDigits) - 1`. We then split into cases: +TODO: Pictures here + * **Case** Small CET (`end - start + 1 < maxError`) * In this case we consider the primary oracle's CET's range as it relates to the `maxError`-sized interval, beginning at some multiple of `maxError`, which contains the CET in question. @@ -195,7 +197,30 @@ We then split into cases: * This can be computed as the first `(numDigits - maxErrorExp)` binary digits of `end + minFail` followed by any additional `0` digits. * **Case** Large CET (`end - start + 1 >= maxError`) - * + * In this case, up to three CETs are needed, a `middleCET` for when both oracles agree that + the outcome is within the large range of this CET, a `leftCET` for when the secondary oracle + is within an acceptable range to the left of the large CET, and a `rightCET` for when the + secondary oracle is within an acceptable range to the right of the large CET. + * The `leftCET` is paired with a new primary CET called `leftInnerCET`. + * The `rightCET` is paired with a new primary CET called `rightInnerCET`. + * **Special Case** Leftmost Large CET (`start == 0`) + * The `leftInnerCET` and `leftCET` do not need to be computed and are not used. + * **Special Case** Rightmost Large CET (`end == maxNum`) + * The `rightInnerCET` and `rightCET` do not need to be computed and are not used. + * The `middleCET` is always equal to the input CET, `[start, end]`. + * This may actually violate the `maxError` bound but since this is one large CET, it must + be the case that even with this larger than `maxError` difference between the oracles, + the payout resulting from either outcome is the same so that this is not an issue. + * If `maximizeCoverage` is `true`, + * `leftInnerCET = numToVec(start, numDigits, maxErrorExp - 1)` + * `leftCET = numToVec(start - halfMaxError, numDigits, maxErrorExp - 1)` + * `rightInnerCET = numToVec(end - halfMaxError + 1, numDigits, maxErrorExp - 1)` + * `rightCET = numToVec(end + 1, numDigits, maxErrorExp - 1)` + * Otherwise (`maximizeCoverage` is `false`), + * `leftInnerCET = numToVec(start, numDigits, minFailExp)` + * `leftCET = numToVec(start - minFail, numDigits, minFailExp)` + * `rightInnerCET = numToVec(end - minFail + 1, numDigits, minFailExp)` + * `rightCET = numToVec(end + 1, numDigits, minFailExp)` ### n-of-n Oracles with Bounded Error From e4e00c04bbd10f9e8eb7587a33e7779ebf3057f1 Mon Sep 17 00:00:00 2001 From: nkohen Date: Tue, 29 Dec 2020 19:03:10 -0600 Subject: [PATCH 04/17] Finished analysis of n-of-n with bounded differences algos --- MultiOracle.md | 65 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/MultiOracle.md b/MultiOracle.md index 3126def..7645843 100644 --- a/MultiOracle.md +++ b/MultiOracle.md @@ -88,7 +88,8 @@ Other schemes considered included: ## Multiple Oracles for Numeric Outcome Events -todo +todo (explain when bounded error should be used, and that at all other times multi-oracle support follows +the enumerated outcome procedures) ### 2-of-2 Oracles with Bounded Error @@ -224,11 +225,69 @@ TODO: Pictures here ### n-of-n Oracles with Bounded Error -todo +The simplest method for achieving n-of-n oracle support for n greater than 2 is to run the 2-of-2 +algorithm in a slightly modified fashion so that if, on a given primary CET, the algorithm returns +2 secondary CETs, we instead return `2^(n-1)` aggregate secondary CETs. + +For example, if there are two secondary oracles, Omar and Odette, and two CETs, A and B, returned +by the 2-of-2 algorithm, then this modified algorithm would return four aggregate CETs: + +* Omar signs A and Odette signs A +* Omar signs A and Odette signs B +* Omar signs B and Odette signs A +* Omar signs B and Odette signs B + +If the 2-of-2 algorithm returns a single secondary CET then we simply use the aggregate of all oracles +signing an event that is covered by that one CET. + +However, in the large CET case where three CETs are normally returned, we can make some +more custom alterations. +The `middleCET` case remains the same, but where an aggregate of all oracles signing an event +covered by that CET is used. +But from each of the `(leftCET, leftInnerCET)` and `(rightCET, rightInnerCET)` pairs, we instead generate +`2^(n-1)-1` tuples `(xCET, xInnerCET, middleCET)` (where `x` is `left` or `right`) where `xInnerCET` consists of +only the primary oracle (as usual) and where `xCET` and `middleCET` are aggregations of secondary oracles such that + +* All secondary oracles are included in exactly one of `xCET` or `middleCET` and +* `xCET` is non-empty. + +To summarize, for n-of-n oracle support, the 2-of-2 algorithm is run where the primary oracle's + +* Small Middle CETs result in a single aggregate CET +* Small non-Middle CETs result in `2^(n-1)` aggregate CETs +* Large CETs result in a total of `2^n - 1` aggregate CETs + * One aggregate middle CET + * `2^(n-1) - 1` aggregate non-middle CETs for each side + * Totaling `2^n - 2` non-middle aggregate CETs. + +#### Analysis + +Luckily, there are very few large CETs in any given DLC. +Thus, the primary multiplier to be concerned with is that of small non-middle CETs. + +If the difference between `maxErrorExp` and `minFailExp` is only one, then all small +CETs will be non-middle so that additional oracles are guaranteed to lead to exponential +growth in this multiplier (though one should note that exponential growth is already likely +when using the below t-of-n scheme so that this may not be a primary concern). + +If, on the other hand, the difference between `maxErrorExp` and `minFailExp` is larger +than one, then the majority of CETs are expected to be middle CETs with exponentially larger +numbers of middle CETs the bigger the difference between those two parameters. + +Therefore, there is a trade-off between the tightness of error bounds (i.e. the size of the non- +guaranteed successes or failures between `minFail` and `maxError`) and the number of CETs +when using more than two oracles. + +It should also be noted that the actual values of `minFailExp` and `maxErrorExp` are not part of +this trade-off, only their relative difference. +For example, having `minFail=32` and `maxError = 128` should yield similar results to having +`minFail = 256` and `maxError = 1024`. ### t-of-n Oracles with Bounded Error -todo +Just as in the [t-of-n Oracles for enumerated outcomes](#t-of-n-oracles) case, to support a threshold t-of-n oracles for +numeric outcomes with allowed (bounded) error, we simply run the t-of-t algorithm above on all of the +`n C t` possible combinations of `t` oracles. ## Reference Implementations From a46d7312307bf6df4e8fb085a32d5153ea70de59 Mon Sep 17 00:00:00 2001 From: nkohen Date: Wed, 30 Dec 2020 13:38:55 -0600 Subject: [PATCH 05/17] Added table of contents --- MultiOracle.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/MultiOracle.md b/MultiOracle.md index 7645843..cf6bab0 100644 --- a/MultiOracle.md +++ b/MultiOracle.md @@ -6,7 +6,18 @@ todo ## Table of Contents -todo +* [Multiple Oracles for Enumerated Outcome Events](#multiple-oracles-for-enumerated-outcome-events) + * [n-of-n Oracles](#n-of-n-oracles) + * [t-of-n Oracles](#t-of-n-oracles) + * [Example Algorithm](#example-algorithm) +* [Multiple Oracles for Numeric Outcome Events](#multiple-oracles-for-numeric-outcome-events) + * [2-of-2 Oracles with Bounded Error](#2-of-2-oracles-with-bounded-error) + * [Algorithm](#algorithm) + * [n-of-n Oracles with Bounded Error](#n-of-n-oracles-with-bounded-error) + * [Analysis](#analysis) + * [t-of-n Oracles with Bounded Error](#t-of-n-oracles-with-bounded-error) +* [Reference Implementations](#reference-implementations) +* [Authors](#authors) ## Multiple Oracles for Enumerated Outcome Events From b3c8f614427e6d70a885240aec951e7f8c658d67 Mon Sep 17 00:00:00 2001 From: nkohen Date: Wed, 30 Dec 2020 13:54:30 -0600 Subject: [PATCH 06/17] Wrote introduction --- MultiOracle.md | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/MultiOracle.md b/MultiOracle.md index cf6bab0..1e1b75b 100644 --- a/MultiOracle.md +++ b/MultiOracle.md @@ -2,7 +2,30 @@ ## Introduction -todo +The Discreet Log Contract security model is entirely reliant on the existence of trustworthy oracles. +However, even if an oracle appears trustworthy and has a good history of truth-telling, there is always +some amount of risk associated with the oracle becoming unresponsive, or worse, corrupted. +This risk is particularly worrisome for large value DLCs, as well as high volume DLCs where the pool +of funds that could profitably bribe or fund attacks on oracles is relatively larger. +This specification aims to significantly reduce oracle risk by introducing mechanisms with which to +construct DLCs where some threshold of multiple oracles is required for successful execution. + +Using multiple oracles multiplies the cost of bribery and other attacks, while simultaneously offering +protection against unresponsive and otherwise corrupted oracles. + +Using multiple oracles also provides a better environment for contract updates to a new oracle should +one of the oracles being used announce that it will become unresponsive or has lost control of its keys. + +This document begins by examining the case of enumerated outcome event DLCs, which can also be +applied to numeric outcome DLCs in cases where all oracles are expected and required to produce exactly +the same events. +The majority of this document, however, is devoted to treating the numeric case where oracles are allowed +to have bounded disagreements. + +In any of these cases, using multiple oracles does introduce a multiplier on total the number of CETs. +In general, this multiplier grows exponentially with the number of oracles, but remains low enough +for small numbers of oracles to enable the most common use cases (2-of-3 and 3-of-5) without much trouble. +Larger numbers of oracles can still be used in cases where they are needed, but the CET cost incurred may be large. ## Table of Contents From f8c7a0c7185ec9fbd948de637d3f74dadbb8ed9a Mon Sep 17 00:00:00 2001 From: nkohen Date: Wed, 30 Dec 2020 16:02:24 -0600 Subject: [PATCH 07/17] Completed introductory sections and design section for numeric outcome with differences --- MultiOracle.md | 102 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 99 insertions(+), 3 deletions(-) diff --git a/MultiOracle.md b/MultiOracle.md index 1e1b75b..c21ccf9 100644 --- a/MultiOracle.md +++ b/MultiOracle.md @@ -34,6 +34,7 @@ Larger numbers of oracles can still be used in cases where they are needed, but * [t-of-n Oracles](#t-of-n-oracles) * [Example Algorithm](#example-algorithm) * [Multiple Oracles for Numeric Outcome Events](#multiple-oracles-for-numeric-outcome-events) + * [Design](#design) * [2-of-2 Oracles with Bounded Error](#2-of-2-oracles-with-bounded-error) * [Algorithm](#algorithm) * [n-of-n Oracles with Bounded Error](#n-of-n-oracles-with-bounded-error) @@ -44,7 +45,21 @@ Larger numbers of oracles can still be used in cases where they are needed, but ## Multiple Oracles for Enumerated Outcome Events -todo +In the case of enumerated outcome events, where there is no macroscopic structure to the set of +CETs and all oracles of a given event are expected to sign the same outcomes, then there is little +work to do to support multiple oracles. + +The n-of-n case is accomplished by simple point addition in the same manner as is done to combine +multiple digit signatures in numeric outcome DLCs from digit decomposition. +This specification opts to reduce the threshold (t-of-n) case to a combination of many t-of-t constructions. + +If two oracles for an enumerated outcome have similar, but not exactly equivalent enumerations of all +possible outcomes, some care must be taken to ensure expected behavior. +For example, if one weather oracle has only the events `["rainy", "sunny", "cloudy"]` while a second +oracle has more events, `["rainy", "sunny", "partly cloudy", "cloudy"]`, then the DLC participants +must decide what should happen in the case that the second oracle signs the message `"partly cloudy"`. +They can either choose to not support that event (refund), or construct CETs for when the first party signs +`"sunny"`, `"cloudy"`, or either (that is, two individual CETs). ### n-of-n Oracles @@ -122,8 +137,89 @@ Other schemes considered included: ## Multiple Oracles for Numeric Outcome Events -todo (explain when bounded error should be used, and that at all other times multi-oracle support follows -the enumerated outcome procedures) +There are two kinds of numeric outcome DLCs when it comes to using multiple oracles: those where +there is no expectation or allowance for variance between oracles, and those where some small +variance is acceptable and must be supported. + +For example, if there is some numeric data feed which broadcasts a single number daily, and multiple +DLC oracles attest to this number, then all of these oracles should be expected to sign exactly the same +number, down to the last binary digit. + +On the other hand if there is some less precise data source, such as a continuous price feed or multiple +price feeds from different exchanges for the same asset, then oracles may differ by some small amount due +to the non-deterministic nature of the data sampling as they may draw from the feed at slightly different times +or from different exchanges entirely. +In these kinds of DLCs, some amount of difference between oracles is expected and some larger difference +is also acceptable. + +When executing the first kind of DLC, where no variance is allowed, then one should simply follow the same +procedure as was [specified for enumerated outcomes above](#multiple-oracles-for-enumerated-outcome-events) because no macroscopic structure of the numeric +nature of the outcomes is used from a multi-oracle support perspective. + +If instead the second kind of DLC is being executed, then a special, more intricate procedure detailed below +must be used to ensure proper execution. +This procedure differs from the simple enumerated or exact numeric case as it uses the numeric structure of +related outcomes. +Specifically distance is used so that outcomes are related if they are sufficiently near each other. + +### Design + +It turns out that there is an exceedingly large design space of approaches that can be taken to support multiple +oracles with some acceptable variance. +It seems to be generally true, however, that a trade-off exists between the precision of guarantees that a procedure +can make, and the size of the multiplier on the number of CETs required for the DLC. +This specification chooses to prioritize CET reduction at the expense of precise guarantees so as to more easily +support more oracles, which should generally counteract some of the imprecision surrounding variance support. +Although this resulting design is extremely opinionated in some sense, it does leave three parameters unspecified +to be negotiated or chosen by DLC participants. + +The first two parameters are the orders of magnitude of expected and of allowed difference between oracles. +By expected difference we mean the differences for which support is required by users, and by allowed difference +we mean the differences for which support is acceptable but not required. +These parameters will, from now on, be called `minFail` and `maxError` as they also represent the lower bound +on failure (non-support) and the upper bound on allowed (support) difference/error between oracles. +When we say that the guarantees made by this proposal are not precise, we mean two things. +First, that `minFail` is strictly less than `maxError` so that while it is true that all differences less than `minFail` and none +greater than `maxError` are supported, there are no guarantees made for differences in between these two parameters. +Second, that `minFail` and `maxError` are required to be powers of `2` and not arbitrary numbers so that in reality, allowed +variance is only expressed in terms of order of magnitude, which is a somewhat coarse measure. +These two things together also imply that `minFail` must be at most half of `maxError` so that the gap between `minFail` +and `maxError` where no strict guarantees can be made is of significant size. + +The third parameter offers a minimal remedy to these lack of guarantees. +It is a boolean flag (`true` or `false`) called `maximizeCoverage`. +This parameter arises from the fact that there is a decision to be made when covering the `minFail` variance to +either cover as much as possible (up to `maxError`) or as little as possible, and this decision has no consequence +on the number of CETs. +That is to say that maximizing or minimizing the cases of variance between `minFail` and `maxError` require exactly +the same number of CETs, hence this choice is left to the DLC participants. +While this flag does improve the probabilistic guarantees which can be made for the `maxError`-`minFail` gap, it +should be noted that these are still only probabilistic as even if `maximizeCoverage` is set to `true`, there can still +be differences of `minFail + 1` which are unsupported in the worst case and likewise, differences of `maxError - 1` +may still succeed even if `maximizeCoverage` is set to `false` in the worst case. +Yet in the average case this maximizing coverage will make it much more likely that cases in the `maxError`-`minFail` gap +will succeed and minimizing coverage will make it much more likely that these cases fail (are not supported). + +There exist many versions of this proposal which allow more exact guarantees, such as ones that lift either or both of the +constraints on the variance parameters, but they all require significantly more CETs. +This proposal can be thought of as defining the maximally coarse CET coverage algorithm which results in the fewest +possible multiplier on the number of CETs. + +At a high level the algorithm works as follows (many details and some special cases are omitted). +Designate one oracle in every t-of-t grouping to be the primary oracle and generate the set of CETs required for the DLC +in question as would be done for a single oracle. +This primary oracle functionally determines the execution price, meaning that the UX should be the same as if this +primary oracle was used on its own. +Then, for each of these CETs representing the primary oracle's attested result, label the first and last outcome covered +by this CET as `[start, end]` and compute the largest allowed range `[end - maxError, start + maxError]` for +secondary oracles. +Compute the set of CETs required to cover this range (using the [CET compression algorithm](CETCompression.md#cet-compression)) and discard all but the +largest CETs in this set, which by definition cover the vast majority of the range. +This discarding is the primary opinion decidedly made from the design space by this proposal, and discarding any less +leads to better guarantees at the expense of more CETs. +The resulting CET(s) can then either be used (in the case of maximize coverage) or shrunk until they cover as little as +possible while still containing `[start - minFail, end + minFail]` by repeatedly cutting them in half on either side. +This process results in 1-3 secondary oracle CETs for ever single CET of the primary oracle. ### 2-of-2 Oracles with Bounded Error From 8d4ac73b5a3c7975ad1bb2db01857763987afcb4 Mon Sep 17 00:00:00 2001 From: nkohen Date: Wed, 30 Dec 2020 16:10:58 -0600 Subject: [PATCH 08/17] Finished non-diagram initial TODOs --- MultiOracle.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/MultiOracle.md b/MultiOracle.md index c21ccf9..7b6eb28 100644 --- a/MultiOracle.md +++ b/MultiOracle.md @@ -355,6 +355,8 @@ TODO: Pictures here ### n-of-n Oracles with Bounded Error +Just as in the two oracle case, mark one oracle as primary and all others as secondary. + The simplest method for achieving n-of-n oracle support for n greater than 2 is to run the 2-of-2 algorithm in a slightly modified fashion so that if, on a given primary CET, the algorithm returns 2 secondary CETs, we instead return `2^(n-1)` aggregate secondary CETs. @@ -419,9 +421,20 @@ Just as in the [t-of-n Oracles for enumerated outcomes](#t-of-n-oracles) case, t numeric outcomes with allowed (bounded) error, we simply run the t-of-t algorithm above on all of the `n C t` possible combinations of `t` oracles. +The only additional work that must be done is that there must be a decision procedure to determine +which oracle in a given group of `t` oracles is primary, and additionally what values should be used +for `minFail` and `maxError` for a given group of `t` oracles (as this can vary between groups). + +The simplest candidate would be a negotiated ordered ranking of the oracles where the highest ranking +oracle in any group of `t` oracles is chosen as primary. +The values `minFail` and `maxError` can also be computed as some function of the rankings of a group +of `t` oracles, or else they can be set as constant parameters across all groupings. + +TODO: Decide how this is done and communicated. + ## Reference Implementations -* bitcoin-s +* [bitcoin-s](https://github.com/nkohen/bitcoin-s-core/tree/multi-oracle) ## Authors From 5775d67db37bb5d5b23ad057dde671b363373f65 Mon Sep 17 00:00:00 2001 From: nkohen Date: Wed, 30 Dec 2020 16:24:37 -0600 Subject: [PATCH 09/17] Added comment about client-side nature of proposal --- MultiOracle.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/MultiOracle.md b/MultiOracle.md index 7b6eb28..26bfa79 100644 --- a/MultiOracle.md +++ b/MultiOracle.md @@ -16,6 +16,10 @@ protection against unresponsive and otherwise corrupted oracles. Using multiple oracles also provides a better environment for contract updates to a new oracle should one of the oracles being used announce that it will become unresponsive or has lost control of its keys. +A key feature of this proposal is that no change in behavior is required of oracles when compared to +single-oracle DLCs. +All work is done by DLC participants using existing DLC oracles as they are. + This document begins by examining the case of enumerated outcome event DLCs, which can also be applied to numeric outcome DLCs in cases where all oracles are expected and required to produce exactly the same events. From 8e65dd528a65e192a063b96b56817442009d1c58 Mon Sep 17 00:00:00 2001 From: nkohen Date: Wed, 30 Dec 2020 16:25:54 -0600 Subject: [PATCH 10/17] Added rationale to table of contents --- MultiOracle.md | 1 + 1 file changed, 1 insertion(+) diff --git a/MultiOracle.md b/MultiOracle.md index 26bfa79..2b06489 100644 --- a/MultiOracle.md +++ b/MultiOracle.md @@ -37,6 +37,7 @@ Larger numbers of oracles can still be used in cases where they are needed, but * [n-of-n Oracles](#n-of-n-oracles) * [t-of-n Oracles](#t-of-n-oracles) * [Example Algorithm](#example-algorithm) + * [Rationale](#rationale) * [Multiple Oracles for Numeric Outcome Events](#multiple-oracles-for-numeric-outcome-events) * [Design](#design) * [2-of-2 Oracles with Bounded Error](#2-of-2-oracles-with-bounded-error) From 086047e4a308a0a838e6108fcebb81ef61174995 Mon Sep 17 00:00:00 2001 From: nkohen Date: Tue, 2 Feb 2021 13:52:08 -0600 Subject: [PATCH 11/17] Responded to some review --- MultiOracle.md | 101 +++++++++++++++++++++++++------------------------ 1 file changed, 51 insertions(+), 50 deletions(-) diff --git a/MultiOracle.md b/MultiOracle.md index 2b06489..65a7b69 100644 --- a/MultiOracle.md +++ b/MultiOracle.md @@ -5,8 +5,8 @@ The Discreet Log Contract security model is entirely reliant on the existence of trustworthy oracles. However, even if an oracle appears trustworthy and has a good history of truth-telling, there is always some amount of risk associated with the oracle becoming unresponsive, or worse, corrupted. -This risk is particularly worrisome for large value DLCs, as well as high volume DLCs where the pool -of funds that could profitably bribe or fund attacks on oracles is relatively larger. +This risk is particularly worrisome for large value DLCs, as well as widely used DLC oracle events where +the pool of funds that could profitably bribe or fund attacks on oracles is relatively larger. This specification aims to significantly reduce oracle risk by introducing mechanisms with which to construct DLCs where some threshold of multiple oracles is required for successful execution. @@ -16,7 +16,7 @@ protection against unresponsive and otherwise corrupted oracles. Using multiple oracles also provides a better environment for contract updates to a new oracle should one of the oracles being used announce that it will become unresponsive or has lost control of its keys. -A key feature of this proposal is that no change in behavior is required of oracles when compared to +A key feature of this proposal is that no change in behavior is required of oracles when compared to single-oracle DLCs. All work is done by DLC participants using existing DLC oracles as they are. @@ -26,7 +26,7 @@ the same events. The majority of this document, however, is devoted to treating the numeric case where oracles are allowed to have bounded disagreements. -In any of these cases, using multiple oracles does introduce a multiplier on total the number of CETs. +In any of these cases, using multiple oracles does introduce a multiplier on the total number of CETs. In general, this multiplier grows exponentially with the number of oracles, but remains low enough for small numbers of oracles to enable the most common use cases (2-of-3 and 3-of-5) without much trouble. Larger numbers of oracles can still be used in cases where they are needed, but the CET cost incurred may be large. @@ -51,8 +51,8 @@ Larger numbers of oracles can still be used in cases where they are needed, but ## Multiple Oracles for Enumerated Outcome Events In the case of enumerated outcome events, where there is no macroscopic structure to the set of -CETs and all oracles of a given event are expected to sign the same outcomes, then there is little -work to do to support multiple oracles. +CETs and all oracles of a given event are expected to sign the same outcomes, little work is required +to support multiple oracles. The n-of-n case is accomplished by simple point addition in the same manner as is done to combine multiple digit signatures in numeric outcome DLCs from digit decomposition. @@ -72,7 +72,7 @@ In much the same way as we create [adaptor points for oracles publishing multipl can similarly compute aggregate adaptor points for multiple oracles' signatures by simply using `s(1..n) * G = (s1 + s2 + ... + sn) * G = s1 * G + s2 * G + ... + sn * G` where `si` is the `i`th oracle's signature scalar. -When the oracles then broadcast their `n` signatures, the corresponding adaptor secret +When all oracles have broadcast their signatures, the corresponding adaptor secret `s(1..n) = s1 + s2 + ... + sn` can be used to broadcast the CET. Thus, enumerated outcome DLCs constructed for some n-of-n oracles can be constructed @@ -87,7 +87,7 @@ To construct a DLC for an enumerated outcome event using some threshold t-of-n o we construct CETs for all outcomes for all possible combinations of t-of-t oracles. For example, say there are three oracles, Olivia, Oren, and Ollivander, who will be attesting -two one of two outcomes, A or B. +to one of two outcomes, A or B. If we wish to construct a 2-of-3 DLC over these outcomes using these oracles, we will construct and adaptor sign a total of 6 CETs: @@ -180,29 +180,30 @@ to be negotiated or chosen by DLC participants. The first two parameters are the orders of magnitude of expected and of allowed difference between oracles. By expected difference we mean the differences for which support is required by users, and by allowed difference -we mean the differences for which support is acceptable but not required. -These parameters will, from now on, be called `minFail` and `maxError` as they also represent the lower bound +we mean the differences for which support is acceptable but not required so that they may or may not be covered +by the multi-oracle CET construction algorithm. +These parameters will, from now on, be called `minSupport` and `maxError` as they also represent the lower bound on failure (non-support) and the upper bound on allowed (support) difference/error between oracles. When we say that the guarantees made by this proposal are not precise, we mean two things. -First, that `minFail` is strictly less than `maxError` so that while it is true that all differences less than `minFail` and none +First, that `minSupport` is strictly less than `maxError` so that while it is true that all differences less than `minSupport` and none greater than `maxError` are supported, there are no guarantees made for differences in between these two parameters. -Second, that `minFail` and `maxError` are required to be powers of `2` and not arbitrary numbers so that in reality, allowed +Second, that `minSupport` and `maxError` are required to be powers of `2` and not arbitrary numbers so that in reality, allowed variance is only expressed in terms of order of magnitude, which is a somewhat coarse measure. -These two things together also imply that `minFail` must be at most half of `maxError` so that the gap between `minFail` +These two things together also imply that `minSupport` must be at most half of `maxError` so that the gap between `minSupport` and `maxError` where no strict guarantees can be made is of significant size. The third parameter offers a minimal remedy to these lack of guarantees. It is a boolean flag (`true` or `false`) called `maximizeCoverage`. -This parameter arises from the fact that there is a decision to be made when covering the `minFail` variance to +This parameter arises from the fact that there is a decision to be made when covering the `minSupport` variance to either cover as much as possible (up to `maxError`) or as little as possible, and this decision has no consequence on the number of CETs. -That is to say that maximizing or minimizing the cases of variance between `minFail` and `maxError` require exactly +That is to say that maximizing or minimizing the cases of variance between `minSupport` and `maxError` require exactly the same number of CETs, hence this choice is left to the DLC participants. -While this flag does improve the probabilistic guarantees which can be made for the `maxError`-`minFail` gap, it +While this flag does improve the probabilistic guarantees which can be made for the `maxError`-`minSupport` gap, it should be noted that these are still only probabilistic as even if `maximizeCoverage` is set to `true`, there can still -be differences of `minFail + 1` which are unsupported in the worst case and likewise, differences of `maxError - 1` +be differences of `minSupport + 1` which are unsupported in the worst case and likewise, differences of `maxError - 1` may still succeed even if `maximizeCoverage` is set to `false` in the worst case. -Yet in the average case this maximizing coverage will make it much more likely that cases in the `maxError`-`minFail` gap +Yet in the average case this maximizing coverage will make it much more likely that cases in the `maxError`-`minSupport` gap will succeed and minimizing coverage will make it much more likely that these cases fail (are not supported). There exist many versions of this proposal which allow more exact guarantees, such as ones that lift either or both of the @@ -223,8 +224,8 @@ largest CETs in this set, which by definition cover the vast majority of the ran This discarding is the primary opinion decidedly made from the design space by this proposal, and discarding any less leads to better guarantees at the expense of more CETs. The resulting CET(s) can then either be used (in the case of maximize coverage) or shrunk until they cover as little as -possible while still containing `[start - minFail, end + minFail]` by repeatedly cutting them in half on either side. -This process results in 1-3 secondary oracle CETs for ever single CET of the primary oracle. +possible while still containing `[start - minSupport, end + minSupport]` by repeatedly cutting them in half on either side. +This process results in 1 to 3 secondary oracle CETs for ever single CET of the primary oracle (see [algorithm below](#algorithm)). ### 2-of-2 Oracles with Bounded Error @@ -239,12 +240,12 @@ primary oracle's CET. The maximum possible support range is parameterized by a maximum error exponent, `maxErrorExp`, where all difference more than `maxError = 2^maxErrorExp` are guaranteed **not** to be supported. -The minimum supported range is parameterized by a minimum failure exponent, `minFailExp`, where -all differences of up to `minFail = 2^minFailExp` are guaranteed to be supported. -It is required that `minFailExp` be strictly less than `maxErrorExp` because this gap is key to the +The minimum supported range is parameterized by a minimum failure exponent, `minSupportExp`, where +all differences of up to `minSupport = 2^minSupportExp` are guaranteed to be supported. +It is required that `minSupportExp` be strictly less than `maxErrorExp` because this gap is key to the existence of the following algorithm. -If the two oracles sign outcomes that are between `minFail` and `maxError` apart, then this procedure +If the two oracles sign outcomes that are between `minSupport` and `maxError` apart, then this procedure can provide only probabilistic guarantees. That said, DLC participants can decide in advance whether they wish to maximize the probability of failure or of success in these cases. @@ -264,9 +265,9 @@ First, let us define some subprocedures. the binary digits corresponding to that CET. We take as input the number of digits to be signed by the oracle, `numDigits`, the binary digits of the primary -oracle's CET which we wish to cover with the secondary oracle, `cetDigits`, `maxErrorExp`, `minFailExp`, +oracle's CET which we wish to cover with the secondary oracle, `cetDigits`, `maxErrorExp`, `minSupportExp`, and a boolean flag `maximizeCoverage` which signals whether to maximize the probability of success for -outcomes differing by less than `maxError` and more than `minFail` or not (in which case failure is maximized). +outcomes differing by less than `maxError` and more than `minSupport` or not (in which case failure is maximized). Let `[start, end] = computeCETIntervalBinary(cetDigits, numDigits)`, let `halfMaxError = 2^(maxErrorExp - 1)`, @@ -288,13 +289,13 @@ TODO: Pictures here * Let `errorCET = numToVec(leftErrorCET, numDigits, maxErrorExp)`. * We now split into cases again depending on whether or not the small CET is near either boundary of its containing interval `[leftErrorCET, rightErrorCET]`. - * **Case** Middle CET (`start >= leftErrorCET + minFail` and `end <= rightErrorCET - minFail`) + * **Case** Middle CET (`start >= leftErrorCET + minSupport` and `end <= rightErrorCET - minSupport`) * In this case, only a single secondary CET is needed to cover all cases in which it agrees with the input primary CET! * If `maximizeCoverage` is `true`, then `errorCET` is to be used. - * Otherwise, use the smallest CET which contains `[start - minFail, end + minFail]`. + * Otherwise, use the smallest CET which contains `[start - minSupport, end + minSupport]`. * This can be computed as the common prefix between the binary digits of those two endpoints. - * **Case** Left CET (`start < leftErrorCET + minFail`) + * **Case** Left CET (`start < leftErrorCET + minSupport`) * In this case, two secondary CETs are needed: `leftCET` and `rightCET`, one on each side of `leftErrorCET`. * **Special Case** Leftmost CET (`leftErrorCET == 0`) @@ -302,18 +303,18 @@ TODO: Pictures here * If `maximizeCoverage` is `true`, then `rightCET = errorCET`. * Otherwise, `rightCET` is the CET resulting from repeatedly deleting the right half of `errorCET` until any more deletions would no longer result in a right endpoint greater - than `end + minFail`. + than `end + minSupport`. * This can be computed as taking the first `(numDigits - maxErrorExp)` binary digits of - `end + minFail` followed by any additional `0` digits after that. + `end + minSupport` followed by any additional `0` digits after that. * If `maximizeCoverage` is `true`, then `leftCET = numToVec(leftErrorCET - halfMaxError, numDigits, maxErrorExp - 1)`. * This is the CET of width `halfMaxError` covering the interval `[leftErrorCET - halfMaxError, leftErrorCET - 1]`. * Otherwise, `leftCET` is the CET of minimum width containing - `[leftErrorCET - minFail, leftErrorCET - 1]`. + `[leftErrorCET - minSupport, leftErrorCET - 1]`. * This can be computed as the first `(numDigits - maxErrorExp)` binary digits of - `start - minFail` followed by any additional `1` digits after that. - * **Case** Right CET (`end > rightErrorCET - minFail`) + `start - minSupport` followed by any additional `1` digits after that. + * **Case** Right CET (`end > rightErrorCET - minSupport`) * In this case, two secondary CETs are needed: `leftCET` and `rightCET`, one on each side of `rightErrorCET`. * **Special Case** Rightmost CET (`rightErrorCET == maxNum`) @@ -321,17 +322,17 @@ TODO: Pictures here * If `maximizeCoverage` is `true`, then `leftCET = errorCET`. * Otherwise, `leftCET` is the CET resulting from repeatedly deleting the left half of `errorCET` until any more deletions would no longer result in a left endpoint greater - than `start - minFail`. + than `start - minSupport`. * This can be computed as taking the first `(numDigits - maxErrorExp)` binary digits of - `start - minFail` followed by any additional `1` digits. + `start - minSupport` followed by any additional `1` digits. * If `maximizeCoverage` is `true` then `rightCET = numToVec(rightErrorCET + 1, numDigits, maxErrorExp - 1)`. * This is the CET of width `halfMaxError` covering the interval `[rightErrorCET + 1, rightErrorCET + halfMaxError]`. * Otherwise, `rightCET` is the CET of minimum width containing - `[rightErrorCET + 1, end + minFail]`. + `[rightErrorCET + 1, end + minSupport]`. * This can be computed as the first `(numDigits - maxErrorExp)` binary digits of - `end + minFail` followed by any additional `0` digits. + `end + minSupport` followed by any additional `0` digits. * **Case** Large CET (`end - start + 1 >= maxError`) * In this case, up to three CETs are needed, a `middleCET` for when both oracles agree that the outcome is within the large range of this CET, a `leftCET` for when the secondary oracle @@ -353,10 +354,10 @@ TODO: Pictures here * `rightInnerCET = numToVec(end - halfMaxError + 1, numDigits, maxErrorExp - 1)` * `rightCET = numToVec(end + 1, numDigits, maxErrorExp - 1)` * Otherwise (`maximizeCoverage` is `false`), - * `leftInnerCET = numToVec(start, numDigits, minFailExp)` - * `leftCET = numToVec(start - minFail, numDigits, minFailExp)` - * `rightInnerCET = numToVec(end - minFail + 1, numDigits, minFailExp)` - * `rightCET = numToVec(end + 1, numDigits, minFailExp)` + * `leftInnerCET = numToVec(start, numDigits, minSupportExp)` + * `leftCET = numToVec(start - minSupport, numDigits, minSupportExp)` + * `rightInnerCET = numToVec(end - minSupport + 1, numDigits, minSupportExp)` + * `rightCET = numToVec(end + 1, numDigits, minSupportExp)` ### n-of-n Oracles with Bounded Error @@ -402,23 +403,23 @@ To summarize, for n-of-n oracle support, the 2-of-2 algorithm is run where the p Luckily, there are very few large CETs in any given DLC. Thus, the primary multiplier to be concerned with is that of small non-middle CETs. -If the difference between `maxErrorExp` and `minFailExp` is only one, then all small +If the difference between `maxErrorExp` and `minSupportExp` is only one, then all small CETs will be non-middle so that additional oracles are guaranteed to lead to exponential growth in this multiplier (though one should note that exponential growth is already likely when using the below t-of-n scheme so that this may not be a primary concern). -If, on the other hand, the difference between `maxErrorExp` and `minFailExp` is larger +If, on the other hand, the difference between `maxErrorExp` and `minSupportExp` is larger than one, then the majority of CETs are expected to be middle CETs with exponentially larger numbers of middle CETs the bigger the difference between those two parameters. Therefore, there is a trade-off between the tightness of error bounds (i.e. the size of the non- -guaranteed successes or failures between `minFail` and `maxError`) and the number of CETs +guaranteed successes or failures between `minSupport` and `maxError`) and the number of CETs when using more than two oracles. -It should also be noted that the actual values of `minFailExp` and `maxErrorExp` are not part of +It should also be noted that the actual values of `minSupportExp` and `maxErrorExp` are not part of this trade-off, only their relative difference. -For example, having `minFail=32` and `maxError = 128` should yield similar results to having -`minFail = 256` and `maxError = 1024`. +For example, having `minSupport=32` and `maxError = 128` should yield similar results to having +`minSupport = 256` and `maxError = 1024`. ### t-of-n Oracles with Bounded Error @@ -428,11 +429,11 @@ numeric outcomes with allowed (bounded) error, we simply run the t-of-t algorith The only additional work that must be done is that there must be a decision procedure to determine which oracle in a given group of `t` oracles is primary, and additionally what values should be used -for `minFail` and `maxError` for a given group of `t` oracles (as this can vary between groups). +for `minSupport` and `maxError` for a given group of `t` oracles (as this can vary between groups). The simplest candidate would be a negotiated ordered ranking of the oracles where the highest ranking oracle in any group of `t` oracles is chosen as primary. -The values `minFail` and `maxError` can also be computed as some function of the rankings of a group +The values `minSupport` and `maxError` can also be computed as some function of the rankings of a group of `t` oracles, or else they can be set as constant parameters across all groupings. TODO: Decide how this is done and communicated. From 8dc589c004f1a69b61b141d620c54a4ca968219a Mon Sep 17 00:00:00 2001 From: nkohen Date: Tue, 9 Mar 2021 14:46:27 -0600 Subject: [PATCH 12/17] Renamed everything with the word CET in it to be more descriptive including algorithm variable names --- MultiOracle.md | 265 +++++++++++++++++++++++++------------------------ 1 file changed, 134 insertions(+), 131 deletions(-) diff --git a/MultiOracle.md b/MultiOracle.md index 65a7b69..383760f 100644 --- a/MultiOracle.md +++ b/MultiOracle.md @@ -26,10 +26,10 @@ the same events. The majority of this document, however, is devoted to treating the numeric case where oracles are allowed to have bounded disagreements. -In any of these cases, using multiple oracles does introduce a multiplier on the total number of CETs. -In general, this multiplier grows exponentially with the number of oracles, but remains low enough +In any of these cases, using multiple oracles does introduce a multiplier on the total number of adaptor signatures needed. +In general, the adaptor signature set grows exponentially with the number of oracles, but remains small enough for small numbers of oracles to enable the most common use cases (2-of-3 and 3-of-5) without much trouble. -Larger numbers of oracles can still be used in cases where they are needed, but the CET cost incurred may be large. +Larger numbers of oracles can still be used in cases where they are needed, but the adaptor signature cost incurred may be large. ## Table of Contents @@ -50,8 +50,8 @@ Larger numbers of oracles can still be used in cases where they are needed, but ## Multiple Oracles for Enumerated Outcome Events -In the case of enumerated outcome events, where there is no macroscopic structure to the set of -CETs and all oracles of a given event are expected to sign the same outcomes, little work is required +In the case of enumerated outcome events, where there is no macroscopic structure to the set of outcomes +and all oracles of a given event are expected to sign perfectly corresponding outcomes, little work is required to support multiple oracles. The n-of-n case is accomplished by simple point addition in the same manner as is done to combine @@ -84,12 +84,12 @@ For a more detailed rationale for this approach see [this section](CETCompressio ### t-of-n Oracles To construct a DLC for an enumerated outcome event using some threshold t-of-n oracles, -we construct CETs for all outcomes for all possible combinations of t-of-t oracles. +we construct adaptor signatures for all outcomes for all possible combinations of t-of-t oracles. For example, say there are three oracles, Olivia, Oren, and Ollivander, who will be attesting to one of two outcomes, A or B. If we wish to construct a 2-of-3 DLC over these outcomes using these oracles, we will construct -and adaptor sign a total of 6 CETs: +a total of 6 adaptor signatures: * Olivia and Oren sign A. * Olivia and Ollivander sign A. @@ -98,7 +98,7 @@ and adaptor sign a total of 6 CETs: * Olivia and Ollivander sign B. * Oren and Ollivander sign B. -In general, the resulting DLC will have as many CETs as it did in the single oracle case, +In general, the resulting DLC will have as many adaptor signatures as it did in the single oracle case, with a multiplier of `n C t`. #### Example Algorithm @@ -172,16 +172,16 @@ Specifically distance is used so that outcomes are related if they are sufficien It turns out that there is an exceedingly large design space of approaches that can be taken to support multiple oracles with some acceptable variance. It seems to be generally true, however, that a trade-off exists between the precision of guarantees that a procedure -can make, and the size of the multiplier on the number of CETs required for the DLC. -This specification chooses to prioritize CET reduction at the expense of precise guarantees so as to more easily -support more oracles, which should generally counteract some of the imprecision surrounding variance support. +can make, and the size of the multiplier on the number of adaptor signatures required for the DLC. +This specification chooses to prioritize adaptor signature reduction at the expense of precise guarantees so as to more +easily support more oracles, which should generally counteract some of the imprecision surrounding variance support. Although this resulting design is extremely opinionated in some sense, it does leave three parameters unspecified to be negotiated or chosen by DLC participants. The first two parameters are the orders of magnitude of expected and of allowed difference between oracles. By expected difference we mean the differences for which support is required by users, and by allowed difference we mean the differences for which support is acceptable but not required so that they may or may not be covered -by the multi-oracle CET construction algorithm. +by the multi-oracle DLC construction algorithm. These parameters will, from now on, be called `minSupport` and `maxError` as they also represent the lower bound on failure (non-support) and the upper bound on allowed (support) difference/error between oracles. When we say that the guarantees made by this proposal are not precise, we mean two things. @@ -196,9 +196,9 @@ The third parameter offers a minimal remedy to these lack of guarantees. It is a boolean flag (`true` or `false`) called `maximizeCoverage`. This parameter arises from the fact that there is a decision to be made when covering the `minSupport` variance to either cover as much as possible (up to `maxError`) or as little as possible, and this decision has no consequence -on the number of CETs. +on the number of adaptor signatures. That is to say that maximizing or minimizing the cases of variance between `minSupport` and `maxError` require exactly -the same number of CETs, hence this choice is left to the DLC participants. +the same number of adaptor signatures, hence this choice is left to the DLC participants. While this flag does improve the probabilistic guarantees which can be made for the `maxError`-`minSupport` gap, it should be noted that these are still only probabilistic as even if `maximizeCoverage` is set to `true`, there can still be differences of `minSupport + 1` which are unsupported in the worst case and likewise, differences of `maxError - 1` @@ -207,43 +207,44 @@ Yet in the average case this maximizing coverage will make it much more likely t will succeed and minimizing coverage will make it much more likely that these cases fail (are not supported). There exist many versions of this proposal which allow more exact guarantees, such as ones that lift either or both of the -constraints on the variance parameters, but they all require significantly more CETs. -This proposal can be thought of as defining the maximally coarse CET coverage algorithm which results in the fewest -possible multiplier on the number of CETs. +constraints on the variance parameters, but they all require significantly more adaptor signatures. +This proposal can be thought of as defining the maximally coarse coverage algorithm which results in the fewest +possible multiplier on the number of adaptor signatures. At a high level the algorithm works as follows (many details and some special cases are omitted). -Designate one oracle in every t-of-t grouping to be the primary oracle and generate the set of CETs required for the DLC -in question as would be done for a single oracle. +Designate one oracle in every t-of-t grouping to be the primary oracle and generate the set of digit prefixes and corresponding +adaptor points required for the DLC in question as would be done for a single oracle. This primary oracle functionally determines the execution price, meaning that the UX should be the same as if this primary oracle was used on its own. -Then, for each of these CETs representing the primary oracle's attested result, label the first and last outcome covered -by this CET as `[start, end]` and compute the largest allowed range `[end - maxError, start + maxError]` for +Then, for each of these digit prefixes representing the primary oracle's attested result, label the first and last outcome covered +by this digit prefix as `[start, end]` and compute the largest allowed range `[end - maxError, start + maxError]` for secondary oracles. -Compute the set of CETs required to cover this range (using the [CET compression algorithm](CETCompression.md#cet-compression)) and discard all but the -largest CETs in this set, which by definition cover the vast majority of the range. +Compute the set of digit prefixes required to cover this range (using the [CET compression algorithm](CETCompression.md#cet-compression)) and discard all but the +shortest prefixes (corresponding to the largest intervals) in this set, which by definition cover the vast majority of the range. This discarding is the primary opinion decidedly made from the design space by this proposal, and discarding any less -leads to better guarantees at the expense of more CETs. -The resulting CET(s) can then either be used (in the case of maximize coverage) or shrunk until they cover as little as -possible while still containing `[start - minSupport, end + minSupport]` by repeatedly cutting them in half on either side. -This process results in 1 to 3 secondary oracle CETs for ever single CET of the primary oracle (see [algorithm below](#algorithm)). +leads to better guarantees at the expense of more adaptor signatures. +The resulting digit prefix(es) can then either be used (in the case of maximize coverage) or shrunk until they cover as little as possible +while still containing `[start - minSupport, end + minSupport]` by repeatedly cutting the interval(s) in half on either side. +This process results in 1 or 2 secondary oracle digit prefixes for ever single CET of the primary oracle (see [algorithm below](#algorithm)). ### 2-of-2 Oracles with Bounded Error In the two oracle case, mark one oracle as primary and the other as secondary. -First, generate all adaptor points for the primary oracle as is done in the single-oracle +First, generate all digit prefixes for the primary oracle as is done in the single-oracle case for [numeric outcome DLCs](NumericOutcome.md). -Then we shall construct a list of 1-3 secondary points with which to combine each primary point. -This scheme can be thought of as computing a set of 1-3 CETs for the secondary oracle to cover -at least the minimum range and at most the maximum range of outcomes allowed given the each -primary oracle's CET. +Then we shall construct a list of 1 or 2 secondary digit prefixes whose corresponding adaptor points will +be combined with the adaptor point corresponding to the primary oracle digit prefix. +This scheme can be thought of as computing a set of 1 or 2 digit prefixes for the secondary oracle to +cover at least the minimum range and at most the maximum range of outcomes allowed given each +primary oracle's digit prefix. The maximum possible support range is parameterized by a maximum error exponent, `maxErrorExp`, where all difference more than `maxError = 2^maxErrorExp` are guaranteed **not** to be supported. -The minimum supported range is parameterized by a minimum failure exponent, `minSupportExp`, where +The minimum supported range is parameterized by a minimum support exponent, `minSupportExp`, where all differences of up to `minSupport = 2^minSupportExp` are guaranteed to be supported. It is required that `minSupportExp` be strictly less than `maxErrorExp` because this gap is key to the -existence of the following algorithm. +functioning of the following algorithm. If the two oracles sign outcomes that are between `minSupport` and `maxError` apart, then this procedure can provide only probabilistic guarantees. @@ -251,25 +252,25 @@ That said, DLC participants can decide in advance whether they wish to maximize failure or of success in these cases. With these parameters in mind, we shall now detail the algorithm for computing the secondary oracle's -adaptor points given those of the first. +digit prefixes given those of the first. #### Algorithm First, let us define some subprocedures. -* `computeCETIntervalBinary` takes as input a list of digits corresponding to a CET, and the total - number of binary digits to be signed by an oracle, and returns an interval `[start, end]` - which that CET covers. -* `numToVec` takes as input an integer representing the left endpoint of a CET's range, the number - of binary digits to be signed by the oracle, and a number of digits to ignore, and returns - the binary digits corresponding to that CET. +* `computeCETIntervalBinary` takes as input a digit prefix corresponding to an outcome interval, and the + total number of binary digits to be signed by an oracle, and returns an interval `[start, end]` + which that digit prefix covers. +* `numToVec` takes as input an integer representing the left endpoint of a digit prefix's range, the number + of binary digits to be signed by the oracle, and a number of digits to ignore/omit, and returns + the binary digits corresponding to that digit prefix. We take as input the number of digits to be signed by the oracle, `numDigits`, the binary digits of the primary -oracle's CET which we wish to cover with the secondary oracle, `cetDigits`, `maxErrorExp`, `minSupportExp`, +oracle's digit prefix which we wish to cover with the secondary oracle, `primaryDigits`, `maxErrorExp`, `minSupportExp`, and a boolean flag `maximizeCoverage` which signals whether to maximize the probability of success for outcomes differing by less than `maxError` and more than `minSupport` or not (in which case failure is maximized). -Let `[start, end] = computeCETIntervalBinary(cetDigits, numDigits)`, +Let `[start, end] = computeCETIntervalBinary(primaryDigits, numDigits)`, let `halfMaxError = 2^(maxErrorExp - 1)`, and let `maxNum = (2^numDigits) - 1`. @@ -277,143 +278,145 @@ We then split into cases: TODO: Pictures here -* **Case** Small CET (`end - start + 1 < maxError`) - * In this case we consider the primary oracle's CET's range as it relates to the `maxError`-sized +* **Case** Small Primary Interval (`end - start + 1 < maxError`) + * In this case we consider the primary oracle's digit prefix's range as it relates to the `maxError`-sized interval, beginning at some multiple of `maxError`, which contains the CET in question. - * Note that the CET cannot be part of two such `maxError`-sized intervals as this would - imply that there are fewer `cetDigits` than `numDigits - maxErrorExp` which would - result in a large CET, but we are in the small CET case. + * Note that the primary interval cannot be part of two such `maxError`-sized intervals as this would + imply that there are fewer `primaryDigits` than `numDigits - maxErrorExp` which would + result in a large primary interval, but we are in the small primary interval case. * Definitions - * Let `leftErrorCET` be the first multiple of `maxError` to the left of `start`. - * Let `rightErrorCET` be the first multiple of `maxError` to the right of `end`. - * Let `errorCET = numToVec(leftErrorCET, numDigits, maxErrorExp)`. + * Let `leftMaxErrorMult` be the first multiple of `maxError` to the left of `start`. + * Let `rightMaxErrorMult` be the first multiple of `maxError` to the right of `end`. + * Let `maxCoverPrefix = numToVec(leftMaxErrorMult, numDigits, maxErrorExp)`. * We now split into cases again depending on whether or not the small CET is near either boundary - of its containing interval `[leftErrorCET, rightErrorCET]`. - * **Case** Middle CET (`start >= leftErrorCET + minSupport` and `end <= rightErrorCET - minSupport`) - * In this case, only a single secondary CET is needed to cover all cases in which it agrees with - the input primary CET! - * If `maximizeCoverage` is `true`, then `errorCET` is to be used. - * Otherwise, use the smallest CET which contains `[start - minSupport, end + minSupport]`. + of its containing interval `[leftErrorCET, rightErrorCET - 1]`. + * **Case** Middle Primary Interval (`start >= leftMaxErrorMult + minSupport` and `end < rightMaxErrorMult - minSupport`) + * In this case, only a single secondary digit prefix is needed to cover all cases in which it agrees with + the input primary interval! + * If `maximizeCoverage` is `true`, then `maxCoverPrefix` is to be used. + * Otherwise, use the smallest interval which contains `[start - minSupport, end + minSupport]`. * This can be computed as the common prefix between the binary digits of those two endpoints. - * **Case** Left CET (`start < leftErrorCET + minSupport`) - * In this case, two secondary CETs are needed: `leftCET` and `rightCET`, one on each side - of `leftErrorCET`. - * **Special Case** Leftmost CET (`leftErrorCET == 0`) - * In this case only `rightCET` needs to be computed and used - * If `maximizeCoverage` is `true`, then `rightCET = errorCET`. - * Otherwise, `rightCET` is the CET resulting from repeatedly deleting the right half of - `errorCET` until any more deletions would no longer result in a right endpoint greater + * **Case** Left Primary Interval (`start < leftMaxErrorMult + minSupport`) + * In this case, two secondary digit prefixes are needed: `leftPrefix` and `rightPrefix`, one on each side + of `leftMaxErrorMult`. + * **Special Case** Leftmost Primary Interval (`leftMaxErrorMult == 0`) + * In this case only `rightPrefix` needs to be computed and used + * If `maximizeCoverage` is `true`, then `rightPrefix = maxCoverPrefix`. + * Otherwise, `rightPrefix` is the interval resulting from repeatedly deleting the right half of + `maxCoverPrefix`'s interval until any more deletions would no longer result in a right endpoint greater than `end + minSupport`. * This can be computed as taking the first `(numDigits - maxErrorExp)` binary digits of `end + minSupport` followed by any additional `0` digits after that. * If `maximizeCoverage` is `true`, then - `leftCET = numToVec(leftErrorCET - halfMaxError, numDigits, maxErrorExp - 1)`. - * This is the CET of width `halfMaxError` covering the interval - `[leftErrorCET - halfMaxError, leftErrorCET - 1]`. - * Otherwise, `leftCET` is the CET of minimum width containing - `[leftErrorCET - minSupport, leftErrorCET - 1]`. + `leftPrefix = numToVec(leftMaxErrorMult - halfMaxError, numDigits, maxErrorExp - 1)`. + * This prefix has the interval of width `halfMaxError` covering + `[leftMaxErrorMult - halfMaxError, leftMaxErrorMult - 1]`. + * Otherwise, `leftPrefix` covers the interval of minimum width containing + `[leftMaxErrorMult - minSupport, leftMaxErrorMult - 1]`. * This can be computed as the first `(numDigits - maxErrorExp)` binary digits of `start - minSupport` followed by any additional `1` digits after that. - * **Case** Right CET (`end > rightErrorCET - minSupport`) - * In this case, two secondary CETs are needed: `leftCET` and `rightCET`, one on each side - of `rightErrorCET`. - * **Special Case** Rightmost CET (`rightErrorCET == maxNum`) - * In this case only `leftCET` needs to be computed and used - * If `maximizeCoverage` is `true`, then `leftCET = errorCET`. - * Otherwise, `leftCET` is the CET resulting from repeatedly deleting the left half of - `errorCET` until any more deletions would no longer result in a left endpoint greater + * **Case** Right Primary Interval (`end > rightMaxErrorMult - minSupport`) + * In this case, two secondary digit prefixes are needed: `leftPrefix` and `rightPrefix`, one on each side + of `rightMaxErrorMult`. + * **Special Case** Rightmost Primary Interval (`rightMaxErrorMult == maxNum`) + * In this case only `leftPrefix` needs to be computed and used + * If `maximizeCoverage` is `true`, then `leftPrefix = maxCoverPrefix`. + * Otherwise, `leftPrefix` is the interval resulting from repeatedly deleting the left half of + `maxCoverPrefix`'s interval until any more deletions would no longer result in a left endpoint greater than `start - minSupport`. * This can be computed as taking the first `(numDigits - maxErrorExp)` binary digits of `start - minSupport` followed by any additional `1` digits. * If `maximizeCoverage` is `true` then - `rightCET = numToVec(rightErrorCET + 1, numDigits, maxErrorExp - 1)`. - * This is the CET of width `halfMaxError` covering the interval - `[rightErrorCET + 1, rightErrorCET + halfMaxError]`. - * Otherwise, `rightCET` is the CET of minimum width containing - `[rightErrorCET + 1, end + minSupport]`. + `rightPrefix = numToVec(rightMaxErrorMult + 1, numDigits, maxErrorExp - 1)`. + * This prefix has the interval of width `halfMaxError` covering + `[rightMaxErrorMult + 1, rightMaxErrorMult + halfMaxError]`. + * Otherwise, `rightPrefix` covers the interval of minimum width containing + `[rightMaxErrorMult + 1, end + minSupport]`. * This can be computed as the first `(numDigits - maxErrorExp)` binary digits of `end + minSupport` followed by any additional `0` digits. -* **Case** Large CET (`end - start + 1 >= maxError`) - * In this case, up to three CETs are needed, a `middleCET` for when both oracles agree that - the outcome is within the large range of this CET, a `leftCET` for when the secondary oracle - is within an acceptable range to the left of the large CET, and a `rightCET` for when the - secondary oracle is within an acceptable range to the right of the large CET. - * The `leftCET` is paired with a new primary CET called `leftInnerCET`. - * The `rightCET` is paired with a new primary CET called `rightInnerCET`. - * **Special Case** Leftmost Large CET (`start == 0`) - * The `leftInnerCET` and `leftCET` do not need to be computed and are not used. - * **Special Case** Rightmost Large CET (`end == maxNum`) - * The `rightInnerCET` and `rightCET` do not need to be computed and are not used. - * The `middleCET` is always equal to the input CET, `[start, end]`. - * This may actually violate the `maxError` bound but since this is one large CET, it must +* **Case** Large Primary Interval (`end - start + 1 >= maxError`) + * In this case, we partition the primary interval into three pieces where one secondary prefix is needed for each of the three primary intervals. + The three secondary prefixes are a `middlePrefix` for when both oracles agree that + the outcome is within the large primary interval, a `leftPrefix` for when the secondary oracle + is within an acceptable range to the left of the large primary interval, and a `rightPrefix` for when the + secondary oracle is within an acceptable range to the right of the large primary interval. + * The `leftPrefix` is paired with a new primary prefix called `leftInnerPrefix`. + * The `rightPrefix` is paired with a new primary prefix called `rightInnerPrefix`. + * The `middlePrefix` is paired with the original (large) primary interval. + * **Special Case** Leftmost Large Primary Interval (`start == 0`) + * The `leftInnerPrefix` and `leftPrefix` do not need to be computed and are not used. + * **Special Case** Rightmost Large Primary Interval (`end == maxNum`) + * The `rightInnerPrefix` and `rightPrefix` do not need to be computed and are not used. + * The `middlePrefix` always covers exactly the input primary interval, `[start, end]`. + * This may actually violate the `maxError` bound but since this is one large primary interval, it must be the case that even with this larger than `maxError` difference between the oracles, the payout resulting from either outcome is the same so that this is not an issue. * If `maximizeCoverage` is `true`, - * `leftInnerCET = numToVec(start, numDigits, maxErrorExp - 1)` - * `leftCET = numToVec(start - halfMaxError, numDigits, maxErrorExp - 1)` - * `rightInnerCET = numToVec(end - halfMaxError + 1, numDigits, maxErrorExp - 1)` - * `rightCET = numToVec(end + 1, numDigits, maxErrorExp - 1)` + * `leftInnerPrefix = numToVec(start, numDigits, maxErrorExp - 1)` + * `leftPrefix = numToVec(start - halfMaxError, numDigits, maxErrorExp - 1)` + * `rightInnerPrefix = numToVec(end - halfMaxError + 1, numDigits, maxErrorExp - 1)` + * `rightPrefix = numToVec(end + 1, numDigits, maxErrorExp - 1)` * Otherwise (`maximizeCoverage` is `false`), - * `leftInnerCET = numToVec(start, numDigits, minSupportExp)` - * `leftCET = numToVec(start - minSupport, numDigits, minSupportExp)` - * `rightInnerCET = numToVec(end - minSupport + 1, numDigits, minSupportExp)` - * `rightCET = numToVec(end + 1, numDigits, minSupportExp)` + * `leftInnerPrefix = numToVec(start, numDigits, minSupportExp)` + * `leftPrefix = numToVec(start - minSupport, numDigits, minSupportExp)` + * `rightInnerPrefix = numToVec(end - minSupport + 1, numDigits, minSupportExp)` + * `rightPrefix = numToVec(end + 1, numDigits, minSupportExp)` ### n-of-n Oracles with Bounded Error Just as in the two oracle case, mark one oracle as primary and all others as secondary. The simplest method for achieving n-of-n oracle support for n greater than 2 is to run the 2-of-2 -algorithm in a slightly modified fashion so that if, on a given primary CET, the algorithm returns -2 secondary CETs, we instead return `2^(n-1)` aggregate secondary CETs. +algorithm in a slightly modified fashion so that if, on a given primary interval, the algorithm returns +2 secondary digit prefixes, we instead return `2^(n-1)` aggregate adaptor points. -For example, if there are two secondary oracles, Omar and Odette, and two CETs, A and B, returned -by the 2-of-2 algorithm, then this modified algorithm would return four aggregate CETs: +For example, if there are two secondary oracles, Omar and Odette, and two digit prefixes, A and B, returned +by the 2-of-2 algorithm, then this modified algorithm would return four aggregate adaptor points: * Omar signs A and Odette signs A * Omar signs A and Odette signs B * Omar signs B and Odette signs A * Omar signs B and Odette signs B -If the 2-of-2 algorithm returns a single secondary CET then we simply use the aggregate of all oracles -signing an event that is covered by that one CET. +If the 2-of-2 algorithm returns a single secondary digit prefix then we simply use the aggregate of all oracles +signing an event that is covered by that one digit prefix. -However, in the large CET case where three CETs are normally returned, we can make some +However, in the large primary interval case where three digit prefixes are normally returned, we can make some more custom alterations. -The `middleCET` case remains the same, but where an aggregate of all oracles signing an event -covered by that CET is used. -But from each of the `(leftCET, leftInnerCET)` and `(rightCET, rightInnerCET)` pairs, we instead generate -`2^(n-1)-1` tuples `(xCET, xInnerCET, middleCET)` (where `x` is `left` or `right`) where `xInnerCET` consists of -only the primary oracle (as usual) and where `xCET` and `middleCET` are aggregations of secondary oracles such that +The `middlePrefix` case remains the same, but where an aggregate of all oracles signing an event +covered by that prefix is used. +But from each of the `(leftPrefix, leftInnerPrefix)` and `(rightPrefix, rightInnerPrefix)` pairs, we instead generate +`2^(n-1)-1` tuples `(xPrefix, xInnerPrefix, middlePrefix)` (where `x` is `left` or `right`) where `xInnerPrefix` consists of +only the primary oracle (as usual) and where `xPrefix` and `middlePrefix` are aggregations of secondary oracles such that -* All secondary oracles are included in exactly one of `xCET` or `middleCET` and -* `xCET` is non-empty. +* All secondary oracles are included in exactly one of `xPrefix` or `middlePrefix` and +* `xPrefix` is non-empty. To summarize, for n-of-n oracle support, the 2-of-2 algorithm is run where the primary oracle's -* Small Middle CETs result in a single aggregate CET -* Small non-Middle CETs result in `2^(n-1)` aggregate CETs -* Large CETs result in a total of `2^n - 1` aggregate CETs - * One aggregate middle CET - * `2^(n-1) - 1` aggregate non-middle CETs for each side - * Totaling `2^n - 2` non-middle aggregate CETs. +* Small Middle Primary Intervals result in a single aggregate adaptor point +* Small non-Middle Primary Intervals result in `2^(n-1)` aggregate adaptor points +* Large Primary Intervals result in a total of `2^n - 1` aggregate adaptor points + * One aggregate middle point + * `2^(n-1) - 1` aggregate non-middle points for each side + * Totaling `2^n - 2` non-middle aggregate points. #### Analysis -Luckily, there are very few large CETs in any given DLC. -Thus, the primary multiplier to be concerned with is that of small non-middle CETs. +Luckily, there are very few large primary intervals in any given DLC. +Thus, the primary multiplier to be concerned with is that of small non-middle primary intervals. If the difference between `maxErrorExp` and `minSupportExp` is only one, then all small -CETs will be non-middle so that additional oracles are guaranteed to lead to exponential +primary intervals will be non-middle so that additional oracles are guaranteed to lead to exponential growth in this multiplier (though one should note that exponential growth is already likely when using the below t-of-n scheme so that this may not be a primary concern). -If, on the other hand, the difference between `maxErrorExp` and `minSupportExp` is larger -than one, then the majority of CETs are expected to be middle CETs with exponentially larger -numbers of middle CETs the bigger the difference between those two parameters. +If, on the other hand, the difference between `maxErrorExp` and `minSupportExp` is larger than one, +then the majority of primary intervals are expected to be middle primary intervals with exponentially +larger numbers of middle primary intervals the bigger the difference between those two parameters. Therefore, there is a trade-off between the tightness of error bounds (i.e. the size of the non- -guaranteed successes or failures between `minSupport` and `maxError`) and the number of CETs +guaranteed successes or failures between `minSupport` and `maxError`) and the number of adaptor points when using more than two oracles. It should also be noted that the actual values of `minSupportExp` and `maxErrorExp` are not part of From 7ff5fba877e55704f9771e1723b84e0527708510 Mon Sep 17 00:00:00 2001 From: nkohen Date: Tue, 9 Mar 2021 15:21:18 -0600 Subject: [PATCH 13/17] Added diagram illustrating minSupport and maxError usage --- MultiOracle.md | 5 +++++ images/SecondaryDLCOracle.png | Bin 0 -> 11346 bytes 2 files changed, 5 insertions(+) create mode 100644 images/SecondaryDLCOracle.png diff --git a/MultiOracle.md b/MultiOracle.md index 383760f..a9b34ca 100644 --- a/MultiOracle.md +++ b/MultiOracle.md @@ -206,6 +206,11 @@ may still succeed even if `maximizeCoverage` is set to `false` in the worst case Yet in the average case this maximizing coverage will make it much more likely that cases in the `maxError`-`minSupport` gap will succeed and minimizing coverage will make it much more likely that these cases fail (are not supported). +Here is a diagram which illustrates how the error bounds `minSupport` and `maxError` are used to constrain the selection +of secondary oracle intervals: + +![image](images/SecondaryDLCOracle.png) + There exist many versions of this proposal which allow more exact guarantees, such as ones that lift either or both of the constraints on the variance parameters, but they all require significantly more adaptor signatures. This proposal can be thought of as defining the maximally coarse coverage algorithm which results in the fewest diff --git a/images/SecondaryDLCOracle.png b/images/SecondaryDLCOracle.png new file mode 100644 index 0000000000000000000000000000000000000000..1327bc65139dcc84580a047ff9d290e83fa2e792 GIT binary patch literal 11346 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 literal 0 HcmV?d00001 From f18a2cd399300e1d07818b850bfc2f47979fa851 Mon Sep 17 00:00:00 2001 From: nkohen Date: Tue, 9 Mar 2021 15:59:44 -0600 Subject: [PATCH 14/17] Added some initial diagrams --- MultiOracle.md | 4 ++++ images/LargePrimaryInterval.png | Bin 0 -> 8249 bytes images/SmallPrimaryInterval.png | Bin 0 -> 10163 bytes 3 files changed, 4 insertions(+) create mode 100644 images/LargePrimaryInterval.png create mode 100644 images/SmallPrimaryInterval.png diff --git a/MultiOracle.md b/MultiOracle.md index a9b34ca..eb4cc08 100644 --- a/MultiOracle.md +++ b/MultiOracle.md @@ -283,6 +283,10 @@ We then split into cases: TODO: Pictures here +![Small Primary Interval](images/SmallPrimaryInterval.png) + +![Large Primary Interval](images/LargePrimaryInterval.png) + * **Case** Small Primary Interval (`end - start + 1 < maxError`) * In this case we consider the primary oracle's digit prefix's range as it relates to the `maxError`-sized interval, beginning at some multiple of `maxError`, which contains the CET in question. diff --git a/images/LargePrimaryInterval.png b/images/LargePrimaryInterval.png new file mode 100644 index 0000000000000000000000000000000000000000..3f772b3ceef9185974c51d3c2962354f75ea606e GIT binary patch literal 8249 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 AV*mgE literal 0 HcmV?d00001 diff --git a/images/SmallPrimaryInterval.png b/images/SmallPrimaryInterval.png new file mode 100644 index 0000000000000000000000000000000000000000..7fa56920d06d415bb5503205397751c3f78829c7 GIT binary patch literal 10163 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 SG_f1(0NUyXYV|5M@BR;mhbWE! literal 0 HcmV?d00001 From 0b7624b93c49965ed50c203e7900f8c1154c6996 Mon Sep 17 00:00:00 2001 From: nkohen Date: Tue, 9 Mar 2021 16:41:28 -0600 Subject: [PATCH 15/17] some clean-up --- MultiOracle.md | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/MultiOracle.md b/MultiOracle.md index eb4cc08..d3823e9 100644 --- a/MultiOracle.md +++ b/MultiOracle.md @@ -230,7 +230,7 @@ This discarding is the primary opinion decidedly made from the design space by t leads to better guarantees at the expense of more adaptor signatures. The resulting digit prefix(es) can then either be used (in the case of maximize coverage) or shrunk until they cover as little as possible while still containing `[start - minSupport, end + minSupport]` by repeatedly cutting the interval(s) in half on either side. -This process results in 1 or 2 secondary oracle digit prefixes for ever single CET of the primary oracle (see [algorithm below](#algorithm)). +This process results in 1 or 2 secondary oracle digit prefixes for every digit prefix of the primary oracle (see [algorithm below](#algorithm)). ### 2-of-2 Oracles with Bounded Error @@ -263,7 +263,7 @@ digit prefixes given those of the first. First, let us define some subprocedures. -* `computeCETIntervalBinary` takes as input a digit prefix corresponding to an outcome interval, and the +* `computePrefixIntervalBinary` takes as input a digit prefix corresponding to an outcome interval, and the total number of binary digits to be signed by an oracle, and returns an interval `[start, end]` which that digit prefix covers. * `numToVec` takes as input an integer representing the left endpoint of a digit prefix's range, the number @@ -275,21 +275,19 @@ oracle's digit prefix which we wish to cover with the secondary oracle, `primary and a boolean flag `maximizeCoverage` which signals whether to maximize the probability of success for outcomes differing by less than `maxError` and more than `minSupport` or not (in which case failure is maximized). -Let `[start, end] = computeCETIntervalBinary(primaryDigits, numDigits)`, +Let `[start, end] = computePrefixIntervalBinary(primaryDigits, numDigits)`, let `halfMaxError = 2^(maxErrorExp - 1)`, and let `maxNum = (2^numDigits) - 1`. We then split into cases: -TODO: Pictures here - ![Small Primary Interval](images/SmallPrimaryInterval.png) ![Large Primary Interval](images/LargePrimaryInterval.png) * **Case** Small Primary Interval (`end - start + 1 < maxError`) * In this case we consider the primary oracle's digit prefix's range as it relates to the `maxError`-sized - interval, beginning at some multiple of `maxError`, which contains the CET in question. + interval, beginning at some multiple of `maxError`, which contains the primary interval in question. * Note that the primary interval cannot be part of two such `maxError`-sized intervals as this would imply that there are fewer `primaryDigits` than `numDigits - maxErrorExp` which would result in a large primary interval, but we are in the small primary interval case. @@ -297,8 +295,8 @@ TODO: Pictures here * Let `leftMaxErrorMult` be the first multiple of `maxError` to the left of `start`. * Let `rightMaxErrorMult` be the first multiple of `maxError` to the right of `end`. * Let `maxCoverPrefix = numToVec(leftMaxErrorMult, numDigits, maxErrorExp)`. - * We now split into cases again depending on whether or not the small CET is near either boundary - of its containing interval `[leftErrorCET, rightErrorCET - 1]`. + * We now split into cases again depending on whether or not the small primary interval is near either boundary + of its containing interval `[leftMaxErrorMult, rightMaxErrorMult - 1]`. * **Case** Middle Primary Interval (`start >= leftMaxErrorMult + minSupport` and `end < rightMaxErrorMult - minSupport`) * In this case, only a single secondary digit prefix is needed to cover all cases in which it agrees with the input primary interval! From aeb907829820d06013dc6482ddd2290a4525f004 Mon Sep 17 00:00:00 2001 From: nkohen Date: Thu, 11 Mar 2021 02:07:01 -0600 Subject: [PATCH 16/17] Added (end - maxError, start + maxError) rationale --- MultiOracle.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/MultiOracle.md b/MultiOracle.md index d3823e9..059a358 100644 --- a/MultiOracle.md +++ b/MultiOracle.md @@ -221,9 +221,10 @@ Designate one oracle in every t-of-t grouping to be the primary oracle and gener adaptor points required for the DLC in question as would be done for a single oracle. This primary oracle functionally determines the execution price, meaning that the UX should be the same as if this primary oracle was used on its own. -Then, for each of these digit prefixes representing the primary oracle's attested result, label the first and last outcome covered -by this digit prefix as `[start, end]` and compute the largest allowed range `[end - maxError, start + maxError]` for -secondary oracles. +Then, for each of these digit prefixes representing the primary oracle's attested result, label the first and last outcome covered by +this digit prefix as `[start, end]` and compute the largest allowed range `(end - maxError, start + maxError)` for secondary +oracles where this is the largest allowed range because `end - maxError` is the smallest outcome within `maxError` of **all** outcomes +in `[start, end]` and `start + maxError` is the greatest outcome within `maxError` of **all** outcomes (see diagram above). Compute the set of digit prefixes required to cover this range (using the [CET compression algorithm](CETCompression.md#cet-compression)) and discard all but the shortest prefixes (corresponding to the largest intervals) in this set, which by definition cover the vast majority of the range. This discarding is the primary opinion decidedly made from the design space by this proposal, and discarding any less From c681d30f8f4f175e1fbbd45f0342baf7b1e5ff1d Mon Sep 17 00:00:00 2001 From: nkohen Date: Tue, 16 Mar 2021 01:32:40 -0500 Subject: [PATCH 17/17] Added white-background versions of pngs --- MultiOracle.md | 6 +++--- images/LargePrimaryIntervalWhiteBack.png | Bin 0 -> 14712 bytes images/SecondaryDLCOracleWhiteBack.png | Bin 0 -> 20970 bytes images/SmallPrimaryIntervalWhiteBack.png | Bin 0 -> 17888 bytes 4 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 images/LargePrimaryIntervalWhiteBack.png create mode 100644 images/SecondaryDLCOracleWhiteBack.png create mode 100644 images/SmallPrimaryIntervalWhiteBack.png diff --git a/MultiOracle.md b/MultiOracle.md index 059a358..64b537c 100644 --- a/MultiOracle.md +++ b/MultiOracle.md @@ -209,7 +209,7 @@ will succeed and minimizing coverage will make it much more likely that these ca Here is a diagram which illustrates how the error bounds `minSupport` and `maxError` are used to constrain the selection of secondary oracle intervals: -![image](images/SecondaryDLCOracle.png) +![image](images/SecondaryDLCOracleWhiteBack.png) There exist many versions of this proposal which allow more exact guarantees, such as ones that lift either or both of the constraints on the variance parameters, but they all require significantly more adaptor signatures. @@ -282,9 +282,9 @@ and let `maxNum = (2^numDigits) - 1`. We then split into cases: -![Small Primary Interval](images/SmallPrimaryInterval.png) +![Small Primary Interval](images/SmallPrimaryIntervalWhiteBack.png) -![Large Primary Interval](images/LargePrimaryInterval.png) +![Large Primary Interval](images/LargePrimaryIntervalWhiteBack.png) * **Case** Small Primary Interval (`end - start + 1 < maxError`) * In this case we consider the primary oracle's digit prefix's range as it relates to the `maxError`-sized diff --git a/images/LargePrimaryIntervalWhiteBack.png b/images/LargePrimaryIntervalWhiteBack.png new file mode 100644 index 0000000000000000000000000000000000000000..e0198df5ca9b359a56933b272e3a7bd2a394335f GIT binary patch literal 14712 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�t8DcK+KDm4rIic9n5jU3lwZ@Mhb#jZQ*Py!2 zHY%V!^z`(c1)4G4!ju;d*jX(t_fJ6xg9D|@pZice@kR}NJyYQl|sFWc&$4qT8Ac+pL|^kW$iz?mU`CSBNK_Op!h)fU^=JRy zv9PseKs2{pV~}G@kQpgLv+01E@yUl~k@M$uRt%A#V$L=tzOhLXVVZ(s#NZDwF7;T9 zR$y8UV@rvSI|u)IV_Csyc3^OQazQQzj z<9v9h9(;KAbz(#gK6NjAppY?S z1(cAG9}1(XaMRD>SfSBI z$1#TxBDZkQ+5|da*0%Zx4a5{lF7fXFNg~`mQ%g$=`M4J@UEA{w3BniU&kG7hh$6YQ_%#Ho zPfl_Yf3N{U593PbzFfq_|J}4S0c<2~!q}_GY1$@o>`THN9P$#{Ea8jC>W9XsB9_s> z8qPDvBQ2-rI6_bS!OjUvoTs6s6;f+ulwbA*bPxnmiqIEv9-E15^Ew8LhE5nbe2XasmWS(OoHH9}g8#6Xk%_x5xXOrm1I34ZTBQb5XJYGbC zjrG*@S_!6aEa3Y_2E0CO({VN?W&#dWga1pkHh&glH!8w@;N2!Ks4=49iU5r3ql779 zNixLo&Gj5;w9NYln&1E`OH`t6Y& zMDuv(!{vs$VPV6a8(7R*(!$+zI5epH{pu}z-zjGAK{DoF~?vV(ZJm?+i4k3 zMZob8#qb$%+}ZgMsOmbx4X=w-Y2=Y|-iWA>X!u#^hTcsO@K!R#jsAi&{STvws6-S< zHeaF=!0&+IgkbE;@xh;<0$ju&Ovxn!JqcfUbpvSBgfB9tWcYK$gx45#C4_B6$Uv1(=)bh+x&5`s0pM*i88j|w${ld ztbIF-WSA6m1Q{rkP9hJSV7wf+4H!gD7?R_;UK5y!YpBv)-L)=a{PXm%r?$--1a#A5cZ1G<^+3vn zdF4rmw>Vj8B?Avt53`5n_P{i~0Q>fpu*ljFZNtxa5fkH8CEAEHB8KIq1Mhaj4QrSV znrYFqxmLr}3FUt-w>D_1q^L+hLSEPAckC~ioaY|td9lBM1({nq(8hr=yNM26?6HM= zP0PFd{CroNbbo(^l>8+OV#6Qxc&)1|tk>&vymM7#%|5fE3FB7{^qxa&>nv6bAw7b$ z1tYawYpy@W=Sv!eo@L^gA!#HJLH>$Y7JwXW`1%0(^-k@)4bRy zvhUmKH=W)n+$y4m+CHQ9MVYLQFG2q@E?pGjZo_=4_|oev$@dT8Xwiousw0i9|K&r2 g|HnyH&l=T3u8JRL0%xi5DM><2Nkj3~NmIZ732n)F00000 literal 0 HcmV?d00001 diff --git a/images/SecondaryDLCOracleWhiteBack.png b/images/SecondaryDLCOracleWhiteBack.png new file mode 100644 index 0000000000000000000000000000000000000000..75a8dfabc865c3f59591640835fb63d7b14af74a GIT binary patch literal 20970 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 literal 0 HcmV?d00001