ECRecovery.sol 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. pragma solidity ^0.4.11;
  2. /**
  3. * Eliptic curve signature operations
  4. * Based on https://gist.github.com/axic/5b33912c6f61ae6fd96d6c4a47afde6d
  5. */
  6. library ECRecovery {
  7. // Duplicate Solidity's ecrecover, but catching the CALL return value
  8. function safeRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal returns (bool, address) {
  9. // We do our own memory management here. Solidity uses memory offset
  10. // 0x40 to store the current end of memory. We write past it (as
  11. // writes are memory extensions), but don't update the offset so
  12. // Solidity will reuse it. The memory used here is only needed for
  13. // this context.
  14. bool ret;
  15. address addr;
  16. assembly {
  17. let size := mload(0x40)
  18. mstore(size, hash)
  19. mstore(add(size, 32), v)
  20. mstore(add(size, 64), r)
  21. mstore(add(size, 96), s)
  22. // NOTE: we can reuse the request memory because we deal with
  23. // the return code
  24. ret := call(3000, 1, 0, size, 128, size, 32)
  25. addr := mload(size)
  26. }
  27. return (ret, addr);
  28. }
  29. function recover(bytes32 hash, bytes sig) internal returns (address) {
  30. bytes32 r;
  31. bytes32 s;
  32. uint8 v;
  33. if (sig.length != 65)
  34. return (address(0));
  35. assembly {
  36. r := mload(add(sig, 32))
  37. s := mload(add(sig, 64))
  38. v := byte(0, mload(add(sig, 96)))
  39. }
  40. // albeit non-transactional signatures are not specified by the YP, one would expect it
  41. // to match the YP range of [27, 28]
  42. //
  43. // geth uses [0, 1] and some clients have followed. This might change, see:
  44. // https://github.com/ethereum/go-ethereum/issues/2053
  45. if (v < 27)
  46. v += 27;
  47. if (v != 27 && v != 28)
  48. return (address(0));
  49. bool ret;
  50. address addr;
  51. (ret, addr) = safeRecover(hash, v, r, s);
  52. if (!ret)
  53. return address(0);
  54. else
  55. return addr;
  56. }
  57. }