Skip to content

Commit e7d3e5c

Browse files
eigenmikemypatil12
authored andcommitted
refactor: sig verification into library (#1455)
**Motivation:** *Explain here the context, and why you're making that change. What is the problem you're trying to solve.* **Modifications:** *Describe the modifications you've done.* **Result:** *After your change, what will change.*
1 parent ea5b65a commit e7d3e5c

File tree

4 files changed

+109
-81
lines changed

4 files changed

+109
-81
lines changed
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// SPDX-License-Identifier: BUSL-1.1
2+
pragma solidity ^0.8.27;
3+
4+
import {BN254} from "./BN254.sol";
5+
6+
/**
7+
* @title BN254SignatureVerifier
8+
* @notice Library for BN254 signature verification
9+
* @dev Provides unified signature verification with consistent gamma calculation and hash-to-G1 conversion
10+
*/
11+
library BN254SignatureVerifier {
12+
using BN254 for BN254.G1Point;
13+
14+
/**
15+
* @notice Core BN254 signature verification function with optional gas limiting
16+
* @param msgHash The message hash that was signed
17+
* @param signature The BLS signature to verify (G1 point)
18+
* @param pubkeyG1 The G1 component of the public key
19+
* @param pubkeyG2 The G2 component of the public key
20+
* @param useGasLimit Whether to use gas-limited safe pairing
21+
* @param pairingGas Gas limit for pairing (ignored if useGasLimit is false)
22+
* @return success True if verification succeeded (always true if useGasLimit=false due to revert)
23+
* @return pairingSuccessful True if pairing operation completed (only relevant when useGasLimit=true)
24+
*/
25+
function verifySignature(
26+
bytes32 msgHash,
27+
BN254.G1Point memory signature,
28+
BN254.G1Point memory pubkeyG1,
29+
BN254.G2Point memory pubkeyG2,
30+
bool useGasLimit,
31+
uint256 pairingGas
32+
) internal view returns (bool success, bool pairingSuccessful) {
33+
BN254.G1Point memory messagePoint = BN254.hashToG1(msgHash);
34+
uint256 gamma = _calculateGamma(msgHash, pubkeyG1, pubkeyG2, signature);
35+
36+
// Calculate pairing inputs
37+
BN254.G1Point memory leftG1 = signature.plus(pubkeyG1.scalar_mul(gamma));
38+
BN254.G1Point memory rightG1 = messagePoint.plus(BN254.generatorG1().scalar_mul(gamma));
39+
40+
if (useGasLimit) {
41+
// Use safe pairing with gas limit
42+
(pairingSuccessful, success) =
43+
BN254.safePairing(leftG1, BN254.negGeneratorG2(), rightG1, pubkeyG2, pairingGas);
44+
} else {
45+
success = BN254.pairing(leftG1, BN254.negGeneratorG2(), rightG1, pubkeyG2);
46+
if (success) {
47+
pairingSuccessful = true;
48+
}
49+
}
50+
}
51+
52+
/**
53+
* @notice Internal function to calculate gamma value for signature verification
54+
* @param msgHash The message hash
55+
* @param pubkeyG1 The G1 component of the public key
56+
* @param pubkeyG2 The G2 component of the public key
57+
* @param signature The signature point
58+
* @return gamma The calculated gamma value
59+
*/
60+
function _calculateGamma(
61+
bytes32 msgHash,
62+
BN254.G1Point memory pubkeyG1,
63+
BN254.G2Point memory pubkeyG2,
64+
BN254.G1Point memory signature
65+
) internal pure returns (uint256 gamma) {
66+
gamma = uint256(
67+
keccak256(
68+
abi.encodePacked(
69+
msgHash,
70+
pubkeyG1.X,
71+
pubkeyG1.Y,
72+
pubkeyG2.X[0],
73+
pubkeyG2.X[1],
74+
pubkeyG2.Y[0],
75+
pubkeyG2.Y[1],
76+
signature.X,
77+
signature.Y
78+
)
79+
)
80+
) % BN254.FR_MODULUS;
81+
}
82+
}

src/contracts/multichain/BN254CertificateVerifier.sol

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ pragma solidity ^0.8.27;
44
import "@openzeppelin-upgrades/contracts/proxy/utils/Initializable.sol";
55

66
import {BN254} from "../libraries/BN254.sol";
7+
import {BN254SignatureVerifier} from "../libraries/BN254SignatureVerifier.sol";
78
import {Merkle} from "../libraries/Merkle.sol";
89
import {OperatorSet} from "../libraries/OperatorSetLib.sol";
910

@@ -162,27 +163,12 @@ contract BN254CertificateVerifier is Initializable, BN254CertificateVerifierStor
162163
BN254.G2Point memory apkG2,
163164
BN254.G1Point memory signature
164165
) internal view returns (bool pairingSuccessful, bool signatureValid) {
165-
uint256 gamma = uint256(
166-
keccak256(
167-
abi.encodePacked(
168-
msgHash,
169-
aggPubkey.X,
170-
aggPubkey.Y,
171-
apkG2.X[0],
172-
apkG2.X[1],
173-
apkG2.Y[0],
174-
apkG2.Y[1],
175-
signature.X,
176-
signature.Y
177-
)
178-
)
179-
) % BN254.FR_MODULUS;
180-
181-
(pairingSuccessful, signatureValid) = BN254.safePairing(
182-
signature.plus(aggPubkey.scalar_mul(gamma)), // sigma + apk*gamma
183-
BN254.negGeneratorG2(), // -G2
184-
BN254.hashToG1(msgHash).plus(BN254.generatorG1().scalar_mul(gamma)), // H(m) + g1*gamma
185-
apkG2, // apkG2
166+
return BN254SignatureVerifier.verifySignature(
167+
msgHash,
168+
signature,
169+
aggPubkey,
170+
apkG2,
171+
true, // use gas limit
186172
PAIRING_EQUALITY_CHECK_GAS
187173
);
188174
}

src/contracts/permissions/KeyRegistrar.sol

Lines changed: 9 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ pragma solidity ^0.8.27;
44
import "@openzeppelin-upgrades/contracts/proxy/utils/Initializable.sol";
55
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
66
import "../libraries/BN254.sol";
7+
import "../libraries/BN254SignatureVerifier.sol";
78
import "../mixins/PermissionControllerMixin.sol";
89
import "../mixins/SignatureUtilsMixin.sol";
910
import "../interfaces/IPermissionController.sol";
@@ -193,9 +194,14 @@ contract KeyRegistrar is KeyRegistrarStorage, PermissionControllerMixin, Signatu
193194
);
194195
bytes32 signableDigest = _calculateSignableDigest(structHash);
195196

196-
// hash to g1
197-
BN254.G1Point memory messagePoint = BN254.hashToG1(signableDigest);
198-
_verifyBN254Signature(messagePoint, signature, g1Point, g2Point);
197+
// Decode signature from bytes to G1 point
198+
(uint256 sigX, uint256 sigY) = abi.decode(signature, (uint256, uint256));
199+
BN254.G1Point memory signaturePoint = BN254.G1Point(sigX, sigY);
200+
201+
// Verify signature
202+
(, bool pairingSuccessful) =
203+
BN254SignatureVerifier.verifySignature(signableDigest, signaturePoint, g1Point, g2Point, false, 0);
204+
require(pairingSuccessful, InvalidSignature());
199205

200206
// Calculate key hash and check global uniqueness
201207
bytes32 keyHash = _getKeyHashForKeyData(keyData, CurveType.BN254);
@@ -242,56 +248,6 @@ contract KeyRegistrar is KeyRegistrarStorage, PermissionControllerMixin, Signatu
242248
revert InvalidCurveType();
243249
}
244250

245-
/**
246-
* @notice Verifies a BN254 signature
247-
* @param messagePoint The G1 point representing the hashed message
248-
* @param signature The signature bytes
249-
* @param pubkeyG1 The G1 component of the public key
250-
* @param pubkeyG2 The G2 component of the public key
251-
*/
252-
function _verifyBN254Signature(
253-
BN254.G1Point memory messagePoint,
254-
bytes memory signature,
255-
BN254.G1Point memory pubkeyG1,
256-
BN254.G2Point memory pubkeyG2
257-
) public view {
258-
// Decode signature
259-
BN254.G1Point memory sigPoint;
260-
{
261-
(uint256 sigX, uint256 sigY) = abi.decode(signature, (uint256, uint256));
262-
sigPoint = BN254.G1Point(sigX, sigY);
263-
}
264-
265-
// gamma = h(sigma, P, P', H(m)) - exact same pattern as BLSApkRegistry
266-
uint256 gamma = uint256(
267-
keccak256(
268-
abi.encodePacked(
269-
sigPoint.X,
270-
sigPoint.Y,
271-
pubkeyG1.X,
272-
pubkeyG1.Y,
273-
pubkeyG2.X[0],
274-
pubkeyG2.X[1],
275-
pubkeyG2.Y[0],
276-
pubkeyG2.Y[1],
277-
messagePoint.X,
278-
messagePoint.Y
279-
)
280-
)
281-
) % BN254.FR_MODULUS;
282-
283-
// e(sigma + P * gamma, [1]_2) = e(H(m) + [1]_1 * gamma, P')
284-
require(
285-
BN254.pairing(
286-
sigPoint.plus(pubkeyG1.scalar_mul(gamma)),
287-
BN254.negGeneratorG2(),
288-
messagePoint.plus(BN254.generatorG1().scalar_mul(gamma)),
289-
pubkeyG2
290-
),
291-
InvalidSignature()
292-
);
293-
}
294-
295251
/**
296252
*
297253
* VIEW FUNCTIONS

src/test/unit/KeyRegistrarUnit.t.sol

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import "forge-std/Test.sol";
77
import "src/contracts/permissions/KeyRegistrar.sol";
88
import "src/contracts/interfaces/IKeyRegistrar.sol";
99
import "src/contracts/libraries/BN254.sol";
10+
import "src/contracts/libraries/BN254SignatureVerifier.sol";
1011
import "src/contracts/interfaces/IPermissionController.sol";
1112
import "src/contracts/mixins/PermissionControllerMixin.sol";
1213
import "src/test/utils/EigenLayerUnitTestSetup.sol";
@@ -663,20 +664,23 @@ contract KeyRegistrarUnitTests is EigenLayerUnitTestSetup {
663664

664665
// Generate signature with private key
665666
BN254.G1Point memory msgPoint = BN254.hashToG1(messageHash);
666-
BN254.G1Point memory signature = msgPoint.scalar_mul(bn254PrivKey1);
667-
bytes memory signatureBytes = abi.encode(signature.X, signature.Y);
667+
BN254.G1Point memory signature = msgPoint.scalar_mul(bn254PrivKey2);
668668

669-
// Should not revert for valid signature
670-
keyRegistrar._verifyBN254Signature(msgPoint, signatureBytes, bn254G1Key1, bn254G2Key1);
669+
(bool success, bool pairingSuccessful) =
670+
BN254SignatureVerifier.verifySignature(messageHash, signature, bn254G1Key2, bn254G2Key2, false, 0);
671+
assertTrue(success && pairingSuccessful);
671672
}
672673

673674
function testVerifyBN254Signature_RevertInvalid() public {
674675
bytes32 messageHash = keccak256("test message");
675-
bytes memory invalidSignature = abi.encode(uint(1), uint(2));
676+
677+
// Use a signature generated with the wrong private key - this should fail verification
676678
BN254.G1Point memory msgPoint = BN254.hashToG1(messageHash);
679+
BN254.G1Point memory invalidSignature = msgPoint.scalar_mul(bn254PrivKey1); // Wrong private key
677680

678-
vm.expectRevert(ISignatureUtilsMixinErrors.InvalidSignature.selector);
679-
keyRegistrar._verifyBN254Signature(msgPoint, invalidSignature, bn254G1Key1, bn254G2Key1);
681+
(bool success, bool pairingSuccessful) =
682+
BN254SignatureVerifier.verifySignature(messageHash, invalidSignature, bn254G1Key2, bn254G2Key2, false, 0);
683+
assertFalse(success && pairingSuccessful);
680684
}
681685

682686
function testRegisterBN254Key_RevertGloballyRegistered() public {

0 commit comments

Comments
 (0)