Skip to content

Commit 9e858bd

Browse files
committed
feat: update tests
1 parent 4c49dcb commit 9e858bd

File tree

9 files changed

+868
-550
lines changed

9 files changed

+868
-550
lines changed

script/deploy/devnet/mutlichain/deploy_multichain_l2.s.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ contract DeployMultichain_L2 is Script, Test {
6262
operatorTableUpdaterImplementation = new OperatorTableUpdater(
6363
bn254CertificateVerifier, IECDSACertificateVerifier(address(emptyContract)), "0.0.1"
6464
);
65-
bn254CertificateVerifierImplementation = new BN254CertificateVerifier(operatorTableUpdater);
65+
bn254CertificateVerifierImplementation = new BN254CertificateVerifier(operatorTableUpdater, "1.0.0");
6666

6767
// Third, upgrade the proxies to point to the new implementations
6868
proxyAdmin.upgrade(

src/contracts/interfaces/IBN254CertificateVerifier.sol

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ interface IBN254CertificateVerifierTypes is IBN254TableCalculatorTypes {
1111
* @notice A witness for an operator
1212
* @param operatorIndex the index of the nonsigner in the `BN254OperatorInfo` tree
1313
* @param operatorInfoProofs merkle proofs of the nonsigner at the index. Empty if operator is in cache.
14-
* @param operatorInfo the `BN254OperatorInfo` for the operator
14+
* @param operatorInfo the `BN254OperatorInfo` for the operator. Empty if operator is in cache
1515
*/
1616
struct BN254OperatorInfoWitness {
1717
uint32 operatorIndex;
@@ -110,4 +110,58 @@ interface IBN254CertificateVerifier is
110110
BN254Certificate memory cert,
111111
uint256[] memory totalStakeNominalThresholds
112112
) external returns (bool);
113+
114+
/**
115+
* @notice Attempts signature verification with gas limit for safety
116+
* @param msgHash The message hash that was signed
117+
* @param aggPubkey The aggregate public key of signers
118+
* @param apkG2 The G2 point representation of the aggregate public key
119+
* @param signature The BLS signature to verify
120+
* @return pairingSuccessful Whether the pairing operation completed successfully
121+
* @return signatureValid Whether the signature is valid
122+
*/
123+
function trySignatureVerification(
124+
bytes32 msgHash,
125+
BN254.G1Point memory aggPubkey,
126+
BN254.G2Point memory apkG2,
127+
BN254.G1Point memory signature
128+
) external view returns (bool pairingSuccessful, bool signatureValid);
129+
130+
/**
131+
* @notice Get cached nonsigner operator info
132+
* @param operatorSet The operator set
133+
* @param referenceTimestamp The reference timestamp
134+
* @param operatorIndex The operator index
135+
* @return The cached operator info
136+
* @dev If the operator is not in the cache, the operator info will be empty
137+
*/
138+
function getNonsignerOperatorInfo(
139+
OperatorSet memory operatorSet,
140+
uint32 referenceTimestamp,
141+
uint256 operatorIndex
142+
) external view returns (BN254OperatorInfo memory);
143+
144+
/**
145+
* @notice Check if a nonsigner is cached
146+
* @param operatorSet The operator set
147+
* @param referenceTimestamp The reference timestamp
148+
* @param operatorIndex The operator index
149+
* @return Whether the operator is cached
150+
*/
151+
function isNonsignerCached(
152+
OperatorSet memory operatorSet,
153+
uint32 referenceTimestamp,
154+
uint256 operatorIndex
155+
) external view returns (bool);
156+
157+
/**
158+
* @notice Get operator set info for a timestamp
159+
* @param operatorSet The operator set
160+
* @param referenceTimestamp The reference timestamp
161+
* @return The operator set info
162+
*/
163+
function getOperatorSetInfo(
164+
OperatorSet memory operatorSet,
165+
uint32 referenceTimestamp
166+
) external view returns (BN254OperatorSetInfo memory);
113167
}

src/contracts/multichain/BN254CertificateVerifier.sol

Lines changed: 66 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ pragma solidity ^0.8.27;
33

44
import "@openzeppelin-upgrades/contracts/proxy/utils/Initializable.sol";
55

6-
import {BN254} from "../libraries/BN254.sol";
7-
import {BN254SignatureVerifier} from "../libraries/BN254SignatureVerifier.sol";
8-
import {Merkle} from "../libraries/Merkle.sol";
9-
import {OperatorSet} from "../libraries/OperatorSetLib.sol";
10-
6+
import "../libraries/BN254.sol";
7+
import "../libraries/BN254SignatureVerifier.sol";
8+
import "../libraries/Merkle.sol";
9+
import "../libraries/OperatorSetLib.sol";
10+
import "../mixins/SemVerMixin.sol";
1111
import "./BN254CertificateVerifierStorage.sol";
1212

1313
/**
@@ -16,7 +16,7 @@ import "./BN254CertificateVerifierStorage.sol";
1616
* @dev This contract uses BN254 curves for signature verification and
1717
* caches operator information for efficient verification
1818
*/
19-
contract BN254CertificateVerifier is Initializable, BN254CertificateVerifierStorage {
19+
contract BN254CertificateVerifier is Initializable, BN254CertificateVerifierStorage, SemVerMixin {
2020
using Merkle for bytes;
2121
using BN254 for BN254.G1Point;
2222

@@ -42,36 +42,20 @@ contract BN254CertificateVerifier is Initializable, BN254CertificateVerifierStor
4242
* @notice Constructor for the certificate verifier
4343
* @dev Disables initializers to prevent implementation initialization
4444
* @param _operatorTableUpdater Address authorized to update operator tables
45+
* @param _version The semantic version of the contract
4546
*/
4647
constructor(
47-
IOperatorTableUpdater _operatorTableUpdater
48-
) BN254CertificateVerifierStorage(_operatorTableUpdater) {
48+
IOperatorTableUpdater _operatorTableUpdater,
49+
string memory _version
50+
) BN254CertificateVerifierStorage(_operatorTableUpdater) SemVerMixin(_version) {
4951
_disableInitializers();
5052
}
5153

52-
///@inheritdoc IBaseCertificateVerifier
53-
function getOperatorSetOwner(
54-
OperatorSet memory operatorSet
55-
) external view returns (address) {
56-
bytes32 operatorSetKey = operatorSet.key();
57-
return _operatorSetOwners[operatorSetKey];
58-
}
59-
60-
///@inheritdoc IBaseCertificateVerifier
61-
function maxOperatorTableStaleness(
62-
OperatorSet memory operatorSet
63-
) external view returns (uint32) {
64-
bytes32 operatorSetKey = operatorSet.key();
65-
return _maxStalenessPeriods[operatorSetKey];
66-
}
67-
68-
///@inheritdoc IBaseCertificateVerifier
69-
function latestReferenceTimestamp(
70-
OperatorSet memory operatorSet
71-
) external view returns (uint32) {
72-
bytes32 operatorSetKey = operatorSet.key();
73-
return _latestReferenceTimestamps[operatorSetKey];
74-
}
54+
/**
55+
*
56+
* EXTERNAL FUNCTIONS
57+
*
58+
*/
7559

7660
///@inheritdoc IBN254CertificateVerifier
7761
function updateOperatorTable(
@@ -148,21 +132,13 @@ contract BN254CertificateVerifier is Initializable, BN254CertificateVerifierStor
148132
return true;
149133
}
150134

151-
/**
152-
* @notice Attempts signature verification with gas limit for safety
153-
* @param msgHash The message hash that was signed
154-
* @param aggPubkey The aggregate public key of signers
155-
* @param apkG2 The G2 point representation of the aggregate public key
156-
* @param signature The BLS signature to verify
157-
* @return pairingSuccessful Whether the pairing operation completed successfully
158-
* @return signatureValid Whether the signature is valid
159-
*/
135+
///@inheritdoc IBN254CertificateVerifier
160136
function trySignatureVerification(
161137
bytes32 msgHash,
162138
BN254.G1Point memory aggPubkey,
163139
BN254.G2Point memory apkG2,
164140
BN254.G1Point memory signature
165-
) internal view returns (bool pairingSuccessful, bool signatureValid) {
141+
) public view returns (bool pairingSuccessful, bool signatureValid) {
166142
return BN254SignatureVerifier.verifySignature(
167143
msgHash,
168144
signature,
@@ -173,6 +149,12 @@ contract BN254CertificateVerifier is Initializable, BN254CertificateVerifierStor
173149
);
174150
}
175151

152+
/**
153+
*
154+
* INTERNAL FUNCTIONS
155+
*
156+
*/
157+
176158
/**
177159
* @notice Internal function to verify a certificate
178160
* @param operatorSet The operator set the certificate is for
@@ -232,7 +214,7 @@ contract BN254CertificateVerifier is Initializable, BN254CertificateVerifierStor
232214
require(witness.operatorIndex < ctx.operatorSetInfo.numOperators, InvalidOperatorIndex());
233215

234216
BN254OperatorInfo memory operatorInfo =
235-
_getOrCacheOperatorInfo(ctx.operatorSetKey, cert.referenceTimestamp, witness);
217+
_getOrCacheNonsignerOperatorInfo(ctx.operatorSetKey, cert.referenceTimestamp, witness);
236218

237219
nonSignerApk = nonSignerApk.plus(operatorInfo.pubkey);
238220

@@ -252,12 +234,12 @@ contract BN254CertificateVerifier is Initializable, BN254CertificateVerifierStor
252234
* @param witness The operator info witness containing proof data
253235
* @return operatorInfo The verified operator information
254236
*/
255-
function _getOrCacheOperatorInfo(
237+
function _getOrCacheNonsignerOperatorInfo(
256238
bytes32 operatorSetKey,
257239
uint32 referenceTimestamp,
258240
BN254OperatorInfoWitness memory witness
259241
) internal returns (BN254OperatorInfo memory operatorInfo) {
260-
BN254OperatorInfo storage cachedInfo = _operatorInfos[operatorSetKey][referenceTimestamp][witness.operatorIndex];
242+
BN254OperatorInfo memory cachedInfo = _operatorInfos[operatorSetKey][referenceTimestamp][witness.operatorIndex];
261243

262244
// Check if operator info is cached using pubkey existence (weights can be 0)
263245
bool isInfoCached = (cachedInfo.pubkey.X != 0 || cachedInfo.pubkey.Y != 0);
@@ -317,13 +299,13 @@ contract BN254CertificateVerifier is Initializable, BN254CertificateVerifierStor
317299
}
318300

319301
/**
320-
* @notice Get cached operator info
321-
* @param operatorSet The operator set
322-
* @param referenceTimestamp The reference timestamp
323-
* @param operatorIndex The operator index
324-
* @return The cached operator info
302+
*
303+
* VIEW FUNCTIONS
304+
*
325305
*/
326-
function getOperatorInfo(
306+
307+
///@inheritdoc IBN254CertificateVerifier
308+
function getNonsignerOperatorInfo(
327309
OperatorSet memory operatorSet,
328310
uint32 referenceTimestamp,
329311
uint256 operatorIndex
@@ -332,12 +314,19 @@ contract BN254CertificateVerifier is Initializable, BN254CertificateVerifierStor
332314
return _operatorInfos[operatorSetKey][referenceTimestamp][operatorIndex];
333315
}
334316

335-
/**
336-
* @notice Get operator set info for a timestamp
337-
* @param operatorSet The operator set
338-
* @param referenceTimestamp The reference timestamp
339-
* @return The operator set info
340-
*/
317+
///@inheritdoc IBN254CertificateVerifier
318+
function isNonsignerCached(
319+
OperatorSet memory operatorSet,
320+
uint32 referenceTimestamp,
321+
uint256 operatorIndex
322+
) external view returns (bool) {
323+
bytes32 operatorSetKey = operatorSet.key();
324+
BN254OperatorInfo memory operatorInfo = _operatorInfos[operatorSetKey][referenceTimestamp][operatorIndex];
325+
// Check if operator info is cached using pubkey existence (weights can be 0)
326+
return operatorInfo.pubkey.X != 0 && operatorInfo.pubkey.Y != 0;
327+
}
328+
329+
///@inheritdoc IBN254CertificateVerifier
341330
function getOperatorSetInfo(
342331
OperatorSet memory operatorSet,
343332
uint32 referenceTimestamp
@@ -346,9 +335,27 @@ contract BN254CertificateVerifier is Initializable, BN254CertificateVerifierStor
346335
return _operatorSetInfos[operatorSetKey][referenceTimestamp];
347336
}
348337

349-
/// @dev Only used in a test environment
350-
function setMaxStalenessPeriod(OperatorSet memory operatorSet, uint32 maxStalenessPeriod) external {
338+
///@inheritdoc IBaseCertificateVerifier
339+
function getOperatorSetOwner(
340+
OperatorSet memory operatorSet
341+
) external view returns (address) {
342+
bytes32 operatorSetKey = operatorSet.key();
343+
return _operatorSetOwners[operatorSetKey];
344+
}
345+
346+
///@inheritdoc IBaseCertificateVerifier
347+
function maxOperatorTableStaleness(
348+
OperatorSet memory operatorSet
349+
) external view returns (uint32) {
351350
bytes32 operatorSetKey = operatorSet.key();
352-
_maxStalenessPeriods[operatorSetKey] = maxStalenessPeriod;
351+
return _maxStalenessPeriods[operatorSetKey];
352+
}
353+
354+
///@inheritdoc IBaseCertificateVerifier
355+
function latestReferenceTimestamp(
356+
OperatorSet memory operatorSet
357+
) external view returns (uint32) {
358+
bytes32 operatorSetKey = operatorSet.key();
359+
return _latestReferenceTimestamps[operatorSetKey];
353360
}
354361
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// SPDX-License-Identifier: BUSL-1.1
2+
pragma solidity ^0.8.27;
3+
4+
import "forge-std/Test.sol";
5+
6+
import "src/contracts/multichain/CrossChainRegistry.sol";
7+
8+
contract CrossChainRegistryMock is Test, ICrossChainRegistryTypes {
9+
using OperatorSetLib for OperatorSet;
10+
11+
receive() external payable {}
12+
fallback() external payable {}
13+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// SPDX-License-Identifier: BUSL-1.1
2+
pragma solidity ^0.8.27;
3+
4+
import "forge-std/Test.sol";
5+
import "src/contracts/interfaces/IOperatorTableUpdater.sol";
6+
7+
contract OperatorTableUpdaterMock is Test {
8+
receive() external payable {}
9+
fallback() external payable {}
10+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
.
2+
└── BN254CertificateVerifier (**** denotes that integration tests are needed to fully validate path)
3+
├── when updateOperatorTable is called
4+
│ ├── given that the caller is not the table updater
5+
│ │ └── it should revert
6+
│ ├── given that the reference timestamp is not greater than the latest
7+
│ │ └── it should revert
8+
│ └── given that all parameters are valid
9+
│ └── it should update operator set info, timestamp, owner, and staleness period & emit event
10+
├── when verifyCertificate is called
11+
│ ├── given that the reference timestamp does not exist
12+
│ │ └── it should revert
13+
│ ├── given that the certificate is stale
14+
│ │ └── it should revert
15+
│ ├── given that a non-signer witness has invalid operator index
16+
│ │ └── it should revert
17+
│ ├── given that a non-signer witness has invalid merkle proof
18+
│ │ └── it should revert
19+
│ ├── given that the signature is invalid
20+
│ │ └── it should revert
21+
│ ├── given that all operators are signers
22+
│ │ └── it should return full stake amounts
23+
│ ├── given that some operators are non-signers
24+
│ │ └── it should deduct non-signer stakes from total
25+
│ └── given that operator info is not cached
26+
│ └── it should cache operator info after verification
27+
├── when verifyCertificateProportion is called
28+
│ ├── given that array lengths mismatch
29+
│ │ └── it should revert
30+
│ ├── given that the certificate meets thresholds
31+
│ │ └── it should return true
32+
│ └── given that the certificate does not meet thresholds
33+
│ └── it should return false
34+
├── when verifyCertificateNominal is called
35+
│ ├── given that array lengths mismatch
36+
│ │ └── it should revert
37+
│ ├── given that the certificate meets thresholds
38+
│ │ └── it should return true
39+
│ └── given that the certificate does not meet thresholds
40+
│ └── it should return false
41+
├── when trySignatureVerification is called
42+
│ ├── given a valid signature
43+
│ │ └── it should return pairing successful and signature valid
44+
│ └── given an invalid signature
45+
│ └── it should return pairing successful and signature invalid
46+
└── when view functions are called
47+
├── getOperatorSetOwner
48+
│ └── it should return the correct owner address
49+
├── maxOperatorTableStaleness
50+
│ └── it should return the correct staleness period
51+
├── latestReferenceTimestamp
52+
│ └── it should return the latest timestamp
53+
├── getOperatorSetInfo
54+
│ └── it should return the correct operator set info
55+
└── getOperatorInfo
56+
└── it should return the cached operator info

0 commit comments

Comments
 (0)