Compare commits
No commits in common. "4ec272ca4a8bd8a3d4791ef3ae8183cf481f5765" and "92a8ce4b440c2059ae7feed6ab59a742cb197da7" have entirely different histories.
4ec272ca4a
...
92a8ce4b44
31
README.md
31
README.md
@ -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 | | | | |
|
||||||
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
||||||
| 3269040 | 14905 | | | | |
|
| 3247879 | 14807 | | | | |
|
||||||
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
||||||
| | | | | | |
|
| | | | | | |
|
||||||
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
||||||
@ -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 | 699 | 699 | 699 | 699 | 45 |
|
| doubleGhost | 732 | 732 | 732 | 732 | 45 |
|
||||||
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
||||||
| doubleJacobian | 1101 | 1101 | 1101 | 1101 | 45 |
|
| doubleJacobian | 1101 | 1101 | 1101 | 1101 | 45 |
|
||||||
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
||||||
| doubleProjective | 677 | 677 | 677 | 677 | 45 |
|
| doubleProjective | 710 | 710 | 710 | 710 | 45 |
|
||||||
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
||||||
| isOnCurve | 296 | 296 | 296 | 296 | 306 |
|
| isOnCurve | 335 | 335 | 335 | 335 | 306 |
|
||||||
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
||||||
| isOnCurveGhost | 824 | 824 | 824 | 824 | 306 |
|
| isOnCurveGhost | 863 | 863 | 863 | 863 | 306 |
|
||||||
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
||||||
| mulPairEc | 103705 | 731500 | 1058710 | 1270392 | 44 |
|
| mulPairEc | 103705 | 731500 | 1058710 | 1270392 | 44 |
|
||||||
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
||||||
| mulPairGhost | 4185 | 174517 | 303073 | 330416 | 44 |
|
| mulPairGhost | 4241 | 178420 | 310213 | 337584 | 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 | 1775 | 109646 | 143531 | 212019 | 44 |
|
| mulSingleGhost | 1803 | 113386 | 148753 | 219187 | 44 |
|
||||||
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
||||||
| mulSingleProjective | 1916 | 114289 | 149838 | 220860 | 44 |
|
| mulSingleProjective | 1916 | 114289 | 149838 | 220860 | 44 |
|
||||||
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
|----------------------------------------+-----------------+---------+---------+---------+---------|
|
||||||
@ -96,26 +96,23 @@ For full background and protocol details see the [project wiki](https://git.ghos
|
|||||||
+============================================================================================================+
|
+============================================================================================================+
|
||||||
| Deployment Cost | Deployment Size | | | | |
|
| Deployment Cost | Deployment Size | | | | |
|
||||||
|-----------------------------------------------------+-----------------+--------+--------+--------+---------|
|
|-----------------------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
| 1687628 | 7589 | | | | |
|
| 1871747 | 8463 | | | | |
|
||||||
|-----------------------------------------------------+-----------------+--------+--------+--------+---------|
|
|-----------------------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
| | | | | | |
|
| | | | | | |
|
||||||
|-----------------------------------------------------+-----------------+--------+--------+--------+---------|
|
|-----------------------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
| Function Name | Min | Avg | Median | Max | # Calls |
|
| Function Name | Min | Avg | Median | Max | # Calls |
|
||||||
|-----------------------------------------------------+-----------------+--------+--------+--------+---------|
|
|-----------------------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
| setPubkey | 111516 | 111529 | 111528 | 111540 | 9 |
|
| setPubkey | 111552 | 111565 | 111564 | 111576 | 9 |
|
||||||
|-----------------------------------------------------+-----------------+--------+--------+--------+---------|
|
|-----------------------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
| verify | 538818 | 609541 | 578174 | 884038 | 9 |
|
| verify | 611046 | 680989 | 648023 | 955747 | 9 |
|
||||||
╰-----------------------------------------------------+-----------------+--------+--------+--------+---------╯
|
╰-----------------------------------------------------+-----------------+--------+--------+--------+---------╯
|
||||||
```
|
```
|
||||||
|
|
||||||
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:
|
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_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.
|
||||||
|
|
||||||
|
|||||||
@ -27,8 +27,6 @@ abstract contract GhostVerifier {
|
|||||||
bytes calldata proof,
|
bytes calldata proof,
|
||||||
bytes calldata missedIndexes
|
bytes calldata missedIndexes
|
||||||
) internal view returns (uint256 res) {
|
) internal view returns (uint256 res) {
|
||||||
require(s < GhostEllipticCurves.N); // scalar check
|
|
||||||
|
|
||||||
uint256 px = pubkeyX;
|
uint256 px = pubkeyX;
|
||||||
uint256 py = pubkeyY;
|
uint256 py = pubkeyY;
|
||||||
uint256 e;
|
uint256 e;
|
||||||
@ -36,22 +34,21 @@ abstract contract GhostVerifier {
|
|||||||
uint256 ry;
|
uint256 ry;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
uint256[] memory rNonces = new uint256[](4);
|
||||||
uint256[] memory coefficients = new uint256[](2);
|
uint256[] memory coefficients = new uint256[](2);
|
||||||
|
|
||||||
{
|
_reconstructNonces(rNonces, nonces);
|
||||||
uint256[] memory rNonces = new uint256[](4);
|
_computeCoefficients(px, m, rNonces, coefficients);
|
||||||
_reconstructNonces(rNonces, nonces);
|
|
||||||
_computeCoefficients(px, m, rNonces, coefficients);
|
|
||||||
(rx, ry) = _aggregateNonce(rNonces, coefficients);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
(rx, ry) = _aggregateNonce(rNonces, coefficients);
|
||||||
e = _computeChallenge(bytes32(rx), bytes32(px), m);
|
e = _computeChallenge(bytes32(rx), bytes32(px), m);
|
||||||
require(e < GhostEllipticCurves.N); // scalar check
|
|
||||||
(rx, ry) = _restoreAdaptiveNonce(nonces, coefficients);
|
(rx, ry) = _restoreAdaptiveNonce(nonces, coefficients);
|
||||||
}
|
}
|
||||||
|
|
||||||
require(signersHash == sha256(proof)); // check proof correctness
|
{
|
||||||
(px, py) = _aggregatePubkey(px, py, proof, missedIndexes);
|
require(signersHash == sha256(proof)); // check proof correctness
|
||||||
|
(px, py) = _aggregatePubkey(px, py, proof, missedIndexes);
|
||||||
|
}
|
||||||
|
|
||||||
unchecked {
|
unchecked {
|
||||||
s = GhostEllipticCurves.N - mulmod(s, px, GhostEllipticCurves.N);
|
s = GhostEllipticCurves.N - mulmod(s, px, GhostEllipticCurves.N);
|
||||||
@ -151,6 +148,81 @@ abstract contract GhostVerifier {
|
|||||||
return (r1x, r1y);
|
return (r1x, r1y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _computeAggregationCoefficients(
|
||||||
|
uint16 length,
|
||||||
|
bytes32[] memory ais,
|
||||||
|
bytes calldata proof
|
||||||
|
) internal pure {
|
||||||
|
uint16 i = length;
|
||||||
|
for (; i > 0;) {
|
||||||
|
unchecked { --i; }
|
||||||
|
|
||||||
|
uint256 pix;
|
||||||
|
uint16 l;
|
||||||
|
uint16 r;
|
||||||
|
|
||||||
|
assembly {
|
||||||
|
let base := add(proof.offset, mul(i, 128))
|
||||||
|
pix := calldataload(base)
|
||||||
|
|
||||||
|
l := add(shl(1, i), 1)
|
||||||
|
r := add(l, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
ais[i] = bytes32(_computeCoefficientKeyAgg(
|
||||||
|
l < length ? ais[l] : bytes32(0x0),
|
||||||
|
r < length ? ais[r] : bytes32(0x0),
|
||||||
|
bytes32(pix)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _checkAggregationCorrectness(
|
||||||
|
uint256 xx, uint256 yy, uint256 ai,
|
||||||
|
bytes calldata proof
|
||||||
|
) internal pure returns (uint256 res) {
|
||||||
|
uint256 px;
|
||||||
|
uint256 py;
|
||||||
|
uint256 pz;
|
||||||
|
|
||||||
|
uint16 i;
|
||||||
|
for (; i < 3;) {
|
||||||
|
uint256 x;
|
||||||
|
uint256 y;
|
||||||
|
|
||||||
|
assembly {
|
||||||
|
let base := add(proof.offset, mul(i, 128))
|
||||||
|
let j := mul(gt(i, 0), 64)
|
||||||
|
x := calldataload(add(base, j))
|
||||||
|
y := calldataload(add(base, add(32, j)))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
(px, py, pz) = GhostEllipticCurves.mulAddAffineSingle(x, y, ai);
|
||||||
|
} else {
|
||||||
|
(px, py, pz) = GhostEllipticCurves.projectiveAddMixed(px, py, pz, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
unchecked { ++i; }
|
||||||
|
}
|
||||||
|
|
||||||
|
(px, py) = GhostEllipticCurves.toAffine(px, py, pz);
|
||||||
|
uint256 hix;
|
||||||
|
assembly {
|
||||||
|
let base := proof.offset
|
||||||
|
hix := calldataload(add(base, 64))
|
||||||
|
let hiy := calldataload(add(base, 96))
|
||||||
|
|
||||||
|
if iszero(and(eq(xx, px), eq(xx, hix))) {
|
||||||
|
revert(0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
if iszero(and(eq(yy, py), eq(yy, hiy))) {
|
||||||
|
revert(0, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function _aggregatePubkey(
|
function _aggregatePubkey(
|
||||||
uint256 px, uint256 py,
|
uint256 px, uint256 py,
|
||||||
bytes calldata proof,
|
bytes calldata proof,
|
||||||
|
|||||||
@ -147,20 +147,18 @@ 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
|
||||||
|
|
||||||
assembly {
|
uint256 t0 = mulmod(Y, Y, P); // 1. t0 ← Y · Y => (Y²)
|
||||||
let t0 := mulmod(Y, Y, P) // 1. t0 ← Y · Y => (Y²)
|
Z3 = mulmod(8, t0, P); // 2. Z3 ← t0 + t0 => (8Y²)
|
||||||
Z3 := mulmod(8, t0, P) // 2. Z3 ← t0 + t0 => (8Y²)
|
uint256 t1 = mulmod(Y, Z, P); // 3. t1 ← Y · Z => (YZ)
|
||||||
let t1 := mulmod(Y, Z, P) // 3. t1 ← Y · Z => (YZ)
|
uint256 t2 = mulmod(Z, Z, P); // 4. t2 ← Z · Z => (Z²)
|
||||||
let t2 := mulmod(Z, Z, P) // 4. t2 ← Z · Z => (Z²)
|
t2 = mulmod(21, t2, P); // 5. t2 ← b3 · t2 => (3bZ²)
|
||||||
t2 := mulmod(21, t2, P) // 5. t2 ← b3 · t2 => (3bZ²)
|
X3 = mulmod(t2, Z3, P); // 6. X3 ← t2 · Z3 => (3bZ²8Y²)
|
||||||
X3 := mulmod(t2, Z3, P) // 6. X3 ← t2 · Z3 => (3bZ²8Y²)
|
Y3 = addmod(t0, t2, P); // 7. Y3 ← t0 + t2 => (Y² + 3bZ²)
|
||||||
Y3 := addmod(t0, t2, P) // 7. Y3 ← t0 + t2 => (Y² + 3bZ²)
|
Z3 = mulmod(t1, Z3, P); // 8. Z3 ← t1 · Z3 => (YZ · 8Y² = 8Y³Z)
|
||||||
Z3 := mulmod(t1, Z3, P) // 8. Z3 ← t1 · Z3 => (YZ · 8Y² = 8Y³Z)
|
t1 = addmod(t0, P - mulmod(3, t2, P), P); // 9. t1 ← t0 - (3 · t2) => (Y² - 9bZ²)
|
||||||
t1 := addmod(t0, sub(P, mulmod(3, t2, P)), P) // 9. t1 ← t0 - (3 · t2) => (Y² - 9bZ²)
|
Y3 = addmod(X3, mulmod(t1, Y3, P), P); // 10. Y3 ← t1 · (t1 · Y3) => ((Y² - 9bZ²) · (Y² + 3bZ²))
|
||||||
Y3 := addmod(X3, mulmod(t1, Y3, P), P) // 10. Y3 ← t1 · (t1 · Y3) => ((Y² - 9bZ²) · (Y² + 3bZ²))
|
X3 = mulmod(t1, mulmod(X, Y, P), P); // 11. X3 ← t1 · (X1 · Y1) => ((Y² - 9bZ²) · XY)
|
||||||
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)
|
||||||
X3 := addmod(X3, X3, P) // 12. X3 ← X3 + X3 => ((Y² - 9bZ²) · 2XY
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function projectiveAddMixed(
|
function projectiveAddMixed(
|
||||||
@ -219,63 +217,66 @@ library GhostEllipticCurves {
|
|||||||
// Y3 = (Y1Y2 + 3bZ1Z2)(Y1Y2 − 3bZ1Z2) + 9bX1X2(X1Z2 + X2Z1),
|
// Y3 = (Y1Y2 + 3bZ1Z2)(Y1Y2 − 3bZ1Z2) + 9bX1X2(X1Z2 + X2Z1),
|
||||||
// Z3 = (Y1Z2 + Y2Z1)(Y1Y2 + 3bZ1Z2) + 3X1X2(X1Y2 + X2Y1),
|
// Z3 = (Y1Z2 + Y2Z1)(Y1Y2 + 3bZ1Z2) + 3X1X2(X1Y2 + X2Y1),
|
||||||
|
|
||||||
uint256 t0 = mulmod(X1, X2, P); // 1. t0 ← X1 · X2 => (X1·X2)
|
uint256 t0 = mulmod(X1, X2, P); // 1. t0 ← X1 · X2 => (X1·X2)
|
||||||
uint256 t1 = mulmod(Y1, Y2, P); // 2. t1 ← Y1 · Y2 => (Y1·Y2)
|
uint256 t1 = mulmod(Y1, Y2, P); // 2. t1 ← Y1 · Y2 => (Y1·Y2)
|
||||||
uint256 t2 = mulmod(Z1, Z2, P); // 3. t2 ← Z1 · Z2 => (Z1·Z2)
|
uint256 t2 = mulmod(Z1, Z2, P); // 3. t2 ← Z1 · Z2 => (Z1·Z2)
|
||||||
uint256 t3 = addmod(X1, Y1, P); // 4. t3 ← X1 + Y1 => (X1 + Y1)
|
uint256 t3 = addmod(X1, Y1, P); // 4. t3 ← X1 + Y1 => (X1 + Y1)
|
||||||
uint256 t4 = addmod(X2, Y2, P); // 5. t4 ← X2 + Y2 => (X2 + Y2)
|
uint256 t4 = addmod(X2, Y2, P); // 5. t4 ← X2 + Y2 => (X2 + Y2)
|
||||||
t3 = mulmod(t3, t4, P); // 6. t3 ← t3 · t4 => ((X1 + Y1) · (X2 + Y2))
|
t3 = mulmod(t3, t4, P); // 6. t3 ← t3 · t4 => ((X1 + Y1) · (X2 + Y2))
|
||||||
t4 = addmod(t0, t1, P); // 7. t4 ← t0 + t1 => (X1·X2 + Y1·Y2)
|
t4 = addmod(t0, t1, P); // 7. t4 ← t0 + t1 => (X1·X2 + Y1·Y2)
|
||||||
t3 = addmod(t3, P - t4, P); // 8. t3 ← t3 - t4 => ((X1 + Y1)·(X2 + Y2) - X1·X2 - Y1·Y2)
|
t3 = addmod(t3, P - t4, P); // 8. t3 ← t3 - t4 => ((X1 + Y1)·(X2 + Y2) - X1·X2 - Y1·Y2)
|
||||||
t4 = addmod(Y1, Z1, P); // 9. t4 ← Y1 + Z1 => (Y1 + Z1)
|
t4 = addmod(Y1, Z1, P); // 9. t4 ← Y1 + Z1 => (Y1 + Z1)
|
||||||
X3 = addmod(Y2, Z2, P); // 10. X3 ← Y2 + Z2 => (Y2 + Z2)
|
X3 = addmod(Y2, Z2, P); // 10. X3 ← Y2 + Z2 => (Y2 + Z2)
|
||||||
t4 = mulmod(t4, X3, P); // 11. t4 ← t4 · X3 => ((Y1 + Z1) · (Y2 + Z2))
|
t4 = mulmod(t4, X3, P); // 11. t4 ← t4 · X3 => ((Y1 + Z1) · (Y2 + Z2))
|
||||||
X3 = addmod(t1, t2, P); // 12. X3 ← t1 + t2 => (Y1·Y2 + Z1·Z2)
|
X3 = addmod(t1, t2, P); // 12. X3 ← t1 + t2 => (Y1·Y2 + Z1·Z2)
|
||||||
t4 = addmod(t4, P - X3, P); // 13. t4 ← t4 - X3 => ((Y1 + Z1)·(Y2 + Z2) - Y1·Y2 - Z1·Z2)
|
t4 = addmod(t4, P - X3, P); // 13. t4 ← t4 - X3 => ((Y1 + Z1)·(Y2 + Z2) - Y1·Y2 - Z1·Z2)
|
||||||
X3 = addmod(X1, Z1, P); // 14. X3 ← X1 + Z1 => (X1 + Z1)
|
X3 = addmod(X1, Z1, P); // 14. X3 ← X1 + Z1 => (X1 + Z1)
|
||||||
Y3 = addmod(X2, Z2, P); // 15. Y3 ← X2 + Z2 => (X2 + Z2)
|
Y3 = addmod(X2, Z2, P); // 15. Y3 ← X2 + Z2 => (X2 + Z2)
|
||||||
X3 = mulmod(X3, Y3, P); // 16. X3 ← X3 · Y3 => ((X1 + Z1) · (X2 + Z2))
|
X3 = mulmod(X3, Y3, P); // 16. X3 ← X3 · Y3 => ((X1 + Z1) · (X2 + Z2))
|
||||||
Y3 = addmod(t0, t2, P); // 17. Y3 ← t0 + t2 => (X1·X2 + Z1·Z2)
|
Y3 = addmod(t0, t2, P); // 17. Y3 ← t0 + t2 => (X1·X2 + Z1·Z2)
|
||||||
Y3 = addmod(X3, P - Y3, P); // 18. Y3 ← X3 - Y3 => ((X1 + Z1)·(X2 + Z2) - X1·X2 - Z1·Z2)
|
Y3 = addmod(X3, P - Y3, P); // 18. Y3 ← X3 - Y3 => ((X1 + Z1)·(X2 + Z2) - X1·X2 - Z1·Z2)
|
||||||
X3 = addmod(t0, t0, P); // 19. X3 ← t0 + t0 => (2·X1·X2)
|
X3 = addmod(t0, t0, P); // 19. X3 ← t0 + t0 => (2·X1·X2)
|
||||||
t0 = addmod(X3, t0, P); // 20. t0 ← X3 + t0 => (3·X1·X2)
|
t0 = addmod(X3, t0, P); // 20. t0 ← X3 + t0 => (3·X1·X2)
|
||||||
t2 = mulmod(21, t2, P); // 21. t2 ← B3 · t2 => 3b · Z1·Z2
|
t2 = mulmod(21, t2, P); // 21. t2 ← B3 · t2 => 3b · Z1·Z2
|
||||||
Z3 = addmod(t1, t2, P); // 22. Z3 ← t1 + t2 => Y1·Y2 + 3·b·Z1·Z2
|
Z3 = addmod(t1, t2, P); // 22. Z3 ← t1 + t2 => Y1·Y2 + 3·b·Z1·Z2
|
||||||
t1 = addmod(t1, P - t2, P); // 23. t1 ← t1 - t2 => Y1·Y2 - 3·b·Z1·Z2
|
t1 = addmod(t1, P - t2, P); // 23. t1 ← t1 - t2 => Y1·Y2 - 3·b·Z1·Z2
|
||||||
Y3 = mulmod(21, Y3, P); // 24. Y3 ← B3 · Y3 => 3b · ((X1+Z1)(X2+Z2) - X1·X2 - Z1·Z2)
|
Y3 = mulmod(21, Y3, P); // 24. Y3 ← B3 · Y3 => 3b · ((X1+Z1)(X2+Z2) - X1·X2 - Z1·Z2)
|
||||||
X3 = mulmod(t4, Y3, P); // 25. X3 ← t4 · Y3 => 3b·((Y1+Z1)(Y2+Z2)-Y1·Y2-Z1·Z2) · ((X1+Z1)(X2+Z2)-X1·X2-Z1·Z2)
|
X3 = mulmod(t4, Y3, P); // 25. X3 ← t4 · Y3 => 3b·((Y1+Z1)(Y2+Z2)-Y1·Y2-Z1·Z2) · ((X1+Z1)(X2+Z2)-X1·X2-Z1·Z2)
|
||||||
t2 = mulmod(t3, t1, P); // 26. t2 ← t3 · t1 => ((X1+Y1)(X2+Y2)-X1·X2-Y1·Y2) · (Y1·Y2 - 3·b·Z1·Z2)
|
t2 = mulmod(t3, t1, P); // 26. t2 ← t3 · t1 => ((X1+Y1)(X2+Y2)-X1·X2-Y1·Y2) · (Y1·Y2 - 3·b·Z1·Z2)
|
||||||
X3 = addmod(t2, P - X3, P); // 27. X3 ← t2 - X3 => (X1Y2+X2Y1)(Y1·Y2-3·b·Z1·Z2) - 3b(Y1·Z2+Y2·Z1)(X1·Z2+X2·Z1)
|
X3 = addmod(t2, P - X3, P); // 27. X3 ← t2 - X3 => (X1Y2+X2Y1)(Y1·Y2-3·b·Z1·Z2) - 3b(Y1·Z2+Y2·Z1)(X1·Z2+X2·Z1)
|
||||||
Y3 = mulmod(Y3, t0, P); // 28. Y3 ← Y3 · t0 => 3·b·((X1+Z1)(X2+Z2) - X1·X2 - Z1·Z2) · 3·X1·X2 = 9·b·X1·X2·(X1·Z2+X2·Z1)
|
Y3 = mulmod(Y3, t0, P); // 28. Y3 ← Y3 · t0 => 3·b·((X1+Z1)(X2+Z2) - X1·X2 - Z1·Z2) · 3·X1·X2 = 9·b·X1·X2·(X1·Z2+X2·Z1)
|
||||||
t1 = mulmod(t1, Z3, P); // 29. t1 ← t1 · Z3 => (Y1·Y2-3·b·Z1·Z2) · (Y1·Y2+3·b·Z1·Z2)
|
t1 = mulmod(t1, Z3, P); // 29. t1 ← t1 · Z3 => (Y1·Y2-3·b·Z1·Z2) · (Y1·Y2+3·b·Z1·Z2)
|
||||||
Y3 = addmod(t1, Y3, P); // 30. Y3 ← t1 + Y3 => (Y1Y2+3·b·Z1·Z2)(Y1·Y2-3·b·Z1·Z2) + 9b·X1·X2·(X1·Z2+X2·Z1)
|
Y3 = addmod(t1, Y3, P); // 30. Y3 ← t1 + Y3 => (Y1Y2+3·b·Z1·Z2)(Y1·Y2-3·b·Z1·Z2) + 9b·X1·X2·(X1·Z2+X2·Z1)
|
||||||
t0 = mulmod(t0, t3, P); // 31. t0 ← t0 · t3 => (3·X1·X2) · ((X1+Y1)(X2+Y2)-X1·X2-Y1·Y2)
|
t0 = mulmod(t0, t3, P); // 31. t0 ← t0 · t3 => (3·X1·X2) · ((X1+Y1)(X2+Y2)-X1·X2-Y1·Y2)
|
||||||
Z3 = mulmod(Z3, t4, P); // 32. Z3 ← Z3 · t4 => (Y1·Y2+3·b·Z1·Z2) · ((Y1+Z1)(Y2+Z2)-Y1·Y2-Z1·Z2)
|
Z3 = mulmod(Z3, t4, P); // 32. Z3 ← Z3 · t4 => (Y1·Y2+3·b·Z1·Z2) · ((Y1+Z1)(Y2+Z2)-Y1·Y2-Z1·Z2)
|
||||||
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 result) {
|
function isOnCurve(uint256 x, uint256 y) internal pure returns (bool) {
|
||||||
assembly {
|
uint lhs = mulmod(y, y, P); // y^2
|
||||||
let lhs := mulmod(y, y, P)
|
uint rhs = mulmod(mulmod(x, x, P), x, P); // x^3
|
||||||
let rhs := mulmod(mulmod(x, x, P), x, P)
|
rhs = addmod(rhs, B, P); // x^3 + 7
|
||||||
rhs := addmod(rhs, B, P)
|
return lhs == rhs;
|
||||||
result := eq(lhs, rhs)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function toAffine(
|
function toAffine(
|
||||||
uint256 x,
|
uint256 x,
|
||||||
uint256 y,
|
uint256 y,
|
||||||
uint256 z
|
uint256 z
|
||||||
) internal pure returns (uint256 x_, uint256 y_) {
|
) internal pure returns (uint256, uint256) {
|
||||||
|
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)
|
||||||
@ -294,9 +295,6 @@ 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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user