This repository has been archived by the owner on Sep 30, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 13
/
BLSValidator.sol
89 lines (68 loc) · 3.53 KB
/
BLSValidator.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.4 <0.9.0;
import {IKernelValidator, UserOperation} from "kernel/src/interfaces/IKernelValidator.sol";
import {ValidationData} from "kernel/src/common/Types.sol";
import {SIG_VALIDATION_FAILED, ValidationData} from "kernel/src/common/Constants.sol";
import {BLS} from "account-abstraction/samples/bls/lib/hubble-contracts/contracts/libs/BLS.sol";
/*//////////////////////////////////////////////////////////////////////////
THIS CONTRACT IS STILL IN ACTIVE DEVELOPMENT. NOT FOR PRODUCTION USE
//////////////////////////////////////////////////////////////////////////*/
// BLSValidator is a validator that uses BLS signatures to validate transactions.
// TODO: Consider account recovery, aggregate signatures, and use EIP 712.
// Note: This is not audited and should not be used in production.
contract BLSValidator is IKernelValidator {
bytes32 public constant BLS_DOMAIN = keccak256("eip4337.bls.domain");
event OwnerChanged(address indexed kernel, uint256[4] indexed oldPublicKey, uint256[4] indexed newPublicKey);
mapping(address => uint256[4]) public blsValidatorStorage;
function disable(bytes calldata) external payable override {
delete blsValidatorStorage[msg.sender];
}
function enable(bytes calldata _data) external payable override {
require(_data.length >= 128, "Calldata is not long enough for bls public key");
uint256[4] memory publicKey = abi.decode(_data, (uint256[4]));
uint256[4] memory oldPublicKey = blsValidatorStorage[msg.sender];
blsValidatorStorage[msg.sender] = publicKey;
emit OwnerChanged(msg.sender, oldPublicKey, publicKey);
}
function validateUserOp(UserOperation calldata _userOp, bytes32 _userOpHash, uint256)
external
payable
override
returns (ValidationData)
{
require(_userOp.signature.length == 64, "BLS Validator: Sig bytes length must be 64");
uint256[2] memory decodedSignature = abi.decode(_userOp.signature, (uint256[2]));
uint256[4] memory publicKey = blsValidatorStorage[_userOp.sender];
require(publicKey[0] != 0, "BLS Validator: Public key not set");
bytes memory hashBytes = abi.encodePacked(_userOpHash);
uint256[2] memory message = BLS.hashToPoint(
BLS_DOMAIN,
hashBytes
);
(bool verified, bool callSuccess) = BLS.verifySingle(decodedSignature, publicKey, message);
if (verified && callSuccess) {
return ValidationData.wrap(0);
}
// TODO: check if wallet recovered
return SIG_VALIDATION_FAILED;
}
function validateSignature(bytes32 hash, bytes calldata signature) public view override returns (ValidationData) {
require(signature.length == 64, "VG: Sig bytes length must be 64");
uint256[4] memory publicKey = blsValidatorStorage[msg.sender];
uint256[2] memory decodedSignature = abi.decode(signature, (uint256[2]));
bytes memory hashBytes = abi.encodePacked(hash);
uint256[2] memory message = BLS.hashToPoint(
BLS_DOMAIN,
hashBytes
);
(bool verified, bool callSuccess) = BLS.verifySingle(decodedSignature, publicKey, message);
if (verified && callSuccess) {
return ValidationData.wrap(0);
}
// TODO: check if wallet recovered
return SIG_VALIDATION_FAILED;
}
function validCaller(address caller, bytes calldata data) external view returns (bool) {
revert("Not implemented");
}
}