コード例 #1
0
ファイル: validation.py プロジェクト: dad1x/concent
def validate_task_to_compute(task_to_compute: message.TaskToCompute) -> None:
    if not isinstance(task_to_compute, message.TaskToCompute):
        raise ConcentValidationError(
            f"Expected TaskToCompute instead of {type(task_to_compute).__name__}.",
            error_code=ErrorCode.MESSAGE_INVALID,
        )

    if any(
            map(lambda x: x is None, [
                getattr(task_to_compute, attribute) for attribute in [
                    'compute_task_def', 'provider_public_key',
                    'requestor_public_key'
                ]
            ])):
        raise ConcentValidationError(
            "Invalid TaskToCompute",
            error_code=ErrorCode.MESSAGE_WRONG_FIELDS,
        )

    validate_compute_task_def(task_to_compute.compute_task_def)

    validate_hex_public_key(task_to_compute.provider_public_key,
                            'provider_public_key')
    validate_hex_public_key(task_to_compute.requestor_public_key,
                            'requestor_public_key')
    validate_secure_hash_algorithm(task_to_compute.package_hash)
    validate_positive_integer_value(task_to_compute.price)
コード例 #2
0
def validate_compute_task_def(compute_task_def: message.tasks.ComputeTaskDef) -> None:
    string_fields = ["output_format", "scene_file"]
    other_mandatory_fields = ["frames"]

    validate_value_is_int_convertible_and_positive(compute_task_def['deadline'])

    validate_id_value(compute_task_def['task_id'], 'task_id')
    validate_id_value(compute_task_def['subtask_id'], 'subtask_id')

    extra_data = compute_task_def.get("extra_data")
    if extra_data is None:
        raise ConcentValidationError(
            "'extra_data' is missing in ComputeTaskDef",
            ErrorCode.MESSAGE_INVALID
        )

    for mandatory_data in string_fields + other_mandatory_fields:
        if mandatory_data not in extra_data:
            raise ConcentValidationError(
                f"{mandatory_data} is missing in ComputeTaskDef",
                ErrorCode.MESSAGE_INVALID
            )

    validate_frames(extra_data["frames"])

    for string_field in string_fields:
        if not isinstance(extra_data[string_field], str):
            raise ConcentValidationError(
                f"{string_field} should be string",
                ErrorCode.MESSAGE_VALUE_NOT_STRING
            )

    validate_scene_file(extra_data['scene_file'])
コード例 #3
0
ファイル: validation.py プロジェクト: robertdigital/concent
def validate_task_to_compute(task_to_compute: message.TaskToCompute) -> None:
    if not isinstance(task_to_compute, message.TaskToCompute):
        raise ConcentValidationError(
            f"Expected TaskToCompute instead of {type(task_to_compute).__name__}.",
            error_code=ErrorCode.MESSAGE_INVALID,
        )

    if any(
            map(lambda x: x is None, [
                getattr(task_to_compute, attribute) for attribute in [
                    'compute_task_def', 'provider_public_key',
                    'requestor_public_key'
                ]
            ])):
        raise ConcentValidationError(
            "Invalid TaskToCompute",
            error_code=ErrorCode.MESSAGE_WRONG_FIELDS,
        )
    if not task_to_compute.verify_all_promissory_notes(
            deposit_contract_address=settings.GNT_DEPOSIT_CONTRACT_ADDRESS):
        raise ConcentValidationError(
            "The signature of the PromissiryNote for the Provider, which should be signed by Requestor is incorrect",
            error_code=ErrorCode.MESSAGE_INVALID,
        )

    validate_compute_task_def(task_to_compute.compute_task_def)
    validate_hex_public_key(task_to_compute.provider_public_key,
                            'provider_public_key')
    validate_hex_public_key(task_to_compute.requestor_public_key,
                            'requestor_public_key')
    validate_secure_hash_algorithm(task_to_compute.package_hash)
    validate_positive_task_price(task_to_compute.price)
コード例 #4
0
ファイル: validation.py プロジェクト: robertdigital/concent
def validate_samples(samples: int) -> None:
    if not isinstance(samples, int):
        raise ConcentValidationError(
            'samples must be integer',
            ErrorCode.MESSAGE_INVALID,
        )
    if samples < 0:
        raise ConcentValidationError(
            'samples must be bigger or equal zero',
            ErrorCode.MESSAGE_INVALID,
        )
コード例 #5
0
ファイル: validation.py プロジェクト: robertdigital/concent
def validate_scene_file(scene_file: str) -> None:
    if not scene_file.endswith(SCENE_FILE_EXTENSION):
        raise ConcentValidationError(
            f'{scene_file} must ends with {SCENE_FILE_EXTENSION} filename extension',
            ErrorCode.MESSAGE_INVALID)

    if not any(
            scene_file.startswith(file_path)
            for file_path in VALID_SCENE_FILE_PREFIXES):
        raise ConcentValidationError(
            f'{scene_file} path must starts with one of {VALID_SCENE_FILE_PREFIXES} paths',
            ErrorCode.MESSAGE_INVALID)
コード例 #6
0
ファイル: validation.py プロジェクト: robertdigital/concent
def validate_uuid(id_: str) -> None:
    if not isinstance(id_, str):
        raise ConcentValidationError(
            f'ID must be string with maximum {MESSAGE_TASK_ID_MAX_LENGTH} characters length',
            error_code=ErrorCode.MESSAGE_WRONG_UUID_TYPE)
    try:
        UUID(id_, version=4)
    except ValueError:
        raise ConcentValidationError(
            'ID must be a UUID derivative.',
            error_code=ErrorCode.MESSAGE_WRONG_UUID_VALUE,
        )
コード例 #7
0
def get_validated_client_public_key_from_client_message(golem_message: message.base.Message):
    if isinstance(golem_message, message.concents.ForcePayment):
        if (
            isinstance(golem_message.subtask_results_accepted_list, list) and
            len(golem_message.subtask_results_accepted_list) > 0
        ):
            task_to_compute = golem_message.subtask_results_accepted_list[0].task_to_compute
        else:
            raise ConcentValidationError(
                "subtask_results_accepted_list must be a list type and contains at least one message",
                error_code=ErrorCode.MESSAGE_VALUE_WRONG_LENGTH,
            )

    elif isinstance(golem_message, message.tasks.TaskMessage):
        if not golem_message.is_valid():
            raise GolemMessageValidationError(
                "Golem message invalid",
                error_code=ErrorCode.MESSAGE_INVALID
            )
        task_to_compute = golem_message.task_to_compute
    else:
        raise ConcentValidationError(
            "Unknown message type",
            error_code=ErrorCode.MESSAGE_UNKNOWN,
        )

    if task_to_compute is not None:
        if isinstance(golem_message, (
            message.ForceReportComputedTask,
            message.concents.ForceSubtaskResults,
            message.concents.ForcePayment,
            message.concents.SubtaskResultsVerify,
        )):
            client_public_key = task_to_compute.provider_public_key
            validate_hex_public_key(client_public_key, 'provider_public_key')
        elif isinstance(golem_message, (
            message.AckReportComputedTask,
            message.RejectReportComputedTask,
            message.concents.ForceGetTaskResult,
            message.concents.ForceSubtaskResultsResponse,
        )):
            client_public_key = task_to_compute.requestor_public_key
            validate_hex_public_key(client_public_key, 'requestor_public_key')
        else:
            raise ConcentValidationError(
                "Unknown message type",
                error_code=ErrorCode.MESSAGE_UNKNOWN,
            )

        return hex_to_bytes_convert(client_public_key)

    return None
コード例 #8
0
ファイル: validation.py プロジェクト: robertdigital/concent
def validate_subtask_results_verify(msg: SubtaskResultsVerify,
                                    deposit_contract_address: str) -> None:
    if not msg.verify_concent_promissory_note(deposit_contract_address):
        raise ConcentValidationError(
            "The signature of the PromissiryNote for Concent is incorrect",
            error_code=ErrorCode.MESSAGE_INVALID,
        )
コード例 #9
0
ファイル: validation.py プロジェクト: robertdigital/concent
def validate_blender_output_format(output_format: str) -> None:
    if adjust_format_name(
            output_format
    ) not in BlenderSubtaskDefinition.OutputFormat.__members__.keys():
        raise ConcentValidationError(
            f'Unsupported Blender format!',
            error_code=ErrorCode.MESSAGE_VALUE_NOT_ALLOWED)
コード例 #10
0
ファイル: validation.py プロジェクト: dad1x/concent
def validate_all_messages_identical(
        golem_messages_list: List[message.Message]) -> None:
    assert isinstance(golem_messages_list, list)
    assert len(golem_messages_list) >= 1
    assert all(
        isinstance(golem_message, message.Message)
        for golem_message in golem_messages_list)
    assert len(
        set(type(golem_message) for golem_message in golem_messages_list)) == 1

    base_golem_message = golem_messages_list[0]

    for i, golem_message in enumerate(golem_messages_list[1:], start=1):
        for slot in base_golem_message.__slots__:
            if getattr(base_golem_message, slot) != getattr(
                    golem_message, slot):
                raise ConcentValidationError(
                    '{} messages are not identical. '
                    'There is a difference between messages with index 0 on passed list and with index {}'
                    'The difference is on field {}: {} is not equal {}'.format(
                        type(base_golem_message).__name__,
                        i,
                        slot,
                        getattr(base_golem_message, slot),
                        getattr(golem_message, slot),
                    ),
                    error_code=ErrorCode.MESSAGES_NOT_IDENTICAL,
                )
コード例 #11
0
def validate_golem_message_subtask_results_rejected(subtask_results_rejected: message.tasks.SubtaskResultsRejected):
    if not isinstance(subtask_results_rejected,  message.tasks.SubtaskResultsRejected):
        raise ConcentValidationError(
            "subtask_results_rejected should be of type:  SubtaskResultsRejected",
            error_code=ErrorCode.MESSAGE_INVALID,
        )
    validate_task_to_compute(subtask_results_rejected.report_computed_task.task_to_compute)
コード例 #12
0
def validate_positive_integer_value(value):
    validate_expected_value_type(value, 'value', int)

    if value < 0:
        raise ConcentValidationError(
            "Value cannot be an negative value",
            error_code=ErrorCode.MESSAGE_VALUE_NEGATIVE,
        )
コード例 #13
0
ファイル: validation.py プロジェクト: robertdigital/concent
def validate_value_is_int_convertible(value: int) -> None:
    try:
        int(value)
    except (ValueError, TypeError):
        raise ConcentValidationError(
            "Wrong type, expected a value that can be converted to an integer.",
            error_code=ErrorCode.MESSAGE_VALUE_NOT_INTEGER,
        )
コード例 #14
0
def validate_report_computed_task_time_window(report_computed_task):
    assert isinstance(report_computed_task, message.ReportComputedTask)

    if report_computed_task.timestamp < report_computed_task.task_to_compute.timestamp:
        raise ConcentValidationError(
            "ReportComputedTask timestamp is older then nested TaskToCompute.",
            error_code=ErrorCode.MESSAGE_TIMESTAMP_TOO_OLD,
        )
コード例 #15
0
def validate_expected_value_type(
    value,
    value_name: str,
    expected_type,
):
    if not isinstance(value, expected_type):
        raise ConcentValidationError(
            f"{value_name} must be {expected_type.__name__}.",
            error_code=ErrorCode.MESSAGE_VALUE_WRONG_TYPE,
        )
コード例 #16
0
def validate_id_value(value, field_name):
    validate_expected_value_type(value, field_name, str)

    if value == '':
        raise ConcentValidationError(
            "{} cannot be blank.".format(field_name),
            error_code=ErrorCode.MESSAGE_VALUE_BLANK,
        )

    if len(value) > MESSAGE_TASK_ID_MAX_LENGTH:
        raise ConcentValidationError(
            "{} cannot be longer than {} chars.".format(field_name, MESSAGE_TASK_ID_MAX_LENGTH),
            error_code=ErrorCode.MESSAGE_VALUE_WRONG_LENGTH,
        )

    if VALID_ID_REGEX.fullmatch(value) is None:
        raise ConcentValidationError(
            f'{field_name} must contain only alphanumeric chars.',
            error_code=ErrorCode.MESSAGE_VALUE_NOT_ALLOWED,
        )
コード例 #17
0
ファイル: validation.py プロジェクト: robertdigital/concent
def validate_key_with_desired_parameters(key_name: str, key_value: Union[bytes,
                                                                         str],
                                         expected_type: Any,
                                         expected_length: int) -> None:
    validate_expected_value_type(key_value, key_name, expected_type)

    if len(key_value) != expected_length:
        raise ConcentValidationError(
            "The length of {} must be exactly {} characters.".format(
                key_name, expected_length),
            error_code=ErrorCode.MESSAGE_VALUE_WRONG_LENGTH,
        )
コード例 #18
0
ファイル: validation.py プロジェクト: robertdigital/concent
def validate_resolution(resolution: List[float]) -> None:
    if not isinstance(resolution, list):
        raise ConcentValidationError(
            'resolution is not a list',
            ErrorCode.MESSAGE_INVALID,
        )
    if len(resolution) != 2:
        raise ConcentValidationError(
            'resolution must contain exactly 2 values',
            ErrorCode.MESSAGE_INVALID,
        )
    for element in resolution:
        if not isinstance(element, int):
            raise ConcentValidationError(
                'resolution is not a list of integers',
                ErrorCode.MESSAGE_INVALID,
            )
        if element <= 0:
            raise ConcentValidationError(
                'resolution must contain positive integers',
                ErrorCode.MESSAGE_INVALID,
            )
コード例 #19
0
ファイル: validation.py プロジェクト: robertdigital/concent
def validate_blender_script_parameters(extra_data: Any) -> None:
    mandatory_fields = ['resolution', 'use_compositing', 'samples', 'crops']

    for field in mandatory_fields:
        if field not in extra_data:
            raise ConcentValidationError(
                f"{field} is missing in 'extra_data' in ComputeTaskDef",
                ErrorCode.MESSAGE_INVALID,
            )
    validate_resolution(extra_data['resolution'])
    validate_use_compositing(extra_data['use_compositing'])
    validate_samples(extra_data['samples'])
    validate_crops(extra_data['crops'])
コード例 #20
0
def validate_value_is_int_convertible_and_positive(value):
    """
    Checks if value is an integer. If not, tries to cast it to an integer.
    Then checks if value is non-negative.

    """
    if not isinstance(value, int):
        try:
            value = int(value)
        except (ValueError, TypeError):
            raise ConcentValidationError(
                "Wrong type, expected a value that can be converted to an integer.",
                error_code=ErrorCode.MESSAGE_VALUE_NOT_INTEGER,
            )
    validate_positive_integer_value(value)
コード例 #21
0
ファイル: validation.py プロジェクト: robertdigital/concent
def validate_crops(crops: List[Dict[str, List[float]]]) -> None:
    if not isinstance(crops, list):
        raise ConcentValidationError(
            "crops field in 'extra_data' must be a list",
            ErrorCode.MESSAGE_INVALID,
        )
    if len(crops) != 1:
        raise ConcentValidationError(
            "crops field must contain exactly one dict with borders details",
            ErrorCode.MESSAGE_INVALID,
        )
    crop_details = crops[0]
    mandatory_fields = ['borders_x', 'borders_y']
    for field in mandatory_fields:
        if field not in crop_details:
            raise ConcentValidationError(
                f'{field} does not exist in crop_details dict',
                ErrorCode.MESSAGE_INVALID,
            )
        if not isinstance(crop_details[field], list):
            raise ConcentValidationError(
                f'{field} is not a list',
                ErrorCode.MESSAGE_INVALID,
            )
        if len(crop_details[field]) != 2:
            raise ConcentValidationError(f'{field} must have exactly 2 fields',
                                         ErrorCode.MESSAGE_INVALID)
        for border in crop_details[field]:
            if not isinstance(border, float):
                raise ConcentValidationError(
                    f'{field} must contain float borders',
                    ErrorCode.MESSAGE_INVALID,
                )
            if border > 1.0 or border < 0.0:
                raise ConcentValidationError(
                    f'Border in {field} must has value between 0.0 and 1.0',
                    ErrorCode.MESSAGE_INVALID,
                )
        if crop_details[field][0] >= crop_details[field][1]:
            raise ConcentValidationError(
                f'Minimum of {field} can not be bigger or equal maximum',
                ErrorCode.MESSAGE_INVALID,
            )
コード例 #22
0
ファイル: validation.py プロジェクト: robertdigital/concent
def validate_all_messages_identical(
        golem_messages_list: List[message.Message]) -> None:
    assert isinstance(golem_messages_list, list)
    assert len(golem_messages_list) >= 1
    assert all(
        isinstance(golem_message, message.Message)
        for golem_message in golem_messages_list)
    assert len(
        set(type(golem_message) for golem_message in golem_messages_list)) == 1

    base_golem_message = golem_messages_list[0]

    for golem_message in golem_messages_list[1:]:
        if base_golem_message != golem_message:
            raise ConcentValidationError(
                f'Messages {base_golem_message.__class__.__name__} are not identical',
                error_code=ErrorCode.MESSAGES_NOT_IDENTICAL,
            )
コード例 #23
0
def validate_scene_file(scene_file):
    if not scene_file.endswith('.blend'):
        raise ConcentValidationError(
            f'{scene_file} must ends with ".blend" filename extension',
            ErrorCode.MESSAGE_INVALID
        )
コード例 #24
0
ファイル: validation.py プロジェクト: robertdigital/concent
def validate_use_compositing(use_compositing: bool) -> None:
    if not isinstance(use_compositing, bool):
        raise ConcentValidationError(
            'use_compositing must be a boolean',
            ErrorCode.MESSAGE_INVALID,
        )