Skip to content

Commit f0e8889

Browse files
committed
refactor: separate BLSSignatureChecker storage
1 parent 5fd87d1 commit f0e8889

File tree

6 files changed

+137
-110
lines changed

6 files changed

+137
-110
lines changed

src/BLSApkRegistryStorage.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ abstract contract BLSApkRegistryStorage is Initializable, IBLSApkRegistry {
2323

2424
/// @inheritdoc IBLSApkRegistry
2525
mapping(bytes32 pubkeyHash => address operator) public pubkeyHashToOperator;
26-
26+
2727
/// @inheritdoc IBLSApkRegistry
2828
mapping(address operator => BN254.G1Point pubkeyG1) public operatorToPubkey;
2929

src/BLSSignatureChecker.sol

Lines changed: 13 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,91 +1,45 @@
11
// SPDX-License-Identifier: BUSL-1.1
22
pragma solidity ^0.8.27;
33

4-
import {IBLSSignatureChecker} from "./interfaces/IBLSSignatureChecker.sol";
5-
import {IRegistryCoordinator} from "./interfaces/IRegistryCoordinator.sol";
6-
import {IBLSApkRegistry} from "./interfaces/IBLSApkRegistry.sol";
7-
import {IStakeRegistry, IDelegationManager} from "./interfaces/IStakeRegistry.sol";
8-
94
import {BitmapUtils} from "./libraries/BitmapUtils.sol";
105
import {BN254} from "./libraries/BN254.sol";
116

7+
import "./BLSSignatureCheckerStorage.sol";
8+
129
/**
1310
* @title Used for checking BLS aggregate signatures from the operators of a `BLSRegistry`.
1411
* @author Layr Labs, Inc.
1512
* @notice Terms of Service: https://docs.eigenlayer.xyz/overview/terms-of-service
1613
* @notice This is the contract for checking the validity of aggregate operator signatures.
1714
*/
18-
contract BLSSignatureChecker is IBLSSignatureChecker {
15+
contract BLSSignatureChecker is BLSSignatureCheckerStorage {
1916
using BN254 for BN254.G1Point;
2017

21-
// CONSTANTS & IMMUTABLES
22-
23-
// gas cost of multiplying 2 pairings
24-
uint256 internal constant PAIRING_EQUALITY_CHECK_GAS = 120_000;
25-
26-
IRegistryCoordinator public immutable registryCoordinator;
27-
IStakeRegistry public immutable stakeRegistry;
28-
IBLSApkRegistry public immutable blsApkRegistry;
29-
IDelegationManager public immutable delegation;
30-
/// @notice If true, check the staleness of the operator stakes and that its within the delegation withdrawalDelayBlocks window.
31-
bool public staleStakesForbidden;
18+
/// MODIFIERS
3219

3320
modifier onlyCoordinatorOwner() {
3421
require(msg.sender == registryCoordinator.owner(), OnlyRegistryCoordinatorOwner());
3522
_;
3623
}
3724

25+
/// CONSTRUCTION
26+
3827
constructor(
3928
IRegistryCoordinator _registryCoordinator
40-
) {
41-
registryCoordinator = _registryCoordinator;
42-
stakeRegistry = _registryCoordinator.stakeRegistry();
43-
blsApkRegistry = _registryCoordinator.blsApkRegistry();
44-
delegation = stakeRegistry.delegation();
45-
}
29+
) BLSSignatureCheckerStorage(_registryCoordinator) {}
30+
31+
/// ACTIONS
4632

47-
/**
48-
* /**
49-
* RegistryCoordinator owner can either enforce or not that operator stakes are staler
50-
* than the delegation.minWithdrawalDelayBlocks() window.
51-
* @param value to toggle staleStakesForbidden
52-
*/
33+
/// @inheritdoc IBLSSignatureChecker
5334
function setStaleStakesForbidden(
5435
bool value
5536
) external onlyCoordinatorOwner {
5637
_setStaleStakesForbidden(value);
5738
}
5839

59-
struct NonSignerInfo {
60-
uint256[] quorumBitmaps;
61-
bytes32[] pubkeyHashes;
62-
}
40+
/// VIEW
6341

64-
/**
65-
* @notice This function is called by disperser when it has aggregated all the signatures of the operators
66-
* that are part of the quorum for a particular taskNumber and is asserting them into onchain. The function
67-
* checks that the claim for aggregated signatures are valid.
68-
*
69-
* The thesis of this procedure entails:
70-
* - getting the aggregated pubkey of all registered nodes at the time of pre-commit by the
71-
* disperser (represented by apk in the parameters),
72-
* - subtracting the pubkeys of all the signers not in the quorum (nonSignerPubkeys) and storing
73-
* the output in apk to get aggregated pubkey of all operators that are part of quorum.
74-
* - use this aggregated pubkey to verify the aggregated signature under BLS scheme.
75-
*
76-
* @dev Before signature verification, the function verifies operator stake information. This includes ensuring that the provided `referenceBlockNumber`
77-
* is correct, i.e., ensure that the stake returned from the specified block number is recent enough and that the stake is either the most recent update
78-
* for the total stake (of the operator) or latest before the referenceBlockNumber.
79-
* @param msgHash is the hash being signed
80-
* @dev NOTE: Be careful to ensure `msgHash` is collision-resistant! This method does not hash
81-
* `msgHash` in any way, so if an attacker is able to pass in an arbitrary value, they may be able
82-
* to tamper with signature verification.
83-
* @param quorumNumbers is the bytes array of quorum numbers that are being signed for
84-
* @param referenceBlockNumber is the block number at which the stake information is being verified
85-
* @param params is the struct containing information on nonsigners, stakes, quorum apks, and the aggregate signature
86-
* @return quorumStakeTotals is the struct containing the total and signed stake for each quorum
87-
* @return signatoryRecordHash is the hash of the signatory record, which is used for fraud proofs
88-
*/
42+
/// @inheritdoc IBLSSignatureChecker
8943
function checkSignatures(
9044
bytes32 msgHash,
9145
bytes calldata quorumNumbers,
@@ -253,15 +207,7 @@ contract BLSSignatureChecker is IBLSSignatureChecker {
253207
return (stakeTotals, signatoryRecordHash);
254208
}
255209

256-
/**
257-
* trySignatureAndApkVerification verifies a BLS aggregate signature and the veracity of a calculated G1 Public key
258-
* @param msgHash is the hash being signed
259-
* @param apk is the claimed G1 public key
260-
* @param apkG2 is provided G2 public key
261-
* @param sigma is the G1 point signature
262-
* @return pairingSuccessful is true if the pairing precompile call was successful
263-
* @return siganatureIsValid is true if the signature is valid
264-
*/
210+
/// @inheritdoc IBLSSignatureChecker
265211
function trySignatureAndApkVerification(
266212
bytes32 msgHash,
267213
BN254.G1Point memory apk,
@@ -300,8 +246,4 @@ contract BLSSignatureChecker is IBLSSignatureChecker {
300246
staleStakesForbidden = value;
301247
emit StaleStakesForbiddenUpdate(value);
302248
}
303-
304-
// storage gap for upgradeability
305-
// slither-disable-next-line shadowing-state
306-
uint256[49] private __GAP;
307249
}

src/BLSSignatureCheckerStorage.sol

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// SPDX-License-Identifier: BUSL-1.1
2+
pragma solidity ^0.8.27;
3+
4+
import {IBLSSignatureChecker} from "./interfaces/IBLSSignatureChecker.sol";
5+
import {IRegistryCoordinator} from "./interfaces/IRegistryCoordinator.sol";
6+
import {IBLSApkRegistry} from "./interfaces/IBLSApkRegistry.sol";
7+
import {IStakeRegistry, IDelegationManager} from "./interfaces/IStakeRegistry.sol";
8+
9+
abstract contract BLSSignatureCheckerStorage is IBLSSignatureChecker {
10+
/// @dev Returns the assumed gas cost of multiplying 2 pairings.
11+
uint256 internal constant PAIRING_EQUALITY_CHECK_GAS = 120_000;
12+
13+
/// @inheritdoc IBLSSignatureChecker
14+
IRegistryCoordinator public immutable registryCoordinator;
15+
/// @inheritdoc IBLSSignatureChecker
16+
IStakeRegistry public immutable stakeRegistry;
17+
/// @inheritdoc IBLSSignatureChecker
18+
IBLSApkRegistry public immutable blsApkRegistry;
19+
/// @inheritdoc IBLSSignatureChecker
20+
IDelegationManager public immutable delegation;
21+
22+
/// STATE
23+
24+
/// @inheritdoc IBLSSignatureChecker
25+
bool public staleStakesForbidden;
26+
27+
constructor(
28+
IRegistryCoordinator _registryCoordinator
29+
) {
30+
registryCoordinator = _registryCoordinator;
31+
stakeRegistry = _registryCoordinator.stakeRegistry();
32+
blsApkRegistry = _registryCoordinator.blsApkRegistry();
33+
delegation = stakeRegistry.delegation();
34+
}
35+
36+
// slither-disable-next-line shadowing-state
37+
uint256[49] private __GAP;
38+
}

src/interfaces/IBLSApkRegistry.sol

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,16 @@ interface IBLSApkRegistry is IRegistry, IBLSApkRegistryErrors, IBLSApkRegistryEv
8484
/// @notice Maps `operator` to their BLS public key hash (`operatorId`).
8585
/// @param operator The address of the operator.
8686
/// @return operatorId The hash of the operator's BLS public key.
87-
function operatorToPubkeyHash(address operator) external view returns (bytes32 operatorId);
87+
function operatorToPubkeyHash(
88+
address operator
89+
) external view returns (bytes32 operatorId);
8890

8991
/// @notice Maps `pubkeyHash` to their corresponding `operator` address.
9092
/// @param pubkeyHash The hash of a BLS public key.
9193
/// @return operator The address of the operator who registered this public key.
92-
function pubkeyHashToOperator(bytes32 pubkeyHash) external view returns (address operator);
94+
function pubkeyHashToOperator(
95+
bytes32 pubkeyHash
96+
) external view returns (address operator);
9397

9498
/// @notice Maps `operator` to their BLS public key in G1.
9599
/// @dev Returns a non-encoded BN254.G1Point.

src/interfaces/IBLSSignatureChecker.sol

Lines changed: 75 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -31,25 +31,41 @@ interface IBLSSignatureCheckerErrors {
3131
}
3232

3333
interface IBLSSignatureCheckerTypes {
34+
/// @notice Contains bitmap and pubkey hash information for non-signing operators.
35+
/// @param quorumBitmaps Array of bitmaps indicating which quorums each non-signer was registered for.
36+
/// @param pubkeyHashes Array of BLS public key hashes for each non-signer.
37+
struct NonSignerInfo {
38+
uint256[] quorumBitmaps;
39+
bytes32[] pubkeyHashes;
40+
}
41+
42+
/// @notice Contains non-signer information and aggregated signature data for BLS verification.
43+
/// @param nonSignerQuorumBitmapIndices The indices of all non-signer quorum bitmaps.
44+
/// @param nonSignerPubkeys The G1 public keys of all non-signers.
45+
/// @param quorumApks The aggregate G1 public key of each quorum.
46+
/// @param apkG2 The aggregate G2 public key of all signers.
47+
/// @param sigma The aggregate G1 signature of all signers.
48+
/// @param quorumApkIndices The indices of each quorum's aggregate public key in the APK registry.
49+
/// @param totalStakeIndices The indices of each quorum's total stake in the stake registry.
50+
/// @param nonSignerStakeIndices The indices of each non-signer's stake within each quorum.
51+
/// @dev Used as input to checkSignatures() to verify BLS signatures.
3452
struct NonSignerStakesAndSignature {
35-
uint32[] nonSignerQuorumBitmapIndices; // is the indices of all nonsigner quorum bitmaps
36-
BN254.G1Point[] nonSignerPubkeys; // is the G1 pubkeys of all nonsigners
37-
BN254.G1Point[] quorumApks; // is the aggregate G1 pubkey of each quorum
38-
BN254.G2Point apkG2; // is the aggregate G2 pubkey of all signers
39-
BN254.G1Point sigma; // is the aggregate G1 signature of all signers
40-
uint32[] quorumApkIndices; // is the indices of each quorum aggregate pubkey
41-
uint32[] totalStakeIndices; // is the indices of each quorums total stake
42-
uint32[][] nonSignerStakeIndices; // is the indices of each non signers stake within a quorum
53+
uint32[] nonSignerQuorumBitmapIndices;
54+
BN254.G1Point[] nonSignerPubkeys;
55+
BN254.G1Point[] quorumApks;
56+
BN254.G2Point apkG2;
57+
BN254.G1Point sigma;
58+
uint32[] quorumApkIndices;
59+
uint32[] totalStakeIndices;
60+
uint32[][] nonSignerStakeIndices;
4361
}
4462

45-
/**
46-
* @notice this data structure is used for recording the details on the total stake of the registered
47-
* operators and those operators who are part of the quorum for a particular taskNumber
48-
*/
63+
/// @notice Records the total stake amounts for operators in each quorum.
64+
/// @param signedStakeForQuorum Array of total stake amounts from operators who signed, per quorum.
65+
/// @param totalStakeForQuorum Array of total stake amounts from all operators, per quorum.
66+
/// @dev Used to track stake distribution and calculate quorum thresholds. Array indices correspond to quorum numbers.
4967
struct QuorumStakeTotals {
50-
// total stake of the operators in each quorum
5168
uint96[] signedStakeForQuorum;
52-
// total amount staked by all operators in each quorum
5369
uint96[] totalStakeForQuorum;
5470
}
5571
}
@@ -62,49 +78,73 @@ interface IBLSSignatureCheckerEvents is IBLSSignatureCheckerTypes {
6278
interface IBLSSignatureChecker is IBLSSignatureCheckerErrors, IBLSSignatureCheckerEvents {
6379
/// STATE
6480

81+
/// @notice Returns the address of the registry coordinator contract.
82+
/// @return The address of the registry coordinator.
83+
/// @dev This value is immutable and set during contract construction.
6584
function registryCoordinator() external view returns (IRegistryCoordinator);
6685

86+
/// @notice Returns the address of the stake registry contract.
87+
/// @return The address of the stake registry.
88+
/// @dev This value is immutable and set during contract construction.
6789
function stakeRegistry() external view returns (IStakeRegistry);
68-
90+
91+
/// @notice Returns the address of the BLS APK registry contract.
92+
/// @return The address of the BLS APK registry.
93+
/// @dev This value is immutable and set during contract construction.
6994
function blsApkRegistry() external view returns (IBLSApkRegistry);
70-
95+
96+
/// @notice Returns the address of the delegation manager contract.
97+
/// @return The address of the delegation manager.
98+
/// @dev This value is immutable and set during contract construction.
7199
function delegation() external view returns (IDelegationManager);
72-
100+
101+
/// @notice Returns whether stale stakes are forbidden in signature verification.
102+
/// @return True if stale stakes are forbidden, false otherwise.
73103
function staleStakesForbidden() external view returns (bool);
74104

75105
// ACTIONS
76106

77-
function setStaleStakesForbidden(bool value) external;
107+
/// @notice Sets `value` as the new staleStakesForbidden flag.
108+
/// @param value True to forbid stale stakes, false to allow them.
109+
/// @dev Access restricted to the registry coordinator owner.
110+
function setStaleStakesForbidden(
111+
bool value
112+
) external;
78113

79114
/// VIEW
80115

81-
/**
82-
* @notice This function is called by disperser when it has aggregated all the signatures of the operators
83-
* that are part of the quorum for a particular taskNumber and is asserting them into onchain. The function
84-
* checks that the claim for aggregated signatures are valid.
85-
*
86-
* The thesis of this procedure entails:
87-
* - getting the aggregated pubkey of all registered nodes at the time of pre-commit by the
88-
* disperser (represented by apk in the parameters),
89-
* - subtracting the pubkeys of all the signers not in the quorum (nonSignerPubkeys) and storing
90-
* the output in apk to get aggregated pubkey of all operators that are part of quorum.
91-
* - use this aggregated pubkey to verify the aggregated signature under BLS scheme.
92-
*
93-
* @dev Before signature verification, the function verifies operator stake information. This includes ensuring that the provided `referenceBlockNumber`
94-
* is correct, i.e., ensure that the stake returned from the specified block number is recent enough and that the stake is either the most recent update
95-
* for the total stake (or the operator) or latest before the referenceBlockNumber.
96-
*/
116+
/// @notice Verifies aggregated BLS signatures and stake information for message hash `msgHash` across `quorumNumbers` at block `referenceBlockNumber`.
117+
/// @param msgHash The hash of the message that was signed.
118+
/// @param quorumNumbers The quorum numbers to verify signatures for, where each byte is an 8-bit integer.
119+
/// @param referenceBlockNumber The block number to use for stake information.
120+
/// @param nonSignerStakesAndSignature Contains non-signer information and aggregated signature data.
121+
/// @return Stake totals for each quorum and a hash of the verification data.
122+
/// @dev The thesis of this procedure entails:
123+
/// 1. Getting the aggregated pubkey of all registered nodes at the time of pre-commit
124+
/// 2. Subtracting the pubkeys of all non-signers (nonSignerPubkeys)
125+
/// 3. Using the resulting aggregated pubkey to verify the aggregated signature under BLS scheme
126+
/// @dev Before signature verification, the function verifies:
127+
/// 1. The reference block number is valid and recent enough
128+
/// 2. Stake information is either most recent or latest before reference block
129+
/// 3. The aggregated signature is valid under the BLS scheme
97130
function checkSignatures(
98131
bytes32 msgHash,
99132
bytes calldata quorumNumbers,
100133
uint32 referenceBlockNumber,
101134
NonSignerStakesAndSignature memory nonSignerStakesAndSignature
102135
) external view returns (QuorumStakeTotals memory, bytes32);
103136

137+
/// @notice Attempts to verify signature `sigma` against message hash `msgHash` using aggregate public keys `apk` and `apkG2`.
138+
/// @param msgHash The hash of the message that was signed.
139+
/// @param apk The aggregate public key in G1.
140+
/// @param apkG2 The aggregate public key in G2.
141+
/// @param sigma The signature to verify.
142+
/// @return pairingSuccessful True if the pairing check succeeded.
143+
/// @return siganatureIsValid True if the signature is valid.
104144
function trySignatureAndApkVerification(
105145
bytes32 msgHash,
106146
BN254.G1Point memory apk,
107147
BN254.G2Point memory apkG2,
108148
BN254.G1Point memory sigma
109149
) external view returns (bool pairingSuccessful, bool siganatureIsValid);
110-
}
150+
}

test/unit/BLSSignatureCheckerUnit.t.sol

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ pragma solidity ^0.8.27;
33

44
import "../../src/BLSSignatureChecker.sol";
55
import "../utils/BLSMockAVSDeployer.sol";
6-
import {IBLSSignatureCheckerErrors, IBLSSignatureCheckerTypes} from "../../src/interfaces/IBLSSignatureChecker.sol";
6+
import {
7+
IBLSSignatureCheckerErrors,
8+
IBLSSignatureCheckerTypes
9+
} from "../../src/interfaces/IBLSSignatureChecker.sol";
710
import {IBLSApkRegistryErrors} from "../../src/interfaces/IBLSApkRegistry.sol";
811
import {QuorumBitmapHistoryLib} from "../../src/libraries/QuorumBitmapHistoryLib.sol";
912
import {IStakeRegistryErrors} from "../../src/interfaces/IStakeRegistry.sol";

0 commit comments

Comments
 (0)