https://solidity.readthedocs.io/en/latest/units-and-global-variables.html#mathematical-and-cryptographic-functions
- recover the address associated with the public key from elliptic curve signature or return zero on error ( example usage)
ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address)
:
It might be that you run into Out-of-Gas for sha256
, ripemd160
or ecrecover
on a private blockchain. The reason for this is that those are implemented as so-called precompiled contracts and these contracts only really exist after they received the first message (although their contract code is hardcoded). Messages to non-existing contracts are more expensive and thus the execution runs into an Out-of-Gas error. A workaround for this problem is to first send e.g. 1 Wei to each of the contracts before you use them in your actual contracts. This is not an issue on the official or test net.
ecrecover
的思想是,可以计算对应于用于创建ECDSA
签名的私钥的公钥,这两个额外的字节通常是由签名提供的。签名本身是椭圆曲线点R和S的两个(编码),而V是恢复公钥所需的两个附加位。
这也解释了为什么返回类型是地址:它返回对应于恢复的公钥(即其sha3/keccak的哈希)的地址。这意味着要实际验证签名,检查返回的地址是否等于相应的私钥应该已经签署哈希的那个地址。
找到了这个接口的代码:
// https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_ecRecover func (s *PrivateAccountAPI) EcRecover(ctx context.Context, data, sig hexutil.Bytes) (common.Address, error) { if len(sig) != 65 { return common.Address{}, fmt.Errorf("signature must be 65 bytes long") } if sig[64] != 27 && sig[64] != 28 { return common.Address{}, fmt.Errorf("invalid Ethereum signature (V is not 27 or 28)") } sig[64] -= 27 // Transform yellow paper V from 27/28 to 0/1 rpk, err := crypto.Ecrecover(signHash(data), sig) if err != nil { return common.Address{}, err } pubKey := crypto.ToECDSAPub(rpk) recoveredAddr := crypto.PubkeyToAddress(*pubKey) return recoveredAddr, nil }
从这里我们可以看见,如果你使用web3来调用geth,你的v只有27,28两种选择,不会有分叉中的35,36
https://github.com/ethereum/go-ethereum/blob/55599ee95d4151a2502465e0afc7c47bd1acba77/internal/ethapi/api.go#L452-L459
这是所有api接口的内部实现代码,go-ethereum/internal/ethapi/api.go