https://solidity.readthedocs.io/en/latest/units-and-global-variables.html#mathematical-and-cryptographic-functions
-
ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address)
: - recover the address associated with the public key from elliptic curve signature or return zero on error ( example usage)
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