Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/multichain/destination/CertificateVerifier.md
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,7 @@ The contract supports 3 verification patterns:
* @param signature the G1 signature of the message. The signature is over the signable digest, which is calculated by `calculateCertificateDigest`
* @param apk the G2 aggregate public key
* @param nonSignerWitnesses an array of witnesses of non-signing operators
* @dev Non-signer witnesses MUST be strictly increasing by `operatorIndex`
* @dev The `referenceTimestamp` is used to key into the operatorSet's stake weights. It is NOT the timestamp at which the certificate was generated off-chain
*/
struct BN254Certificate {
Expand Down Expand Up @@ -475,6 +476,7 @@ Verifies a BN254 certificate by checking the aggregated signature against the op
* The root at the `referenceTimestamp` MUST not be disabled
* The operator set info MUST exist for the `referenceTimestamp`
* The `operatorIndex` must be valid for the non signer
* The non-signer witnesses MUST be strictly increasing by `operatorIndex`
* All merkle proofs for nonsigners MUST be valid
* The BLS signature MUST verify correctly

Expand Down
9 changes: 9 additions & 0 deletions src/contracts/interfaces/IBN254CertificateVerifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ interface IBN254CertificateVerifierTypes is IOperatorTableCalculatorTypes {
* @param signature the G1 signature of the message. The signature is over the signable digest, which is calculated by `calculateCertificateDigest`
* @param apk the G2 aggregate public key
* @param nonSignerWitnesses an array of witnesses of non-signing operators
* @dev Non-signer witnesses MUST be strictly increasing by `operatorIndex`
* @dev The `referenceTimestamp` is used to key into the operatorSet's stake weights. It is NOT the timestamp at which the certificate was generated off-chain
*/
struct BN254Certificate {
Expand All @@ -52,6 +53,11 @@ interface IBN254CertificateVerifierErrors {
/// @dev Error code: 0x03f4a78e
/// @dev We enforce that operator indices are within valid bounds to prevent out-of-bounds access in the merkle tree verification
error InvalidOperatorIndex();

/// @notice thrown when the non-signer witnesses are not strictly increasing by operatorIndex
/// @dev Error code: 0xec6268b8
/// @dev We enforce strictly increasing order to prevent duplicates and ensure deterministic processing
error NonSignerIndicesNotSorted();
}

/// @notice An interface for verifying BN254 certificates
Expand Down Expand Up @@ -128,6 +134,7 @@ interface IBN254CertificateVerifier is
* - ReferenceTimestampDoesNotExist: No operator table exists for the referenceTimestamp
* - RootDisabled: The global table root for this timestamp has been disabled
* - InvalidOperatorIndex: Operator index provided in nonSigner witness is invalid
* - NonSignerIndicesNotSorted: Non-signer witnesses are not strictly increasing by operatorIndex
* - VerificationFailed: Merkle proof verification failed or BLS signature verification failed
*/
function verifyCertificate(
Expand Down Expand Up @@ -156,6 +163,7 @@ interface IBN254CertificateVerifier is
* - ReferenceTimestampDoesNotExist: No operator table exists for the referenceTimestamp
* - RootDisabled: The global table root for this timestamp has been disabled
* - InvalidOperatorIndex: Operator index provided in nonSigner witness is invalid
* - NonSignerIndicesNotSorted: Non-signer witnesses are not strictly increasing by operatorIndex
* - VerificationFailed: Merkle proof verification failed or BLS signature verification failed
* - ArrayLengthMismatch: signedStakes length does not equal totalStakeProportionThresholds length
*/
Expand Down Expand Up @@ -186,6 +194,7 @@ interface IBN254CertificateVerifier is
* - ReferenceTimestampDoesNotExist: No operator table exists for the referenceTimestamp
* - RootDisabled: The global table root for this timestamp has been disabled
* - InvalidOperatorIndex: Operator index provided in nonSigner witness is invalid
* - NonSignerIndicesNotSorted: Non-signer witnesses are not strictly increasing by operatorIndex
* - VerificationFailed: Merkle proof verification failed or BLS signature verification failed
* - ArrayLengthMismatch: signedStakes length does not equal totalStakeNominalThresholds length
*/
Expand Down
8 changes: 8 additions & 0 deletions src/contracts/multichain/BN254CertificateVerifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -202,10 +202,16 @@ contract BN254CertificateVerifier is
BN254Certificate memory cert
) internal returns (BN254.G1Point memory nonSignerApk) {
nonSignerApk = BN254.G1Point(0, 0);
uint32 previousOperatorIndex = 0;

for (uint256 i = 0; i < cert.nonSignerWitnesses.length; i++) {
BN254OperatorInfoWitness memory witness = cert.nonSignerWitnesses[i];

if (i > 0) {
// Enforce strictly increasing order of non-signer operator indices
require(witness.operatorIndex > previousOperatorIndex, NonSignerIndicesNotSorted());
}

require(witness.operatorIndex < ctx.operatorSetInfo.numOperators, InvalidOperatorIndex());

BN254OperatorInfo memory operatorInfo =
Expand All @@ -219,6 +225,8 @@ contract BN254CertificateVerifier is
ctx.totalSignedStakeWeights[j] -= operatorInfo.weights[j];
}
}

previousOperatorIndex = witness.operatorIndex;
}
}

Expand Down