188 lines
13 KiB
Markdown
188 lines
13 KiB
Markdown
# EXODUS - EXchange Of Digital Uniformed Signatures
|
||
|
||
## Overview
|
||
|
||
This module optimizes a hot spot in the verification formula used for missing‑signer recovery. The target expression is:
|
||
|
||
`k*P + l*Q + d*M`
|
||
|
||
which requires three scalar multiplications and two point additions. Naive elliptic‑curve routines make this very gas‑expensive; this work reduces cost while maintaining correctness.
|
||
|
||
For full background and protocol details see the [project wiki](https://git.ghostchain.io/ghostchain/ghost-exodus-draft/wiki/Description).
|
||
|
||
## Goals
|
||
|
||
* Reduce gas for the targeted combination of scalar multiplications and additions.
|
||
* Keep implementation compact and auditable for on‑chain use.
|
||
* Maintain correctness and safety for cryptographic operations.
|
||
|
||
## Design choices
|
||
|
||
* Use Projective coordinates (not Jacobian) to cut down on the number of `mulmod`/`addmod` operations where possible while retaining simple formulas for point addition and doubling.
|
||
* Perform the final conversion to affine coordinates with an optimized `Extended Euclidean Algorithm` implemented in inline assembly to reduce gas compared with high‑level inversion routines.
|
||
* Benchmark against the Jacobian implementation from the [witnet elliptic‑curve‑solidity project](https://github.com/witnet/elliptic-curve-solidity) as a reference.
|
||
|
||
## Rationale
|
||
|
||
* Projective coordinates: fewer modular multiplications in the common path, making point operations cheaper on average.
|
||
* Assembly `Extended Euclidean Algorithm` for inversion: this algorithm in optimized inline assembly typically yields lower gas for single inversions compared with repeated `mulmod` exponentiation or other higher‑level approaches.
|
||
* Comparing to a well‑maintained Jacobian implementation gives a meaningful baseline for gas and correctness.
|
||
|
||
## Gas Usage
|
||
|
||
`Jacobian` is the original implementation used as a reference implementation, while `Projective` is optimized one.
|
||
|
||
```bash
|
||
╭----------------------------------------+-----------------+---------+---------+---------+---------╮
|
||
| src/MathTester.sol:MathTester Contract | | | | | |
|
||
+==================================================================================================+
|
||
| Deployment Cost | Deployment Size | | | | |
|
||
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
||
| 3247879 | 14807 | | | | |
|
||
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
||
| | | | | | |
|
||
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
||
| Function Name | Min | Avg | Median | Max | # Calls |
|
||
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
||
| addGhost | 1450 | 1450 | 1450 | 1450 | 44 |
|
||
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
||
| addJacobian | 1976 | 1976 | 1976 | 1976 | 88 |
|
||
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
||
| addMixedGhost | 1084 | 1084 | 1084 | 1084 | 44 |
|
||
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
||
| addMixedProjective | 1098 | 1098 | 1098 | 1098 | 44 |
|
||
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
||
| addProjective | 1252 | 1252 | 1252 | 1252 | 44 |
|
||
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
||
| doubleGhost | 732 | 732 | 732 | 732 | 45 |
|
||
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
||
| doubleJacobian | 1101 | 1101 | 1101 | 1101 | 45 |
|
||
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
||
| doubleProjective | 710 | 710 | 710 | 710 | 45 |
|
||
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
||
| isOnCurve | 335 | 335 | 335 | 335 | 306 |
|
||
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
||
| isOnCurveGhost | 863 | 863 | 863 | 863 | 306 |
|
||
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
||
| mulPairEc | 103705 | 731500 | 1058710 | 1270392 | 44 |
|
||
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
||
| mulPairGhost | 4241 | 178420 | 310213 | 337584 | 44 |
|
||
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
||
| mulPairProjective | 5275 | 182401 | 327577 | 361377 | 44 |
|
||
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
||
| mulQuartetEc | 308036 | 1561245 | 1982575 | 2672715 | 42 |
|
||
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
||
| mulQuartetProjective | 12468 | 206689 | 346026 | 396570 | 42 |
|
||
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
||
| mulSingleEc | 2093 | 327159 | 408874 | 600125 | 44 |
|
||
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
||
| mulSingleGhost | 1803 | 113386 | 148753 | 219187 | 44 |
|
||
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
||
| mulSingleProjective | 1916 | 114289 | 149838 | 220860 | 44 |
|
||
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
||
| mulTripletEc | 205416 | 1140277 | 1546137 | 1958683 | 43 |
|
||
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
||
| mulTripletProjective | 6636 | 199868 | 346618 | 397506 | 43 |
|
||
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
||
| toAffineGhost | 11853 | 13845 | 13925 | 15527 | 176 |
|
||
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
||
| toAffineJacobian | 40395 | 47860 | 47979 | 53983 | 133 |
|
||
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
||
| toAffineProjective | 11165 | 13918 | 13900 | 16214 | 351 |
|
||
╰----------------------------------------+-----------------+---------+---------+---------+---------╯
|
||
|
||
╭-----------------------------------------------------+-----------------+--------+--------+--------+---------╮
|
||
| test/GhostVerifier.t.sol:GhostVerifierImpl Contract | | | | | |
|
||
+============================================================================================================+
|
||
| Deployment Cost | Deployment Size | | | | |
|
||
|-----------------------------------------------------+-----------------+--------+--------+--------+---------|
|
||
| 1871747 | 8463 | | | | |
|
||
|-----------------------------------------------------+-----------------+--------+--------+--------+---------|
|
||
| | | | | | |
|
||
|-----------------------------------------------------+-----------------+--------+--------+--------+---------|
|
||
| Function Name | Min | Avg | Median | Max | # Calls |
|
||
|-----------------------------------------------------+-----------------+--------+--------+--------+---------|
|
||
| setPubkey | 111552 | 111565 | 111564 | 111576 | 9 |
|
||
|-----------------------------------------------------+-----------------+--------+--------+--------+---------|
|
||
| verify | 611046 | 680989 | 648023 | 955747 | 9 |
|
||
╰-----------------------------------------------------+-----------------+--------+--------+--------+---------╯
|
||
```
|
||
|
||
The `verify` function consumes a maximum of 955,747 gas units when processing 1,000 signers with 300 missing signatures. Assuming an ETH price of $4,200 and gas cost of 2 gwei:
|
||
|
||
* test_verify_5_of_5_works() (gas: 735686 = $6.18) - Baseline (100%)
|
||
* test_verify_67_of_100() (gas: 812318 = $6.82) - 10% increase
|
||
* test_verify_700_of_1000() (gas: 1118143 = $9.39) - 51% increase
|
||
|
||
The gas cost scales reasonably across different numbers of signers, making the solution practical for real-world use cases.
|
||
|
||
### Compiler Inconsistency Note
|
||
|
||
We observed unexpected behavior in the Solidity compiler. Despite identical code in `ECMathProjective` and `GhostEllipticCurves` libraries, gas costs vary for critical elliptic curve operations:
|
||
|
||
* `doubleProjective` and `addProjective` show inconsistent gas costs between implementations
|
||
* `mulSingleGhost` unexpectedly consumes less gas than `mulSingleProjective`
|
||
|
||
These variations occur even with clean compilation runs, suggesting compiler-level optimizations that behave unpredictably with identical code in different library contexts. The root cause remains unclear.
|
||
|
||
## Implementation Details
|
||
|
||
Final implementation formula is:
|
||
|
||
```
|
||
s*G + sum_i^n (e*ai*(Pi) + b*R1m + d*R2m) = R + e*Hagg
|
||
s*G + sum_i^n (e*ai*(Pi)) + sum_i^n (b*R1m) + sum_i^n (b*R2m) = b*R1 + d*R2 + e*Hagg
|
||
s*G + e*(Hagg - sum_i^n Hi) = b*(R1 - sum_i^n R1m) + d*(R2 - sum_i^n R2m)
|
||
s*G + e*(Hagg - sum_i^n Hi) = b*R1e + d*R2e
|
||
|
||
where
|
||
R1 = R1e + R1m (existing nonce + missing nonce)
|
||
R2 = R2e + R2m
|
||
Hi = ai*Pi
|
||
```
|
||
|
||
### Nonce Abuse
|
||
|
||
Our approach enables any participant to submit pairs of (`R1e`, `R1m`) and (`R2e`, `R2m`), which we use to reconstruct the original nonces `R1` and `R2`. These reconstructed values are essential for computing `b` and `d` during the verification process, ultimately deriving the final `R` required for commitment `e`.
|
||
|
||
This design leverages circular dependencies and cryptographic hash functions to ensure verification integrity.
|
||
|
||
```
|
||
arbitrary data: s, msg, R1e, R1m, R2e, R2m
|
||
s*G + e*H` = b*R1e + d*R2e
|
||
s*G = b*R1e + d*R2e - e*H`
|
||
s*G = target_value (Discrete Log Problem)
|
||
```
|
||
|
||
However, the hash dependencies create a circular constraint similar to the "chicken and egg" problem:
|
||
|
||
```
|
||
b = sha256(R1e + R1m, R2e + R2m, H, msg)
|
||
d = sha256(msg, H, R2e + R2m, R1e + R1m)
|
||
e = sha256(b*(R1e+R1m) + d*(R2e+R2m), H, msg)
|
||
|
||
b*R1e + d*R2e - s*G = e*H`
|
||
```
|
||
|
||
For now it looks safe if `sha256` or `keccak256` hashing algorithm is used.
|
||
|
||
### Missing Aggregation Abuse
|
||
|
||
We are proposing the to store not only final `Hagg` point but the hash of all signers (both coordinates for each) in the sequence that they were aggregated. Thus each `verify` call will have all list of `Xi=ai*Pi` with indexes of missing signers. Here we are relying on fact that `sha256` and `keccak256` do not have any known ability to find collisions and resistant to preimage attack.
|
||
|
||
We propose storing not only the final aggregated point `Hagg` but also the cryptographic hash of all signers' coordinates in their aggregation sequence. This approach ensures each verify call has access to the complete list of `Xi = ai * Pi` along with indexes of missing signers.
|
||
|
||
This design relies on the cryptographic security of `sha256` and `keccak256`, both of which:
|
||
|
||
* Have no known practical collision attacks
|
||
* Maintain strong resistance to preimage attacks
|
||
* Provide robust security guarantees for our verification process
|
||
|
||
### Precompile Abuse
|
||
|
||
The step by step hack is described [here](https://git.ghostchain.io/ghostchain/ghost-exodus-draft/wiki/Description#abuse-of-ecrecover-precompile).
|
||
|
||
## Contributing
|
||
|
||
All contributions are welcome — whether it's code, documentation, tests, performance benchmarks, or review. Please submit commits, issues, or pull requests; any help to improve correctness, security, or gas efficiency is greatly appreciated.
|