mirror of
https://github.com/aljazceru/dlcspecs.git
synced 2026-01-30 11:14:24 +01:00
Add adaptor point computation optimizations (#154)
This commit is contained in:
committed by
GitHub
parent
4992647b2c
commit
746e50597c
@@ -35,6 +35,9 @@ where attestations are ignored.
|
||||
* [Counting Adaptor Points](#counting-adaptor-points)
|
||||
* [Optimizations](#optimizations)
|
||||
* [Algorithms](#algorithms)
|
||||
* [Adaptor Point Computation Optimizations](#adaptor-point-computation-optimizations)
|
||||
* [Pre-computing](#pre-computing)
|
||||
* [Memoization](#memoization)
|
||||
* [Reference Implementations](#reference-implementations)
|
||||
* [Authors](#authors)
|
||||
|
||||
@@ -49,6 +52,8 @@ points is used: `s(1..m) * G = (s1 + s2 + ... + sm) * G = s1 * G + s2 * G + ...
|
||||
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.
|
||||
|
||||
Note that [optimizations](#Adaptor-Point-Computation-Optimizations) can be applied when computing signature points.
|
||||
|
||||
#### Rationale
|
||||
|
||||
This design allows implementations to re-use all [transaction construction](Transactions.md) and signing code without modification
|
||||
@@ -370,6 +375,78 @@ def groupByIgnoringDigits(start: Long, end: Long, base: Int, numDigits: Int): Ve
|
||||
}
|
||||
```
|
||||
|
||||
## Adaptor Point Computation Optimizations
|
||||
|
||||
Computing a large number of adaptor points for events with outcome composed of many digits is a computationally intensive process which accounts for a significant portion of DLC setup time.
|
||||
To reduce the time and resources required, some optimizations can be applied.
|
||||
For more detailed information on these optimizations please check out [this blog post](https://medium.com/crypto-garage/optimizing-numeric-outcome-dlc-creation-6d6091ac0e47).
|
||||
|
||||
### Pre-computing
|
||||
|
||||
The first optimization is to first compute the signature points for the possible value of each digit.
|
||||
For example, for an event with outcomes decomposed in base 2 with 10 digits, first compute:
|
||||
```
|
||||
S0_0 = R0 + 0 * P
|
||||
S0_1 = R0 + 1 * P
|
||||
S1_0 = R1 + 0 * P
|
||||
S1_1 = R1 + 1 * P
|
||||
...
|
||||
S9_0 = R9 + 0 * P
|
||||
S9_1 = R9 + 1 * P
|
||||
```
|
||||
|
||||
Then compute the aggregate signature points by combining the Si_j.
|
||||
For example, to compute the signature point for the value `0 0 0 0 0 0 0 0 0 0`, compute:
|
||||
```
|
||||
S = S0_0 + S1_0 + ... + S9_0
|
||||
```
|
||||
|
||||
To compute another signature point, for example for the value `1 0 0 0 0 0 0 0 0 1`, compute:
|
||||
```
|
||||
S' = S0_1 + S1_0 + ... + S9_1
|
||||
```
|
||||
|
||||
### Memoization
|
||||
|
||||
In addition to the above pre-computation, [memoization](https://en.wikipedia.org/wiki/Memoization) can be used to further improve performance.
|
||||
Note however that if using the [secp256k1-zkp library](https://github.com/ElementsProject/secp256k1-zkp) this optimization is actually not effective as adding the points in batch using only pre-computation was found to be faster.
|
||||
|
||||
Taking as example an event with outcomes decomposed in base 2 with 10 digits, the algorithm would proceed as follow:
|
||||
1. Compute `S0_0` for the value `0`
|
||||
2. Compute `S = S0_0 + S1_0` for the value `0 0`
|
||||
3. Compute `S' = S0_0 + S1_0 + S2_0` for the value `0 0 0`
|
||||
...
|
||||
10. Compute `S'' = S0_0 + S1_0 + ... + S8_0` for the value `0 0 0 0 0 0 0 0 0`
|
||||
11. Compute `S''' = S0_0 + S1_0 + ... + S9_0` for the value `0 0 0 0 0 0 0 0 0 0`
|
||||
12. Compute `S'''' = S'' + S9_1` for the value `0 0 0 0 0 0 0 0 0 1`
|
||||
|
||||
A recursive implementation of this algorithm is given below:
|
||||
```typescript
|
||||
function computeSigPoints(
|
||||
index: number,
|
||||
prev: PublicKey | undefined,
|
||||
noncesSigPoints: PublicKey[][],
|
||||
result: PublicKey[]
|
||||
): void {
|
||||
for (let i = 0; i < noncesSigPoints.length; i++) {
|
||||
let next = undefined
|
||||
if (prev === undefined) {
|
||||
next = noncesSigPoints[0][index]
|
||||
} else {
|
||||
next = prev.combine(noncesSigPoints[index][i])
|
||||
}
|
||||
if (index < noncesSigPoints.length - 1) {
|
||||
computeSigPoints(index + 1, next, noncesSigPoints, result)
|
||||
} else {
|
||||
result.push(next)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const result: PublicKey[] = []
|
||||
computeSigPoints(0, undefined, noncesSigPoints, result)
|
||||
```
|
||||
|
||||
## Reference Implementations
|
||||
|
||||
* [bitcoin-s](https://github.com/bitcoin-s/bitcoin-s/blob/adaptor-dlc/core/src/main/scala/org/bitcoins/core/protocol/dlc/CETCalculator.scala)
|
||||
|
||||
Reference in New Issue
Block a user