gas optimization with assembly

Signed-off-by: Uncle Fatso <uncle.fatso@ghostchain.io>
This commit is contained in:
Uncle Fatso 2025-10-29 17:49:37 +03:00
parent fef183db9a
commit 4ec272ca4a
Signed by: f4ts0
GPG Key ID: 565F4F2860226EBB
2 changed files with 77 additions and 72 deletions

View File

@ -38,7 +38,7 @@ For full background and protocol details see the [project wiki](https://git.ghos
+==================================================================================================+ +==================================================================================================+
| Deployment Cost | Deployment Size | | | | | | Deployment Cost | Deployment Size | | | | |
|----------------------------------------+-----------------+---------+---------+---------+---------| |----------------------------------------+-----------------+---------+---------+---------+---------|
| 3247879 | 14807 | | | | | | 3269040 | 14905 | | | | |
|----------------------------------------+-----------------+---------+---------+---------+---------| |----------------------------------------+-----------------+---------+---------+---------+---------|
| | | | | | | | | | | | | |
|----------------------------------------+-----------------+---------+---------+---------+---------| |----------------------------------------+-----------------+---------+---------+---------+---------|
@ -54,19 +54,19 @@ For full background and protocol details see the [project wiki](https://git.ghos
|----------------------------------------+-----------------+---------+---------+---------+---------| |----------------------------------------+-----------------+---------+---------+---------+---------|
| addProjective | 1252 | 1252 | 1252 | 1252 | 44 | | addProjective | 1252 | 1252 | 1252 | 1252 | 44 |
|----------------------------------------+-----------------+---------+---------+---------+---------| |----------------------------------------+-----------------+---------+---------+---------+---------|
| doubleGhost | 732 | 732 | 732 | 732 | 45 | | doubleGhost | 699 | 699 | 699 | 699 | 45 |
|----------------------------------------+-----------------+---------+---------+---------+---------| |----------------------------------------+-----------------+---------+---------+---------+---------|
| doubleJacobian | 1101 | 1101 | 1101 | 1101 | 45 | | doubleJacobian | 1101 | 1101 | 1101 | 1101 | 45 |
|----------------------------------------+-----------------+---------+---------+---------+---------| |----------------------------------------+-----------------+---------+---------+---------+---------|
| doubleProjective | 710 | 710 | 710 | 710 | 45 | | doubleProjective | 677 | 677 | 677 | 677 | 45 |
|----------------------------------------+-----------------+---------+---------+---------+---------| |----------------------------------------+-----------------+---------+---------+---------+---------|
| isOnCurve | 335 | 335 | 335 | 335 | 306 | | isOnCurve | 296 | 296 | 296 | 296 | 306 |
|----------------------------------------+-----------------+---------+---------+---------+---------| |----------------------------------------+-----------------+---------+---------+---------+---------|
| isOnCurveGhost | 863 | 863 | 863 | 863 | 306 | | isOnCurveGhost | 824 | 824 | 824 | 824 | 306 |
|----------------------------------------+-----------------+---------+---------+---------+---------| |----------------------------------------+-----------------+---------+---------+---------+---------|
| mulPairEc | 103705 | 731500 | 1058710 | 1270392 | 44 | | mulPairEc | 103705 | 731500 | 1058710 | 1270392 | 44 |
|----------------------------------------+-----------------+---------+---------+---------+---------| |----------------------------------------+-----------------+---------+---------+---------+---------|
| mulPairGhost | 4241 | 178420 | 310213 | 337584 | 44 | | mulPairGhost | 4185 | 174517 | 303073 | 330416 | 44 |
|----------------------------------------+-----------------+---------+---------+---------+---------| |----------------------------------------+-----------------+---------+---------+---------+---------|
| mulPairProjective | 5275 | 182401 | 327577 | 361377 | 44 | | mulPairProjective | 5275 | 182401 | 327577 | 361377 | 44 |
|----------------------------------------+-----------------+---------+---------+---------+---------| |----------------------------------------+-----------------+---------+---------+---------+---------|
@ -76,7 +76,7 @@ For full background and protocol details see the [project wiki](https://git.ghos
|----------------------------------------+-----------------+---------+---------+---------+---------| |----------------------------------------+-----------------+---------+---------+---------+---------|
| mulSingleEc | 2093 | 327159 | 408874 | 600125 | 44 | | mulSingleEc | 2093 | 327159 | 408874 | 600125 | 44 |
|----------------------------------------+-----------------+---------+---------+---------+---------| |----------------------------------------+-----------------+---------+---------+---------+---------|
| mulSingleGhost | 1803 | 113386 | 148753 | 219187 | 44 | | mulSingleGhost | 1775 | 109646 | 143531 | 212019 | 44 |
|----------------------------------------+-----------------+---------+---------+---------+---------| |----------------------------------------+-----------------+---------+---------+---------+---------|
| mulSingleProjective | 1916 | 114289 | 149838 | 220860 | 44 | | mulSingleProjective | 1916 | 114289 | 149838 | 220860 | 44 |
|----------------------------------------+-----------------+---------+---------+---------+---------| |----------------------------------------+-----------------+---------+---------+---------+---------|
@ -96,23 +96,26 @@ For full background and protocol details see the [project wiki](https://git.ghos
+============================================================================================================+ +============================================================================================================+
| Deployment Cost | Deployment Size | | | | | | Deployment Cost | Deployment Size | | | | |
|-----------------------------------------------------+-----------------+--------+--------+--------+---------| |-----------------------------------------------------+-----------------+--------+--------+--------+---------|
| 1871747 | 8463 | | | | | | 1687628 | 7589 | | | | |
|-----------------------------------------------------+-----------------+--------+--------+--------+---------| |-----------------------------------------------------+-----------------+--------+--------+--------+---------|
| | | | | | | | | | | | | |
|-----------------------------------------------------+-----------------+--------+--------+--------+---------| |-----------------------------------------------------+-----------------+--------+--------+--------+---------|
| Function Name | Min | Avg | Median | Max | # Calls | | Function Name | Min | Avg | Median | Max | # Calls |
|-----------------------------------------------------+-----------------+--------+--------+--------+---------| |-----------------------------------------------------+-----------------+--------+--------+--------+---------|
| setPubkey | 111552 | 111565 | 111564 | 111576 | 9 | | setPubkey | 111516 | 111529 | 111528 | 111540 | 9 |
|-----------------------------------------------------+-----------------+--------+--------+--------+---------| |-----------------------------------------------------+-----------------+--------+--------+--------+---------|
| verify | 611046 | 680989 | 648023 | 955747 | 9 | | verify | 538818 | 609541 | 578174 | 884038 | 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: The `verify` function consumes a maximum of ~~955,747~~ 884,038 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_5_of_5_works() (gas: 735686 = $6.18) - Baseline (100%)~~
* test_verify_67_of_100() (gas: 812318 = $6.82) - 10% increase * ~~test_verify_67_of_100() (gas: 812318 = $6.82) - 10% increase~~
* test_verify_700_of_1000() (gas: 1118143 = $9.39) - 51% increase * ~~test_verify_700_of_1000() (gas: 1118143 = $9.39) - 51% increase~~
* test_verify_5_of_5_works() (gas: 663441 = $5.57) - Baseline (100%)
* test_verify_67_of_100() (gas: 740823 = $6.22) - 11% increase
* test_verify_700_of_1000() (gas: 1046398 = $8.78) - 57% increase
The gas cost scales reasonably across different numbers of signers, making the solution practical for real-world use cases. The gas cost scales reasonably across different numbers of signers, making the solution practical for real-world use cases.

View File

@ -147,18 +147,20 @@ library GhostEllipticCurves {
// Y3 = (Y^2 9bZ^2)(Y^2 + 3bZ^2) + 24bY^2Z^2, // Y3 = (Y^2 9bZ^2)(Y^2 + 3bZ^2) + 24bY^2Z^2,
// Z3 = 8Y^3Z // Z3 = 8Y^3Z
uint256 t0 = mulmod(Y, Y, P); // 1. t0 Y · Y => (Y²) assembly {
Z3 = mulmod(8, t0, P); // 2. Z3 t0 + t0 => (8Y²) let t0 := mulmod(Y, Y, P) // 1. t0 Y · Y => (Y²)
uint256 t1 = mulmod(Y, Z, P); // 3. t1 Y · Z => (YZ) Z3 := mulmod(8, t0, P) // 2. Z3 t0 + t0 => (8Y²)
uint256 t2 = mulmod(Z, Z, P); // 4. t2 Z · Z => (Z²) let t1 := mulmod(Y, Z, P) // 3. t1 Y · Z => (YZ)
t2 = mulmod(21, t2, P); // 5. t2 b3 · t2 => (3bZ²) let t2 := mulmod(Z, Z, P) // 4. t2 Z · Z => (Z²)
X3 = mulmod(t2, Z3, P); // 6. X3 t2 · Z3 => (3bZ²8Y²) t2 := mulmod(21, t2, P) // 5. t2 b3 · t2 => (3bZ²)
Y3 = addmod(t0, t2, P); // 7. Y3 t0 + t2 => (Y² + 3bZ²) X3 := mulmod(t2, Z3, P) // 6. X3 t2 · Z3 => (3bZ²8Y²)
Z3 = mulmod(t1, Z3, P); // 8. Z3 t1 · Z3 => (YZ · 8Y² = 8Y³Z) Y3 := addmod(t0, t2, P) // 7. Y3 t0 + t2 => (Y² + 3bZ²)
t1 = addmod(t0, P - mulmod(3, t2, P), P); // 9. t1 t0 - (3 · t2) => (Y² - 9bZ²) Z3 := mulmod(t1, Z3, P) // 8. Z3 t1 · Z3 => (YZ · 8Y² = 8Y³Z)
Y3 = addmod(X3, mulmod(t1, Y3, P), P); // 10. Y3 t1 · (t1 · Y3) => ((Y² - 9bZ²) · (Y² + 3bZ²)) t1 := addmod(t0, sub(P, mulmod(3, t2, P)), P) // 9. t1 t0 - (3 · t2) => (Y² - 9bZ²)
X3 = mulmod(t1, mulmod(X, Y, P), P); // 11. X3 t1 · (X1 · Y1) => ((Y² - 9bZ²) · XY) Y3 := addmod(X3, mulmod(t1, Y3, P), P) // 10. Y3 t1 · (t1 · Y3) => ((Y² - 9bZ²) · (Y² + 3bZ²))
X3 = addmod(X3, X3, P); // 12. X3 X3 + X3 => ((Y² - 9bZ²) · 2XY) X3 := mulmod(t1, mulmod(X, Y, P), P) // 11. X3 t1 · (X1 · Y1) => ((Y² - 9bZ²) · XY)
X3 := addmod(X3, X3, P) // 12. X3 X3 + X3 => ((Y² - 9bZ²) · 2XY
}
} }
function projectiveAddMixed( function projectiveAddMixed(
@ -252,31 +254,28 @@ library GhostEllipticCurves {
Z3 = addmod(Z3, t0, P); // 33. Z3 Z3 + t0 => (Y1·Z2+Y2·Z1)·(Y1·Y2+3·b·Z1·Z2) + 3·X1·X2·(X1·Y2+X2·Y1) Z3 = addmod(Z3, t0, P); // 33. Z3 Z3 + t0 => (Y1·Z2+Y2·Z1)·(Y1·Y2+3·b·Z1·Z2) + 3·X1·X2·(X1·Y2+X2·Y1)
} }
function isOnCurve(uint256 x, uint256 y) internal pure returns (bool) { function isOnCurve(uint256 x, uint256 y) internal pure returns (bool result) {
uint lhs = mulmod(y, y, P); // y^2 assembly {
uint rhs = mulmod(mulmod(x, x, P), x, P); // x^3 let lhs := mulmod(y, y, P)
rhs = addmod(rhs, B, P); // x^3 + 7 let rhs := mulmod(mulmod(x, x, P), x, P)
return lhs == rhs; rhs := addmod(rhs, B, P)
result := eq(lhs, rhs)
}
} }
function toAffine( function toAffine(
uint256 x, uint256 x,
uint256 y, uint256 y,
uint256 z uint256 z
) internal pure returns (uint256, uint256) { ) internal pure returns (uint256 x_, uint256 y_) {
uint256 t0 = modInverse(z);
x = mulmod(x, t0, P);
y = mulmod(y, t0, P);
return (x, y);
}
function modInverse(uint256 r1) internal pure returns (uint256 t0) {
// Extended Euclidean algorithm (iterative, assembly) // Extended Euclidean algorithm (iterative, assembly)
// Typically lower average gas than the modexp precompile for single inversions, // Typically lower average gas than the modexp precompile for single inversions,
// but execution time (and gas) depends on input values not constant-time. // but execution time (and gas) depends on input values not constant-time.
assembly { assembly {
let t0 := 0
let t1 := 1 let t1 := 1
let r0 := P let r0 := P
let r1 := z
for {} r1 {} { for {} r1 {} {
let q := div(r0, r1) let q := div(r0, r1)
@ -295,6 +294,9 @@ library GhostEllipticCurves {
if slt(t0, 0) { if slt(t0, 0) {
t0 := add(t0, P) t0 := add(t0, P)
} }
x_ := mulmod(x, t0, P)
y_ := mulmod(y, t0, P)
} }
} }
} }