Skip to content

Commit 4c49dcb

Browse files
eigenmikem8sunyuan
andauthored
feat: ecdsacv views (#1475)
<!-- 🚨 ATTENTION! 🚨 This PR template is REQUIRED. PRs not following this format will be closed without review. Requirements: - PR title must follow commit conventions: https://www.conventionalcommits.org/en/v1.0.0/ - Label your PR with the correct type (e.g., 🐛 Bug, ✨ Enhancement, 🧪 Test, etc.) - Provide clear and specific details in each section --> **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.* --------- Co-authored-by: Michael Sun <[email protected]>
1 parent dbd273b commit 4c49dcb

File tree

2 files changed

+145
-89
lines changed

2 files changed

+145
-89
lines changed

src/contracts/interfaces/IECDSACertificateVerifier.sol

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,4 +84,50 @@ interface IECDSACertificateVerifier is IECDSACertificateVerifierEvents, IBaseCer
8484
ECDSACertificate memory cert,
8585
uint256[] memory totalStakeNominalThresholds
8686
) external returns (bool);
87+
88+
/**
89+
* @notice Get operator infos for a timestamp
90+
* @param operatorSet The operator set
91+
* @param referenceTimestamp The reference timestamp
92+
* @return The operator infos
93+
*/
94+
function getOperatorInfos(
95+
OperatorSet calldata operatorSet,
96+
uint32 referenceTimestamp
97+
) external view returns (ECDSAOperatorInfo[] memory);
98+
99+
/**
100+
* @notice Get a single operator info by index
101+
* @param operatorSet The operator set
102+
* @param referenceTimestamp The reference timestamp
103+
* @param operatorIndex The index of the operator
104+
* @return The operator info
105+
*/
106+
function getOperatorInfo(
107+
OperatorSet calldata operatorSet,
108+
uint32 referenceTimestamp,
109+
uint32 operatorIndex
110+
) external view returns (ECDSAOperatorInfo memory);
111+
112+
/**
113+
* @notice Get the total number of operators for a given reference timestamp
114+
* @param operatorSet The operator set
115+
* @param referenceTimestamp The reference timestamp
116+
* @return The number of operators
117+
*/
118+
function getOperatorCount(
119+
OperatorSet calldata operatorSet,
120+
uint32 referenceTimestamp
121+
) external view returns (uint32);
122+
123+
/**
124+
* @notice Get the total stakes for all operators at a given reference timestamp
125+
* @param operatorSet The operator set to calculate stakes for
126+
* @param referenceTimestamp The reference timestamp
127+
* @return totalStakes The total stakes for all operators
128+
*/
129+
function getTotalStakes(
130+
OperatorSet calldata operatorSet,
131+
uint32 referenceTimestamp
132+
) external view returns (uint256[] memory);
87133
}

src/contracts/multichain/ECDSACertificateVerifier.sol

Lines changed: 99 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,104 @@ contract ECDSACertificateVerifier is Initializable, ECDSACertificateVerifierStor
116116
emit TableUpdated(operatorSet, referenceTimestamp, operatorInfos);
117117
}
118118

119+
///@inheritdoc IECDSACertificateVerifier
120+
function verifyCertificate(
121+
OperatorSet calldata operatorSet,
122+
ECDSACertificate calldata cert
123+
) external view returns (uint256[] memory) {
124+
return _verifyECDSACertificate(operatorSet, cert);
125+
}
126+
127+
///@inheritdoc IECDSACertificateVerifier
128+
function verifyCertificateProportion(
129+
OperatorSet calldata operatorSet,
130+
ECDSACertificate calldata cert,
131+
uint16[] calldata totalStakeProportionThresholds
132+
) external view returns (bool) {
133+
uint256[] memory signedStakes = _verifyECDSACertificate(operatorSet, cert);
134+
uint256[] memory totalStakes = getTotalStakes(operatorSet, cert.referenceTimestamp);
135+
require(signedStakes.length == totalStakeProportionThresholds.length, ArrayLengthMismatch());
136+
for (uint256 i = 0; i < signedStakes.length; i++) {
137+
uint256 threshold = (totalStakes[i] * totalStakeProportionThresholds[i]) / 10_000;
138+
if (signedStakes[i] < threshold) {
139+
return false;
140+
}
141+
}
142+
return true;
143+
}
144+
145+
///@inheritdoc IECDSACertificateVerifier
146+
function verifyCertificateNominal(
147+
OperatorSet calldata operatorSet,
148+
ECDSACertificate calldata cert,
149+
uint256[] memory totalStakeNominalThresholds
150+
) external view returns (bool) {
151+
uint256[] memory signedStakes = _verifyECDSACertificate(operatorSet, cert);
152+
if (signedStakes.length != totalStakeNominalThresholds.length) revert ArrayLengthMismatch();
153+
for (uint256 i = 0; i < signedStakes.length; i++) {
154+
if (signedStakes[i] < totalStakeNominalThresholds[i]) {
155+
return false;
156+
}
157+
}
158+
return true;
159+
}
160+
161+
/// @inheritdoc IECDSACertificateVerifier
162+
function getOperatorInfos(
163+
OperatorSet memory operatorSet,
164+
uint32 referenceTimestamp
165+
) external view returns (ECDSAOperatorInfo[] memory) {
166+
bytes32 operatorSetKey = operatorSet.key();
167+
uint32 numOperators = uint32(_numOperators[operatorSetKey][referenceTimestamp]);
168+
ECDSAOperatorInfo[] memory operatorInfos = new ECDSAOperatorInfo[](numOperators);
169+
170+
for (uint32 i = 0; i < numOperators; i++) {
171+
operatorInfos[i] = _operatorInfos[operatorSetKey][referenceTimestamp][i];
172+
}
173+
174+
return operatorInfos;
175+
}
176+
177+
/// @inheritdoc IECDSACertificateVerifier
178+
function getOperatorInfo(
179+
OperatorSet memory operatorSet,
180+
uint32 referenceTimestamp,
181+
uint32 operatorIndex
182+
) external view returns (ECDSAOperatorInfo memory) {
183+
bytes32 operatorSetKey = operatorSet.key();
184+
require(operatorIndex < _numOperators[operatorSetKey][referenceTimestamp], "Operator index out of bounds");
185+
return _operatorInfos[operatorSetKey][referenceTimestamp][operatorIndex];
186+
}
187+
188+
/// @inheritdoc IECDSACertificateVerifier
189+
function getOperatorCount(
190+
OperatorSet memory operatorSet,
191+
uint32 referenceTimestamp
192+
) external view returns (uint32) {
193+
bytes32 operatorSetKey = operatorSet.key();
194+
return uint32(_numOperators[operatorSetKey][referenceTimestamp]);
195+
}
196+
197+
/// @inheritdoc IECDSACertificateVerifier
198+
function getTotalStakes(
199+
OperatorSet calldata operatorSet,
200+
uint32 referenceTimestamp
201+
) public view returns (uint256[] memory) {
202+
bytes32 operatorSetKey = operatorSet.key();
203+
require(_latestReferenceTimestamps[operatorSetKey] == referenceTimestamp, ReferenceTimestampDoesNotExist());
204+
uint256 operatorCount = _numOperators[operatorSetKey][referenceTimestamp];
205+
require(operatorCount > 0, ReferenceTimestampDoesNotExist());
206+
uint256 stakeTypesCount = _operatorInfos[operatorSetKey][referenceTimestamp][0].weights.length;
207+
uint256[] memory totalStakes = new uint256[](stakeTypesCount);
208+
for (uint256 i = 0; i < operatorCount; i++) {
209+
uint256[] memory weights = _operatorInfos[operatorSetKey][referenceTimestamp][uint32(i)].weights;
210+
for (uint256 j = 0; j < weights.length && j < stakeTypesCount; j++) {
211+
totalStakes[j] += weights[j];
212+
}
213+
}
214+
return totalStakes;
215+
}
216+
119217
/**
120218
* @notice Internal function to verify a certificate
121219
* @param cert The certificate to verify
@@ -134,7 +232,7 @@ contract ECDSACertificateVerifier is Initializable, ECDSACertificateVerifierStor
134232
require(_latestReferenceTimestamps[operatorSetKey] == cert.referenceTimestamp, ReferenceTimestampDoesNotExist());
135233

136234
// Get the total stakes
137-
uint256[] memory totalStakes = _getTotalStakes(operatorSet, cert.referenceTimestamp);
235+
uint256[] memory totalStakes = getTotalStakes(operatorSet, cert.referenceTimestamp);
138236
uint256[] memory signedStakes = new uint256[](totalStakes.length);
139237

140238
// Compute the EIP-712 digest for signature recovery
@@ -175,48 +273,6 @@ contract ECDSACertificateVerifier is Initializable, ECDSACertificateVerifierStor
175273
return signedStakes;
176274
}
177275

178-
///@inheritdoc IECDSACertificateVerifier
179-
function verifyCertificate(
180-
OperatorSet calldata operatorSet,
181-
ECDSACertificate calldata cert
182-
) external view returns (uint256[] memory) {
183-
return _verifyECDSACertificate(operatorSet, cert);
184-
}
185-
186-
///@inheritdoc IECDSACertificateVerifier
187-
function verifyCertificateProportion(
188-
OperatorSet calldata operatorSet,
189-
ECDSACertificate calldata cert,
190-
uint16[] calldata totalStakeProportionThresholds
191-
) external view returns (bool) {
192-
uint256[] memory signedStakes = _verifyECDSACertificate(operatorSet, cert);
193-
uint256[] memory totalStakes = _getTotalStakes(operatorSet, cert.referenceTimestamp);
194-
require(signedStakes.length == totalStakeProportionThresholds.length, ArrayLengthMismatch());
195-
for (uint256 i = 0; i < signedStakes.length; i++) {
196-
uint256 threshold = (totalStakes[i] * totalStakeProportionThresholds[i]) / 10_000;
197-
if (signedStakes[i] < threshold) {
198-
return false;
199-
}
200-
}
201-
return true;
202-
}
203-
204-
///@inheritdoc IECDSACertificateVerifier
205-
function verifyCertificateNominal(
206-
OperatorSet calldata operatorSet,
207-
ECDSACertificate calldata cert,
208-
uint256[] memory totalStakeNominalThresholds
209-
) external view returns (bool) {
210-
uint256[] memory signedStakes = _verifyECDSACertificate(operatorSet, cert);
211-
if (signedStakes.length != totalStakeNominalThresholds.length) revert ArrayLengthMismatch();
212-
for (uint256 i = 0; i < signedStakes.length; i++) {
213-
if (signedStakes[i] < totalStakeNominalThresholds[i]) {
214-
return false;
215-
}
216-
}
217-
return true;
218-
}
219-
220276
/**
221277
* @notice Parse signatures from the concatenated signature bytes
222278
* @param messageHash The message hash that was signed
@@ -261,50 +317,4 @@ contract ECDSACertificateVerifier is Initializable, ECDSACertificateVerifierStor
261317

262318
return (signers, true);
263319
}
264-
265-
/**
266-
* @notice Get operator infos for a timestamp
267-
* @param operatorSet The operator set
268-
* @param referenceTimestamp The reference timestamp
269-
* @return The operator infos
270-
*/
271-
function getOperatorInfos(
272-
OperatorSet memory operatorSet,
273-
uint32 referenceTimestamp
274-
) external view returns (ECDSAOperatorInfo[] memory) {
275-
bytes32 operatorSetKey = operatorSet.key();
276-
uint32 numOperators = uint32(_numOperators[operatorSetKey][referenceTimestamp]);
277-
ECDSAOperatorInfo[] memory operatorInfos = new ECDSAOperatorInfo[](numOperators);
278-
279-
for (uint32 i = 0; i < numOperators; i++) {
280-
operatorInfos[i] = _operatorInfos[operatorSetKey][referenceTimestamp][i];
281-
}
282-
283-
return operatorInfos;
284-
}
285-
286-
/**
287-
* @notice Calculate the total stakes for all operators at a given reference timestamp
288-
* @param operatorSet The operator set to calculate stakes for
289-
* @param referenceTimestamp The reference timestamp
290-
* @return totalStakes The total stakes for all operators
291-
*/
292-
function _getTotalStakes(
293-
OperatorSet calldata operatorSet,
294-
uint32 referenceTimestamp
295-
) internal view returns (uint256[] memory totalStakes) {
296-
bytes32 operatorSetKey = operatorSet.key();
297-
require(_latestReferenceTimestamps[operatorSetKey] == referenceTimestamp, ReferenceTimestampDoesNotExist());
298-
uint256 operatorCount = _numOperators[operatorSetKey][referenceTimestamp];
299-
require(operatorCount > 0, ReferenceTimestampDoesNotExist());
300-
uint256 stakeTypesCount = _operatorInfos[operatorSetKey][referenceTimestamp][0].weights.length;
301-
totalStakes = new uint256[](stakeTypesCount);
302-
for (uint256 i = 0; i < operatorCount; i++) {
303-
uint256[] memory weights = _operatorInfos[operatorSetKey][referenceTimestamp][uint32(i)].weights;
304-
for (uint256 j = 0; j < weights.length && j < stakeTypesCount; j++) {
305-
totalStakes[j] += weights[j];
306-
}
307-
}
308-
return totalStakes;
309-
}
310320
}

0 commit comments

Comments
 (0)