ghost-exodus-draft/README.md
Uncle Fatso 92a8ce4b44
update readme based on the latest code changes
Signed-off-by: Uncle Fatso <uncle.fatso@ghostchain.io>
2025-10-28 21:32:06 +03:00

188 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# EXODUS - EXchange Of Digital Uniformed Signatures
## Overview
This module optimizes a hot spot in the verification formula used for missingsigner recovery. The target expression is:
`k*P + l*Q + d*M`
which requires three scalar multiplications and two point additions. Naive ellipticcurve routines make this very gasexpensive; 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 onchain 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 highlevel inversion routines.
* Benchmark against the Jacobian implementation from the [witnet ellipticcurvesolidity 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 higherlevel approaches.
* Comparing to a wellmaintained 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.