diff --git a/AttestationPoint.md b/AttestationPoint.md new file mode 100644 index 0000000..b93ef48 --- /dev/null +++ b/AttestationPoint.md @@ -0,0 +1,108 @@ +# Deterministic Attestation Point Computation + +## Introduction + +Discreet Log Contracts (DLCs) are oracle contracts enforced using a set of adaptor signature "point-locks." +This means that in order to spend any execution branch of a DLC, one must reveal the scalar pre-image for a point. +As is described in this document, the points used for adaptor signing correspond to anticipations of all +possible oracle attestations such that exactly one adaptor secret is revealed, unlocking exactly one signature, +making exactly one Contract Execution Transaction (CET) valid for on-chain publication. + +By an anticipation of an oracle attestation, we mean an elliptic curve point `S` whose scalar pre-image `s` (i.e. `S = s*G`) +is an oracle attestation of a specific message, `m` (or the sum of multiple such attestations). +The point `S` can be thought of as an encryption key to be used on the signature of the CET which corresponds to the +event where `m` is attested to so that this signature can only be used should this attestation be broadcast. +The key point is that `S` can be computed *in advance* given information in oracle announcements so that anticipation points +(aka attestation points or sometimes adaptor points) can be used to construct a DLC and later the corresponding attestations +are used to execute that DLC. + +At a high level, this is done using the fact that oracle attestations, `s`, are validated against public key information in the usual way +by checking that `s*G` is equal to a point computed in another way from public information, thus this point can be used as an attestation point. + +## Table of Contents + +* [Disambiguation of Terms](#disambiguation-of-terms) +* [Attestation Point Computation](#attestation-point-computation) + * [Single Attestation Points](#single-attestation-points) + * [Multiple Attestation Aggregate Points](#multiple-attestation-aggregate-points) +* [Single Oracle Enumerated Outcome Attestation Points](#single-oracle-enumerated-outcome-attestation-points) +* [Single Oracle Numeric Outcome Attestation Points](#single-oracle-numeric-outcome-attestation-points) +* [Multiple Oracle Attestation Points](#multiple-oracle-attestation-points) +* [Authors](#authors) + +## Disambiguation of Terms + +* **CET** - A Contract Execution Transaction (CET) is a Bitcoin transaction which spends the DLC funding output as an input + and outputs the DLC participants payouts. + Note that every adaptor point, attestation point, adaptor signature, and oracle outcome will map to some CET but that this mapping + is not one-to-one since multiple points/signatures/outcomes can map to the same CET if those outcomes result in equal payouts. +* **Adaptor Point** - An Adaptor Point is an elliptic curve point used as an encryption key for a signature so that the encrypted signature + is known as an adaptor signature. + This encryption is used to make signatures (and transitively, transactions) conditional on the scalar pre-image of this point becoming known. + Often times an adaptor point is assigned meaning through its functional use in a Bitcoin contracting scheme such as a DLC. + Specifically for DLCs, adaptor points always correspond to oracle attestations so that they are always attestation points and + these two terms are occasionally used inter-changeably in these specifications. +* **Attestation Point** - Also known as an anticipation point, an Attestation Point is an elliptic curve point `S = s*G` such that its scalar pre-image, + `s`, is an oracle attestation (or sum of multiple oracle attestations). + These points can be computed without explicitly knowing the scalar pre-image using only an oracle's public announcement information. + These points are used in the DLC specification as Adaptor Points. +* **Adaptor Signature** - An Adaptor Signature is an encrypted (on-chain-valid) digital signature which is constructed by a signer with their key + along with an Adaptor Point, which is an encryption (public) key. + This signature can be validated without decryption so long as the verifier knows not only the message being signed and the signers public key, + but also the Adaptor Point used to encrypt the signature. + The adaptor signature can only be decrypted into a valid on-chain signature using knowledge of the scalar pre-image of the Adaptor Point. + This process also leaks this scalar pre-image to the adaptor signer as the difference between the decrypted and encrypted signature is this secret. +* **Digit Prefix** - When an oracle attests to a numeric outcomes such as `77 = 001001101` each bit is individually attested to. + As such, when DLC payouts are constant on some interval, DLC participants often only use a prefix of the bits signed and not all of them to + correspond to the set of outcomes where that prefix is followed by any bit-string, e.g. the Digit Prefix `001001` corresponds to the inclusive + interval of outcomes `[72, 79]` (assuming a `num_digits` of `9`) because `72 = 001001000` and `79 = 001001111`. +* **Oracle Outcome** - TODO + +TODO: Don't forget to link to this from Protocol and Messaging docs as well as the two Numeric Outcome docs. + +## Attestation Point Computation + +### Single Attestation Points + +When a single oracle attests to a single value (e.g. an element of an enumeration or a single digit of a numeric outcome), +their attestation is `s = k + m*x` where `k` is the scalar pre-image of the nonce, `R = k*G`, committed to in the +announcement, `m` is the index of the message value being attested to, and `x` is the oracle's private attestation key. + +Thus, to compute the point `S = s*G = (k + m*x)*G = k*G + m*(x*G) = R + m*P` we simply add the nonce, `R`, to +the index, `m`, times the oracle public attestation key, `P = x*G`. + +Using an attestation point computed in this way as an adaptor point will result in an adaptor signature which can only be decrypted +in the case that the oracle attestation of the specific value in question, `m`, becomes known. + +### Multiple Attestation Aggregate Points + +Given public keys `P1, ..., Pn` and nonces `R1, ..., Rn` we can compute `n` individual adaptor points for +a given events `(m1, ..., mn)` in the usual way: `Si = si * G = Ri + mi*Pi`. +To compute an aggregate attestation point for the event where the oracles attestation keys `Pi` are each attesting to their +corresponding `mi` the sum of the corresponding adaptor points is used: +`S(1..n) = s(1..n) * G = (s1 + s2 + ... + sn) * G = s1 * G + s2 * G + ... + sn * G = S1 + S2 + ... + Sn`. + +When the oracle broadcasts its `n` attestations `s1, ..., sn`, the corresponding aggreate adaptor secret +can be computed as `s(1..m) = s1 + s2 + ... + sm` which can be used to broadcast a corresponding CET. + +Intro the usefulness of aggregate attestation points (as a general AND process for oracle locks) and then paste and modify [this](NumericOutcomeCompression.md#adaptor-points-with-multiple-attestations). + +## Single Oracle Enumerated Outcome Attestation Points + +Link to single attestation points and then simply contextualize within single oracle enum outcome and explicitly define order. + +## Single Oracle Numeric Outcome Attestation Points + +Link to aggregate attestation points and then contextualize within single oracle numeric outcome with explicit discussion of digit prefixes including examples and then explicitly define order by linking out to the Numeric Outcome docs. + +## Multiple Oracle Attestation Points + +Link to aggregate attestation points and then define multi-oracle ordering as the chosen combination generating function paired with the orders defined earlier in this document. + +## 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 diff --git a/NumericOutcome.md b/NumericOutcome.md index cb3e979..546b3df 100644 --- a/NumericOutcome.md +++ b/NumericOutcome.md @@ -2,30 +2,30 @@ ## Introduction -This document combines the [CET Compression](CETCompression.md) and [Payout Curve](PayoutCurve.md) specifications, along with +This document combines the [Numeric Outcome Compression](NumericOutcomeCompression.md) and [Payout Curve](PayoutCurve.md) specifications, along with independently introduced [Rounding Intervals](#rounding-intervals) to specify the complete procedure for CET construction, adaptor signing, and signature verification for DLCs over numeric outcomes. -When dealing with enumerated outcomes, DLCs require a single nonce and Contract Execution -Transactions (CETs) are claimed using a single oracle signature. -This scheme results in DLCs which contain a unique CET for every possible outcome, which is -only feasible if the number of possible outcomes is of manageable size. +When dealing with enumerated outcomes, DLCs require only a single nonce and Contract Execution +Transactions (CETs) are claimed using a single oracle attestation. +This scheme results in DLCs which contain a unique adaptor signature for every possible outcome, which +is only feasible if the number of possible outcomes is of manageable size. If an outcome can be any of a large range of numbers, then using a simple enumeration of all possible numbers in this range is unwieldy. We optimize for this case by using numeric decomposition in which the oracle signs each digit of the outcome -individually so that many possible outcomes can be [compressed](CETCompression.md) into a single CET by ignoring certain digits. +individually so that many possible outcomes can be [compressed](NumericOutcomeCompression.md) into a single adaptor signature by ignoring certain digits. We also compress the information needed to communicate all outcomes, as this can usually be viewed as a -[payout curve](PayoutCurve.md) parameterized by only a few numbers which determine payouts for the entire possible range. +[payout curve](PayoutCurve.md) parameterized by only a few numbers which determine payouts for the entire possible domain. -Lastly, we introduce a method of deterministic rounding which allows DLC participants to increase CET -compression where they are willing to allow some additional rounding error in their payouts. +Lastly, we introduce a method of deterministic rounding which allows DLC participants to increase Numeric +outcome compression in places where they are willing to allow some additional rounding error in their payouts. -We put all of these pieces together to specify CET calculation and signature validation procedures +We put all of these pieces together to specify CET calculation, adaptor signing, and signature validation procedures for Numeric Outcome DLCs. -This specification, as well as the [payout curve](PayoutCurve.md) and [CET compression](CETCompression.md) specifications are primarily concerned +This specification, as well as the [payout curve](PayoutCurve.md) and [Numeric Outcome compression](NumericOutcomeCompression.md) specifications are primarily concerned with the protocol-level deterministic reproduction and concise communication of generic higher-level information. These documents are not likely to concern application-level and UI/UX developers, who should operate at their own levels of abstraction, only to compile application-level information into the formats specified here @@ -37,18 +37,19 @@ when interacting with lowest-level core DLC logic. * [Reference Implementations](#reference-implementations) * [Rounding Interval Serialization](#rounding-interval-serialization) -* [Contract Execution Transaction Calculation](#contract-execution-transaction-calculation) +* [Contract Execution Transaction Calculation and Signing](#contract-execution-transaction-calculation-and-signing) * [Contract Execution Transaction Signature Validation](#contract-execution-transaction-signature-validation) * [Authors](#authors) ## Rounding Intervals -As detailed in the [CET compression document](CETCompression.md#cet-compression), any time some continuous interval of the domain results in the same payout value, -we can compress the CETs required for that interval to be logarithmic in size compared to using one CET per outcome on the interval. +As detailed in the [numeric outcome compression document](NumericOutcomeCompression.md#numeric-outcome-compression), any time some continuous interval of the domain results in a constant +payout value, we can compress the adaptor signatures required for that interval to be logarithmic in size compared to using one adaptor +signature per outcome on the interval. As such, it can be beneficial to round the outputs of the payout function to allow for bounded approximation of pieces of the payout curve by constant-payout intervals. For example, if two parties are both willing to round payout values to the nearest 100 satoshis, they can have significant savings -on the number of CETs required to enforce their contract. +on the number of adaptor signatures required to enforce their contract. To this end, we allow parties to negotiate rounding intervals which may vary along the curve, allowing for less rounding near more probable outcomes and allowing for more rounding to occur near extremes. @@ -88,12 +89,12 @@ If `begin_interval_1` is strictly greater than `0`, then the interval between `0 * `begin_interval_1`, if it exists, MUST be non-negative. * `begin_interval` MUST strictly increase. -## Contract Execution Transaction Calculation +## Contract Execution Transaction Calculation and Signing Given the offerrer's [payout function](PayoutCurve.md), a `total_collateral` amount and [rounding intervals](#rounding-intervals), we wish to compute a list of pairs of digit prefixes (i.e. arrays of integers) and Satoshi values. -Each of these pairs will then be turned into a CET whose adaptor point is [computed from the digit prefix](CETCompression.md#adaptor-points-with-multiple-signatures) and whose -output values will be equal to the Satoshi payout and `total_collateral` minus that payout. +Each of these pairs will then be turned into a CET whose adaptor point used for signing is [computed from the digit prefix](NumericOutcomeCompression.md#adaptor-points-with-multiple-signatures) and +whose output values will be equal to the Satoshi payout and `total_collateral` minus that payout. We must first modify the pure function given to us (e.g. by interpolating points) by applying rounding, and then setting all negative payouts to `0` and all computed payouts above `total_collateral` to equal `total_collateral`. @@ -111,21 +112,31 @@ at the unmodified function's derivatives. Regardless of how these intervals are computed, it is required that the constant-valued intervals be as large as possible. For example, if you have two constant-valued intervals in a row with the same value, these must be merged. -Finally, once these intervals have been computed, the [CET compression](CETCompression.md#cet-compression) algorithm is run on each constant-valued interval which generates -a digit prefix (list of integers) to be paired with the (constant) payout for that interval. -For variable-payout intervals, a unique CET is constructed for every `event_outcome` where all digits of that `event_outcome` are included -in the array of integers and the Satoshi payout is equal to the output of the modified function for that `event_outcome`. +Finally, once these intervals have been computed, the [numeric outcome compression](NumericOutcomeCompression.md#numeric-outcome-compression) algorithm is run on each constant-valued interval +which generates a digit prefix (list of integers) to be paired with the (constant) payout for that interval. +Only a single CET is required for each interval (as these intervals have constant payouts) where each of them receives multiple adaptor signatures. + +For variable-payout intervals, a unique CET and adaptor signature is constructed for every `event_outcome` where all digits of that `event_outcome` +are included in the digit prefix (array of integers) and the Satoshi payout is equal to the output of the modified function for that `event_outcome`. + +The following diagram illustrates the entire process starting with the domain of all possible outcomes and the modified payout curve, then +partitioning by payout into intervals of constant value (in red), running numeric outcome compression to get digit prefixes, turning these prefixes +into adaptor points for their interval's CET and finally using those adaptor points to create adaptor signatures on their corresponding CETs. + +![CET and Adaptor Signature Construction](images/DLCCompressionWhiteBack.png) ## Contract Execution Transaction Signature Validation -To validate the adaptor signatures for CETs given in a `dlc_accept` or `dlc_sign` message, do the [process above](#contract-execution-transaction-calculation[) of computing the list of pairs of +To validate the adaptor signatures for CETs given in a `dlc_accept` or `dlc_sign` message, do the [process above](#contract-execution-transaction-calculation-and-signing) of computing the list of pairs of arrays of digits and payout values to construct the CETs and their adaptor points and then run the `adaptor_verify` function. -However, if `adaptor_verify` results in a failed validation, do not terminate the CET signing process. +However, if `adaptor_verify` results in a failed validation, do not terminate the CET signature validation process. Instead, you must look at whether you rounded up (to `value - (value % rounding_mod) + rounding_mod`) or down (to `value - (value % rounding_mod)`). -If you rounded up, compute the CET resulting from rounding down or if you rounded down, compute the CET resulting from rounding up. -Call the `adaptor_verify` function against this new CET and if it passes verification, consider that adaptor signature valid and continue. +If you rounded up, compute the CET and adaptor point resulting from rounding down or if you rounded down, compute the CET and adaptor point + resulting from rounding up. +Call the `adaptor_verify` function against this new CET with the new adaptor point and if it passes verification, consider that adaptor signature +valid and continue. This extra step is necessary because there is no way to introduce deterministic floating point computations into this specification without also introducing complexity of magnitude much larger than that of this entire specification. diff --git a/CETCompression.md b/NumericOutcomeCompression.md similarity index 78% rename from CETCompression.md rename to NumericOutcomeCompression.md index 7eddaed..d44b9d0 100644 --- a/CETCompression.md +++ b/NumericOutcomeCompression.md @@ -1,87 +1,88 @@ -# Contract Execution Transaction Compression +# Numeric Outcome Compression ## Introduction When constructing a DLC for a [numeric outcome](NumericOutcome.md), there are often an unreasonably large number of -possible outcomes to construct a unique CET for every outcome. -We remedy this fact with a CET compression mechanism specified in this document which allows -any flat portions of the DLC's [payout curve](PayoutCurve.md) to be covered with only a logarithmic number of CETs. +possible outcomes to construct a unique adaptor signature for every outcome. +We remedy this fact with a numeric outcome compression mechanism specified in this document which allows +any flat portions of the DLC's [payout curve](PayoutCurve.md) to be covered with only a logarithmic number of adaptor signatures. It is common for payout curves to have constant extremal payouts for a large number of cases representing all outcomes considered sufficiently unlikely. These intervals with constant extremal payouts are often called "collars" and these collars -can be compressed to negligible size making the remaining number of CETs proportional +can be compressed to negligible size making the remaining number of adaptor signatures proportional to the number of sufficiently likely outcomes. Furthermore, through the use of [rounding intervals](NumericOutcome.md#rounding-intervals), even portions of the payout curve which are not -completely flat can be compressed to some extent, normally causing the total number of CETs to be -divided by some power of two. +completely flat can be compressed to some extent, normally causing the total number of adaptor +signatures to be divided by some power of two. This is accomplished through the use of digit decomposition where oracles attesting to numeric outcomes sign each digit of the outcome individually. -There are as many nonces as there are possible digits required and CETs are claimed using -only some of these signatures, not necessarily all of them. +There are as many nonces as there are possible digits required and adaptor points are constructed using +only some of the corresponding attestations, not necessarily all of them. -When not all of the signatures are used, then that corresponding CET represents all events -which agree on the digits for which signatures were used and may have any value at all other -digits where signatures were ignored. +When not all of the attestations are used, then that corresponding adaptor point represents all events +which agree on the digits for which attestations are used and may have any value at all other digits +where attestations are ignored. ## Table of Contents -* [Adaptor Points with Multiple Signatures](#adaptor-points-with-multiple-signatures) -* [CET Compression](#cet-compression) +* [Adaptor Points with Multiple Attestations](#adaptor-points-with-multiple-attestations) +* [Numeric Outcome Compression](#numeric-outcome-compression) * [Concrete Example](#concrete-example) * [Abstract Example](#abstract-example) - * [Analysis of CET Compression](#analysis-of-cet-compression) - * [Counting CETs](#counting-cets) + * [Analysis of Numeric Outcome Compression](#analysis-of-numeric-outcome-compression) + * [Counting Adaptor Points](#counting-adaptor-points) * [Optimizations](#optimizations) * [Algorithms](#algorithms) * [Reference Implementations](#reference-implementations) * [Authors](#authors) -## Adaptor Points with Multiple Signatures +## Adaptor Points with Multiple Attestations -Given public key `P` and nonces `R1, ..., Rn` we can compute `n` individual signature points for +Given public key `P` and nonces `R1, ..., Rn` we can compute `n` individual adaptor points for a given event `(d1, ..., dn)` in the usual way: `si * G = Ri + H(P, Ri, di)*P`. -To compute a composite adaptor point for all events which agree on the first `m` digits, where -`m` is any positive number less than or equal to `n`, the sum of the corresponding signature +To compute an aggregate adaptor point for all events which agree on the first `m` digits, where +`m` is any positive number less than or equal to `n`, the sum of the corresponding adaptor points points is used: `s(1..m) * G = (s1 + s2 + ... + sm) * G = s1 * G + s2 * G + ... + sm * G`. -When the oracle broadcasts its `n` signatures `s1, ..., sn`, the corresponding adaptor secret can be -computed as `s(1..m) = s1 + s2 + ... + sm` which can be used to broadcast the CET. +When the oracle broadcasts its `n` attestations `s1, ..., sn`, the corresponding aggreate adaptor secret +can be computed as `s(1..m) = s1 + s2 + ... + sm` which can be used to broadcast a corresponding CET. #### Rationale -This design allows implementations to re-use all [transaction construction code](Transactions.md) without modification -because every CET needs as input exactly one adaptor point just like in the single-nonce setting. +This design allows implementations to re-use all [transaction construction](Transactions.md) and signing code without modification +as every adaptor signature needs as input exactly one adaptor point just like in the single-nonce setting. Another design that was considered was adding keys to the funding output so that parties could collaboratively construct `m` adaptor signatures and where `n` signatures are put on-chain in every CET which would reveal -all oracle signatures to both parties when a CET is published. -This design's major drawbacks is that it creates a very distinct fingerprint and makes CET fees significantly worse. +all oracle attestations to both parties when a CET is published. +This design's major drawbacks are that it creates a very distinct fingerprint and makes CET fees significantly worse. Additionally it leads to extra complexity in contract construction. This design's only benefit is that it results in simpler and slightly more informative (although larger) fraud proofs. The large multi-signature design was abandoned because the above proposal is sufficient to generate fraud proofs. -If an oracle incorrectly signs for an event, then only the sum of the digit signatures `s(1..m)` +If an oracle incorrectly attests for an event, then only the sum of the digit signatures `s(1..m)` is recoverable on-chain using the adaptor signature which was given to one's counter-party. This sum is sufficient information to determine what was signed however as one can iterate through all possible composite adaptor points until they find one whose pre-image is the signature sum found on-chain. This will determine what digits `(d1, ..., dm)` were signed and these values along with the oracle announcement and `s(1..m)` is sufficient information to generate a fraud proof in the multi-nonce setting. -## CET Compression +## Numeric Outcome Compression -Anytime there is an interval of numeric outcomes `[start, end]` (inclusive) which result in the same payouts for all parties, -then a compression function described in this section can be run to reduce the number of CETs from `O(L)` to `O(log(L))` -where `L = end - start + 1` is the length of the interval of outcomes being compressed. +Anytime there is an interval of numeric outcomes `[start, end]` (inclusive) where all outcomes result in the same +payouts for all parties, then a compression function described in this section can be run to reduce the number of +adaptor signatures needed from `O(L)` to `O(log(L))` where `L = end - start + 1` is the length of the interval +of outcomes being compressed. -Because this compression of CETs only works for intervals with constant payouts, the [CET calculation algorithm](NumericOutcome.md#contract-execution-transaction-calculation) +Because this compression of numeric outcomes only works for intervals with constant payouts, the [CET calculation algorithm](NumericOutcome.md#contract-execution-transaction-calculation-and-signing) first splits the domain into intervals of equal payout, and then applies the compression algorithm from this -document to the individual intervals, `[start, end]` where all values in each interval have some fixed payout. +document to the individual intervals, `[start, end]` where all values in each interval have some constant payout. -Most contracts are expected to be concerned with some subset of the total possible domain and every +Most contracts are expected to be primarily concerned with some subset of the total possible domain and every outcome before or after that likely subset will result in some constant maximal or minimal payout. -This means that compression will drastically reduce the number of CETs to be of the order of the size +This means that compression will drastically reduce the number of adaptor signatures to be of the order of the size of the probable domain, with further optimizations available when parties are willing to do some [rounding](NumericOutcome.md#rounding-intervals). The compression algorithm takes as input an interval `[start, end]`, a base `B`, and the number of digits @@ -115,8 +116,8 @@ To cover all cases while looking at as few digits as possible in this interval w where `_` refers to an ignored digit (an omission from the array of integers representing the digit prefix). (Recall that all of these are prefixed by `13`). -Each of these digit prefixes can be used to construct a single CET. -Thus, we are able to cover the entire interval of `2944` outcomes using only `20` CETs! +Each of these digit prefixes can be used to construct a single adaptor signature. +Thus, we are able to cover the entire interval of `2944` outcomes using only `20` adaptor signatures! Let us reconsider this example in binary (specifically the interval `[5677, 8621]`, not the original interval with the `13` prefix in base 10): The individual outliers are `5677 = 01011000101101` and `8621 = 10000110101101` with cases: @@ -137,7 +138,7 @@ The individual outliers are `5677 = 01011000101101` and `8621 = 10000110101101` 10000110101100 ``` -And so again we are able to cover the entire interval (of `2944` outcomes) using only `14` CETs this time. +And so again we are able to cover the entire interval (of `2944` outcomes) using only `14` adaptor signatures this time. ### Abstract Example @@ -164,24 +165,24 @@ WXY0, WXY1, ..., WXY(Z-1) where `_` refers to an ignored digit (an omission from the array of integers) and all of these cases have the `prefix`. -### Analysis of CET Compression +### Analysis of Numeric Outcome Compression This specification refers to the first three rows of the abstract example above as the **front groupings** the fourth row in the example as the **middle grouping** and the last three rows in the example as the **back groupings**. Notice that the patterns for the front and back groupings are nearly identical. -#### Counting CETs +#### Counting Adaptor Signatures Also note that in total the number of elements in each row of the front groupings is equal to `B-1` minus the corresponding digit. That is to say, `B-1` minus the last digit is the number of elements in the first row and then the second to last digit and so on. Likewise the number of elements in each row of the back groupings is equal to the corresponding digit. That is to say, the last digit corresponds to the last row, second to last digit is the second to last row and so on. This covers all but the first digit of both `start` and `end` (as well as the two outliers `wxyz` and `WXYZ`). -Thus the total number of CETs required to cover the interval will be equal to the sum of the unique digits of `end` except the first, -plus the sum of the unique digits of `start` except for the first subtracted from `B-1` plus the difference of the first digits plus one. +Thus the total number of adaptor signatures required to cover the interval will be equal to the sum of the unique digits of `end` except the +first, plus the sum of the unique digits of `start` except for the first subtracted from `B-1` plus the difference of the first digits plus one. -A corollary of this is that the number of CETs required to cover an interval of length `L` will be `O(B*log_B(L))` because `log_B(L)` +A corollary of this is that the number of adaptor signatures required to cover an interval of length `L` will be `O(B*log_B(L))` because `log_B(L)` corresponds to the number of unique digits between the start and end of the interval and for each unique digit a row is generated in both the front and back groupings of length at most `B-1 ` which corresponds to the coefficient in the order bound. @@ -196,16 +197,16 @@ However, a random three digit number in base 10 is expected to have a digit sum Thus we should expect base 2 to outperform base 10 by around 3x on average. This is because using binary results in a compression where each row in the diagram above has only a single element, which corresponds to binary compression's ability to efficiently reach the largest possible number of digits ignored which itself covers the largest number of cases. -Meanwhile in a base like 10, each row can take up to 9 CETs before moving to a larger number of digits ignored (and cases covered). +Meanwhile in a base like 10, each row can take up to 9 adaptor signatures before moving to a larger number of digits ignored (and cases covered). Another way to put this is that the inefficiency of base 10 which seems intuitive at small scales is actually equally present at *all scales*! One final abstract way of intuiting that base 2 is optimal is the following: -We wish to maximize the amount of information that we may ignore when constructing CETs, because abstractly every bit of information ignored -in a CET doubles the number of cases covered with a single transaction and signature. +We wish to maximize the amount of information that we may ignore when constructing adaptor signatures, because abstractly every bit of information +ignored in an adaptor signature computation doubles the number of cases covered with a single signature. Thus, if we use any base other than 2, say 10, then we will almost always run into situations where redundant information is needed because we can only ignore a decimal digit at a time where a decimal digit has 3.3 bits of information. Meanwhile in binary where every digit encodes exactly a single bit of information, we are able to perfectly ignore all redundant bits of information -resulting in some number near 3.3 times fewer CETs on average. +resulting in some number near 3.3 times fewer adaptor signatures on average. #### Optimizations @@ -241,7 +242,7 @@ In the example above, `end` ends with three nines so that the last three rows ca There is one more optimization that can potentially be made. If the unique digits of `start` are all `0` and the unique digits of `end` are all `B-1` then we will have no need for a middle grouping as we can cover -this whole interval with just a single CET of `(prefix)_..._`. +this whole interval with just a single adaptor signature of `(prefix)_..._`. This optimization is called the **total optimization**. ### Algorithms @@ -297,7 +298,7 @@ def frontGroupings( val fromFront = nonZeroDigits.init.flatMap { // Note the flatMap collapses the rows of the grouping case (lastImportantDigit, unimportantDigits) => val fixedDigits = digits.dropRight(unimportantDigits + 1) - (lastImportantDigit + 1).until(base).map { lastDigit => // Note that this range excludes lastImportantDigit and base + (lastImportantDigit + 1).until(base).map { lastDigit => // Note that this loop excludes lastImportantDigit and base fixedDigits :+ lastDigit } } @@ -307,7 +308,7 @@ def frontGroupings( } def backGroupings( - digits: Vector[Int], // The unique digits of the range's end + digits: Vector[Int], // The unique digits of the interval's end base: Int): Vector[Vector[Int]] = { val nonMaxDigits = digits.reverse.zipWithIndex.dropWhile(_._1 == base - 1) // Endpoint Optimization @@ -318,7 +319,7 @@ def backGroupings( val fromBack = nonMaxDigits.init.flatMap { // Note the flatMap collapses the rows of the grouping case (lastImportantDigit, unimportantDigits) => val fixedDigits = digits.dropRight(unimportantDigits + 1) - 0.until(lastImportantDigit).reverse.toVector.map { // Note that this range excludes lastImportantDigit + 0.until(lastImportantDigit).reverse.toVector.map { // Note that this loop excludes lastImportantDigit lastDigit => fixedDigits :+ lastDigit } @@ -329,9 +330,9 @@ def backGroupings( } def middleGrouping( - firstDigitStart: Int, // The first unique digit of the range's start - firstDigitEnd: Int): Vector[Vector[Int]] = { // The first unique digit of the range's end - (firstDigitStart + 1).until(firstDigitEnd).toVector.map { firstDigit => // Note that this range excludes firstDigitEnd + firstDigitStart: Int, // The first unique digit of the interval's start + firstDigitEnd: Int): Vector[Vector[Int]] = { // The first unique digit of the interval's end + (firstDigitStart + 1).until(firstDigitEnd).toVector.map { firstDigit => // Note that this loop excludes firstDigitEnd Vector(firstDigit) } } @@ -343,7 +344,7 @@ Finally we are able to use all of these pieces to compress an interval to an app def groupByIgnoringDigits(start: Long, end: Long, base: Int, numDigits: Int): Vector[Vector[Int]] = { val (prefixDigits, startDigits, endDigits) = separatePrefix(start, end, base, numDigits) - if (start == end) { // Special Case: Range Length 1 + if (start == end) { // Special Case: Interval Length 1 Vector(prefixDigits) } else if (startDigits.forall(_ == 0) && endDigits.forall(_ == base - 1)) { if (prefixDigits.nonEmpty) { diff --git a/images/DLCCompression.png b/images/DLCCompression.png new file mode 100644 index 0000000..4643458 Binary files /dev/null and b/images/DLCCompression.png differ diff --git a/images/DLCCompressionWhiteBack.png b/images/DLCCompressionWhiteBack.png new file mode 100644 index 0000000..d1b85a1 Binary files /dev/null and b/images/DLCCompressionWhiteBack.png differ