P256
Authors: Solady (https://github.com/vectorized/solady/blob/main/src/utils/P256.sol), Modified from Daimo P256 Verifier (https://github.com/daimo-eth/p256-verifier/blob/master/src/P256.sol), Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/P256.sol)
Gas optimized P256 wrapper.
Constants
VERIFIER
Address of the Solidity P256 verifier.
Please make sure the contract is deployed onto the chain you are working on.
See: https://gist.github.com/Vectorized/599b0d8a94d21bc74700eb1354e2f55c
Unlike RIP-7212, this verifier returns uint256(0) on failure, to
facilitate easier existence check. This verifier will also never revert.
address internal constant VERIFIER = 0x000000000000D01eA45F9eFD5c54f037Fa57Ea1a;CANARY
The existence of this contract, as determined by non-empty bytecode,
implies the existence of the RIP-7212 precompile.
See: https://gist.github.com/Vectorized/3c69dcf4604b9e1216525cabcd06ee34
This is to enable the optimization to skip the VERIFIER entirely
when the RIP_PRECOMPILE returns empty returndata for an invalid signature.
address internal constant CANARY = 0x0000000000001Ab2e8006Fd8B71907bf06a5BDEE;RIP_PRECOMPILE
Address of the RIP-7212 P256 verifier precompile. Currently, we don't support EIP-7212's precompile at 0x0b as it has not been finalized. See: https://github.com/ethereum/RIPs/blob/master/RIPS/rip-7212.md
address internal constant RIP_PRECOMPILE = 0x0000000000000000000000000000000000000100;N
The order of the secp256r1 elliptic curve.
uint256 internal constant N =
0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551;_HALF_N
N/2. Used for checking the malleability of the signature.
uint256 private constant _HALF_N =
0x7fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a8;Functions
verifySignatureAllowMalleability
Returns if the signature (r, s) is valid for hash and public key (x, y).
Does NOT include the malleability check.
function verifySignatureAllowMalleability(
bytes32 hash,
bytes32 r,
bytes32 s,
bytes32 x,
bytes32 y
) internal view returns (bool isValid);Parameters
| Name | Type | Description |
|---|---|---|
| hash | bytes32 | |
| r | bytes32 | |
| s | bytes32 | |
| x | bytes32 | |
| y | bytes32 |
Returns
| Name | Type | Description |
|---|---|---|
| isValid | bool |
verifySignature
Returns if the signature (r, s) is valid for hash and public key (x, y).
Includes the malleability check.
function verifySignature(bytes32 hash, bytes32 r, bytes32 s, bytes32 x, bytes32 y)
internal
view
returns (bool isValid);Parameters
| Name | Type | Description |
|---|---|---|
| hash | bytes32 | |
| r | bytes32 | |
| s | bytes32 | |
| x | bytes32 | |
| y | bytes32 |
Returns
| Name | Type | Description |
|---|---|---|
| isValid | bool |
hasPrecompile
Returns if the RIP-7212 precompile exists.
function hasPrecompile() internal view returns (bool result);Returns
| Name | Type | Description |
|---|---|---|
| result | bool |
hasPrecompileOrVerifier
Returns if either the RIP-7212 precompile or the verifier exists.
Since verifySignature is made not reverting, this function can be used to
manually implement a revert if the current chain does not have the contracts
to support secp256r1 signature recovery.
function hasPrecompileOrVerifier() internal view returns (bool result);Returns
| Name | Type | Description |
|---|---|---|
| result | bool |
normalized
Returns s normalized to the lower half of the curve.
function normalized(bytes32 s) internal pure returns (bytes32 result);Parameters
| Name | Type | Description |
|---|---|---|
| s | bytes32 |
Returns
| Name | Type | Description |
|---|---|---|
| result | bytes32 |
tryDecodePoint
Helper function for abi.decode(encoded, (bytes32, bytes32)).
If encoded.length < 64, (x, y) will be (0, 0), which is an invalid point.
function tryDecodePoint(bytes memory encoded) internal pure returns (bytes32 x, bytes32 y);Parameters
| Name | Type | Description |
|---|---|---|
| encoded | bytes |
Returns
| Name | Type | Description |
|---|---|---|
| x | bytes32 | |
| y | bytes32 |
tryDecodePointCalldata
Helper function for abi.decode(encoded, (bytes32, bytes32)).
If encoded.length < 64, (x, y) will be (0, 0), which is an invalid point.
function tryDecodePointCalldata(bytes calldata encoded)
internal
pure
returns (bytes32 x, bytes32 y);Parameters
| Name | Type | Description |
|---|---|---|
| encoded | bytes |
Returns
| Name | Type | Description |
|---|---|---|
| x | bytes32 | |
| y | bytes32 |