def test_structured_data_invalid_identifier_filtered_by_regex():
    invalid_structured_data_string = open(
        "tests/fixtures/invalid_struct_identifier_message.json"
    ).read()
    with pytest.raises(ValidationError) as e:
        load_and_validate_structured_message(invalid_structured_data_string)
    assert str(e.value) == "Invalid Identifier `hello wallet` in `Person`"
def test_structured_data_invalid_type_filtered_by_regex():
    invalid_structured_data_string = open(
        "tests/fixtures/invalid_struct_type_message.json"
    ).read()
    with pytest.raises(ValidationError) as e:
        load_and_validate_structured_message(invalid_structured_data_string)
    assert str(e.value) == "Invalid Type `Hello Person` in `Mail`"
Esempio n. 3
0
def encode_structured_data(primitive: Union[bytes, int, Mapping] = None,
                           *,
                           hexstr: str = None,
                           text: str = None) -> SignableMessage:
    """
    Encode an EIP-712_ message.

    EIP-712 is the "structured data" approach (ie~ version 1 of an EIP-191 message).

    Supply the message as exactly one of the three arguments:

        - primitive, as a dict that defines the structured data
        - primitive, as bytes
        - text, as a json-encoded string
        - hexstr, as a hex-encoded (json-encoded) string

    .. WARNING:: Note that this code has not gone through an external audit, and
        the test cases are incomplete.
        Also, watch for updates to the format, as the EIP is still in DRAFT.

    :param primitive: the binary message to be signed
    :type primitive: bytes or int or Mapping (eg~ dict )
    :param hexstr: the message encoded as hex
    :param text: the message as a series of unicode characters (a normal Py3 str)
    :returns: The EIP-191 encoded message, ready for signing

    .. _EIP-712: https://eips.ethereum.org/EIPS/eip-712
    """
    if isinstance(primitive, Mapping):
        validate_structured_data(primitive)
        structured_data = primitive
    else:
        message_string = to_text(primitive, hexstr=hexstr, text=text)
        structured_data = load_and_validate_structured_message(message_string)
    return SignableMessage(
        HexBytes(b'\x01'),
        hash_domain(structured_data),
        hash_eip712_message(structured_data),
    )
Esempio n. 4
0
def signature_wrapper(message, signature_version, version_specific_data):
    if not isinstance(message, bytes):
        raise TypeError("Message is of the type {}, expected bytes".format(
            type(message)))
    if not isinstance(signature_version, bytes):
        raise TypeError(
            "Signature Version is of the type {}, expected bytes".format(
                type(signature_version)))

    if signature_version == PERSONAL_SIGN_VERSION:
        preamble = b'\x19Ethereum Signed Message:\n'
        size = str(len(message)).encode('utf-8')
        return preamble + size + message
    elif signature_version == INTENDED_VALIDATOR_SIGN_VERSION:
        wallet_address = to_bytes(hexstr=version_specific_data)
        if len(wallet_address) != 20:
            raise TypeError(
                "Invalid Wallet Address: {}".format(version_specific_data))
        wrapped_message = b'\x19' + signature_version + wallet_address + message
        return wrapped_message
    elif signature_version == STRUCTURED_DATA_SIGN_VERSION:
        message_string = to_text(primitive=message)
        structured_data = load_and_validate_structured_message(message_string)
        domainSeparator = hash_domain(structured_data)
        wrapped_message = (b'\x19' + signature_version + domainSeparator +
                           hash_message(structured_data))
        return wrapped_message
    else:
        raise NotImplementedError(
            "Currently supported signature versions are: {0}, {1}, {2}. ".
            format(
                '0x' + INTENDED_VALIDATOR_SIGN_VERSION.hex(),
                '0x' + PERSONAL_SIGN_VERSION.hex(),
                '0x' + STRUCTURED_DATA_SIGN_VERSION.hex(),
            ) + "But received signature version {}".format(
                '0x' + signature_version.hex()))