code: func (api *SignerAPI) EcRecover(ctx context.Context, data hexutil.Bytes, sig hexutil.Bytes) (common.Address, error) {
  	// Returns the address for the Account that was used to create the signature.
  	//
  	// Note, this function is compatible with eth_sign and personal_sign. As such it recovers
  	// the address of:
  	// hash = keccak256("\x19${byteVersion}Ethereum Signed Message:\n${message length}${message}")
  	// addr = ecrecover(hash, signature)
  	//
  	// Note, the signature must conform to the secp256k1 curve R, S and V values, where
  	// the V value must be be 27 or 28 for legacy reasons.
  	//
  	// https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_ecRecover
  	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
  	hash := accounts.TextHash(data)
  	rpk, err := crypto.SigToPub(hash, sig)
  	if err != nil {
  		return common.Address{}, err
  	}
  	return crypto.PubkeyToAddress(*rpk), nil
  }
docs: // EcRecover recovers the address associated with the given sig.
  // Only compatible with `text/plain`