You are viewing a single comment's thread from:

RE: Solidity开发指南

in #starnote3 days ago
//v,s,r这三个参数是链下私钥签名签出来的, 这三个参数可以合成一个传给合约然后在合约里面做分割
function test(address owner, address sender, uint256 amount, bytes calldata sign) public {
    bytes32 digest = keccak256(abi.encodePacked(keccak256(abi.encode(sender, amount))));
    require(ecrecovery(digest, sign) == owner, "Sign Validation Failed");
}

function ecrecovery(bytes32 hash, bytes memory sig) private pure returns (address) {
    bytes32 r;
    bytes32 s;
    uint8 v;

    if (sig.length != 65) {
      return address(0);
    }

    assembly {
      r := mload(add(sig, 32))
      s := mload(add(sig, 64))
      v := and(mload(add(sig, 65)), 255)
    }

    // https://github.com/ethereum/go-ethereum/issues/2053
    if (v < 27) {
      v += 27;
    }

    if (v != 27 && v != 28) {
      return address(0);
    }

    /* prefix might be needed for geth only
    * https://github.com/ethereum/go-ethereum/issues/3731
    */
    // bytes memory prefix = "\x19Ethereum Signed Message:\n32";
    // hash = sha3(prefix, hash);

    return ecrecover(hash, v, r, s);
}

//
ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address)
利用椭圆曲线签名恢复与公钥相关的地址,错误返回零值。
函数参数对应于 ECDSA签名的值:
r = 签名的前 32 字节
s = 签名的第232 字节
v = 签名的最后一个字节
ecrecover 返回一个 address, 而不是 address payable 。他们之前的转换参考 address payable ,如果需要转移资金到恢复的地址。