eth_recover address from data hash and signature

def recover(
        data: bytes,
        signature: Signature,
        hasher: Callable[[bytes], bytes] = eth_sign_sha3,
) -> Address:
    """ eth_recover address from data hash and signature """
    _hash = hasher(data)

    # ecdsa_recover accepts only standard [0,1] v's so we add support also for [27,28] here
    # anything else will raise BadSignature
    if signature[-1] >= 27:  # support (0,1,27,28) v values
        signature = Signature(signature[:-1] + bytes([signature[-1] - 27]))

    try:
        sig = keys.Signature(signature_bytes=signature)
        public_key = keys.ecdsa_recover(message_hash=_hash, signature=sig)
    except BadSignature as e:
        raise InvalidSignature from e
    return public_key.to_canonical_address()