def test_case_2c_send_force_payment_with_no_value_to_be_paid(
        cluster_consts: ProtocolConstants, cluster_url: str) -> None:
    #  Test CASE 2C - Send ForcePayment with no value to be paid
    receive_pending_messages_for_requestor_and_provider(
        cluster_url, sci_base, CONCENT_PUBLIC_KEY)
    current_time = get_current_utc_timestamp()
    api_request(
        cluster_url,
        'send',
        sci_base.provider_private_key,
        CONCENT_PUBLIC_KEY,
        force_payment(
            timestamp=timestamp_to_isoformat(current_time),
            subtask_results_accepted_list=[
                create_signed_subtask_results_accepted(
                    timestamp=timestamp_to_isoformat(
                        current_time - cluster_consts.payment_due_time +
                        AVERAGE_TIME_FOR_TWO_BLOCKS),
                    payment_ts=current_time - cluster_consts.payment_due_time -
                    AVERAGE_TIME_FOR_TWO_BLOCKS,
                    report_computed_task=create_signed_report_computed_task(
                        task_to_compute=create_signed_task_to_compute(
                            timestamp=parse_timestamp_to_utc_datetime(
                                current_time),
                            deadline=current_time,
                            price=0,
                            provider_public_key=sci_base.provider_public_key,
                            provider_private_key=sci_base.provider_private_key,
                            requestor_public_key=sci_base.requestor_public_key,
                            requestor_private_key=sci_base.
                            requestor_private_key,
                        ),
                        provider_private_key=sci_base.provider_private_key),
                    requestor_private_key=sci_base.requestor_private_key,
                ),
                create_signed_subtask_results_accepted(
                    timestamp=timestamp_to_isoformat(
                        current_time - cluster_consts.payment_due_time +
                        AVERAGE_TIME_FOR_TWO_BLOCKS),
                    payment_ts=current_time - cluster_consts.payment_due_time -
                    AVERAGE_TIME_FOR_TWO_BLOCKS,
                    report_computed_task=create_signed_report_computed_task(
                        task_to_compute=create_signed_task_to_compute(
                            timestamp=parse_timestamp_to_utc_datetime(
                                current_time),
                            deadline=current_time,
                            price=0,
                            provider_public_key=sci_base.provider_public_key,
                            provider_private_key=sci_base.provider_private_key,
                            requestor_public_key=sci_base.requestor_public_key,
                            requestor_private_key=sci_base.
                            requestor_private_key,
                        ),
                        provider_private_key=sci_base.provider_private_key),
                    requestor_private_key=sci_base.requestor_private_key,
                ),
            ]),
        expected_status=200,
        expected_message_type=message.concents.ServiceRefused,
    )
def test_case_3_test_for_invalid_time(cluster_consts: ProtocolConstants, cluster_url: str) -> None:  # pylint: disable=unused-argument
    receive_pending_messages_for_requestor_and_provider(
        cluster_url,
        sci_base,
        CONCENT_PUBLIC_KEY
    )
    current_time = get_current_utc_timestamp()

    file_content = 'test'
    file_size = len(file_content)
    file_check_sum = 'sha1:' + hashlib.sha1(file_content.encode()).hexdigest()

    api_request(
        cluster_url,
        'send',
        sci_base.provider_private_key,
        CONCENT_PUBLIC_KEY,
        get_subtask_results_verify(
            current_time,
            reason=message.tasks.SubtaskResultsRejected.REASON.VerificationNegative,
            report_computed_task_size=file_size,
            report_computed_task_package_hash=file_check_sum,
            task_to_compute_size=file_size,
            task_to_compute_package_hash=file_check_sum,
            is_verification_deadline_before_current_time=True,
            additional_verification_call_time=cluster_consts.additional_verification_call_time,
            minimum_upload_rate=cluster_consts.minimum_upload_rate,
            render_parameters=get_render_params()
        ),
        expected_status=200,
        expected_message_type=message.concents.ServiceRefused,
        expected_content_type='application/octet-stream',
    )
def test_case_2b_send_force_payment_beyond_payment_time(
        cluster_consts: ProtocolConstants, cluster_url: str) -> None:
    #  Test CASE 2B - Send ForcePayment beyond payment time
    receive_pending_messages_for_requestor_and_provider(
        cluster_url, sci_base, CONCENT_PUBLIC_KEY)
    current_time = get_current_utc_timestamp()
    api_request(
        cluster_url,
        'send',
        sci_base.provider_private_key,
        CONCENT_PUBLIC_KEY,
        force_payment(
            timestamp=timestamp_to_isoformat(current_time),
            subtask_results_accepted_list=[
                create_signed_subtask_results_accepted(
                    timestamp=timestamp_to_isoformat(current_time),
                    payment_ts=current_time,
                    report_computed_task=create_signed_report_computed_task(
                        task_to_compute=create_signed_task_to_compute(
                            timestamp=parse_timestamp_to_utc_datetime(
                                current_time),
                            deadline=current_time,
                            price=15000,
                            provider_public_key=sci_base.provider_public_key,
                            provider_private_key=sci_base.provider_private_key,
                            requestor_public_key=sci_base.requestor_public_key,
                            requestor_private_key=sci_base.
                            requestor_private_key,
                        ),
                        provider_private_key=sci_base.provider_private_key,
                    ),
                    requestor_private_key=sci_base.requestor_private_key),
                create_signed_subtask_results_accepted(
                    timestamp=timestamp_to_isoformat(
                        current_time - cluster_consts.payment_due_time +
                        AVERAGE_TIME_FOR_TWO_BLOCKS),
                    payment_ts=current_time - cluster_consts.payment_due_time -
                    AVERAGE_TIME_FOR_TWO_BLOCKS,
                    report_computed_task=create_signed_report_computed_task(
                        task_to_compute=create_signed_task_to_compute(
                            timestamp=parse_timestamp_to_utc_datetime(
                                current_time),
                            deadline=current_time,
                            price=15000,
                            provider_public_key=sci_base.provider_public_key,
                            provider_private_key=sci_base.provider_private_key,
                            requestor_public_key=sci_base.requestor_public_key,
                            requestor_private_key=sci_base.
                            requestor_private_key,
                        ),
                        provider_private_key=sci_base.provider_private_key,
                    ),
                    requestor_private_key=sci_base.requestor_private_key)
            ]),
        expected_status=200,
        expected_message_type=message.concents.ForcePaymentRejected,
        expected_content_type='application/octet-stream',
    )
def test_case_4_test_for_duplicated_request(cluster_consts: ProtocolConstants, cluster_url: str) -> None:  # pylint: disable=unused-argument
    receive_pending_messages_for_requestor_and_provider(
        cluster_url,
        sci_base,
        CONCENT_PUBLIC_KEY
    )
    current_time = get_current_utc_timestamp()

    result_file_content_1 = 'test'
    source_file_content_2 = 'test'
    result_file_size_1 = len(result_file_content_1)
    source_file_size_2 = len(source_file_content_2)
    result_file_check_sum_1 = 'sha1:' + hashlib.sha1(result_file_content_1.encode()).hexdigest()
    source_file_check_sum_2 = 'sha1:' + hashlib.sha1(source_file_content_2.encode()).hexdigest()

    subtask_results_verify = get_subtask_results_verify(
        current_time,
        reason=message.tasks.SubtaskResultsRejected.REASON.VerificationNegative,
        report_computed_task_size=result_file_size_1,
        report_computed_task_package_hash=result_file_check_sum_1,
        task_to_compute_size=source_file_size_2,
        task_to_compute_package_hash=source_file_check_sum_2,
        render_parameters=get_render_params()
    )

    api_request(
        cluster_url,
        'send',
        sci_base.provider_private_key,
        CONCENT_PUBLIC_KEY,
        subtask_results_verify,
        expected_status=200,
        expected_message_type=message.concents.AckSubtaskResultsVerify,
        expected_content_type='application/octet-stream',
    )

    # Set signature to None so message can be serialized again.
    subtask_results_verify.sig = None

    api_request(
        cluster_url,
        'send',
        sci_base.provider_private_key,
        CONCENT_PUBLIC_KEY,
        subtask_results_verify,
        expected_status=200,
        expected_message_type=message.concents.ServiceRefused,
        expected_content_type='application/octet-stream',
    )
def test_case_6_test_with_invalid_blender_script_parameters(cluster_consts: ProtocolConstants, cluster_url: str) -> None:  # pylint: disable=unused-argument
    receive_pending_messages_for_requestor_and_provider(
        cluster_url,
        sci_base,
        CONCENT_PUBLIC_KEY
    )
    current_time = get_current_utc_timestamp()

    current_dir = os.path.dirname(os.path.abspath(__file__))
    with open(os.path.join(current_dir, 'tests_resources', 'source.zip'), 'rb') as archive:
        source_file_content = archive.read()
    with open(os.path.join(current_dir, 'tests_resources', 'result.zip'), 'rb') as archive:
        result_file_content = archive.read()

    result_file_size = len(result_file_content)
    source_file_size = len(source_file_content)
    result_file_checksum = 'sha1:' + hashlib.sha1(result_file_content).hexdigest()
    source_file_checksum = 'sha1:' + hashlib.sha1(source_file_content).hexdigest()

    subtask_results_verify=get_subtask_results_verify(
        current_time,
        reason=message.tasks.SubtaskResultsRejected.REASON.VerificationNegative,
        report_computed_task_size=result_file_size,
        report_computed_task_package_hash=result_file_checksum,
        task_to_compute_size=source_file_size,
        task_to_compute_package_hash=source_file_checksum,
        price=1000,
    )

    # Setting parameters which are necessary for proper blender work to invalid values
    subtask_results_verify.task_to_compute.compute_task_def['extra_data']['crops'] = None
    subtask_results_verify.task_to_compute.compute_task_def['extra_data']['resolution'] = None
    subtask_results_verify.task_to_compute.compute_task_def['extra_data']['samples'] = None
    subtask_results_verify.task_to_compute.compute_task_def['extra_data']['use_compositing'] = None

    api_request(
        cluster_url,
        'send',
        sci_base.provider_private_key,
        CONCENT_PUBLIC_KEY,
        subtask_results_verify,
        expected_status=400,
        expected_error_code='message.invalid',
    )
示例#6
0
def test_case_2b_not_enough_funds(cluster_consts: ProtocolConstants,
                                  cluster_url: str) -> None:
    #  Test CASE 2B - Send ForceSubtaskResults with not enough amount of funds on account
    receive_pending_messages_for_requestor_and_provider(
        cluster_url, sci_base, CONCENT_PUBLIC_KEY)
    current_time = get_current_utc_timestamp()
    api_request(
        cluster_url,
        'send',
        sci_base.provider_empty_account_private_key,
        CONCENT_PUBLIC_KEY,
        create_force_subtask_results(
            timestamp=timestamp_to_isoformat(current_time),
            ack_report_computed_task=create_ack_report_computed_task(
                timestamp=timestamp_to_isoformat(current_time),
                report_computed_task=create_signed_report_computed_task(
                    task_to_compute=create_signed_task_to_compute(
                        timestamp=calculate_timestamp(
                            current_time,
                            cluster_consts.concent_messaging_time,
                            cluster_consts.minimum_upload_rate),
                        deadline=calculate_deadline(
                            current_time,
                            cluster_consts.concent_messaging_time,
                            cluster_consts.minimum_upload_rate),
                        price=10000,
                        provider_public_key=sci_base.
                        provider_empty_account_public_key,
                        provider_private_key=sci_base.
                        provider_empty_account_private_key,
                        requestor_public_key=sci_base.
                        requestor_empty_account_public_key,
                        requestor_private_key=sci_base.
                        requestor_empty_account_private_key),
                    provider_private_key=sci_base.
                    provider_empty_account_private_key,
                ),
                requestor_private_key=sci_base.
                requestor_empty_account_private_key,
            )),
        expected_status=200,
        expected_message_type=message.concents.ServiceRefused,
        expected_content_type='application/octet-stream',
    )
def test_case_1_test_for_positive_case(cluster_consts: ProtocolConstants, cluster_url: str) -> None:  # pylint: disable=unused-argument
    receive_pending_messages_for_requestor_and_provider(
        cluster_url,
        sci_base,
        CONCENT_PUBLIC_KEY
    )
    current_time = get_current_utc_timestamp()
    provider_deposit_value = sci_base.get_provider_gntb_balance()
    requestor_deposit_value = sci_base.get_requestor_deposit_value()

    current_dir = os.path.dirname(os.path.abspath(__file__))
    with open(os.path.join(current_dir, 'tests_resources', 'source.zip'), 'rb') as archive:
        source_file_content = archive.read()
    with open(os.path.join(current_dir, 'tests_resources', 'result.zip'), 'rb') as archive:
        result_file_content = archive.read()

    result_file_size = len(result_file_content)
    source_file_size = len(source_file_content)
    result_file_checksum = 'sha1:' + hashlib.sha1(result_file_content).hexdigest()
    source_file_checksum = 'sha1:' + hashlib.sha1(source_file_content).hexdigest()

    subtask_results_verify = get_subtask_results_verify(
        current_time,
        reason=message.tasks.SubtaskResultsRejected.REASON.VerificationNegative,
        report_computed_task_size=result_file_size,
        report_computed_task_package_hash=result_file_checksum,
        task_to_compute_size=source_file_size,
        task_to_compute_package_hash=source_file_checksum,
        price=10000,
        render_parameters=get_render_params()
    )

    ack_subtask_results_verify = api_request(
        cluster_url,
        'send',
        sci_base.provider_private_key,
        CONCENT_PUBLIC_KEY,
        subtask_results_verify,
        expected_status=200,
        expected_message_type=message.concents.AckSubtaskResultsVerify,
        expected_content_type='application/octet-stream',
    )

    response = upload_file_to_storage_cluster(
        result_file_content,
        ack_subtask_results_verify.file_transfer_token.files[0]['path'],  # type: ignore
        ack_subtask_results_verify.file_transfer_token,  # type: ignore
        sci_base.provider_private_key,
        sci_base.provider_public_key,
        CONCENT_PUBLIC_KEY,
        STORAGE_CLUSTER_ADDRESS,
    )
    assert_condition(response.status_code, 200, 'File has not been stored on cluster')
    print('\nUploaded file with task_id {}. Checksum of this file is {}, and size of this file is {}.\n'.format(
        subtask_results_verify.task_id,
        result_file_checksum,
        result_file_size
    ))

    response = upload_file_to_storage_cluster(
        source_file_content,
        ack_subtask_results_verify.file_transfer_token.files[1]['path'],  # type: ignore
        ack_subtask_results_verify.file_transfer_token,  # type: ignore
        sci_base.provider_private_key,
        sci_base.provider_public_key,
        CONCENT_PUBLIC_KEY,
        STORAGE_CLUSTER_ADDRESS,
    )
    assert_condition(response.status_code, 200, 'File has not been stored on cluster')
    print('\nUploaded file with task_id {}. Checksum of this file is {}, and size of this file is {}.\n'.format(
        subtask_results_verify.task_id,
        source_file_checksum,
        source_file_size
    ))

    # Adding calculated number of seconds to time sleep makes us sure that subtask is after deadline.
    sleep_time = calculate_verification_deadline(
        subtask_results_verify.subtask_results_rejected.timestamp,
        cluster_consts.additional_verification_call_time,
        subtask_results_verify.subtask_results_rejected.report_computed_task.size,
        cluster_consts.minimum_upload_rate,
    ) - current_time
    print(f"Going to sleep for {sleep_time} secs...")
    time.sleep(
        sleep_time
    )

    api_request(
        cluster_url,
        'receive',
        sci_base.requestor_private_key,
        CONCENT_PUBLIC_KEY,
        create_client_auth_message(sci_base.requestor_private_key, sci_base.requestor_public_key, CONCENT_PUBLIC_KEY),
        expected_status=200,
        expected_message_type=message.concents.SubtaskResultsSettled,
        expected_content_type='application/octet-stream',
    )

    api_request(
        cluster_url,
        'receive',
        sci_base.provider_private_key,
        CONCENT_PUBLIC_KEY,
        create_client_auth_message(sci_base.provider_private_key, sci_base.provider_public_key, CONCENT_PUBLIC_KEY),
        expected_status=200,
        expected_message_type=message.concents.SubtaskResultsSettled,
        expected_content_type='application/octet-stream',
    )
    sci_base.ensure_that_provider_has_specific_gntb_balance(value=provider_deposit_value + 10000)
    sci_base.ensure_that_requestor_has_specific_deposit_balance(value=requestor_deposit_value - 10000)
示例#8
0
def test_case_2d_requestor_rejects_subtask_results(
        cluster_consts: ProtocolConstants, cluster_url: str) -> None:
    # Test CASE 2D + 3 + 4B + 5. Requestor sends ForceSubtaskResultsResponse with SubtaskResultsRejected
    receive_pending_messages_for_requestor_and_provider(
        cluster_url, sci_base, CONCENT_PUBLIC_KEY)
    current_time = get_current_utc_timestamp()
    signed_task_to_compute = create_signed_task_to_compute(
        timestamp=calculate_timestamp(current_time,
                                      cluster_consts.concent_messaging_time,
                                      cluster_consts.minimum_upload_rate),
        deadline=calculate_deadline(current_time,
                                    cluster_consts.concent_messaging_time,
                                    cluster_consts.minimum_upload_rate),
        price=1000,
        provider_public_key=sci_base.provider_public_key,
        provider_private_key=sci_base.provider_private_key,
        requestor_public_key=sci_base.requestor_public_key,
        requestor_private_key=sci_base.requestor_private_key)
    api_request(
        cluster_url,
        'send',
        sci_base.provider_private_key,
        CONCENT_PUBLIC_KEY,
        create_force_subtask_results(
            timestamp=timestamp_to_isoformat(current_time),
            ack_report_computed_task=create_ack_report_computed_task(
                timestamp=timestamp_to_isoformat(current_time),
                report_computed_task=create_signed_report_computed_task(
                    task_to_compute=signed_task_to_compute,
                    provider_private_key=sci_base.provider_private_key,
                ),
                requestor_private_key=sci_base.requestor_private_key)),
        expected_status=202,
    )
    api_request(
        cluster_url,
        'receive',
        sci_base.requestor_private_key,
        CONCENT_PUBLIC_KEY,
        create_client_auth_message(sci_base.requestor_private_key,
                                   sci_base.requestor_public_key,
                                   CONCENT_PUBLIC_KEY),
        expected_status=200,
        expected_message_type=message.concents.ForceSubtaskResults,
        expected_content_type='application/octet-stream',
    )
    api_request(
        cluster_url,
        'send',
        sci_base.requestor_private_key,
        CONCENT_PUBLIC_KEY,
        create_force_subtask_results_response(
            timestamp=timestamp_to_isoformat(current_time),
            subtask_results_rejected=create_subtask_results_rejected(
                reason=message.tasks.SubtaskResultsRejected.REASON.
                VerificationNegative,
                timestamp=timestamp_to_isoformat(current_time),
                report_computed_task=create_signed_report_computed_task(
                    task_to_compute=signed_task_to_compute,
                    timestamp=timestamp_to_isoformat(current_time),
                    provider_private_key=sci_base.provider_private_key,
                ),
                requestor_private_key=sci_base.requestor_private_key)),
        expected_status=202,
    )
    api_request(
        cluster_url,
        'receive',
        sci_base.provider_private_key,
        CONCENT_PUBLIC_KEY,
        create_client_auth_message(sci_base.provider_private_key,
                                   sci_base.provider_public_key,
                                   CONCENT_PUBLIC_KEY),
        expected_status=200,
        expected_message_type=message.concents.ForceSubtaskResultsResponse,
        expected_content_type='application/octet-stream',
    )
示例#9
0
def test_case_2a_send_duplicated_force_subtask_results(
        cluster_consts: ProtocolConstants, cluster_url: str) -> None:
    #  Test CASE 2A + 2D + 3 + 4B + 5 - Send ForceSubtaskResults with same task_id as stored by Concent before
    #  Step 1. Send ForceSubtaskResults first time
    receive_pending_messages_for_requestor_and_provider(
        cluster_url, sci_base, CONCENT_PUBLIC_KEY)
    current_time = get_current_utc_timestamp()
    signed_task_to_compute = create_signed_task_to_compute(
        timestamp=calculate_timestamp(current_time,
                                      cluster_consts.concent_messaging_time,
                                      cluster_consts.minimum_upload_rate),
        deadline=calculate_deadline(current_time,
                                    cluster_consts.concent_messaging_time,
                                    cluster_consts.minimum_upload_rate),
        price=1000,
        provider_public_key=sci_base.provider_public_key,
        provider_private_key=sci_base.provider_private_key,
        requestor_public_key=sci_base.requestor_public_key,
        requestor_private_key=sci_base.requestor_private_key)
    force_subtask_results = create_force_subtask_results(
        timestamp=timestamp_to_isoformat(current_time),
        ack_report_computed_task=create_ack_report_computed_task(
            timestamp=timestamp_to_isoformat(current_time),
            report_computed_task=create_signed_report_computed_task(
                task_to_compute=signed_task_to_compute,
                provider_private_key=sci_base.provider_private_key,
            ),
            requestor_private_key=sci_base.requestor_private_key,
        ))
    signed_report_computed_task = create_signed_report_computed_task(
        task_to_compute=signed_task_to_compute,
        provider_private_key=sci_base.provider_private_key,
    )
    api_request(
        cluster_url,
        'send',
        sci_base.provider_private_key,
        CONCENT_PUBLIC_KEY,
        force_subtask_results,
        expected_status=202,
    )
    time.sleep(1)
    #  Step 2. Send ForceSubtaskResults second time with same task_id
    # Signature must be set to None, because msg will be signed again in api_request()
    force_subtask_results.sig = None
    api_request(
        cluster_url,
        'send',
        sci_base.provider_private_key,
        CONCENT_PUBLIC_KEY,
        force_subtask_results,
        expected_status=200,
        expected_message_type=message.concents.ServiceRefused,
        expected_content_type='application/octet-stream',
    )
    #  Step 3. Requestor wants to receive ForceSubtaskResults from Concent
    api_request(
        cluster_url,
        'receive',
        sci_base.requestor_private_key,
        CONCENT_PUBLIC_KEY,
        create_client_auth_message(sci_base.requestor_private_key,
                                   sci_base.requestor_public_key,
                                   CONCENT_PUBLIC_KEY),
        expected_status=200,
        expected_message_type=message.concents.ForceSubtaskResults,
        expected_content_type='application/octet-stream',
    )

    #  Step 4. Requestor sends ForceSubtaskResultsResponse for the first ForceSubtaskResults
    api_request(
        cluster_url,
        'send',
        sci_base.requestor_private_key,
        CONCENT_PUBLIC_KEY,
        create_force_subtask_results_response(
            timestamp=timestamp_to_isoformat(current_time),
            subtask_results_accepted=create_signed_subtask_results_accepted(
                payment_ts=current_time + 1,
                report_computed_task=signed_report_computed_task,
                requestor_private_key=sci_base.requestor_private_key,
            )),
        expected_status=202,
    )
    #  Step 5. Provider receives ForceSubtaskResultsResponse
    api_request(
        cluster_url,
        'receive',
        sci_base.provider_private_key,
        CONCENT_PUBLIC_KEY,
        create_client_auth_message(sci_base.provider_private_key,
                                   sci_base.provider_public_key,
                                   CONCENT_PUBLIC_KEY),
        expected_status=200,
        expected_message_type=message.concents.ForceSubtaskResultsResponse,
        expected_content_type='application/octet-stream',
    )
示例#10
0
def test_case_4b_requestor_accepts_subtaks_results(
        cluster_consts: ProtocolConstants, cluster_url: str) -> None:
    # Test CASE 4B + 5. Requestor sends ForceSubtaskResultsResponse with SubtaskResultsAccepted
    #  Step 1. Provider sends ForceSubtaskResults
    receive_pending_messages_for_requestor_and_provider(
        cluster_url, sci_base, CONCENT_PUBLIC_KEY)
    current_time = get_current_utc_timestamp()
    signed_task_to_compute = create_signed_task_to_compute(
        timestamp=calculate_timestamp(current_time,
                                      cluster_consts.concent_messaging_time,
                                      cluster_consts.minimum_upload_rate),
        deadline=calculate_deadline(current_time,
                                    cluster_consts.concent_messaging_time,
                                    cluster_consts.minimum_upload_rate),
        price=1000,
        provider_public_key=sci_base.provider_public_key,
        provider_private_key=sci_base.provider_private_key,
        requestor_public_key=sci_base.requestor_public_key,
        requestor_private_key=sci_base.requestor_private_key)
    signed_report_computed_task = create_signed_report_computed_task(
        task_to_compute=signed_task_to_compute,
        provider_private_key=sci_base.provider_private_key,
    )
    api_request(
        cluster_url,
        'send',
        sci_base.provider_private_key,
        CONCENT_PUBLIC_KEY,
        create_force_subtask_results(
            timestamp=timestamp_to_isoformat(current_time),
            ack_report_computed_task=create_ack_report_computed_task(
                timestamp=timestamp_to_isoformat(current_time),
                report_computed_task=signed_report_computed_task,
                requestor_private_key=sci_base.requestor_private_key)),
        expected_status=202,
    )
    time.sleep(1)
    #  Step 2. Requestor receives ForceSubtaskResults
    api_request(
        cluster_url,
        'receive',
        sci_base.requestor_private_key,
        CONCENT_PUBLIC_KEY,
        create_client_auth_message(sci_base.requestor_private_key,
                                   sci_base.requestor_public_key,
                                   CONCENT_PUBLIC_KEY),
        expected_status=200,
        expected_message_type=message.concents.ForceSubtaskResults,
        expected_content_type='application/octet-stream',
    )
    #  Step 3. Requestor sends ForceSubtaskResultsResponse
    api_request(
        cluster_url,
        'send',
        sci_base.requestor_private_key,
        CONCENT_PUBLIC_KEY,
        create_force_subtask_results_response(
            timestamp=timestamp_to_isoformat(current_time),
            subtask_results_accepted=create_signed_subtask_results_accepted(
                payment_ts=current_time + 1,
                report_computed_task=signed_report_computed_task,
                requestor_private_key=sci_base.requestor_private_key,
            )),
        expected_status=202,
    )
    #  Step 4. Provider receives ForceSubtaskResultsResponse
    api_request(
        cluster_url,
        'receive',
        sci_base.provider_private_key,
        CONCENT_PUBLIC_KEY,
        create_client_auth_message(sci_base.provider_private_key,
                                   sci_base.provider_public_key,
                                   CONCENT_PUBLIC_KEY),
        expected_status=200,
        expected_message_type=message.concents.ForceSubtaskResultsResponse,
        expected_content_type='application/octet-stream',
    )
def test_case_2d_send_correct_force_payment(cluster_consts: ProtocolConstants,
                                            cluster_url: str) -> None:
    # Test CASE 2D - Send correct ForcePayment
    receive_pending_messages_for_requestor_and_provider(
        cluster_url, sci_base, CONCENT_PUBLIC_KEY)
    provider_gntb_balance = sci_base.get_provider_gntb_balance()
    current_time = get_current_utc_timestamp()
    correct_force_payment = force_payment(subtask_results_accepted_list=[
        create_signed_subtask_results_accepted(
            timestamp=timestamp_to_isoformat(current_time -
                                             cluster_consts.payment_due_time +
                                             AVERAGE_TIME_FOR_TWO_BLOCKS),
            payment_ts=current_time - cluster_consts.payment_due_time -
            AVERAGE_TIME_FOR_TWO_BLOCKS,
            report_computed_task=create_signed_report_computed_task(
                task_to_compute=create_signed_task_to_compute(
                    timestamp=parse_timestamp_to_utc_datetime(current_time),
                    deadline=current_time,
                    price=1000,
                    provider_public_key=sci_base.provider_public_key,
                    provider_private_key=sci_base.provider_private_key,
                    requestor_public_key=sci_base.requestor_public_key,
                    requestor_private_key=sci_base.requestor_private_key,
                ),
                provider_private_key=sci_base.provider_private_key),
            requestor_private_key=sci_base.requestor_private_key,
        ),
        create_signed_subtask_results_accepted(
            timestamp=timestamp_to_isoformat(current_time -
                                             cluster_consts.payment_due_time +
                                             AVERAGE_TIME_FOR_TWO_BLOCKS),
            payment_ts=current_time - cluster_consts.payment_due_time -
            AVERAGE_TIME_FOR_TWO_BLOCKS,
            report_computed_task=create_signed_report_computed_task(
                task_to_compute=create_signed_task_to_compute(
                    timestamp=parse_timestamp_to_utc_datetime(current_time),
                    deadline=current_time,
                    price=1000,
                    provider_public_key=sci_base.provider_public_key,
                    provider_private_key=sci_base.provider_private_key,
                    requestor_public_key=sci_base.requestor_public_key,
                    requestor_private_key=sci_base.requestor_private_key,
                ),
                provider_private_key=sci_base.provider_private_key),
            requestor_private_key=sci_base.requestor_private_key,
        ),
    ])
    correct_force_payment.sig = None
    requestor_deposit_value = sci_base.get_requestor_deposit_value()
    api_request(
        cluster_url,
        'send',
        sci_base.provider_private_key,
        CONCENT_PUBLIC_KEY,
        correct_force_payment,
        expected_status=200,
        expected_message_type=message.concents.ForcePaymentCommitted,
        expected_content_type='application/octet-stream',
    )
    time.sleep(5)
    api_request(
        cluster_url,
        'receive',
        sci_base.requestor_private_key,
        CONCENT_PUBLIC_KEY,
        create_client_auth_message(sci_base.requestor_private_key,
                                   sci_base.requestor_public_key,
                                   CONCENT_PUBLIC_KEY),
        expected_status=200,
        expected_message_type=message.concents.ForcePaymentCommitted,
        expected_content_type='application/octet-stream',
    )
    sci_base.ensure_that_provider_has_specific_gntb_balance(
        value=provider_gntb_balance + 2000)
    sci_base.ensure_that_requestor_has_specific_deposit_balance(
        value=requestor_deposit_value - 2000)