Add a recover(bytes32,bytes32,bytes32) that follows EIP2098 (#2713)
This commit is contained in:
@ -28,15 +28,13 @@ library ECDSA {
|
|||||||
* - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
|
* - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
|
||||||
*/
|
*/
|
||||||
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
|
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
|
||||||
// Divide the signature in r, s and v variables
|
|
||||||
bytes32 r;
|
|
||||||
bytes32 s;
|
|
||||||
uint8 v;
|
|
||||||
|
|
||||||
// Check the signature length
|
// Check the signature length
|
||||||
// - case 65: r,s,v signature (standard)
|
// - case 65: r,s,v signature (standard)
|
||||||
// - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._
|
// - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._
|
||||||
if (signature.length == 65) {
|
if (signature.length == 65) {
|
||||||
|
bytes32 r;
|
||||||
|
bytes32 s;
|
||||||
|
uint8 v;
|
||||||
// ecrecover takes the signature parameters, and the only way to get them
|
// ecrecover takes the signature parameters, and the only way to get them
|
||||||
// currently is to use assembly.
|
// currently is to use assembly.
|
||||||
assembly {
|
assembly {
|
||||||
@ -44,25 +42,45 @@ library ECDSA {
|
|||||||
s := mload(add(signature, 0x40))
|
s := mload(add(signature, 0x40))
|
||||||
v := byte(0, mload(add(signature, 0x60)))
|
v := byte(0, mload(add(signature, 0x60)))
|
||||||
}
|
}
|
||||||
|
return recover(hash, v, r, s);
|
||||||
} else if (signature.length == 64) {
|
} else if (signature.length == 64) {
|
||||||
|
bytes32 r;
|
||||||
|
bytes32 vs;
|
||||||
// ecrecover takes the signature parameters, and the only way to get them
|
// ecrecover takes the signature parameters, and the only way to get them
|
||||||
// currently is to use assembly.
|
// currently is to use assembly.
|
||||||
assembly {
|
assembly {
|
||||||
let vs := mload(add(signature, 0x40))
|
|
||||||
r := mload(add(signature, 0x20))
|
r := mload(add(signature, 0x20))
|
||||||
s := and(vs, 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
|
vs := mload(add(signature, 0x40))
|
||||||
v := add(shr(255, vs), 27)
|
|
||||||
}
|
}
|
||||||
|
return recover(hash, r, vs);
|
||||||
} else {
|
} else {
|
||||||
revert("ECDSA: invalid signature length");
|
revert("ECDSA: invalid signature length");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Overload of {ECDSA-recover} that receives the `r` and `vs` short-signature fields separately.
|
||||||
|
*
|
||||||
|
* See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
|
||||||
|
*
|
||||||
|
* _Available since v4.2._
|
||||||
|
*/
|
||||||
|
function recover(
|
||||||
|
bytes32 hash,
|
||||||
|
bytes32 r,
|
||||||
|
bytes32 vs
|
||||||
|
) internal pure returns (address) {
|
||||||
|
bytes32 s;
|
||||||
|
uint8 v;
|
||||||
|
assembly {
|
||||||
|
s := and(vs, 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
|
||||||
|
v := add(shr(255, vs), 27)
|
||||||
|
}
|
||||||
return recover(hash, v, r, s);
|
return recover(hash, v, r, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Overload of {ECDSA-recover} that receives the `v`,
|
* @dev Overload of {ECDSA-recover} that receives the `v`, `r` and `s` signature fields separately.
|
||||||
* `r` and `s` signature fields separately.
|
|
||||||
*/
|
*/
|
||||||
function recover(
|
function recover(
|
||||||
bytes32 hash,
|
bytes32 hash,
|
||||||
|
|||||||
Reference in New Issue
Block a user