Files
smom-dbis-138/contracts/mainnet-checkpoint/extensions/ValidatorSigVerifierExtension.sol

72 lines
2.6 KiB
Solidity
Raw Normal View History

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {CheckpointExtensionBase} from "./CheckpointExtensionBase.sol";
import {CheckpointStorage} from "../storage/CheckpointStorage.sol";
import {CheckpointEIP712} from "../libraries/CheckpointEIP712.sol";
import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
/// @notice Validator registry + ECDSA recovery for batch attestations and 65-byte sig bundles.
contract ValidatorSigVerifierExtension is CheckpointExtensionBase {
using ECDSA for bytes32;
mapping(address => bool) public validators;
uint256 public threshold;
address public verifyingContract;
event ValidatorSetUpdated(address[] validators, uint256 threshold);
function HOOK_BEFORE_SUBMIT() external pure override returns (uint32) {
return 1 << 0;
}
function HOOK_AFTER_SUBMIT() external pure override returns (uint32) {
return 0;
}
function HOOK_ON_CCIP() external pure override returns (uint32) {
return 0;
}
function setVerifyingContract(address hub) external {
verifyingContract = hub;
}
function setValidators(address[] calldata addrs, uint256 newThreshold) external {
for (uint256 i = 0; i < addrs.length; i++) {
validators[addrs[i]] = true;
}
threshold = newThreshold;
emit ValidatorSetUpdated(addrs, newThreshold);
}
function beforeSubmit(CheckpointStorage.CheckpointHeader calldata header, bytes calldata validatorSignatures)
external
view
{
if (threshold == 0) return;
require(verifyingContract != address(0), "verifier unset");
bytes32 digest = CheckpointEIP712.digest(verifyingContract, block.chainid, header);
if (validatorSignatures.length == 65) {
address signer = ECDSA.recover(digest, validatorSignatures);
require(validators[signer], "attest signer");
return;
}
require(validatorSignatures.length >= threshold * 65, "sig length");
uint256 valid;
for (uint256 i = 0; i + 65 <= validatorSignatures.length; i += 65) {
bytes memory sig = new bytes(65);
for (uint256 j = 0; j < 65; j++) {
sig[j] = validatorSignatures[i + j];
}
address signer = ECDSA.recover(digest, sig);
if (validators[signer]) valid++;
}
require(valid >= threshold, "threshold");
}
function afterSubmit(CheckpointStorage.CheckpointHeader calldata, bytes calldata) external pure override {}
function onCCIPReceive(bytes calldata) external pure override {}
}