Skip to content

Instantly share code, notes, and snippets.

@RobinLinus
Last active March 14, 2022 23:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RobinLinus/7af908dafbed6319da251c90f0733a5b to your computer and use it in GitHub Desktop.
Save RobinLinus/7af908dafbed6319da251c90f0733a5b to your computer and use it in GitHub Desktop.
Succinct order relations for DLCs

Order Relations for DLCs

We expect an oracle will publish some number 𝑁 by signing each of its n bits.

Given a constant c, we want to express the spending condition 𝑁 ≥ c in a single adaptor point.

The key idea is to construct an OR operator for adaptor points. This is possible with verifiable encryption. An OR operator allows to condense complex spending conditions into a single point. This prevents the combinatorical explosions that usually occure when using multi-oracles. An OR operator makes spending conditions easily composable. In theory, it even enables arbitrary computations.

Number Format

We define B₁ to Bₙ to represent the adaptor points for oracle signatures of those bits of 𝑁 that are equal to 1:

B₁ → "bit 1 is 1"
B₂ → "bit 2 is 1"
B₃ → "bit 3 is 1"
...
Bₙ → "bit n is 1"

For example, if 𝑁 = 9 = 0b00001001 then the oracle will publish the dlogs of B₁ and B₄ because only bit 1 and bit 4 are signed to be 1. All other bits are 0. This bitwise encoding of 𝑁 is helpful to implement our order relation.

Greater Than

Let's say c = 19 = 0b00010001. We use multiple combinations of points Bᵢ to express all potential values of 𝑁 that are greater than c:

T₁ = B₅ + B₁   →   "N is 00010001 or even more bits are 1"
T₂ = B₅ + B₂   →   "N is 00010010 or even more bits are 1"
T₃ = B₅ + B₃   →   "N is 00010100 or even more bits are 1"
T₄ = B₅ + B₄   →   "N is 00011000 or even more bits are 1"
T₅ = B₆        →   "N is 00100000 or even more bits are 1"
T₆ = B₇        →   "N is 01000000 or even more bits are 1"
T₇ = B₈        →   "N is 10000000 or even more bits are 1"

If you learn the dlog of T₁, or T₂, ..., or T₇, then that implies the oracle signed a 𝑁 ≥ c.

Alice and Bob can use these points in 2-of-2 adaptor signatures with public key tweaking such that only a single single-sig transaction hits the chain. For every point Tᵢ Alice signs an adaptor signature for transaction m:

sᵢ' = rᵢ + H(Rᵢ+Tᵢ|P|m) * x

This ensures, if Bob learns any Tᵢ he can complete one of Alice's signatures for the transaction.

In general, to express "greater than" for n-bit numbers, users have to compute about n adaptor points Tᵢ. (Exactly one adaptor point for each zero bit + one point for the number itself.)

Sidenote: The "less than" relation, 𝑁 ≤ c, can be expressed simply by applying the same algorithm to the zero bits instead of the ones.

Condensed Adaptor Points

Our order relation would be much more handy if we could condense the n many points into a single one. In other words, we'd like to have a logical OR operator for adaptor points:

If Alice learns the dlog of T₁, or T₂, ..., or Tₙ, then she also learns the dlog of Q.

This is equivalent to "If 𝑁 ≥ c then Alice learns the dlog of Q". Alice and Bob can agree on such a Q by using verifiable encryption as described here.

  1. Bob chooses a random secret q and sends the corresponding point Q=qG to Alice.
  2. For each Tᵢ:
    1. Bob encrypts q using Tᵢ as public key. He sends the ciphertext to Alice.
    2. Bob also proves that the ciphertext is indeed the dlog of q encrypted with Tᵢ.
  3. Alice verifies the proofs for all ciphertexts to ensure she learns q if he learns the dlog of any Tᵢ.

This condenses all points Tᵢ into a single point Q.

Multi-Oracles

Alice and Bob usually want to use multiple oracles to minimise trust. For each oracleᵢ they compute a condensed point Qᵢ representing "Oracleᵢ signed 𝑁 ≥ c".

Sums of such points, e.g. Qᵢ + Qⱼ + Qₖ, represent that those oracles all agree on 𝑁 ≥ c.

We can form a non-interactive t-of-n threshold point by enumerating all t-of-t subsets. For example, for a 2-of-3 we compute all sums of 2 oracles:

U₁ = Q₁ + Q₂
U₂ = Q₁ + Q₃
U₃ = Q₂ + Q₃

Again, we can condense the points U₁, U₂, U₃ to encode every possible outcome of the multi-oracle in a single point.

A 6-of-10 oracle requires to compute 210 points Uᵢ for all combinations. That is still practical. Unfortunately, enumerating subsets doesn't scale much beyond that. However, for much larger thresholds we could split the oracles up into smaller threshold groups and then condense their points to recursively combine them into one larger threshold group.

Now, we can encode large multi-oracles in a single adaptor point.

Boolean Functions

Suppose our oracle signs only two bits. As shown below, we can construct a NAND gate from the four adaptor points. NAND is a universal gate and thus, DLCs can compute any Boolean function. Furthermore, it is possible to perform complex computations efficiently by condensing the adaptor points recursively - as described above. Thus, we can express payment conditions that perform arbitrary computations on oracle values.

For example, oracle1 signs the BTC/USD price and oracle2 signs USD/EUR. Using those values a DLC can compute a price for BTC/EUR.

NAND Gate

Our oracle signs two bits: bit "A" and bit "B". So, we have 4 adaptor points A0, A1 and B0, B1. We can express a NAND like:

C₁ = A0 + B0   →  "result is 1" 
C₂ = A0 + B1   →  "result is 1"    
C₃ = A1 + B0   →  "result is 1" 
C₄ = A1 + B1   →  "result is 0" 

We map the two possible outcomes 0 and 1 to two points D0 and D1:

D0 = C₄                    →  "result is 0"
D1 = condense(C₁, C₂, C₃)  →  "result is 1"

This gives us composable NAND gates. They can express any Boolean function in a DLC.

A somewhat crazy idea is to use bitcoin as time oracle and validate a block header in a DLC.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment